Master/Slave komunikace RS485

ahojte,potřeboval bych poradit s implementací RS485 komunikace. Když pominu tvar paketu, tak mi není jasné jak udělat detekci začátku a konce zprávy, jak to mám celé jednoduše vyhodnotit. Vycházím z toho že mám funkce send_byte, read_byte a také přerušení když přijde znak nebo je znak odeslán. U slave zařízení potřebuju přijem a vyhodnocení paketu nezávisle na běhu hlavního programu.

Možnosti paketování např.:

  • Zajištění, aby data paketu neobsahovala řídicí znaky. Ohraničení paketu může být pomocí ASCII řídicích kódů (SOH, SYN atd), data jsou zakódovaná do menšího počtu bitů - v nejjednodušším případě jeden bajt jako 2 HEX znaky (zpráva bude 2x delší). V lepším případě se data přenáší např. po 7 bitech, 8 datových bajtů se tak přenese jako 9 paketových bajtů. Nebo se přepíná sada - pro bajty 0…1f se vyšle prefix SI/SO a přenášejí se pak jako 20…3f. Vhodné u rušených linek, lze kontrolovat i neplatné bajty. Varianta s HEX znaky je dobrá u malých zařízení, protože je spolehlivá a jednoduchá. Jsou-li potřeba přenášet jen ASCII znaky, lze data zakódovat po 6 bitech do písmen (0…9, @, A…Z, ', a…z), některé znaky mohou být řídicí (< a > ohraničuje začátek a konec paketu).

  • Escape sekvence - data mohou obsahovat i řídicí znaky, ale před každým bajtem s touto hodnotou se vyšle escape kód informující, že to jsou data. Např. začátek a konec paketu se označí bajty SOH EOT. Objeví-li se v datech hodnota SOH, EOT nebo ESC, vyšle se před ní bajt ESC. Případné rozsynchronizování (chytnutí falešného řídicího kódu) se ošetří kontrolou CRC paketu. Vhodné u středně rušených linek.

  • Binární přenos se startovací sekvencí. Přenáší se všechna data binárně tak jak jsou, ale před paketem je speciální posloupnost několika bajtů (magic bajty, jejichž výskyt v datech je málo pravděpodobný) a paket je zajištěný dobrým CRC. Pokud je příjemce v synchronizaci, je přenos rychlý a stabilní. Pokud se rozjede, čeká na magic posloupnost a ověří CRC paketu, při chybě pokračuje v čekání. U spolehlivých linek je tohle asi tak nejlepší způsob.

U RS485 se neustále poslouchá linka (pomocí přerušení), master se dotazuje jednotlivých zařízení a pokud zařízení má odpovědět, přepne na dobu vysílání vysílací linku a pak ji musí zas uvolnit (sledovat zda se dokončilo odeslání posledního bajtu).

díky za info

pozri si dokumentaciu na www.modbus.org.

nemusis pouzivat vsetky prikazy. Uplne sa da vystacit s “nacitaj word” a “zapis word”
Netreba vymyslat vymyslene a este Tvoje zariadenia budu kompatibilne s priemyselnym standartom. Zaciatok spravy uplne staci detekovat tak, ze pred nou bola urcita casova medzera. Obdobne to plati aj o konci spravy. Predlzenie komunikacie je zdanlive, lebo jedna ci druha strana tak ci tak potrebuje cas na spracovanie otazky a odpovede.
Netreba dodrzovat presne 3,5 nasobok casu vysielania bajtu. kludne to moze byt aj viac. Ja pri 9600Bd sledujem systemovy cas pod 1ms a ak po styroch casovych preruseniach nic nepride (cca 5 bajtov), vyhodnotim to ako ukoncenie spravy. Da sa to samozrejme spravit sofistikovanejsie, ale prax ukazala ze je to pri beznych komunikaciach, uplne zbytocne. Pri priemernej sprave obsahujucej tak 50-70 bajtov je miera neefektivity pod 10%. Pri ASCII komunikacii je miera neefektivity 100% a pri ESC sekvenciach sa neefektivita moze (ale uplne) teoreticky vysplhat na tych 100% tak isto.
Inak plati vsetko co bolo povedane vyssie.

Ahoj já používám klon protokolu MODBUS takto:
Začátek paketu je 0xC0. Konec 0xC1. Podmínka…jakýkoliv výskyt 0xC0 v rámci vždy začíná komunikaci, 0xC1 vždy končí komunikaci. Pokud je v datech 0xC0 ,0xC1 nebo 0x7D vyšle se předním znak 0x7D a za ním následuje odesílaný znak oxorovaný. Já to dělám 0x02^0x7D, 0x02^0xC0 nebo 0x02^0xC1.
Stejně to funguje na příjmu.

tak jsem zase přemýšlel, a ještě bych potřeboval poradit:

Cíl zařízení: Slave zařízení, budou něco řídit a Master zařízení bude monitorovat stavy a měnit parametry. Slave zařízení 8bit nebo ARM Cortex M0, master zařízení ARM Cortex M0 nebo nějaký board s ARMem+Linux

Myšlenka: na každém Slave zařízení si staticky alokovat pamět (např pole bytů), všechny proměnné namapovat do tohoto pole. Obdobně to udělat i na Master zařízení ale vícekrát pro každý Slave. Když to shrnu, tak každé zařízení bude pracovat s proměnnými, které se budou namapovány v poli.

A teď zrovna přemýšlím, jak ty “pole” mezi Master a Slave zařízením synchronizovat. Když to přeženu 32 zařízení, Slave RAM 16KB, vzdálenost do 200m asi i do 100m.

Napadlo mě:

  1. přetáhnout celé pole v kuse- ale jelikož bude RS485 udělaná s UARTU a pokud se nepletu tak to je max 115200Bd (cca 14KB/s) tak to bych měl možná na MASTERU aktuální informace tak 2x za minutu v tom nejhorším případě, když pominu to že by to bylo pomalé, tak by to bylo asi i neefektivní…to mi příjde tak vhodné na začátku, kdy se zařízení zapne

  2. na MATER i SLAVE zařízeních mít frontu s požadavkama co se změnilo a postupně to vyřizovat, ale podle mě by to chtělo nějaký mechanismus, který by poznal že se změnila hodnota proměnné a na základě toho přidal požadavek do fronty…a tohle právě vůbec netuším jak udělat…jedině snad mít nějakou specialní funkci pro zápis dat, která by kontrolovala jestli, došlo ke změně nebo ne a když tak by se rovnou vytvořil požadavek na synchroniaci

  3. všechny zařízení budou MASTER, data do paměti budu zapisovat přes speciální funkci, která vyhodnotí jestli se data změnila nebo ne a v případě že ano, tak zařízení zahájí komunikaci a pošle aktualizující paket konkrétnímu zařízení, tohle mi příjde jednoduché na obsluhu, ale nejhorší na komunikační protokol

máte někdo nějaká tipy a rady? :slight_smile:

  1. UART ide do frekvencie do ktorej to HW dovoli. Su mcu s UARTOM do 11Mbps. Principialne nic nepbrani tomu, aby UART bezal cez 1Gbps.
    Uz aj na staruckej ATmege168 bezi UART pri 16MHz do 2Mbps, tak akych 115200bps. :slight_smile:

Uz len taka RS485 musi bezat do 100m cez 1Mbps, ale urcite pobezi aj viac, to zavisi od budiacich cipov. A tie su dnes dost schopne aj za nizku cenu.

  1. 16kB RAM z kazdeho Cortex M0 je naprosta capina. Nakoniec zistis, ze Ti staci prenasat realne 100-500B. Uz len to, kto by to mnozstvo hlusiny potom z tej RAMky sledoval. Vzdy si stahuj to, co naozaj potrebujes.

Ak Ta napriklad zaujima diagnostika, je nezmysel ju prenasat aj ked ju nepotrebujes. Robi sa to tak, ze niekde do Mastra si kopirujes okno, napriklad o velkosti 64-200B a nejakou premennou si prepinas, ktora ze to napr. 128B cast Ta aktualne zaujima. 16kB sa neda ani rozumne umiestnit na monitore PC, aby si si ju prezeral.
Archivy sa stahuju presne vo forme adresovatelneho okna. Teraz ma zujima tato cast Flash a neskor ina cast Flash.

  1. No a ten zaver, aby sa prenasalo len to co sa zmenilo a este k tomu systemom multimaster, kludne to skus. Liecebna terapia tvorena kombinaciou zlozitostou osetrenia multimastra so stavovym automatom vyhodnocujucim iba zmeny v celom 16kB priestore (automat si bude vyzadovat dalsi 16kB priestor v kazdom “Slave” pre kopiu aby mal ako zistit kde nastala zmena, lebo ak ma kazda rutina zaroven nastavovat nejaky prizn®ak, ze sa RAM modifikovala, bude sa primerane zbytocne zatazovat cely system) bude tak do mesiaca ucinna. Bude to zbytocne zlozite a zo zaciatku teda aj plne chyb a hlavne uplne zbytocne o com Ta presvedci nasledovna prax.

no tak jsem na ty rychlosti koukal pořádně a mcu by možná zvládlo i 12Mb/s , obyčejný max485 maximálně 2,5Mb když by to chodilo spolehlivě na 1Mb, tak 10slave zařízení po 1Kb paměti, kdybych chtěl 1s refresh, tak by mu to trvalo 0,1s a pak by se mohl asi 0,9s flákat

Niemyslim, ze si to spocital spravne :slight_smile:

Pri 1Mb trva prenos jedneho bajtu 10us. Pri 18.432MHz za tu dobu procesor (ATmega) zvladne od 90 do 180 instrukcii.
Aky by bol dovod aby procesor ako taky blbec stal na jednom mieste a cakal kym pride dalsi bajt ked za tu dobu vie spravit nieco uzitocne? Na toto vsetko sluzi prerusenie.
A to ani nehovorim o STM32-kach, ktore maju prenosy cez DMA kanaly, takze sprave sa mcu moze venovat az vtedy, ked pride cela sprava.

Pri vysielani sa naplni bufer a potom sa DMA kanalu povie:“odtialto a odtialto odosli X bajtov tam a tam”.

No a zrazu ma procesor napr. na 48MHz (STM32F0xx) casu a casu :slight_smile:

Na 200m bych už měl obavu s nespolehlivostí linky RS485 na řádově Mb/s kvůli zarušení. Propojujeme zařízení v několika místnostech (tj. smyčka desítky metrů), rychlost myslím 19200kbps a dost často se objevují nějaké chyby v přenosu. Kabeláže nejsou v praxi ideální, např. nedostatečný kontakt v konektoru a vliv průmyslového rušení pak dost narůstá.

No ak by to bolo tak, ako by mohol bezat 1Gb ethernet do 100m?
Je to trochu ine rozhranie, ale stale sa jedna o diferencialny signal, ktory principialne je schopny sa spolahlivo prenasat. Nema tu zmysel riesit modulaciu, ta to vsetko principialne voci jednoduchej RS485 len zhorsuje.

Treba pouzivat pre RS485 dobre kable (FTP Cat 5e), dobre budice (nic nie je zadarmo, ani potreba nie beznej rychlej komunikacie) a kvalitne (cize normalne neodflaknute) vyhotovenie. Ak niekto nevie dotiahnut sroby na svorkovnici, reba mu dat WAGo svorky a ak ani to nepomoze, tak ho teba preradit na cinnost, ktoru je schopny zvladnut. Samozrejme ziadne chyby pri realizacii tienenia a zabranovat vyrovnavacim prudom v nom. Ale inak ziadna velka veda, len poriadna praca.
Mame vo viacerych rozsiahlych priemyselnych komplexoch linky cez 4-6km pri rychlosti 9600Bd pri percente uspesnosti komunikacie cez 97%. A to sa ani nedalo vsade dodrat kabelaz bez odpociek. Najprv sme tam sica mali repeatre od ADAMa, ale boli tak poruchove a zasekavali sa, ze sme ich vyhadzali a od vtedy je pokoj. Signaly mam ocheckovane v kazdom bode osciloskopom, tak viem o com hovorim. Mala rychlost, ale velmi velke vzdialenosti. RS485 je skratka moj milacik, co ma nikdy nenechal v brinde :slight_smile:

Odhadujem, ze sa nakoniec aj tak pride k tomu, ze permanentne prenasat 1kB z kazdej stanice je kontraproduktivne.

No a vzhladom na vypocty co tu odzneli, sprava uz moze byt prenasana aj 10x pomalsou rychlostou, aby sa stihlo preniest 10x1kB do jednej sekundy.

ja to bral 1 Byte 10us, 1KB, 10ms, 10 zařízení 0,1s…jakože nemůžu mít aktuálnější informace než každých 100ms, a i kdybych procesor stál na místě jak blbec, tak by měl ještě čas něco udělat, kdybych chtěl 1s refresh…ale přerušení atd, je samozřejmostí

S tym ja suhlasim, ale aj pocas prenosu tych 10kB moze mcu zobrazovat, reagovat na tlacitka, odpovedat na dotazy z PC, atd, atd, takze mu ostava viac ako 90% casu na inu pracu.

s tým taky souhlasím, ja to myslel tak, že kdyby cílem bylo jenom monitorovat hodnoty- zobrazovat je na např. na displeji, tak by stačilo v cyklu načíst data, zobrazit data atd