Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 19 lut 2025, o 10:27


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 9 ] 
Autor Wiadomość
PostNapisane: 4 mar 2014, o 20:55 
Offline
Użytkownik

Dołączył(a): 08 wrz 2012
Posty: 505
Pomógł: 6

Witam
Mimo wielkich chęci i starań jeszcze chyba nie „dorosłem” do poniższego zadania. Walczę już z problemem kilka dni i nie mogę ruszyć z miejsca a czas mnie goni okropnie. Dlatego zmuszony jestem prosić o pomoc. Mam nadzieję, że mój problem opisałem wystarczająco jak coś to proszę dopytać.

Potrzebuję odbierać dane z komputera po RS232. Są to cztery ramki jak poniżej:
;T0000
;H0000
;P0000
;F0000

Te zera przedstawiają liczbę jedno bajtową zakodowaną/zamienioną w ASCII np.

;T0000\r\n do ;T0255\r\n
;H0000\r\n do ;H0255\r\n
;F0000\r\n do ;F0255\r\n
;O0000\r\n lub ;O1111\r\n tylko ta ramka przyjmuje dwie wartości 0 lub 1111

Powyższe cztery ramki wysyłane są w paczce w której odstęp wynosi 100ms. Kolejna paczka „leci” po 1000ms.

;T0000\r\n (100ms) ;H0000\r\n (100ms) ;F0000\r\n (100ms) ;O0000\r\n (taka paczka powtarzana jest „w kółko” co 1 sekundę)

Proszę o kod który przyjmę to co powyżej i podstawi do zmiennej jedno bajtowej np.

ZmiennaT = wartość przekonwertowana to co po literze czyli od 0 do 255.
ZmiennaH = wartość przekonwertowana to co po literze czyli od 0 do 255.
ZmiennaF = wartość przekonwertowana to co po literze czyli od 0 do 255.
ZmiennaO = „0” gdy ;O0000 lub „1” gdy ;O1111

Program realizuje już wysyłanie podobnych ramek do PC i to mi działa.
Powyższe wartości chcę podstawić jako PWM trzech kanałów. PWM też działa, a czwarta jako znacznik włączenia/wyłączenia
Nie mogę tylko poradzić sobie z odbiorem.

Konwersję czterech liczb ASCII robię jak poniżej:

tysiace = (temp-48)*1000;
setki = (temp-48)*100;
dziesiatki = (temp-48)*10;
jednostki = (temp-48);
ZmiennaT = tysiace + setki + dziesiatki + jednostki;

Jakby ktoś miał ochotę będę bardzo, ale to bardzo wdzięczny.
Pozdrawiam



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 4 mar 2014, o 23:41 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 07 kwi 2013
Posty: 418
Lokalizacja: Rzeszów
Pomógł: 102

Oczywiście niezbędny jest graf, gdyż rozwiązaniem tego typu zadań jest automat.
Pisane na szybko w związku z czym mogą pojawić się drobne błędy. Nie uwzględniałem też sytuacji, które mogą się pojawić tj. brak górnego progu wartości na 255 (w kodzie który przedstawiam jest to 299). Wymaga to niewielkiej modyfikacji, ale myślę, że Kolega będzie już w stanie sobie z tym poradzić (oczywiście jeśli zajdzie taka potrzeba).

Rozumiem, że sposób kodowania ramek został z góry narzucony, gdyż nie jest to zbyt optymalne podejście do tematu (mówię o rozbijaniu liczb na znaki ASCII).

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Autor postu otrzymał pochwałę


Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 mar 2014, o 17:54 
Offline
Użytkownik

Dołączył(a): 08 wrz 2012
Posty: 505
Pomógł: 6

Bardzo Ci dziękuję. Wykorzystam fragmenty bo tak mi chyba będzie lepiej. Jeśli miałbyś chwilę i ochotę czy możesz rozwinąć
Cytuj:
gdyż nie jest to zbyt optymalne podejście do tematu (mówię o rozbijaniu liczb na znaki ASCII).


Pozdrawiam i jeszcze raz dziękuję



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 mar 2014, o 20:51 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 07 kwi 2013
Posty: 418
Lokalizacja: Rzeszów
Pomógł: 102

