Sida 1 av 2

UART: master med flera slavar - protokoll?

Postat: 24 april 2009, 23:43:47
av jesse
Ursäkta ett långt och svamligt inlägg, det blev lite rörigt, :roll: kanske beror på att jag inte helt har tänkt igenom idén... och det är väl det som är orsaken till att jag skriver detta, skulle behöva lite feedback på vad jag sysslar med känns det som.

Ska koppla en master till flera slavar. Slavarnas antal kan variera mellan en och 25. Varje slav har en unik adress (dvs ett nummer i programminnet som den identifierar sig med) Jag kör halv duplex UART.

Funderar lite på adressering och dataöverföring, hur jag löser det smidigast?

några funderingar: allra smidigast vore ett system där mastern vid reset (eller vid särskild uppmaning) letar reda på alla slavar som finns och lägger dessa i ett register. Varje slav ska då ha ett individuellt nummer mellan 0 och 127.

Så mastern får köra igenom alla 128 kombinationer för att se om den får något svar. Sedan har den en lista på vilka som finns närvarande.

Mastern kommer att kalibrera slavarnas UART (timing) genom ett allmänt anrop. Jag har valt FF som kod för detta anrop eftersom just FF är den enskilda siffra som är minst känslig för tidsförskjutning i UARTEN (består bara av en startbit). När slavarna fått in FF väntar de på koden 80 (hex) vilket innebär i praktiken en 8 bitar lång "nolla" på linjen vilken kan mätas och divideras för kalibrering.

Detta har jag fått att fungera (har kopplat upp en slav)

Sedan finns ett antal instruktioner som maser ger till slav. Jag tror inte det kommer att finnas behov för dataöverföring från master till slav (bara instruktioner) men däremot kommer data att skickas i ganska långa serier från slavarna som svar.

slavarna måste kunna reagera allihopa samtidigt på vissa instruktioner (t.ex starta AD-omvandlare) men måste reagera individuellt på andra instruktioner (som t.ex. skicka över inlästa data)

Jag har inte löst detta än, men funderar på att göra det hela enkelt för mig (men det kanske krånglar till det på sikt?).

Nämligen att dela upp de åtta bitarna i varje byte som skickas från master till slavarna i en bit (bit7) som talar om ifall det är en allmän instruktion eller en individuell. Bit 0-6 är då själva instruktionen.

Exempel: (alla koder i hex)

kalibrera UART: FF 80 : tolkas och utföres av alla slavar.
(kod 80 är då reserverat för kalibreringen)
81 = aktivera slav (inaktivera alla andra), följt av adress (00-7F)
82 = deaktivera slav (ingen slav vald)
83 = starta AD-omvandlare (alla slavar)
03 = starta AD-omvandlare (vald slav)
04 = skicka AD-data (vald slav)
05 = skicka status (vald slav)
06 = reset

så om jag kör 81 AA så sätts en flagga i slav nr AA att just den kan ta emot instruktioner med bit7=0
skriver jag sedan 81 AB så nollas flaggan hos alla andra (t.ex hos AA) och aktiveras hos AB.
sen kan jag köra ett gäng instruktioner mot just den processorn. ex. 03 04 06 (läs in AD, skicka data, reset)
Men mitt i alltihop kan jag alltså skicka ett "allmänt anrop" t.ex. 86. 86 är då reser för samtliga slavar.
kod 82 deaktiverar slaven utan att någon annan slav väljs.

sedan funderar jag på att ha nån slags checksum-byte i slutet på alla dataöverföringar från slav för att säkra resultatet (vid flera timmar långa körningar har det hänt att någon byte blivit fel).

enligt följande mönster: NN, AA, DD, DD, DD, DD, CC

NN = antal bytes som skickas.
AA = slavens adress
DD = databyte
CC = checksum, räkns ut så att alla när alla bytes adderas (inklusive checksum) så skall summan bli 00. dvs CC=00-(NN+AA+DD+DD+DD+DD) (8-bitars operationer)

om nu t.ex. NN skulle bli korrupt och visa 243 istället för 7 så kommer inte master att fastna i evighet och vänta på 243 bytes, det finns en timeout både för slav och master på några millisekunder - har inte förväntade data kommit in då så återgår den till normalmode igen och ger ett felmeddelande)

mja..... har egentligen ingen fråga direkt. undrar väl bara i allmänhet om det verkar vetttigt eller om jag missar något väsentligt? Något mer att tänka på innan jag kastar mig över min assemblereditor? Verkar det hela lysande, utmärkt, vettigt, tveksamt, vansinnigt? Kanske är det överambitiöst bara för att hämta lite siffror från några slavar? eller inte? :humf:

Den enda nackdelen jag kan komma på nu är väl att om master ska skicka data till en slav så får det inte finnas data med bit 7 ettställd, då kommer ju de andra slavarna att uppfatta det som "allmänt anrop" och börja utföra den som en instruktion... Just nu har jag inga planer på att överföra data från master till slave , men plötsligt kanske behovet finns där och då har jag bara 7 bitar tillgodo.

Sen är ju funderingen kring om jag ska ha checksum på något vis även för instruktioner från mastern? det är ju ofta bara en eller två bytes långa, men konsekvenserna kan ju bli vad som helst om det skulle bli ett fel.

EDIT: Jag har även sneglat lite på CAN-bus som alternativ. Men det verkar mycket krångligare! Det är bra om det tål tuff miljö, men alla slavar måste också vara galvaniskt isolerade, vilket gör det hela jobbigare om man ska ha aktiva kretsar som sänder och tar emot data på slav-sidan.

Re: master med flera slavar

Postat: 25 april 2009, 00:11:26
av victor_passe
Kommer du kunna koppla in / ut när systemet är aktivt?

Mastern kan kanske 1 gång var 5:te sekund eller något söka efter nya slavar och bortkopplade slavar.

Re: master med flera slavar

Postat: 25 april 2009, 01:32:19
av sodjan
Bara några mindre saker. I stort verkar du ha tänkt på det mesta...

Det kan vara smidigre att ha adressen som första byte.

> Jag tror inte det kommer att finnas behov för dataöverföring från master till slav (bara instruktioner)

USART'erna ser naturligstvis ingen skillnad, så för själva överföringen spelar det inte
någon roll vad du kallar det. Det ligger på en högre nivå i applikationerna i resp ände.

Varför ha aktivering/avaktivering om du i alla fall har adresser i alla kommandon ?
Alla slavar kan väl i princip vara "aktiva" hela tiden ? Vad du nu menar med "aktiv"...

Ha gärna checksumma i alla "paket". Om det blir fel så kan slaven bara strunta i kommandot.
Se bara till att mastern har logik för att testa igen, larma eller vad som är rimligt.

Man får försöka se till att det hela inte hamnar i ett låst läge där alla väntar på någon annan.

Re: master med flera slavar

Postat: 25 april 2009, 01:53:44
av bearing
Lustigt, jag har de senaste dagarna skrivit på ett protokoll som, vad det verkar, har väldigt lika syften och krav som det här. Visserligen är det väl fallet med de flesta protokoll. Ett huvudsyfte med mitt är att mastern ska kunna be om AD-omvandling. Även jag har tänkt att mastern nog aldrig kommer skicka data till slaven, men funktionen är implementerad eftersom att både master och slav använder samma skicka-/ta emot-funktioner.

Jag tänkte lösa broadcast-problemet genom att helt enkelt reservera en adress som är broadcast. Varje gång det kommer en adress jämför slaven adressen med sin egen samt broadcast, som i mitt fall är 0xFF.

Använder 9-bitars UART, där en satt 9:e bit betecknar adress. 9-bitars UART har fördelen att hela 8-bitars-tal alltid kan skickas utan bekymmer över att det ska förväxlas med t.ex. adress (eller "allmänt anrop").

Min lösning använder icke-blockande funktioner som returnerar t.ex. READWAIT om det inte är klart och sedan READOK när det är klart.

Checksumman är i mitt protokoll en byte som ser till att summan av alla bytes i paketet blir 0xFF.
Har även funderat på någon form av handskakning som extra felhantering. Dock blir jag bekymrad över all overhead som blir av finesserna. Även jag har fått känslan att det hela är "overkill" för det enkla syftet.

Min utvecklingsmiljö har bestått av stora finessrika mikrocontrollers som klockats synkront, har därför inte implementerat kalibrering. Det verkar vara en bra ide eftersom koden senare ska flyttas till små kretsar med instabil RC-oscillator som saknar UART.

Om du är intresserad av att ta del av (ofärdiga) koden kan du få den. Den är skriven i C för CC5X.

Re: master med flera slavar

