ComPort.WriteStr - dziwne zachowanie

ComPort.WriteStr - dziwne zachowanie
robertz68
  • Rejestracja:około 18 lat
  • Ostatnio:8 minut
  • Lokalizacja:Zielona Góra
2

Wtrącę trochę do tematu.
Swego czasu skonstruowałem tzw. wyświetlacz klienta. Gdy oprogramowanie drukuje paragon w trybie tzw. offline to klient na bieżąco nie wie jaka jest wartość paragonu. Właśnie do tego stosuje się wyświetlacze klienta. Prosta sprawa, wyświetlacz LCD 2x20 znaków i jakieś sterowanie.
Oczywiście nie wymyślałem wszystkiego od podstaw i odnalazłem dokumentacje popularnego wyświetlacza IBM, moje oprogramowanie emuluje ten właśnie protokół a jest on prosty. Zawsze wysyłane są 40 znaków, sterownik po prostu 21 i następne znaki umieszcza w nowej linii i to wszystko.

Sprawa była bardzo prosta, użyłem najtańsze Arduino NANO z portem USB na Atmedze 328 i kontrolerem CH340 i jak wysyłałem na nie 40 znaków z terminala wszystko działało. Jednak mój program używający komponentu ComPort nie działał? Jednak uwaga, gdy oprogramowanie wgrałem do Arduino Pro Micro na Atmedze 32U4 (która ma kontroler USB w sobie) wszystko działało i z terminala i z komponentu ComPort.
Dla zbadania sprawy nawet zrobiłem analizę ramki wysyłanej przez komputer na oscyloskopie (który potrafi dekodować ramki COM) i nie znalazłem różnicy. Zdekodowana ramka wyglądała tak samo. Chociaż nie przesądza to że fizycznie może ona wyglądać troszkę inaczej, ciężko jednak to analizować na domowym sprzęcie.

W każdym razie, jeśli do sterowania tego robota używasz jakieś Andino, zmień na próbę na inne.
Następna sprawa, jakiej wersji ComPorta używasz, jest tego od groma na rynku i może pomyśl nad zmianą na inny komponent.

MA
  • Rejestracja:ponad 4 lata
  • Ostatnio:około 4 lata
  • Postów:53
0

Mam zainstalowaną ver. 4.11 ComPortu. Zastanawiam się nad zmianą komponentu i dlatego zapytałem jakich używacie.

Jak już pisałem, też zauważyłem, że mimo identycznych ramek i otwierania portu, jeśli łączę się z wirtualnym portem utworzonym w mikrokontrolerze to pojawiają się problemy.

robertz68
  • Rejestracja:około 18 lat
  • Ostatnio:8 minut
  • Lokalizacja:Zielona Góra
0

Też używałem wersji 4.11f ale pamiętaj że to jest komponent z 2011 roku. Autor obiecywał że w wersji 4.20 poprawi dużo zauważonych błędów i są pogłoski że taka wersja nawet została napisana, niestety nigdy nie została opublikowana. W wersji tej także miał się przyłożyć do komunikacji USB - niby to samo ale jednak.
Jakiś czas temu znalazłem na github-ie projekt ComPort-Library i już się ucieszyłem że projekt nadal żyje https://github.com/CWBudde/ComPort-Library
Okazało się jednak że chłopak który "przejął" projekt z sourceforge tak naprawdę tylko dostosowuje go do nowych wersji Delphi. Dobre i to ale jednak potrzebne dzisiaj jest coś więcej.

Dlatego przyglądam się projektowi AsyncPro https://github.com/TurboPack/AsyncPro
Nawet robiłem z nim jakieś testy i nie sprawia problemu. Jednak na razie boję się użyć tego komponentu w rozwiązaniach produkcyjnych gdzie musi po prostu działać.

Może trzeba już zaryzykować i np. wrzucić do projektu dwa sposoby komunikacji. Gdy padnie AsyncPro przełączę się na ComPorta i już.

A może wy macie jakieś spostrzeżenia co do tego komponentu (w końcu jest do pobrania w GetIt)?

Ps. Mirek z firmy Atnel swego czasu napisał komponenty do komunikacji po RS232 a później nawet bezpośrednio USB. Komponenty są płatne i chyba nawet nieźle działają ale problem jest taki że kolega Mirek za bardzo nie nadąża za aktualizacją do nowych wersji Delphi.

MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:12 dni
  • Postów:1082
3

Czy naprawdę potrzeba Wam tych wszystkich zaawansowanych rzeczy które dostarczają te komponenty? Używacie asynchronicznego wysyłania/odbierania danych? Jeśli nie to naprawdę nie rozumiem w czym problem żeby sprawdzić czy te parę linii kodu nie wywoła błędu:

Kopiuj
  int iCom = 12;
  HANDLE hCom = INVALID_HANDLE_VALUE;

// łączenie
  char szCom[100];
  sprintf(szCom,"\\\\.\\COM%d",iCom);
  hCom = CreateFile(szCom,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,NULL,NULL);

  if (hCom == INVALID_HANDLE_VALUE)
  {
    return;
  }
// inicjowanie parametrów transmisji
  DCB dcb;
  bool bSuccess;

  SecureZeroMemory(&dcb, sizeof(DCB));
  dcb.DCBlength = sizeof(DCB);

  bSuccess = GetCommState(hCom, &dcb);

  if (!bSuccess)
  {
    return;
  }

  dcb.BaudRate = CBR_9600;
  dcb.ByteSize = 8;
  dcb.Parity   = NOPARITY;
  dcb.StopBits = ONESTOPBIT;

  SetCommState(hCom, &dcb);
// wysylanie
  char buff[] = "test";
  unsigned long Res;
  WriteFile(hCom,buff,strlen(buff),&Res,NULL);

Niestety kod jest w C, ale w Delphi będzie wyglądać podobnie (nie ma tu nic trudnego do zamiany, same typy proste i funkcje z WinAPI). Ten kod nie ma prawa nie działać. Jest to wersja pozbawiona obsługi błędów tego co siedzi u mnie na produkcji (nie próbowałem tego kompilować, więc mogą być drobne błędy, jednak widać czego należy użyć do tego zadania). Jedyne problemy miałem z wysyłaniem po źle ustawionych parametrach transmisji. Wtedy o dziwo wszystko się powodziło bez błędów jednak urządzenie docelowe nic nie dostawało/reagowało.

Zamknięcie tego we własnej klasie, a nie używanie do tego celu komponentu (i tak nie kładę takich komponentów na formatce, a tworzę w runtime) ma taką zaletę, że nie muszę nic instalować i zaśmiecać tysiącami komponentów do drobnych zadań. Dodatkowo inny programista też w łatwy sposób skompiluje mój system. Co więcej przy zmianie wersji IDE na nową zazwyczaj nic nie muszę zmieniać i kod się od razu kompiluje.

edytowany 1x, ostatnio: Mr.YaHooo
flowCRANE
Sprawdzałeś może czy da się używać procedur Write, WriteLn, Read i ReadLn na pliku portu? Chodzi mi o to, czy da się wysyłać i odbierać dane za pomocą tych podstawowych procedur, bez konieczności używania funkcji z API systemu.
MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:12 dni
  • Postów:1082
1

Na pytanie @furious programming odpowiem jednak w nowym poście, a nie w komentarzu. Ponieważ znalazłem też coś interesującego. Udało mi się znaleźć taki artykuł odnośnie komunikacji po COM'ach w Delphi http://sheepdogguides.com/dt4q.htm Jak widać radzą jeszcze ustawić timeouty transmisji.

Kopiuj
function TDD80f1.SetUpSerPort:byte;
//Call AFTER establishing hCommFile. Returns 0 if setup goes okay.

var
   DCB: TDCB;
   Config : string;
   CommTimeouts : TCommTimeouts;
   bErrCode:byte;

begin
bErrCode:=0;//Will eventually be returned. If zero, no error seen
if not SetupComm(hCommFile, RxBufferSize, TxBufferSize) then
   bErrCode:=1;
   { Raise an exception --- these comments
       all scraps of source material... will try to use exceptions in
       due course!}

if bErrCode=0 then //no "begin" here...  (this is part of kludge avoiding exceptions)
if not GetCommState(hCommFile, DCB) then
   bErrCode:=2;
   { Raise an exception }

Config := 'baud=9600 parity=n data=8 stop=1' + chr(0);

if bErrCode=0 then //no "begin" here...  (this is part of avoiding exceptions)
if not BuildCommDCB(@Config[1], DCB) then
   bErrCode:=3;
   { Raise an exception }

if bErrCode=0 then //no "begin" here...  (this is part of avoiding exceptions)
if not SetCommState(hCommFile, DCB) then
   bErrCode:=4;
   { Raise an exception }

if bErrCode=0 then //no "begin" here...  (this is part of avoiding exceptions)
with CommTimeouts do
begin
   ReadIntervalTimeout := 0;
   ReadTotalTimeoutMultiplier := 0;
   ReadTotalTimeoutConstant := 200;//This determines(?) how long
      //you stay in an attempt to read from serial port. milliseconds
      //I hope these routines are reading from a buffer managed by
      //the OS independently of these routines.
   WriteTotalTimeoutMultiplier := 0;
   WriteTotalTimeoutConstant := 1000;
end;