Oczywiście mam na myśli transmisję bajtową, a nie znakową. Po prostu nie ma sensu liczb od 0 do 255 przesyłać w formie kodów ASCII, tj. 3 bajty, z których każdy reprezentuję kolejno wartość setek, dziesiątek i jedności. Można przesyłać bezpośrednio liczbę z tego zakresu w ramach jednego bajtu, co oczywiście przekłada się na trzykrotne zwiększenie efektywności transmisji. Pominięciu może podlegać również końcowy znak ramki. Reasumując przykładowa ramka może wyglądać w następujący sposób:
<T0-255>
Składają się na nią 4 bajty, a nie 8...

Mój wywód może nie mieć sensu w przypadku gdy wymagany jest taki format przesyłu wartości...



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 6 mar 2014, o 22:14 
Offline
Użytkownik

Dołączył(a): 08 wrz 2012
Posty: 505
Pomógł: 6

Ok. dzięki za wyjaśnienie. UART jest jeszcze dla mnie mroczny i tajemniczy, ale krzeszę, krzeszę iskierki, może coś z tego będzie. :)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 27 mar 2014, o 07:03 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 28 paź 2013
Posty: 61
Lokalizacja: Skierniewice
Pomógł: 0

Witam,
Mam zrobić coś takiego o czym Atmelu powyżej wspomnialeś, tzn.
Cytuj:
transmisja bajtowa, a nie znakowa, nie ma sensu liczb od 0 do 255 przesyłać w formie kodów ASCII, tj. 3 bajty, z których każdy reprezentuję kolejno wartość setek, dziesiątek i jedności.

Mógłby Pan jakoś to szerzej wytłumaczyć, może podać przykład?;)

Dziękuję.
Pozdrawiam



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 27 mar 2014, o 14:54 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 07 kwi 2013
Posty: 418
Lokalizacja: Rzeszów
Pomógł: 102

Przede wszystkim nie Pan - Michał lub atmel jestem ;)

Raczej ciężko będzie mi to bardziej szczegółowo omówić, gdyż jestem raczej słaby w tłumaczeniu, ale spróbuję :)

Ogólnie prawie każdy rodzaj transmisji cyfrowej opiera się na wysyłaniu, bądź też odbieraniu odpowiednich ramek danych (komend, zapytań i odpowiedzi). Nie mówię tutaj oczywiście o samej budowie ramki sprzętowej (dla RS232 są to: rozmiar pola danych, ewentualny bit parzystości, bit/y stopu), tylko o tzw. protokole.

Przechodząc do sedna, zakładamy, że mamy jedno urządzenie nadawcze, które co określony czas wysyła wartość zmierzonej temperatury oraz wilgotność powietrza, a kolejne (może być ich kilka) odbiera te dane i odpowiednio je interpretując wyświetla na LCD - coś na wzór stacji pogody. Kolejne założenie jest takie, że wartość temperatury może być z przedziału od 0 do 100*C (celowo nie uwzględniam wartości ujemnych oraz zmiennoprzecinkowych, żeby łatwiej było zrozumieć o co mi chodzi :) ), a wilgotność od 0 do 100%. Po krótkiej chwili zastanowienia możemy wpaść na pomysł, aby te informacje wysyłać naprzemiennie, ale jest to zgubne podejście i zaraz powiem dlaczego.
W takim razie nasza ramka może wyglądać następująco:
Kod:
TemperaturaWilgotność
    027078 (27*C, 78%)
    100001 (100*C, 1%)
    000100 (0*C, 100%)

Wiadomo również, że te dane "lecą" jedne za drugimi, dlatego otrzymamy taki taśmociąg 027078100001. W naszych prostych rozważaniach nie istotnie są przerwy czasowe między takimi pakietami, chociaż w pewnych sytuacjach mają one kolosalne znaczenie i one również niosą ze sobą informację (omawiane w ostatnim czasie przez naszego Guru Mirka magiczne diody LED :D ).
W ten sposób za każdym razem musimy wysłać aż 6 znaków (bajtów) i na dodatek nie mamy żadnej kontroli, czy otrzymaliśmy poprawny zestaw danych. Pomijam również kwestie dotyczące detekcji/korekcji błędów (nie jestem w stanie wszystkiego opisać w jednym poście, a temat jest naprawdę niezwykle ciekawy i rozbudowany). Co będzie w przypadku, kiedy z jakiś względów utracimy np. 4 bajt w pierwszym pakiecie? Będzie "masakra" :P - odbieramy wtedy:
Kod:
   027781 (27*C, 781%)
   000010 (0*C, 10%)
   itd.