Postat: 25 april 2009, 08:10:45
av manw
Tycker denna grej låter lite mer som att det skulle vara lämpligt att använda I2C-bussen, eftersom det verkar som det hela skall vara någon form av dubbelriktad seriebuss?

Det finns en bra beskrivning här: http://www.instructables.com/id/I2C_Bus ... nd_ATmega/

Re: master med flera slavar

Postat: 25 april 2009, 10:38:53
av Icecap
Jag har ju gjort detta med ett sätt där jag specificerar en block. Varje block har en unik start byte och en unik slutbyte.

Startbyten rensar input buffern och slutbyten aktiverar "behandla inkommande kommando".
Jag använder STX (02h) och ETX (03h) men whatever annat fungerar också.

Med 25 st slaver är RS485 det givna valet för mig då jag antar att "mellan 1 och 25 slaver" betyder att det finns en viss fysisk spridning och där är I²C direkt olämplig. Är det inom samma chassi där man kan sticka i en eller fler sub-units är RS485 fortfarande rätt tycker jag.

Kruxet är att inte valda slaver ser samma data som andra aktiverade slaver sänder. Av den anledning bör man trixa lite.

Jag hade, om kommunikationen måste hållas binär, vald följande:
80h: ETX
81h + 00h-7Dh: STX + enhetsadress.
FFh: STX + gruppadress.
Alla data som skickas _måste_ då vara med MSB satt till '0' vilket gör att alla bytes behöver 2 bytes för att överföras. Jag hade helt enkelt tagit en nippel i varje byte, enkelt och skapligt effektivt.

En checksumma till det hela såklart, överförd på samma sätt.

När ETX kommer kollas checksumman mot inkomna data, är det rätt kollas adressen, är den rätt utförs kommandot.

Jag har testat med 9-bit kommunikation och allt fungerade efter boken ... fast i verkliga livet blev det skit av det hela, av den anledning har jag skippat detta helt.

Mastern hade då skickat:
STX+adress Kommando <data> checksum ETX

Slaver hade skickat:
STX+egen_adress Kommando(det som mastern skickade) Data Checksum ETX

Varje byte som skickas förutom STX+adress och ETX kommer att expanderas till 2 bytes:
t.ex. kommer 83 xy ch 80 att skickas som:
83h 0xh 0yh 0ch 0hh 80h

Re: master med flera slavar

Postat: 25 april 2009, 17:06:13
av sodjan
> som att det skulle vara lämpligt att använda I2C-bussen,

Knappast eftersom det är ganska tydligt att det handlar om lite avstånd.
I2C är främst för kommunikation inom ett (eller ett par sammanbyggda) kretskort.
Om man vill ha någon fördigt med protokoll och allt så ligger CAN närmast.

Re: master med flera slavar

Postat: 25 april 2009, 19:51:21
av jesse
>Kommer du kunna koppla in / ut när systemet är aktivt? Mastern kan kanske 1 gång var 5:te sekund eller något söka efter nya slavar och bortkopplade slavar.

Det är bra om jag kan koppla in/ur då systemet är aktivt, men däremot kommer det att ske ytterst sällan - dvs. när man bygger ut hårdvaran / fler mätobjekt. Detta behöver inte kollas var 5:e sekund. Eftersom det tar tid att scanna alla tänkbara adresser har jag en idé: jag låter mastern göra en scanning - när den träffar på en slav så registeras den i mastern - men även slaven får ett öronmärke i RAM-minnet att "jag är nu registrerad". Sedan kan mastern i jämna mellanrum skicka en fråga "finns det några oregistrerade slavar här?" - då kommer svar om det finns det, och inget svar om alla registrerats. Om svar erhålles så görs en ny scanning. (svaret kan ju inte innehålla någon adress - det blir ju fel om fler än en slav ansluts åt gången och alla svarar samtidigt!) Efter uppdatering visar mastern på displayen antal anslutna slavar och deras status.... Hade helst velat spara registreringen i slavens EEPROM, men då raderas den ju aldrig även om man monterar ur och i igen. Så den måste göras om i så fall vid strömbortfall eller reset. Inte helt bra.

>Varför ha aktivering/avaktivering om du i alla fall har adresser i alla kommandon ?
>Alla slavar kan väl i princip vara "aktiva" hela tiden ? Vad du nu menar med "aktiv"...


