Atmega Bascom odczyt rejestru po RS485 Modbus RTU
-
Zbyszek
- Posty: 96
- Rejestracja: 30 lis 2017, 17:12
Re: Atmega Bascom odczyt rejestru po RS485 Modbus RTU
Siedzę jeszcze w robocie i myślę czy da się tym konwerterem sprawdzić o czym gada licznik z falownikiem ? to bym sobie to rano sprawdził
-
Zbyszek
- Posty: 96
- Rejestracja: 30 lis 2017, 17:12
Re: Atmega Bascom odczyt rejestru po RS485 Modbus RTU
Wygląda to tak. Żeby sprawdzić kablel który mam od licznika do warsztatu ( bo falownik jest w budynku gospodarczym ) dołożyłem dodatkową skrętkę z warsztatu do licznika i kabel który szedł mi do Atmegi wykorzystałem jako przedłużacz pomiędzy licznikiem a falownikiem. Po połączeniu na aplikacji wskazanie licznika się pokazało, więc kabel dobry. Ściągnąłem Modbus Poll do nasłuchiwania i podłączyłem równolegle tą przelotkę USB-RS485 i zaczęło się pokazywać to co w pliku w załączniku. Jak odepnę kabel od falownika to wiadomo same zera i wtedy włączyłem ten program HTerm , wysyłam ramkę ale nic nie odbieram. Nie ma komunikacjii z licznikiem. Podobna sytuacja jest jak podepnę rejestrator P43 do USB-RS485. Na dedykowanym oprogramowaniu chodzi mam podgląd na przetwornik ( czyli przelotka USB-RS485 dobra ) ale jak wysyłam ramkę przez HTerm to odbieram dokładnie to samo co wysłałem, a w przypadku licznika nie odbieram nic. Nie mam już pomysłu co jest nie tak. Bawiłem się ustawieniami programu ale nic to nie dało.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
- niveasoft
- Posty: 1313
- Rejestracja: 17 sie 2015, 12:13
- Kontakt:
Re: Atmega Bascom odczyt rejestru po RS485 Modbus RTU
Nie rozumiem tych Twoich opisów. Dla mnie wyrażasz się nieprecyzyjnie. Napisz prosze albo narysuj w paincie topologię tych połączeń. Tak żeby było wiadomo gdzie licznik gdzie falownik gdzie pecet albo atmega. Który jest po drodze itd...
Log wygląda na dość prosty. Zwykłe zapytanie pod adres 1, odczyt rejestrów(&H03) od adresu 1 i prosimy o dziesięć rejestrów (&H0A) i na końcu CRC
...a adres 1 odpisuje że bedzie podawał rejestry (&H03) i że będzie ich 20 (&H14) bo sa dwubajtowe i podaje te rejestry i CRC.... Nie ma na co patrzeć.
Ciekawi mnie kto tu robi TX. Ten program którego używasz czy jak?
Co to za apka o której piszesz?
No naprawdę nie wróżę tu z kuli.
Log wygląda na dość prosty. Zwykłe zapytanie pod adres 1, odczyt rejestrów(&H03) od adresu 1 i prosimy o dziesięć rejestrów (&H0A) i na końcu CRC
...a adres 1 odpisuje że bedzie podawał rejestry (&H03) i że będzie ich 20 (&H14) bo sa dwubajtowe i podaje te rejestry i CRC.... Nie ma na co patrzeć.
Ciekawi mnie kto tu robi TX. Ten program którego używasz czy jak?
Co to za apka o której piszesz?
No naprawdę nie wróżę tu z kuli.
-
Zbyszek
- Posty: 96
- Rejestracja: 30 lis 2017, 17:12
Re: Atmega Bascom odczyt rejestru po RS485 Modbus RTU
… Znowu weekend w pracy. Trochę postów napisałem … potem usunąłem żeby nie zaśmiecać forum, ale może teraz będzie jaśniej. Sprawdziłem jeszcze raz połączenia i są OK. Kabel od licznika idzie przez mój warsztat do falownika, w warsztacie mam złączkę. Zainstalowałem i ustawiłem program HTerm tak jak sugerowałeś, wpisałem ramkę którą mi podałeś 01 03 20 12 00 02 FF CE i wcisnąłem Enter, ale licznik mi nie odpowiedział. Tu straciłem kupę ( 2 dni ) czasu na szukanie ( głównie po sieci ) sposobu na połączenie się z licznikiem, i wtedy wpadłem na pomysł żeby podsłuchać rozmowę falownika z licznikiem. Podłączyłem licznik do falownika i wpiąłem się do niego równolegle konwerterem USB>>>RS485. Znalazłem w sieci program do podsłuchu linii - Modus Poll i to co mi się wyświetliło na ekranie zapisałem do pliku jako *.log i wstawiłem w poprzednim poście. Szukałem tam m.in. tej twojej ramki … ale nie znalazłem. Dalej przeszukiwanie sieci i znalazłem program Simply Modbus Master ( screen w załączniku ). Podajesz adres slave, funkcję, adres który chcesz odczytać ( podajesz go jako HEX skonwertowany na DEC ) i typ rejestru oraz liczbę rejestrów do odczytania. Program sam w okienku tworzy ci ramkę do wysłania … i wciskasz Send. Pod spodem w okienku otrzymujesz w Hex’ie co licznik odpowiedział i w kolejnym okienku wynik jako liczba dziesiętna ( czyli to co jest na wyświetlaczu licznika ). Do rejestru 2012 Simply Modbus Master utworzył ramkę 01 03 20 12 00 02 6F CE. I tu był błąd zamiast 6F podałeś mi FF. Podłączyłem Atmegę do licznika i równolegle do konwertera USB>>>RS485. Teraz po resecie Atmegi okazało się że wysłała właśnie taką ramkę, ale teraz dlaczego nie odbiera i … kolejny czas. W lewy górnym rogu programu HTerm jest takie okienko do zaznaczenia opisane jako „Show newline characters” jeżeli się tam zaznaczy ptaszka to na końcu ramki którą wysłała Atmega pokazują się dodatkowe znaki 0D 0A. Atmega w rzeczywistości wysyła ramkę tą co trzeba i na jej końcu dodaje od siebie dodatkowe znaki - 01 03 20 12 00 02 6F CE 0D 0A. Wyczytałem że najprostszym sposobem aby się tych znaków pozbyć trzeba na końcu polecenia Print#1… dać średnik ( Print #1 , Makemodbus(1 , 3 , &H2012 , 4); ) czego AI tego nie wiedziało. OK. , wysyła co trzeba ale odczytuje 7 znaków zamiast spodziewanych 9.
Połączenie równoległe Licznik – Atmega - konwerter USB>>>RS485. W oknie Rx programu HTerm pojawia się ramka 01 03 20 12 00 02 6F CE 01 03 04 C6 BC D0 00 5A 9F a na wyświetlaczu Atmegi 01 03 04 C6 D0 5A 9F. To co pojawiło się w oknie Rx programu HTerm to pierwsze 8 znaków które wysłała Atmega a kolejne 9 to odpowiedź licznika czyli 01 03 04 C6 BC D0 00 5A 9F. Czyli Atmega gubi znaki 5 i 7 ( zawsze właśnie te )
HTerm - 01 03 04 C6 BC D0 00 5A 9F
Atmega - 01 03 04 C6 __ D0 __ 5A 9F
Z Simply Modus Master wiemy teraz jaka ma być odpowiedź i mamy wynik czyli wiadomo jak to obliczyć. Wartość to 32-bit IEEE754 float. Czyli jak w screenie HTerm odpowiedź 01 03 04 C6 BC D0 00 5A 9F. Nas interesuje C6 BC D0 00 co wklejamy ( bez spacji ) na stronę https://www.h-schmidt.net/FloatConverter/IEEE754.html w linii Hexadecimal Representation i otrzymujemy wynik jak w screenie -24168, mnożymy przez 0,1 albo dzielimy przez 10 i mamy wynik taki jak na wyświetlaczu licznika DTSU666 w Watach. Dlaczego Atmega gubi znaki przy odczycie ? Tak samo jak podepnę samą Atmegę do laptopa i z HTerm wyślę do Atmegi 01 03 04 C6 BC D0 00 5A 9F to odbierze tylko 01 03 04 C6 D0 5A 9F, czyli bez 5 i 7 znaku ...
Taka ciekawostka - jak z HTerm wyślę do Atmegi 01 03 04 C6 BC to na wyświetlaczu się to wyświetli ( czyli 01 03 04 C6 BC ) ale jeżeli wyślę 01 03 04 C6 BC D0 to na wyświetlaczu mam tylko 01 03 04 C6 D0 - już bez BC. Czyli w trakcie odbierania pomija 5 i 7 znak ... i nie tylko bo jeżeli mu wyślę 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 to na wyświetlaczu pojawi się tylko 01 02 03 04 06 08 11 13 15
Połączenie równoległe Licznik – Atmega - konwerter USB>>>RS485. W oknie Rx programu HTerm pojawia się ramka 01 03 20 12 00 02 6F CE 01 03 04 C6 BC D0 00 5A 9F a na wyświetlaczu Atmegi 01 03 04 C6 D0 5A 9F. To co pojawiło się w oknie Rx programu HTerm to pierwsze 8 znaków które wysłała Atmega a kolejne 9 to odpowiedź licznika czyli 01 03 04 C6 BC D0 00 5A 9F. Czyli Atmega gubi znaki 5 i 7 ( zawsze właśnie te )
HTerm - 01 03 04 C6 BC D0 00 5A 9F
Atmega - 01 03 04 C6 __ D0 __ 5A 9F
Z Simply Modus Master wiemy teraz jaka ma być odpowiedź i mamy wynik czyli wiadomo jak to obliczyć. Wartość to 32-bit IEEE754 float. Czyli jak w screenie HTerm odpowiedź 01 03 04 C6 BC D0 00 5A 9F. Nas interesuje C6 BC D0 00 co wklejamy ( bez spacji ) na stronę https://www.h-schmidt.net/FloatConverter/IEEE754.html w linii Hexadecimal Representation i otrzymujemy wynik jak w screenie -24168, mnożymy przez 0,1 albo dzielimy przez 10 i mamy wynik taki jak na wyświetlaczu licznika DTSU666 w Watach. Dlaczego Atmega gubi znaki przy odczycie ? Tak samo jak podepnę samą Atmegę do laptopa i z HTerm wyślę do Atmegi 01 03 04 C6 BC D0 00 5A 9F to odbierze tylko 01 03 04 C6 D0 5A 9F, czyli bez 5 i 7 znaku ...
Taka ciekawostka - jak z HTerm wyślę do Atmegi 01 03 04 C6 BC to na wyświetlaczu się to wyświetli ( czyli 01 03 04 C6 BC ) ale jeżeli wyślę 01 03 04 C6 BC D0 to na wyświetlaczu mam tylko 01 03 04 C6 D0 - już bez BC. Czyli w trakcie odbierania pomija 5 i 7 znak ... i nie tylko bo jeżeli mu wyślę 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 to na wyświetlaczu pojawi się tylko 01 02 03 04 06 08 11 13 15
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
- niveasoft
- Posty: 1313
- Rejestracja: 17 sie 2015, 12:13
- Kontakt:
Re: Atmega Bascom odczyt rejestru po RS485 Modbus RTU
Duszno ostatnio z wolnym czasem 
Ten Twój odbiór jest bardzo uproszczony i może program nie nadąża odbierać znaków i jeszcze je drukowaćna LCD.
Takim najprostszym sposobem może być odbiór na przerwaniach. Zobacz czy to wystaczy jak dopiszesz te die linijki:
Config Serialin0 = Buffered , Size 30 i Enable Interrupts.
To powinno odbierać znaki do bufora a Ischarwaiting() będzie wskazywał że jest już coś nowego do odebrania nawet jak w miedzyczasie będziesz bazgrał po LCD.
Jak nie pomoże to już trudno i trzeba to będzie napisać profesjonalniej.
Ten Twój odbiór jest bardzo uproszczony i może program nie nadąża odbierać znaków i jeszcze je drukowaćna LCD.
Takim najprostszym sposobem może być odbiór na przerwaniach. Zobacz czy to wystaczy jak dopiszesz te die linijki:
Config Serialin0 = Buffered , Size 30 i Enable Interrupts.
Code: [Zaznacz cały] [Rozwiń/Zwiń]
- Config Com1 = 9600 , Parity = None , Stopbits = 1 , Databits = 8
- Config Serialin0 = Buffered , Size = 30
- Open "COM1:" For Binary As #1
- Enable Interrupts
Jak nie pomoże to już trudno i trzeba to będzie napisać profesjonalniej.
-
Zbyszek
- Posty: 96
- Rejestracja: 30 lis 2017, 17:12
Re: Atmega Bascom odczyt rejestru po RS485 Modbus RTU
Pomogło, teraz wyświetla wszystkie odebrane znaki. Został jeszcze problem w złożeniu 4 bajtów w Single. Spróbuję się tym pobawić bo wynik jest cały czas 0.00. Jak sobie nie poradzę dam znać.
( chyba że masz jakiegoś gotowca
)
Generalnie problem leży w tym
Dim Tempsingle As Single
Poke Varptr(tempsingle) , B1
Poke Varptr(tempsingle) + 1 , B2
Poke Varptr(tempsingle) + 2 , B3
Poke Varptr(tempsingle) + 3 , B4
Value = Tempsingle
Locate 2 , 1
Lcd Fusing(value , "0.00")
Generalnie problem leży w tym
Dim Tempsingle As Single
Poke Varptr(tempsingle) , B1
Poke Varptr(tempsingle) + 1 , B2
Poke Varptr(tempsingle) + 2 , B3
Poke Varptr(tempsingle) + 3 , B4
Value = Tempsingle
Locate 2 , 1
Lcd Fusing(value , "0.00")
- niveasoft
- Posty: 1313
- Rejestracja: 17 sie 2015, 12:13
- Kontakt:
Re: Atmega Bascom odczyt rejestru po RS485 Modbus RTU
Łap. Ten program można nawet testować w symulatorze Bascom gdy stała #const Sim = 1 (tak jak teraz więc potem sobie zmień na 0)
Program odlicza sekundę po czym wysyła żądanie odczytu do licznika.
Gdy zacznie odbierać bajty od licznika to ustawia timeout i co każdy następny bajt go przedłuża.
Gdy licznik skończy nadawać to ten timeout zejdzie do zera i Atmega uzna że licznik skończył nadawać.
Teraz wiedząc że w trzecim bajcie powinna być ilośc bajtów które powiiniśmy otrzymać sprawdza czy też mamy tyle bajtów. Dodaje do tego trzy bajty na header (01 03 04) i dwa bajty na CRC. czyli teoretycznie 3 + 4 + 2 = 9
Jesli mamy tyle bajtów ile potrzeba to sprawdzamy CRC. Obliczamy je z 7 bajtów a nie z 9. Porównujemy czy CRC się zgadza z tym które mamy na końcu wiadomości od licznika.
Jak się CRC zgadza to ładujemy tę wartośc float do naszej zmiennej. Potem się pozbywam danych po przecinku bo nie wiem czy się do czegoś przydadzą no i masz wynik taki jak ze strony.
Program odlicza sekundę po czym wysyła żądanie odczytu do licznika.
Gdy zacznie odbierać bajty od licznika to ustawia timeout i co każdy następny bajt go przedłuża.
Gdy licznik skończy nadawać to ten timeout zejdzie do zera i Atmega uzna że licznik skończył nadawać.
Teraz wiedząc że w trzecim bajcie powinna być ilośc bajtów które powiiniśmy otrzymać sprawdza czy też mamy tyle bajtów. Dodaje do tego trzy bajty na header (01 03 04) i dwa bajty na CRC. czyli teoretycznie 3 + 4 + 2 = 9
Jesli mamy tyle bajtów ile potrzeba to sprawdzamy CRC. Obliczamy je z 7 bajtów a nie z 9. Porównujemy czy CRC się zgadza z tym które mamy na końcu wiadomości od licznika.
Jak się CRC zgadza to ładujemy tę wartośc float do naszej zmiennej. Potem się pozbywam danych po przecinku bo nie wiem czy się do czegoś przydadzą no i masz wynik taki jak ze strony.
Code: [Zaznacz cały] [Rozwiń/Zwiń]
- $regfile = "m328pdef.dat"
- $crystal = 16000000
- $hwstack = 64
- $swstack = 32
- $framesize = 128
- $baud = 9600
- $lib "modbus.lbx"
- Config Lcd = 16x2
- Config Lcdpin = Pin , Db4 = Portc.4 , Db5 = Portc.3 , Db6 = Portc.2 , Db7 = Portc.1 , E = Portc.5 , Rs = Portc.0
- Cursor Off
- Cls
- Config Portd.4 = Output : Reset Portd.4 : Rs485dir Alias Portd.4
- Config Print0 = Portd.4 , Mode = Set
- Config Com1 = 9600 , Parity = None , Stopbits = 1 , Databits = 8
- Config Serialin0 = Buffered , Size = 30
- Open "COM1:" For Binary As #1
- '*************************************************
- '* TIMER2 CONFIG FOR TIME BASE *
- '*************************************************
- Config Timer2 = Timer , Prescale = 1024 , Clear_timer = 1
- Compare2a = 155 '10ms @16MHz/1024
- Enable Interrupts
- Const Timeout_val = 10
- Const Bufflen = 30
- Dim Rxbuff(bufflen) As Byte , Rxidx As Byte
- Dim Rxtimeout As Byte , Gotmsg As Byte
- Dim Miliseconds As Byte , Helpb As Byte
- Dim Mycrc As Word , Crcbuff(2) As Byte At Mycrc Overlay
- Dim Mysingle As Single , Singlebuff(4) As Byte At Mysingle Overlay
- Dim Mylong As Long , Mystring As String * 16
- Const Sim = 1 : Dim Simulation As Byte
- #if Sim
- $sim
- Rxbuff(1) = &H01
- Rxbuff(2) = &H03
- Rxbuff(3) = &H04
- Rxbuff(4) = &HC6
- Rxbuff(5) = &HBC
- Rxbuff(6) = &HD0
- Rxbuff(7) = &H00
- Rxbuff(8) = &H5A
- Rxbuff(9) = &H9F
- Rxidx = 9
- Rxtimeout = 1
- Simulation = 1
- #endif
- Do
- If Ischarwaiting(#1) > 0 Then
- Rxtimeout = Timeout_val 'ustaw timeout bo otrzymujemy znaki
- If Rxidx < Bufflen Then Incr Rxidx
- Rxbuff(rxidx) = Inkey(#1)
- End If
- If Tifr2.ocf2a = 1 Or Simulation > 0 Then '10ms
- Tifr2.ocf2a = 1
- If Miliseconds < 99 Then
- Incr Miliseconds
- Else
- Miliseconds = 0 '1s
- Print #1 , Makemodbus(1 , 3 , &H2012 , 4); 'raz na sekunde
- End If
- If Rxtimeout > 0 Then 'otrzymywalismy znaki
- Decr Rxtimeout
- If Rxtimeout = 0 Then 'przestalismy otrzymywac znaki
- Simulation = 0
- Cls
- 'spodziewamy sie na przyklad 01 03 04 C6 BC D0 00 5A 9F
- 'powinno być 3byte header + tyle co w trzecim + 2byte CRC
- Helpb = Rxbuff(3) + 5 'data + 3byte header + 2byte CRC
- If Helpb = Rxidx Then 'liczba odebranych sie zgadza
- Lcd "IDX OK ,"
- 'sprawdz CRC
- Helpb = Rxidx - 2 'odebrany bufor minus CRC
- Mycrc = Crcmb(rxbuff(1) , Helpb)
- If Crcbuff(1) = Rxbuff(rxidx - 1) And Crcbuff(2) = Rxbuff(rxidx) Then
- Lcd " CRC OK "
- Singlebuff(4) = Rxbuff(4) 'zaladuj float do single
- Singlebuff(3) = Rxbuff(5)
- Singlebuff(2) = Rxbuff(6)
- Singlebuff(1) = Rxbuff(5) '[EDIT] Uwaga. Blad copy-paste. Tu powino pisać Rxbuff(7)
- Mylong = Mysingle 'pozbywamy sie przecinka float/single (rzutowanie/cast)
- Mystring = Str(mylong)
- Mystring = Format(mystring , " ")
- Locate 2 , 1 : Lcd Mystring
- Else
- 'CRC sie nie zgadza
- Lcd " CRC ERR"
- End If
- Else
- 'liczba odebranych sie nie zgadza
- Lcd "IDX ERR,"
- End If
- Rxidx = 0
- End If
- End If
- End If
- Loop
- End
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
-
Zbyszek
- Posty: 96
- Rejestracja: 30 lis 2017, 17:12
Re: Atmega Bascom odczyt rejestru po RS485 Modbus RTU
Bardzo dziękuję
- niveasoft
- Posty: 1313
- Rejestracja: 17 sie 2015, 12:13
- Kontakt:
Re: Atmega Bascom odczyt rejestru po RS485 Modbus RTU
Daj znać czy gada 
-
Zbyszek
- Posty: 96
- Rejestracja: 30 lis 2017, 17:12
Re: Atmega Bascom odczyt rejestru po RS485 Modbus RTU
Wszystko działa jak należy, jeszcze raz dziękuję.
