Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

AVR, Enkoder, Delphi Odczyt pozycji przez RS.

Proteus76 15 Feb 2011 11:17 4981 33
  • #1
    Proteus76
    Level 10  
    Witam !

    Proszę o pomoc w rozwiązaniu takiego problemu. Mam układ obliczający długość przewodu za pomocą Enkodera Kubler (1000 imp.) wykonany na mikrokontrolerze
    ATmega8535. Procesorek ładnie zlicza impulsy z wyjścia INT0, rozpoznaje kierunki oraz wyświetla wszystko na LCD. Problem polega na tym że muszę mieć odczyt długości na aplikacji PC. Wszystko zrealizowałem na BASCOM-ie oraz Delphi. RS działa jednak występują problemy z komunikacją tzn. aplikacja wyświetla mi tylko część wysłanego z procesora poleceniem print komunikatu np. zamiast 1024 tylko 24 lub 024 itp. Na Delphi korzystam z komponentu Comport (wyświetla znak w oknie kiedy zajdzie zdarzenie RXchar). Próbowałem zwolnić transmisję, właczyć bufor wyjściowy portu w BASCOM-ie, powiesić wysyłanie z procesora na przerywaniu z timera. Niestety nic nie pomogło. Dodam że Delphi to dla mnie nowość więc przypuszczam że coś robie nie tak od strony aplikacji PC. Z góry dziękuję za każdy post bo może uda mi się popchnąć dzięki temu projekt do przodu.
  • #2
    mgyz
    Level 13  
    włącz w komponencie ComPort buforowanie danych.
  • #3
    Proteus76
    Level 10  
    Jak mówiłem Delphi to dla mnie nowość. Więc bardzo proszę o dokładniejsze informacje.
  • #4
    LordBlick
    VIP Meritorious for electroda.pl
    Najprościej, to jakby ATmega udawała klawiaturę (wysyłając kody klawiszy po wciśnięciu jakiegoś przycisku kończącego pomiar), to i nie trzeba by było cudować i działałoby na każdym systemie operacyjnym.
  • #5
    Proteus76
    Level 10  
    Tak, tylko że pomiar następuje w sposób ciągły i wymagane jest też wyświetlanie wyniku w czasie rzeczywistym. Wszystko wydawało się bardzo proste ale jak zwykle diabeł tkwi w szczegółach. Nie jestem przekonany że buforowanie pomoże.
  • #6
    asembler
    Level 32  
    Widze że gubi ci poczatkowe znaki. Możnaby dołączyć przedwynikiem kilka pustych znakow. Oczywiscie nie jest to rozwiazanie problemu ale jezeli tak jest to bedzie wiadomo gdzie szukac przyczyny.
  • #7
    mgyz
    Level 13  
    A mi się wydaje, że buforowanie może pomóc, bo jak odbierasz po jednym znaku to zanim program zajmie sie jego obsługą i go wyświetli (czy tam cokolwiek z nim zrobi) to przez ten czas może nadejść kolejny znak a program nie będzie na niego gotowy - będzie robił co innego a nie czekał na znak. Przy włączonym buforze jak program dojedzie do odbioru kolejnego znaku to po prostu wyjmie sobie go z bufora.

    Jeszcze jedno przyjżyj się ustawieniom time-out'ów na odbiór znaku/ ciągu znaków (w helpie jest to opisane)
  • #8
    asembler
    Level 32  
    Z tym że buforowanie od strony PC a autor pisał że od strony AVR spowalniał transmisje i nic nie dało.
  • #9
    mgyz
    Level 13  
    a co ja napisałem?
    mgyz wrote:
    włącz w komponencie ComPort buforowanie danych.
  • #10
    Proteus76
    Level 10  
    Hmm... Tylko na moim poziomie umiejętności w temacie Delphi stwierdzenie "włacz bufor w Comporcie jest" dosyć abstrakcyjne. Czy może ktoś dokładnie opisać co i jak a najlepiej wkleić kawałek niezbędnego kodu. Dalej mam nadzieję poradze sobie sam.
  • #11
    mgyz
    Level 13  
    Z tego co pamiętam to chyba wystarczy we właściwościach kontrolki znaleźć pole bufout oraz bufin i ustawić wartość większą od zera
  • #12
    Piotrek_P
    Level 18  
    nie wiem co tam masz w kodzie Delphi, ale procedura wzięta żywcem z przykładowych programów ComPort'a działa bez zarzutu. Sprawdzone wiele razy.

    Code:

    procedure TForm1.ComPortRxChar(Sender: TObject; Count: Integer);
    var
      Str: String;
    begin
      ComPort.ReadStr(Str, Count);
      Memo.Text := Memo.Text + Str;
    end;



    Mając zawartość bufora w zmiennej Str można już dalej bawić się po swojemu.
    Acha, bufor in/out jest domyślnie ustawiony na 1024 więc przy prostych zastosowaniach nic nie trzeba zmieniać.
  • #13
    GL4DI470R
    Level 11  
    Witam !
    Mam podobny problem z którym jeszcze się nie uporałem. Ale w tym poście chodzi mi o coś innego. Otóż napisałem malutki programik który w ramach możliwości będę rozwijał, narazie umiem odczytywać dane z avr po chłopsku czyli tak jak leci.
    A chodzi mi o to żeby AVR wysyłał z 4 różne zmienne które aplikacja będzie rozpoznawała i umieszczała wynik w odpowienim memo i nie mam pojęcia jak to zrobić. Dodam jeszcze że probram do atmegi jest pisany w Bascom.
    Własnymi siłami próbowałem zrobić to w taki sposób że od strony avr będą 4 zmienne np x,y,z,q i teraz avr najpierw wyśle znak "x" który zostanie odebrany w aplikacji przez pętlę if str=x, w następnej kolejności zostanie wysłana wartość tego x i wartość ta zostanie umieszczona w memo1, później y itd.

    Korzystam z kompomentu ComPort i odczytuję z Atmegi 16 dane w taki sposób :

    procedure TForm1.ComPortRxChar(Sender: TObject; Count: integer );
    var
    str: string;
    begin
    ComPort1.ReadStr(str,count);
    Memo1.text := str;
    end;
    Aplikacja wygląda tak:

    AVR, Enkoder, Delphi Odczyt pozycji przez RS.

    Na koniec dodam że inspiracją tego projektu jest Pan mirekk36 za co mu serdecznie dziękuję !
    Pozdrawiam i proszę o pomoc !
  • #14
    Piotrek_P
    Level 18  
    Ja bym to zrobił tak. Przed wysłaniem danej do PC, sformatował bym odpowiednio ramkę np do takiej postaci:
    *nr_zmiennej*wartość_zmiennej_jako_tekst

    Po odebraniu ramki, sprawdzamy nr_zmiennej:
    Code: delphi
    Log in, to see the code


    Powinno działać. W razie dodatkowych pytań chętnie pomogę.

    Pozdrawiam
    Piotrek
  • #15
    GL4DI470R
    Level 11  
    niestety nie umiem z tego skorzystać. Jestem zielony jeśli chodzi o Delphi i ucze się na zasadzie prób i błędów.
    próbowałem w ten sposób:



    procedure TForm1.ComPortRxChar(Sender: TObject; Count: integer );
    var
    str: string;
    str2:string;




    begin
    ComPort1.ReadStr(str,count);
    if (str='1') then
    ComPort1.WriteStr('1');
    ComPort1.ReadStr(str2,count);
    memo1.text:=str2 ;

    ComPort1.ReadStr(str,count);
    if (str='1') then
    ComPort1.WriteStr('2');
    ComPort1.ReadStr(str3,count);
    memo1.text:=str3 ;
    end;

    I miało to wyglądać tak, że uC wysyła print "1" czyli 1 jako string, aplikacja to odbiera wchodzi w 1 pętlę if, wysyła uC "1" jako znak że jest gotowa do odbioru pierwszej zmiennej do memo1. uC po wysłaniu tej zmiennej miałby wysłać "2" aplikacja mialaby wejsc w nastepna petle if i wpisac kolejna wartosc do memo2 niestety ten sposob nie dziala i ni cholery nie wiem dlaczego.
  • #17
    mirekk36
    Level 42  
    Bardzo przepraszam, że się wcześniej nie odezwałem w tym temacie ale mail mi umknął :(

    Kolega zdaje mi się (tak na szybko) o ile dobrze pamiętam komponent ComPort źle korzysta z jego zdarzeń :( .... a przecież razem z ComPort są przykładowe programy i tam można podejrzeć jak się to robi. Zaglądał tam kolega ?
  • #18
    GL4DI470R
    Level 11  
    Quote:
    Ciekaw jestem szczegolow projektu, mozna sie dowiedziec czegos wiecej?

    A więc cały komputer mam chłodzony wodą, do tego pasjonuję się elektroniką i wpadłem na pomysł żeby wszystko co się da, wentylatory, pompkę, temperaturę, oświetlenie, kontrolować przy pomocy uC. Potem postanowiłem ustawić poprzeczkę wyżej i kontrolować to nie tylko za pomocą uC ale i myszką z poziomu Windowsa. Patrząc na projekty Pana "mirekk36" pomyślałem że też tak chcę (wtedy jeszcze nie wiedziałem że Pan Mirek robi to zawodowo :) ), tak to się mniej więcej zaczęło.

    Quote:
    Kolega zdaje mi się (tak na szybko) o ile dobrze pamiętam komponent ComPort źle korzysta z jego zdarzeń .... a przecież razem z ComPort są przykładowe programy i tam można podejrzeć jak się to robi. Zaglądał tam kolega ?

    Mój obraz działania programu jest "wypracowany" w Bascom, nie znam innego mimo że na studiach troszkę pisałem w C. Cała ta moja aplikacje jest mniej lub bardziej żywcem zerżnięta (przepraszam za słowo) właśnie z programów dołączonych do komponentu, także tak, zaglądałem tam i dzięki temu doszedłem do tego miejsca w którym jestem. Starałem się to "pchnąć" na różne sposoby przez ok. 4 dni i dalej lipa. Proszę o pomoc
  • #19
    mirekk36
    Level 42  
    Przyznam, że założenia projektu fajniutkie ;) ....

    Odnośnie programu, teraz przyjrzałem się tej procedurze to niestety hmm nie mam już dawno tego komponentu i nie pamiętam dokładnie obsługi, ale patrząc na kod widać jednak bardzo poważne błędy. I nie chodzi o to że coś tam jest źle napisane w jednym czy drugim miejscu.

    Po prostu kolega jeszcze nie czuje jak odbierać dane asynchronicznie. Ten komponent oczywiście to umożliwia ale nie na zasadzie, że cały twój kod programu do obsługi odbieranych danych wstawisz do tego zdarzenia :(

    Przecież pomyśl sobie - taka prosta rzecz, masz parametr Count, a to już świadczy o tym, że może zostać odebrany string o różnej długości .... tymczasem ty poniżej robisz proste (zbyt proste i niestety złe porównanie)

    if (str='1') then

    a zastanowiłeś się co stanie się ze znakami ENTER jeśli je w ogóle używasz ? a jeśli nie to źle - lepiej użyć wtedy można w takim zdarzeniu sprawdzać kiedy nadleciał enter i dopiero wtedy porównywać odebrany string (wyłączając z niego enter za pomocą chociażby Trim) i zakładając że będziesz sprawdzał dokładnie to co wysyłasz z procka.

    Generalnie chodzi jak zwykle o wyrobienie sobie i nauczenie się najprostszych mechanizmów parsowania (analizowania) nadlatujących danych. Dlatego wskazówka - przesyłaj je przede wszystkim jako znaki ASCII. A ty nie pokazałeś jak robisz to na procku - a też możesz robić wszystko "do góry nogami" - dlatego ciężko z uruchomieniem tego :(

    dlatego przemyśl przede wszystkim poprawne wysyłanie tych zmiennych i jeszcze raz podpowiadam jako znaki ASCII a nie binarnie

    na końcu każdej przesyłki dawaj SAM ENTER

    a w Delphi sprawdzaj kiedy nadleciał ENTER i to co jest przed nim to twoja zmienna jako string ;)

    Może chociaż taka wskazówka na coś cię naprowadzi ..... A jeszcze raz powiem, że fajny projekt i sam z chęcią zobaczyłbym efekt końcowy ;)

    powodzenia
  • #20
    GL4DI470R
    Level 11  
    Quote:
    a zastanowiłeś się co stanie się ze znakami ENTER jeśli je w ogóle używasz ? a jeśli nie to źle

    To pierwszy słuszny zarzut, znak Enter (czyli znak przejścia do początku następnej linii) jest automatycznie wysyłany przez Basom, a dokładniej instrukcję Print.

    Quote:
    Dlatego wskazówka - przesyłaj je przede wszystkim jako znaki ASCII. A ty nie pokazałeś jak robisz to na procku - a też możesz robić wszystko "do góry nogami" - dlatego ciężko z uruchomieniem tego

    W Bascom to jest tak, że do wysyłania danych przez usart jest kilka instrukcji, z czego instrukcja PRINT wysyła zmienne/stałe wartości znaków w kodzie ASCII.

    Quote:
    i dopiero wtedy porównywać odebrany string (wyłączając z niego enter za pomocą chociażby Trim)

    czy wystarczy zastosować coś takiego ?
    Write(Trim(zmienna));

    Quote:
    a w Delphi sprawdzaj kiedy nadleciał ENTER i to co jest przed nim to twoja zmienna jako string

    może jakaś próbka kodu w jaki sposób to sprawdzić?
  • #21
    Piotrek_P
    Level 18  
    Nie wiem czy moje posty są niewidoczne? Dałem wyżej przykład i komentarz, że jak wysyłamy jakiś "string" z BASCOMA to należy po odebraniu odciąć DWA ostatnie bajty którymi są znaki końca linii (CRLF)
  • #22
    GL4DI470R
    Level 11  
    Quote:
    Nie wiem czy moje posty są niewidoczne? Dałem wyżej przykład i komentarz, że jak wysyłamy jakiś "string" z BASCOMA to należy po odebraniu odciąć DWA ostatnie bajty którymi są znaki końca linii (CRLF)

    próbowałem zastosować, narazie nie idzie także bez nerwów :)

    aplikacja minimalnie ewoluowała,
    AVR, Enkoder, Delphi Odczyt pozycji przez RS.

    co do odbioru wielu zmiennych dalej lipa ;/
    Pozdrawiam
  • #23
    GL4DI470R
    Level 11  
    Witam!
    mam problem ze znikającymi znakami z memo i w końcu wiem skąd to się bierze ale nie wiem dlaczego .
    Otóż wygląda to tak że memo1.text:=str posiada jakby 80 miejsc na znaki.
    znaki z uC wysyłam za pomocą Print (zmienna);chr(13) czyli z komendą powrotu do początku lini co oznacza że po odczytaniu liczby "3.23 V" powinienem zając od początku 6 znaków. Przed następnym odczytem czyszczę memo za pomocą memo1.clear i odczytuje kolejną wartość. Tak to wygląda w teorii w praktyce jest tak że po odczycie 13x danych z uC (13x5znaków =78) dochodzi do jakiegoś dziwnego przepełnienia i odczytane zostają 2 liczby i wpisane do memo i dopiero w kolejnym odczycie wszystko wraca do normy.
    Mam nadzieje że opisałem to w miarę dokładnie, ktoś pomoże?
  • #24
    GL4DI470R
    Level 11  
    masakara jakie tu jest zainteresowanie.
  • #25
    Piotrek_P
    Level 18  
    Wyluzuj kolego :-) Jak Ci napisałem kawałek kodu i nie mogłeś z tego skorzystać to też byłem lekko poirytowany, bo poświęciłem trochę czasu. Od Bascoma odszedłem 5 lat temu i starych działających kodów chyba już nie mam, ale mogę pomóc jak trzeba (na ile pamiętam). Zamieść kod Bascomowy, albo poślij do mnie na PW to zobaczę o co biega.

    PP
  • #26
    GL4DI470R
    Level 11  
    Code: basic4gl
    Log in, to see the code



    Code: delphi
    Log in, to see the code


    W sumie nie ma znaczenia czy wysyłam poprzez "PRINT T" CZY "PRINT T;" CZY "PRINT T;"CHAR(13);zawsze jest to samo po kilkunastu odczytach robi się bałagan i po chwilli wraca do normy. Nie ma też znaczenia czy w memo1.text odczytam poprostu "str", czy poszczególne bajty jak to widać w listingu, robi się to samo dołączam filmik żeby pokazać o co chodzi.


  • #27
    Piotrek_P
    Level 18  
    A co dostajesz po RSie na terminalu Windows :?:
    Może to coś pomoże w analizie. Aplikacją w Delphi można zająć się później
  • #28
    GL4DI470R
    Level 11  
    Sorry, ale nie za bradzo wiem o czym mówisz :)
  • #29
    Piotrek_P
    Level 18  
    Na początek skonfiguruj sobie połączenie COM w Terminalu Windows z prędkością transmisji jaką masz ustawioną w programie procka. Jak transmisja będzie OK to w oknie terminala będziesz widział jakie dane przychodzą do komputera i zweryfikujesz to z tym co wysyłasz.

    PP
  • #30
    GL4DI470R
    Level 11  
    Tak wygląda odbiór w dwóch różnych terminalach, 1 to Bascom a 2 to przykładowy dorzucony do komponentu comport, widać na nich że nie ma żadnego problemu z transmisją w obie strony, po wysłaniu do uC "1" kontroler odpowiada zmierzoną temperaturą.
    Dlatego od początku mówiłem że problem jest z prezentacją odebranego wyniku w aplikacji, gdybym każdy odebrany wynik wyświetlał tak jak w terminalu linijkę niżej niż poprzedni to nie ma problemu, natomiast jak chcę żeby wynik był cały czas w tym samym wierszu to wychodzi jak wychodzi.

    AVR, Enkoder, Delphi Odczyt pozycji przez RS.