Jag har inte adressen i alla kommandon. adressen finns bara i "aktiveringskommandot" som egentligen är en adressering. det som kommer sen är kommandon utan adress, vanligtvis bara en byte långa. Jag har också funderat på att alla kommandon förutom "allmänt anrop" ska innehålla adressen, det går väl lika bra antar jag.

>Jag tänkte lösa broadcast-problemet genom att helt enkelt reservera en adress som är broadcast. Varje gång det kommer en adress jämför slaven adressen med sin egen samt broadcast, som i mitt fall är 0xFF.

Det jag är lite bekymrad över är kanske att ett kommando kanske ser ut så här... (nu överför jag data från mastern): adress kommando data checksum

...så är ju risken att kommando data eller checksum råkar innehålla just 0xFF vilket drar igång alla andra slavar... ska man låta även de passiva slavarna aktivt hänga med och räkna in datan så att de vet när serien är slut för att först då vara beredda på ny adressering, för att undvika att data uppfattas som kommando eller adress? Tycket det låter bökigt och man riskerar att slavar går vilse om de räknar fel.

jag tänkte att när slavarna ligger i normalt väntetillstånd och det kommer in en byte så ska slaven kolla om den är ett giltigt kommando - om det inte är det ska den återgå till vänteläget igen, vilket i praktiken innebär att den testar varje inkommande byte tills ett giltigt kommando kommer in. Detta kräver ju att ingen data som överförs inte får likna ett kommando, inte ens checksummebyten. Det är därför jag reserverat bit 7 till "adresseringsbit"

9-bitars UART hade ju varit enklast ,men ju längre serien blir desto större risk för fel. Jag kalibrerar ju UARTEN, men det blir inte helt perfekt. När jag kör 8 bitar får jag felöverföring några enstaka gånger när jag kört 12 timmar i sträck. Så jag behåller min 8 bitars UART.

Jag har beställt några RS-485 kretsar som jag ska testa någon gång. Kan vara bra att veta hur det funkar vid behov. Är bit-överföringen i RS-485 från processorns UART identisk med RS-232 eller fungerar överföringen annorlunda? Jag förstår att RX och TX delar på samma linje, så allt vad man skickar koller också att läsas in - annars skiljer det väl sig inte mjukvarumässigt?

Min garanti mot att slavar fastnar i väntetillstånd är en timeout. Kommer inget mer inom t.ex. 10 mS så återgår den till vänteläge (och registerar ev. fel om den hade förväntat sig data som aldrig kom).

Då kan mastern alltid ha en paus på 12 mS innan den påbörjar ett nytt kommando. Då vet den att alla slavar garanterat är beredda. Slavarna har var sin lysdiod (alltid bra att ha :idea: ) som blinkar kort var 8:e sekund. Denna blink är inte automatisk via någon timer-interrupt, utan en indikation på att slaven ligger i "vänte-mode" större delen av tiden. Skulle slaven fastna i någon annan loop så slutar LEDen att blinka eller börjar lysa fast.

En fundering är också angående checksumma för masterns en-bytes kommandon. Ett trick kan ju vara, om jag har en begränsad kommandorepertoar, att jag använder 4 bitar till kommadot och resterade tre bitar till en checksumma (sista biten är ju reserverad). Skulle en bit bli fel kommer det troligtvis att upptäckas på så sätt. Man formar kommandona så att minst två bitar måste ändras för att ett nytt giltigt kommando skall kunna formas.

Min mycket enkla kod för slaven som det ser ut just nu - är i princip:

main-loop: sleep (vänta tills byte kommer in)
vid byte-in:
case BYTE
(0xFF) GOTO KALIBRERING
(0x01) GOTO kolla adress
(0x02) GOTO
(0x03) GOTO AD-read
(0x04) GOTO send AD-data
(0x04) GOTO send test-data
(0x04) GOTO send kalibrerings-data
(0x04) GOTO send offset-data
(0x05) GOTO send error-log
annars: ; felaktig indata.
tänd LED
uppdatera error-log
åter main-loop


(att jag kör hopp (GOTO) istället för call är av lite olika praktiska skäl. dels återgår inte alla rutiner till samma ställe, dels blir det mer kod i case-satsen i assembler)

Jag har alltså inte implementerat adresseringen än - jag kör bara med en slav än så länge, men ska snart börja koppla på fler. Då måste även detta kollas. Bit 7 skall skalas av och tolkas, bland annat.

Re: master med flera slavar

Postat: 25 april 2009, 20:35:37
av bearing
> ...så är ju risken att kommando data eller checksum råkar innehålla just 0xFF vilket drar igång alla andra slavar...

Det är en bra synpunkt, kanske inte ska låta just 0xFF vara broadcast eftersom 0xFF tillsammans med satt nionde bit bara innehåller en startbit. Det hade jag inte tänkt på. Men så hade jag som sagt heller inte implementerat det ännu. =)

Jag tycker du ska överväga 9-bit igen. Med 9-bit samt broadcast != 0xFF kommer data eller checksum som innehåller samma tecken som broadcast eller valfri adress *aldrig* (förutsatt att UART-hastighet är i synk) kunna dra igång fel slav, eftersom att slavarna bara vaknar om 9:e bit är satt.

Ett problem jag ser med din lösning är att varje gång någon slav räknar fel på checksumman (i fall en sån kommer implementeras) kan det leda till att slavar pratar i mun på varandra. T.ex. om paketet som säger "deaktivera" eller "aktivera och deaktivera alla andra" får fel checksumma kan det bli så att flera slavar är aktiva.

Re: master med flera slavar

Postat: 26 april 2009, 14:19:17
av jesse
det var ju inte bra... ska fundera på det. Just nu är jag lite knäckt pga att min UART tycks ha pajat ihop helt och hållet... Det började häromdagen med att mätvärdena jag fick blev felaktiga ungefär var femte gång. Trodde det var fel på mätobjektet.. fixade och mätte... undersökte sedan AD-ingångarna ... fixade och mätte ... förstod ingenting... sedan insåg jag att det var UARTen... satans också, den som gick som en klocka i förra veckan... (märks det att jag inte brytt mig om att implementera checksum än :roll: )Har tre slavar, bytte mellan dem och det fungerade bara sämre och sämre och nu får jag knappt ens kontakt. :verysad:

Känns som om jag är tillbaks på ruta ett när det gäller min optiska överföring som gav mig så mycket huvudbry i somras! Tröttsamt det här. Hoppas bara jag hittar felet och kan se till att det inte uppstår igen. Har även förstört min lödkolv så det blir väl att skaffa en vettig lödstation också. Allting går utför känns det som just nu :evil:

Jag har varit slarvig och kablar har hängt och slängt åt alla håll och ESD situationen har varit under all kritik. Hoppas bara det inte är ESD-fel på masterprocessorns ingång. Korkat nog har jag inte något som helst skydd på ingången utan tråden rakt in. :doh: Antar att det är ett nybörjarfel som jag inte gör om. Allt som går utanför kretskortets kanter ska skyddas dubbelt upp! Jag har litat på Atmels skrytiga reklam om att deras ingångar minsann är ESD-skyddade med dioder. Men det finns väl gränser för vad den tål.

Utan en vettig fungerande dataöverföring är det ju ingen idé att fortsätta med överföringsprotokollet.

Re: master med flera slavar

Postat: 26 april 2009, 14:31:49
av bearing
Hur fungerar UARTen?
Externt interrupt och sedan timerinterrupt efter 1.5bittid följt av en gång per bittid?

Re: master med flera slavar

Postat: 26 april 2009, 15:57:54
av manw
sodjan skrev:> som att det skulle vara lämpligt att använda I2C-bussen,

Knappast eftersom det är ganska tydligt att det handlar om lite avstånd.
I2C är främst för kommunikation inom ett (eller ett par sammanbyggda) kretskort.
Om man vill ha någon fördigt med protokoll och allt så ligger CAN närmast.
OK, då hade jag helt missat detta med avstånd.

Re: master med flera slavar

Postat: 26 april 2009, 16:41:52
av sodjan
Nja, eftersom det talades om 1-25 slavar, så antog jag att det inte
var inom samma kretskort i alla fall.

Re: master med flera slavar

Postat: 26 april 2009, 18:03:08
av jesse
bearing: på ena sidan (mastern) är det hårdvaru USART. På slavarna är det extern interrupt och sedan har jag stängt av alla interrupt och pollar bitarna. Så processorn gör inget annat under tiden (den har ändå inget att göra)

Re: master med flera slavar

Postat: 26 april 2009, 20:08:39
av bearing
Har pollningen någon timer som tidsbas?
Vad är lösningen på synkroniseringen?

Om 0x80 används för synkronisering borde den tiden kunna mätas med en timer, för att sedan multipliceras med 1/(7*"pollingar per bit") som sedan blir bit-tiden.