Jeśli nie mamy jakiś warunków saturacyjnych, czy też odrzucających błędne pomiary to później może być już tylko gorzej.
Utracenie danej może polegać na niezsynchronizowaniu urządzeń tj. najpierw włączamy nadajnik, a dopiero po chwili odbiornik, którego szanse na odebranie pierwszego bajtu temperatury są znikome, a uzyskane przesunięcie dramatycznie wnosi się na kolejne pakiety.
Trzeba jakoś temu zaradzić, dlatego decydujemy się na dodanie bajtów startu i stopu, czyli wysłaniu odpowiednich znaków na początku i końcu każdej ramki:
Kod:
[TemperaturaWilgotność]
   [027078]
   [100001]
   [000100]

Co prawda nasz pakiecik rozrósł się o 2 bajty, ale za to mamy pewność, że odebrane informacje są poprawne. W efekcie jeżeli "zgubimy" jakikolwiek bajt danych np. [02778], wtedy taki pakiet w ogóle nie będzie brany po uwagę, bo zawiera błędy. W przypadku kiedy utracony zostanie znak '[' lub ']' postępujemy analogicznie i zakładamy, że dane są niepoprawne: [027078[100001] (pierwszy pakiet błędny, drugi OK).

Teraz przychodzi nam na myśl optymalizacja transmisji. Wiemy, że znaki początku i końca transmisji są niezbędne, więc pasuje zająć się samymi danymi. Nie będziemy już wysyłać szeregu znaków stanowiących kody ASCII cyfr, więc możemy skorzystać z transmisji binarnej, a mianowicie:
Kod:
[Liczba_0-100Liczba_0-100]
Nr bajtu: 1  2   3  4
          [ ESC  N  ] (27*C, 78%)
          [  d  SOH ] (100*C, 1%)

gdzie ESC i SOH odpowiadają liczbom 27 i 1, zgodnie z tablicą kodów ASCII (http://www.asciitable.com).

W ten sposób zamiast 8-miu bajtów mamy 4, jednak zmieniają się tym samym kwestie odbioru tych danych, ale moim zdaniem interpretacja danych binarnych jest dużo prostsza od analizowania znaków (mój pierwszy post w tym temacie).

Ostatecznie możemy zdecydować się na dowolne znaki Start/Stop np. na STX (2), ETX (3), co jest dużo bardziej powszechne w przypadku transmisji binarnej.

Chętnie rozwinę jakąś kwestię jeżeli ktoś byłby zainteresowany.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 20 gru 2015, o 20:05 
Offline
Użytkownik

Dołączył(a): 19 paź 2014
Posty: 357
Lokalizacja: stolyca pyrlandii :)
Pomógł: 18

Cześć.
Atmel od jakiegoś czasu ćwiczę kod który podałeś, aby rozczytać dane napływające z uC do innego uC.
Dane przesyłam w postaci binarnej, na początku ramki jest symbol ; (średnik) w hex 0x3B następnie jeden bajt danych a ramka kończy się symbolem ? w hex 0x3F. Mógłbyś mnie naprowadzić w których miejscach Twojego kodu należałoby dokonać korekty aby zadziałało ?
Bo na moje case1 odpowiada za rozpoznanie początku ramki (symbol średnika - który również mam u siebie). W case2 jest sprawdzany drugi bajt ramki (a zarazem pierwszy bajt danych), case6 sprawdza prawidłowe domknięcie ramki.
Ja ze względu że przesyłam jeden bajt danych podmieniłem case 2 na taką zawartość:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 21 gru 2015, o 16:09 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 07 kwi 2013
Posty: 418
Lokalizacja: Rzeszów
Pomógł: 102

W zasadzie praktycznie wszystko jest ok, poza tym że nie występuje znak 'SPACE'. Jest to ciąg znakowy a nie pojedynczy znak, chociaż ujęty w apostrofy może być interpretowany jako typ "char" (ostatnia litera 'E' zamiast spacji).

Powinno być:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Usunąłem też klamerki ponieważ zbędne jest tutaj ujmowanie pojedynczej instrukcji w blok.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 9 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 3 gości


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO