RS-485 - co je zapotřebí k řízení přenosu?

Máte někdo zkušenosti s touto linkou?
Trochu jsem to studoval a asi bych byl schopen realizovat přenos mezi dvěma zařízeními. Ale to co bych spíš potřeboval je spojit několik zařízení- technicky žádný problém, ale vůbec netuším co je zapotřebí k řízení přenosu. Jaký je vůbec princip. Jak hlídat linku, jestli není “busy”, aby mi tam necpalo data víc vysílačů najednou?

:arrow_right: administrator: přesunuto z "Elektronika s mikrokontroléry, procesory"

:arrow_right: administrator: přejmenováno z "RS 485"

485 může řídit vždy pouze 1 vysílač. To tě vpodstatě omezuje na strukturu 1 master + několik slave. Pak lze s výhodou použít 9ti bitovou víceprocesorovou komunikaci, kde nejvyšší bit určuje zda jde o adresu nebo data. Slave, jemuž adresa patří pak data přijme/odpoví. Jesli potřebuješ režim multimaster, je třeba zvolit/navrhnout sběrnici, kde pracují budiče s otevřeným kolektorem. Např. I2C, CAN…
Na 485 by to možná šlo realizovat stálou hodnotou na vstupu a zapínáním výstupu. Mohlo by být i možné využít budiče pro CAN na přenos 485.

I2C je pro mě nepoužitelná - je to spíš interní meziobvodová sběrnice a CAN bus (vyvinutá pro auta) vlastně taky.
Já chci přenášet data po baráku někdy i pár desítek metrů - proto jsem zvolil 485,která je pro to určená - a nechci zaměstnávat jeden (řídící) procesor pořád dokola tím,že se bude vyptávat slave zařízení,jestli něco nemají v bufferu. A právě , že jsem četl o tom že se multimaster RS 485 používá třeba v lepších zabezpečovačkách - ale nic konkrétního.

Když na nic jiného nepříjdu, tak asi budu muset vyčlenit jeden samostatný procesor (třeba mega88) který bude mít na starosti jenom obsluhu 485ky a po SPI předávat data hlavnímu procesoru

Jen pro upřesnění CAN :wink:

CAN je určen stejně jako 485 do velmi nepříznivých podmínek, míra jeho zabazpečení je na vynikající úrovni. CAN je však primárně určen pro víceprocesorovou komunikaci a tím, že vyslanou zprávu přijímají všichni a zpracovává ji jen ten, kterého zajímá. Je zde vyřešeno určování priorit. Asi by se ti nelíbilo, kdyby ti selhalo ABS nebo vystřelil airbag za jízdy jen tak… Myslíš, že by to využívali v autech, kdyby to nebylo spolehlivý?

Použít 485 jako multimaster můžeš, jen je potřeba mít zkratuvzdorný budiče a během vysílání komunikaci sledovat. To znamená při použití např. SN75176A nevypínat přijímač a stále sledovat, zda ti na lince někdo nezměnil stav. Bohužel u 485 nelze určit logickou hodnotu na sběrnici když se budou 2 drivery přetahovat.

Osobně bych asi radši pro multimaster využil CAN drivery a budil je uartem (sw CAN protokol bude pro mcu docela fuška). Tam je totiž přesně definováno, co se stane při vysílání více uzlů zároveň. Toho se využívá pro zjištění, jesli máš volno a jesli ti do komunikace někdo nezačal kecat později po zahájení přenosu.

Ten CAN bus vypadá zajímavě. Trochu jsem louskal datasheet MAX3050 a vypadá to že ten obvod si umí hlídat stav na lince (viz obr.) a podle toho vysílá, nebo ne , jen nevím jestli umí data podržet a poslat až je volno, nebo jestli je prostě jen nepošle.

Pošle je vždy, u CANu je aktivní TX i RX zároveň. To jesli na sběrnici přistupuje ještě někdo jiný a jesli jsou data vpořádku hlídá až navazující logika (v mcu) tím, že kontroluje, zda okoukaná data na RX souhlasí s TX. Tady není přepínání vysílání/příjem jako na 485.
Podívej se na fyzickou vrstvu a řízení přístupu. To by ti mělo pomoct pochopit způsob práce.

U tohoto švába si dej pozor na ten auto-shutdown. Mohl by ti působit problémy tím, že by přijímač nezachytil první bity na začátku momunikace.
CAN.pdf (905 KB)

CAN je bezpecna zbernica primarne urcena pre male vzdialenosti.
Nizsia bezpecnost oproti RS485 je dana uz len tym, ze log.1 je makka, aby sa dala “prebit” niekym, kto prave vysiela log.0. Na kratke vzdialenosti to nie je kriticke a je to vyvazene jednoduchou realizaciou multimastrovej zostavy procesorov.
Ale iba procesorov, ktore maju priamo CAN implementovany alebo ktore komunikuju so specializovanym cipom pre obsluhu CAN. MAX3050 rozhodne takymto svabom nie je, je to len obycajny budic linky, nieco ako MAX485 (75146, SP485 a podobne) pre RS485. CAN komunikacia nie je klasicka UARTovska napr. typu 8N1, ale prenasa sa naraz viac bitov. To v nejakom jednoduchom jednocipe (na rozdiel od UARTu) tak lahko nenaprogramujes - vratane sledovania stavu linky.

RS485 je principialne odolnejsia prave pre aktivne vysielanie log. 0 i log.1 a to este v diferencialnom stave. Preto sa vyborne hodi pre prenos na vacsie vzdialenosti. I ked na tie uplne najvacsie (desiatky km) sa stale pouzivaju prudove linky. Ale len na prepojenie iba dvoch zariadeni.

Multimaster sa na RS485 riesi nasledovne:
Protokol typu Tokenring. Mastre si postupne posuvaju token, t.j. pravo vyuzivat zbernicu. System je dost narocny na managovanie.

Protokol typu casove okno. Hlavny procesor odvysiela nejaku synchro sekvenciu. Kazdy Slave, ak ma co povedat definovany cas po ukonceni synchrosekvencie odvysiela v jemu pridelenom casovom okne to, co potrebuje. System zabera velmi vela casu, ked sa caka na odpoved (okno treba vyhradit pre maximalnu dlzku spravy od Slave).

Protokol typu Ethernet. Kto co ma, to odvysiela. Podstata je, ze ten co spravu inicializuje caka, ze dostane potvrdenie o jej prevzati. Stanica pocuva linku. Ak nik nevysiela, odvysiela co chce. Aknedostane potvrdenie prevzatia spravy, asi bolo rusenie alebo bola kolizia a v jej dosledku dosla sprava skomolena. Stanica definovany cas pocka (kazda musi mat nastaveny iny cas cakania) a pokusi sa spravu odvisielat znovu.

Horeuvedene sposoby su pouzitelne, ale su vo svojej podstate bud nepruzne, alebo komplikovane.

Pre systemy s dobou odozvy sa najviac osvedcila (tu uz dost ohrnana :slight_smile: ) metoda Master-Slave. Master postupne oslovuje vsetkych podriadenych a ti mu odpovedaju. Tento system je velmi jednoduchy na implementaciu a aj ked Slave nema nic aktualne, je dobre vediet, ze zije a je OK.
Casova narocnost procesu komunikacie nemusi byt vacsia ako par percent behu procesora. Ak pouzijes 19200 8N1 a rozumny procesor s HW UARTom. Pri pouziti ATmega32 (14.7MHz) pocas hw odvisielania jedneho bajtu spravi tento procesor cca 700 instrukcii, pocas ktorych sa komunikacii venovat nemusis. A spracovanie jedneho bajtu (samozrejme pod prerusenim, ako inak) stihnes v priebehu 30-100 instrukcii.
Ak sa ovsem program nespravi tak blbo, ze pocas vysielania jednej spravy procesor caka na jej odvisielanie.
Komunikaciu mozes naprogramovat tak, ze jednotlive Slave iba odpovedaju kratkou spravickou, mam nieco/nemam nic.
Ani nepisem o tom ako ma vyzerat struktura spravy, ako ma byt chranena aspon CHS, ako ma vyzerat binarny protokol, ako ASCII a preco, o tom sa tu ani rozpisovat nebudem, uz to tu bolo mnoho krat popisane. Pripadne si prestuduj definiciu protokolu MODBUS. Aj ked sa Ti to bude zdat na prvy pohlad zlozite, oplati sa do toho lepsie zahlbit.
Pouzit system Master/Slave s nejakym ASCII protokolom je v konecnom dosledku to najjednoduchsie, ako Tvoj problem riesit.

Fyzickou vrstvu CANu jsem mu návrhl právě proto, že trval na multimasteru, jinak bych taky radši použil 485. Nicméně
s tou “měkkostí” bych to neviděl černě, přeci jen 120 Ohm (na každé straně) není úplně zanedbatelných a kroucená dvoulinka značně omezuje nepříznivé vnější vlivy. I CAN přenos je diferenciální :wink:.

Je ovšem pravda, že předávání peška mne nenapadlo. Nikdy jsem to totiž nepoužil pro jednu zásadní nevýhodu: každý musí znát svého logického souseda, nutnost změny konfigurace uzlů po přidání/odebrání jednoho z nich a hlavně selhání sítě při výpadku 1 uzlu.

Ja s Tebou uplne suhlasim.
Podmienka na multimaster je podla mojho odhadu prehnana a vyplyva z “nepodarenych” prikladov kodu pre seriovu komunikaciu na nete, kde cez rozne zpotvorene variacie printf() sa komunikuje cez UART.
Pisal, ze chce aby mu hl. procesor robil i nieco ine ako len komunikoval a chcel tam dat dokonca dalsi komunikacny procesor s ktorym by komunikoval cez SPI. Ale mozno sa mylim.

To je docela dobře možné. Osobně bych se Printf docela bál. Člověk neví jak je to napsaný. V případě, že to čeká na dokončení vysílání, tak je skutečně mcu zabitej a pokud ne, tak zase může snadno přijít v lepším případě o vysílaná data a v horším přeteče nějaký sw buffer a mcu padne. 485 je přímo ukázková školní úloha na práci s přerušeními :slight_smile:.

Osobne pochybujem, ze tie funkcie su pisane cez prerusenie.
Pisane su pre zaciatocnikov, ktory potrebuju, aby sa v mcu diala “naraz” iba jedna cinnost, aby mentalne stihali, ze co sa to tam deje. Printf nema ani ako vediet, ci treba prepinat smer alebo ako, v samotnej funkcii nevidim nejaky priestor na paralelizmus. Ono ani nejde len o vysielanie, ale potom aj o odpoved.
No a bohuzial pri tychto funkciach pokrocili aj ostavaju a mcu im zdanlivo nestihaju a nestihaju :slight_smile:

Podíval jsem se na tu funkci printf jak je dělaná v CV :

(toto mi neříká vůbec nic - vy se v tom vyznáte?)

VERSION:1 SOURCE_TIMESTAMP:37328407
NODE:M LEVEL:0 LINE:7 “STDARG_INCLUDED
NODE:M LEVEL:0 LINE:10 “NULL”
NODE:T LEVEL:0 LINE:13 “va_list”
NODE:M LEVEL:0 LINE:15 “va_start”
NODE:M LEVEL:0 LINE:16 “va_arg”
NODE:M LEVEL:0 LINE:17 “va_end”

tadz už je to lepší:

static void _print(char flash *fmtstr,va_list argptr,ps_s *ps_ptr, unsigned int max_size)

void printf(char flash *fmtstr,…)
{
va_list argptr;
ps_s p;
va_start(argptr,fmtstr);
p.ps=NULL;
_print(fmtstr,argptr,&p,0);
}

a abych se přiznal, moc jsem z toho nevyčetl
pak jsem nechal wizarda vygenerovat kód pro obsluhu přerušení

// USART Transmitter interrupt service routine
interrupt [USART_TXC] void usart_tx_isr(void)
{
if (tx_counter)
{
–tx_counter;
UDR=tx_buffer[tx_rd_index];
if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index=0;
};
}

#ifndef DEBUG_TERMINAL_IO
// Write a character to the USART Transmitter buffer
#define ALTERNATE_PUTCHAR
#pragma used+
void putchar(char c)
{
while (tx_counter == TX_BUFFER_SIZE);
#asm(“cli”)
if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))
{
tx_buffer[tx_wr_index]=c;
if (++tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0;
++tx_counter;
}
else
UDR=c;
#asm(“sei”)
}

a zkusil v debugeru AVR studia - vypadá to jako by printf jen naplnila tx_buffer a program běžel dál. tedy, že printf(“ahoj”) je to samé jako sprintf(tx_buffer,“ahoj”,)
V přerušení se pak vždy jenom přepíše jeden znak z tx_buffer do UDR a program běží dál.

Tak potom je to OK, dobra praca :slight_smile:.

AK by si este mohol vyskusat, ze ak das takyto prikaz vysielania na UART, potom prikaz na nacitanie znakov az po 0x0d cez UART a znovu vysielat nieco cez UART a znovu prikaz na nacitanie znakov az po 0x0d a nakoniec napriklad a++;

A to cele do

while(1) {

… }

To je priklad oslovovania dvoch Slave a cakanie a odpoved od nich. No a to, kolko krat sa vykona a++ (uint32_t) bude hovorit o priepustnosti celeho systemu. Mozno si s tym CV vie poradit (z pohladu priepustnosti systemu), potom klubuk dolu :slight_smile:
Malokedy totizto staci iba vysielat.

uart má dva buffery: UDR a vysílací shift registr. Když je prázdný vysílací shift, přesunou se do něho data z UDR a začne vysílání. Pokud by printf jen zapsalo data do UDR a jelo se dál, tak by musel uživatel před dalším použití kontrolovat flag UDRE (UDR empty). Vyslání dat z shiftu obvykle trvá poměrně dlouho vzhledem k rychlosti programu. Pokud bys parkrát za sebou použil printf, odeslal by se první byte a pak ten, který by v UDR byl po dokončení odesílání prvního. Případná volání printf mezi těmito dvěma okamžiky by byla bez efektu. Pokud nevíš naprosto jistě jak se to chová a zárověň potřebuješ procesorový výkon, tak doporučuji se printf vyhnout.
Takovéhle věci si raši píšu ručně(využití přerušení UDRE, TXC, RXC). Mám jistotu v chování i výkonnosti takového řešení :wink:.

Ja viem, ja tiez :slight_smile:

Pro vysílání UDR není určen, v datashetech se píše UDR I/O location. Data se zapisují na adresu shodnou s UDR, ale jdou přímo na shift registr pokud je UDRE=1. Není tedy double buffered. Do shift reg. se data automaticky nepřesouvají a už vůbec ne z UDR! To musí dělat SW. UART je navržen pro full duplex a obě části musí být na sobě nazávislé.

Momentálně to nemůžu říct najisto (budu si to muset vyzkoušet), ale dovolil bych si oponovat.

Zdrojem je datasheet Tiny2313, str.122
edit: a ještě str. 133 stejného pdf.