if bErrCode=0 then //no "begin" here...  (this is part of avoiding exceptions)
if not SetCommTimeouts(hCommFile, CommTimeouts) then
   bErrCode:=5;
   { Raise an exception }

result:=bErrCode;
end;//function SetUpSerPort:byte;

Jak się zagłębić w stronę więcej jest też co nie co o Arduino i innych tego typu rzeczach.

Co do pytania @furious programming to niestety z uzyciem Write, WriteLn, Read i ReadLn na pliku portu jest pewien problem. Zasadniczo powinno się dać w ten sposób pisać do portu (jak również mapując port jako strumień), jednak nie da się w ten sposób ustawić parametrów transmisji. Pod Windows jedyną możliwością ustawienia parametrów transmisji z poziomu WinAPI jest użycie funkcji SetCommState. Ona wymaga otwarcia portu COM i przekazania uchwytu do portu. Jednak nie istnieje przeciwwskazanie do tego aby otworzyć port za pomocą CreateFile ustawić parametry transmisji za pomocą SetCommState oraz zamknąć port za pomocą CloseFile. Po tym parametry portu COM są niezmienione do czasu aż jakiś inny program nie zmieni ustawień, albo nie zresetujemy komputera. Zatem wydaje się być możliwym użycie AssignFile na porcie COM. Jeśli parametry transmisji będą ok wszystko powinno działać. Największym niestety problemem jest ustawienie prędkości, parzystości oraz bitów stopu. Zatem jeśli byśmy mieli ustawiony poprawnie port, to metoda o którą pytasz powinna zadziałać.

MA
  • Rejestracja:ponad 4 lata
  • Ostatnio:około 4 lata
  • Postów:53
0

Dzisiaj zebrałem jeszcze trochę siły. Łączę się między laptopem, a robotem przez przejściówkę USB-COM i jest OK.
Ale jak na chwilę, dla testu, wyjmę z USB tą przejściówkę to pojawia się błąd nr 5 i od tego momentu już nie mogę nawet zamknąć aplikacji napisanej z ComPort. Muszę zamykać przez ubicie tego procesu.
Dlaczego tak się dzieje, że już nie da się nawet zamknąć programu?

Mam jednak za mało wiedzy, aby tworzyć własne komponenty (przez klasy, itp), więc muszę oprzeć się na waszej wiedzy.
Sprawdziłem ComPort z różnymi timeoutami i dalej pojawia się ten błąd nr. 5.
Macie pomysły jak zneutralizować ten błąd?

Fajnie jakby można było zainstalować w pełni działający komponent, ale @robertz68 mówi że AsyncPro ma jeszcze więcej błędów, więc już sam nie wiem czy jest gdzieś dobrze działający komponent.
A może znacie takie komponenty do transmisji COM?

edytowany 1x, ostatnio: Markoni
robertz68
  • Rejestracja:około 18 lat
  • Ostatnio:8 minut
  • Lokalizacja:Zielona Góra
1
Markoni napisał(a):

Dzisiaj zebrałem jeszcze trochę siły. Łączę się między laptopem, a robotem przez przejściówkę USB-COM i jest OK.
.....

Problem stary jak Świat, niestety nie rozwiązany kompleksowo do dzisiaj.
Jak pisałam gdzieś kiedyś, autor komponentu pisał go z myślą o fizycznych portach com, które dość ciężko odłączyć od komputera, szczególnie w trakcie działania. Niestety wirtualne porty to inna bajka a autor zakończył wsparcie lata temu. Jak też gdzieś pisałem, miał już opracowane rozwiązanie ale go nie opublikował wraz z nową wersją. Szczerze, to nie wiadomo jak by działało bo jednak obsługa wyjątków w comport kuleje dość mocno.

Społeczność jednak nie odpuszczała i starała się jakoś rozwiązać problem. Niestety chyba za dobrze to nie wyszło ale przynajmniej są sposoby żeby zignorować błąd i móc dalej używać aplikację.
Tutaj jest jeden ze sposobów polegających na modyfikacji oryginalnego pliku CPort.pas > https://sourceforge.net/p/comport/discussion/261327/thread/c7ab4c4a/

MA
  • Rejestracja:ponad 4 lata
  • Ostatnio:około 4 lata
  • Postów:53
0

Jeszcze zapytam, z czym związany jest komunikat?:

Kopiuj
#err0041 GetNewComInfo Exception
edytowany 1x, ostatnio: flowCRANE
JA
  • Rejestracja:ponad 17 lat
  • Ostatnio:około miesiąc
0

Do Delphi nie znalazłem dobrego komponentu, odradzam ComPort bo ma błędy i się wysypuje, przynajmniej tak było kiedyś. Żeby to zaczęło dobrze działać komponent napisałem sam co też wam polecam. Niestety nie mogę udostępnić napisanego przeze mnie.

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)