Forum: Mikrocontroller und Digitale Elektronik Busteilnehmer automatisch finden


von jürgen (Gast)


Lesenswert?

Hallo Forum-Gemeinde,

ich hoffe ihr könnt mir bei folgendem "Problem" helfen..

Ich habe ein Master Gerät (Anzeige) das über einen RS485 (Full-Duplex) 
verfügt. Und mehrere Slaves (z.B. Sensoren) die an diesen RS485 Bus 
angeschlossen werden können...

Jedes Gerät hat eine eindeutige ID, quasi in der Art einer MAC-Adresse. 
Bevor man jetzt ein Gerät nutzen kann, muss man am Display diese ID 
eingeben. Mein Haupt-µC fragt dann ab was für ein Gerät es ist und 
welche Daten es liefert, vergibt dem Gerät eine ID und dann kann es los 
gehen.
Das Anschließen ist aber trotzdem kompliziert...
Bevor ein Gerät angeschlossen wird, muss die MAC eingegeben (hab das MAC 
genannt, man könnte es auch Seriennummer nennen) werden, dann Gerät 
anschließen. Mein Haupt µC sendet dann die ID 0xFF + MAC-Adresse (nicht 
konfigurierte Geräte haben die ID 0xFF) mit der zugewiesenen neuen ID. 
Dann kann ich das Gerät erst ansprechen. Jetzt erst können neuen Geräte 
angeschlossen werden.
Wenn man das System ausschaltet, beginnt muss man alle Geräte abziehen 
und so neu verbinden. Bei 10 Geräten etwas umständlich und zeitraubend.

Jetzt würde ich das gerne so lösen, das man alle Geräte an den Bus 
hängt, und der Master nach neuen Geräten fragt mit irgendeiner Broadcast 
ID. Dann sollen sich die anschlossenen Geräte nacheinander melden (ich 
bin MAC 12345 und habe Temperatur, ich bin MAC 12346 und habe Digitale). 
Doch wie macht man sowas das es kein Datensalat auf dem Bus gibt? Da die 
µCs in den Slaves alle gleich sind und auch gleich schnell getaktet, 
würden doch theoretisch alle gleichzeitig senden ... Wie erkenne ich ob 
schon jemand sendet und warte dann bis der fertig ist?

Grüße & THX!!

von Hans J. (hjm)


Lesenswert?

Hallo Jürgen,

die Adresse der Slaves würde ich über DIP einstellbar machen.

Damit die Slaves antworten habe ich bei meinem System folgende Prozedure 
gewählt.

Master sendet Broadcast an alle.

1. Slave mit Adr 1 antwortet.
2. Slave mit adr 2 antwortet.

Wenn einer der Slaves nicht da ist (Timeout) geht die Reihe automatisch 
zum nächsten. So spielt es auch keine Rolle, ob alle vorhanden sind oder 
nicht.

Dies setzt natürlich voraus, das alle Slaves immer zuhören und dadurch 
erkennen wann sie an der Reihe sind.

Ist die Reihe beendet, so sendet der Master ein neues Broadcast. Dadurch 
kann man auch beliebig wechseln, zwischen automatischen Antworten bzw. 
Einzelabfrage der Slaves

Grüße
Hans-Josef

von markus (Gast)


Lesenswert?

[quote] Wie erkenne ich ob
schon jemand sendet und warte dann bis der fertig ist?[/quote]

Lös das Problem doch wie bei Ethernet ->  CSMACD sobald der Befehl zum 
melden der µC kommt, lass jeden eine Zufällige Zeit warten und erst 
danach sein Datenpaket senden.

von Stefan (Gast)


Lesenswert?

Ist denn Deine Hardware schon fertig oder hast Du noch Möglichkeiten, 
etwas in Richtung der Bustreiber zu ändern?
Evtl. wäre es ja pfiffig, sich von den RS-485 zu verabschieden und statt 
dessen CAN-Tranceiver (z.B. PCA82C250) einzusetzen. Die haben ebenfalls 
SO8 oder DIL8 Gehäuse, arbeiten aber nicht mit Push-Pull, sondern mit 
wired-OR Ausgangsstufen; soll heissen, einem Differenzsignal, bei dem 
logisch 0 dominant gegenüber logisch 1 ist.
Angenommen, Du baust darauf basierend einen Bus auf, dann kann jeder 
Teilnehmer auf diesen Bus schreiben und gleichzeitig (!) davon lesen. 
Setzt man das konsequent um, hast Du genau das, was Du suchst...

Ein typisches Szenario sieht dann so aus:
Teilnehmer 1 hat die Adresse 00001101 <- beliebig, jedoch eindeutig
Teilnehmer 2 hat die Adresse 00001001 <- beliebig, jedoch eindeutig

Beide empfangen einen Initialisierungsbefehl vom Master und beginnen 
dann ihre Adresse bitweise zu senden - nach jedem gesendeten Bit, lesen 
sie unmittelbar danach (!) den Busstatus zurück und brechen ggf. die 
Sendung ab, sobald dieser nicht mit dem eigenen gesendeten Bitstatus 
übereinstimmt.
Angenommen, beide beginnen gleichzeitig, sich beim Master zu melden und 
senden bitweise ihre Adresse:
TN1 = 1, TN2 = 1
TN1 = 0, TN2 = 0
TN1 = 1, TN2 = 0 <- hier stellt TN1 fest, dass ein anderer TN den Bus 
belegt hat -denn aus seiner Sicht sollte der Bus ja Status 1 haben- und 
bricht die Übertragung bis zum Ende des Frames ab. Dann nimmt er erneut 
Anlauf und beginnt sein Bit 0 zu senden. Alle TN hören ständig, was auf 
dem Bus passiert und starten eine Übertragung nur bei freiem Bus.
Da eine 0 eine 1 überschreibt, kannst Du mit der Vergabe der Adressen, 
auch deren Buspriorität festlegen. Je niedriger die Adresse, um so 
sicherer ist, dass der TN im ersten Anlauf mit seiner Nachricht 
durchkommt. Ein weiterer Vorteil ist dabei, dass jeder Slave von sich 
aus an den Master senden kann und nicht lanwierig gepollt werden muss. 
So lange Du sicher stellen kannst, dass ein TN mit niedriger Adresse 
nicht permanent den Bus belegt, kann jeder TNsehr kurzfristig seine 
Meldung absetzen und ggf. auch vom Master angesprochen werden...


Gruß, Stefan


---

von jürgen (Gast)


Lesenswert?

@Stefan
tja eigentlich ist die hardware schon fix .. der grund für rs485 sind 
die max. 10Mbps die da drüber gehen, aber realisitsch müssten 1Mbit von 
CAN auch reichen ..

Oder soll ich an den Ausgang vom UART (µC) einen CAN-Transceiver 
dranmachen (also TX an CANTX und RX an CANRX) und nicht komplett auf CAN 
umsteigen? Als Bus dann weiterhin RS485..

Mit CAN liese sich das doch recht elegant lösen oder? Steckt man ein 
neues gerät an, schickt das eine Botschaft mit der ID 10 (z.B.) auf den 
Bus, als Daten dazu Beschreibung was er ist und welche Adresse er hat, 
eine weitere ID die der Master mit Konfig Infos sendet und schon wäre 
der Bus konfiguriert..

Wenn ich das richtig verstehe bricht doch ein CAN-Controller auch das 
Senden ab wenn er merkt das etwas anderes auf dem Bus liegt und 
sendendet automatisch nochmal wenn er fertig ist. Nachteil wäre ich 
müsste einen µC mit CAN holen oder mit externem arbeiten ..

von Gast (Gast)


Lesenswert?

Hallo,

bei CAN wird erst gesendet, wenn der Bus frei ist. Dann kommt die 
Arbitrierungsphase, in der "ausgehandelt" wird wer senden darf falls 
mehrere gleichezeitig senden wollen. Dabei gewinnt der Knoten, der die 
Nachricht mit der kleinsten ID hat. Du musst aber sicherstellen, dass 
jede ID nur einmal vergeben ist.

Gast.

von Reinhard R. (reinhardr)


Lesenswert?

Hallo,

nur mal so ein geistiger Schnellschuss den ich nicht zu Ende gedacht 
habe, (d.h. ohne Gewähr dass die Sache nicht noch einen Hacken hat):

Nach dem Broadcast startet jeder Slave einen Timer der von seiner ID 
abhängt. Nach dem der Timer abgelaufen ist, meldet sich der Slave beim 
Master. Wenn ein anderer Slave zuvorkommt wird der Timer gestoppt bis 
der Bus wieder frei ist. So sollten sich in der Theorie alle Slaves der 
Reihe nach melden. Man muss ev. zwischendurch Maßnahmen zur 
Synchronisation treffen damit man die zeitlichen Toleranzen zwischen den 
Slaves im Griff behält damit nicht zwei Slaves mit unterschiedlicher ID 
sich erst recht wieder zum gleichen Zeitpunkt melden. Wenn die IDs einen 
sehr großen Raum umfassen wird die Sache natürlich sehr langsam. Es 
sollte allerdings schneller sein als ein Verfahren bei dem der Master 
alle möglichen IDs der Reihe nach abklappert und nach deren Anwesenheit 
fragt.

Gruß
Reinhard

von Stefan (Gast)


Lesenswert?

Ich würde den CAN-Tranceiver ganz pur verwenden; also damit nur die 
Harware anbinden und das Protokoll frei nach Schnauze machen. Wichtig 
ist eben nur, dass als erstes immer die Adresse übermittelt wird, damit 
Du die Arbitrierungsmöglichkeiten des wired-OR nutzen kannst. So z.B. 8x 
Adresse + 2x Befehl + 8x Daten oder was auch immer Du brauchst. Das 
Schreiben der Bits, die Kontrolle des Busstatus und die Verwaltung aus 
Sicht des Masters ist mit zwei Portpins doch eigentlich schnell 
geschrieben. Der ganze Kram mit Real-CAN kostet Dich nur extra Bauteile 
und ist doch -in bezug auf Deine Anwendung- wahrscheinlich nicht 
wirklich angemessen...
Ich habe so etwas mal vor 15 Jahren auf einem PIC gemacht; das geht 
wunderbar und läuft sehr zuverlässig :)

Gruß, Stefan

von jürgen (Gast)


Lesenswert?

Gibt es denn eine Möglichkeit das mit der Vorhandenen Hardware zu lösen?

Ich könnte doch z.B. ein Broadcast senden "Bitte alle noch nicht 
konfigurierten Geräte melden".. daraufhin starten alle betrefenden 
Geräte einen Timer (so wie oben vorgeschlagen) der aber Zufällig gesetzt 
wird im Bereich bis 2 oder 3 Sekunden, mit einem Abstand von 0.02 
Sekunden. Also 0.02, 0.04, 0.06, 0.08 oder etwas feiner. Bei 
Timerüberlauf fragt das Gerät nach seiner Konfiguration. Danach beginnt 
das ganze von vorne bis sich in der Zeitspanne kein Gerät mehr meldet ..

Gibt es sonst noch irgendwelche Möglichkeiten? Also ich denke 1-2 
Minuten kann das ruhig dauern. Die IDs sind bislang 8Bit (also max. 256 
Geräte), die "MAC" 24Bit

von Stefan (Gast)


Lesenswert?

Auch wenn die Teilnehmer zufällige Zeiten warten, werden doch immer 
wieder welche 'zufällig' zum gleichen Zeitpunkt senden. Da typische 
RS-485 Tranceiver keine Möglichkeit bieten, den Busstatus zurückzulesen, 
fällt es naturgemäss schwer, eine Kollision zu erkennen. Das wird nur 
über Acknowledges vom Master und längere Time-Outs funktionieren; was 
dann aber die Performance des Systems merklich drücken wird.
Wenn's nur 256 Geräte sind, dann kann Dein Master doch die Adressen 
sequentiell mit einem festen Frame ansprechen und jeweils ein 
Acknowledge-Bit freilassen. Das wird dann ggf. von dem Gerät mit der 
dazu gehörigen Adresse gesetzt, oder eben nicht; so dass der Master nach 
einem Durchlauf genau weiss, welche Geräte physikalisch vorhanden sind 
und sich mit diesen dann im Anschluss gezielt auseinandersezten kann.
100000001x00000010x00000011x00000100x
 ^Adr. 1 ^Acknowlegde vom Slave 1
^Startbit
          ^Adr. 2 ^Acknowlegde vom Slave 2
                   ^Adr. 3 ^Acknowlegde vom Slave 3
                            ^Adr. 4 ^Acknowlegde vom Slave 4
...
Wenn Du also die Slaves mit 19.200 Bps ansprichst, und 255 Bitfelder a 9 
Bits (8x Adresse + 1 Ack vom Slave) hast, dann kennt Dein Master nach 
~120 ms alle Teilnehmer.
Da es nur um die Initialisierung geht, und diese normalerweise nur 
einmalig, nach dem Einschalten der Versorgung stattfindet, brauchst Du 
ja auch keinen speziellen Befehl an die Slaves zu senden. Die warten 
nach dem Einschalten einfach darauf, dass es losgeht und verhalten sich 
entsprechend. Danach kann der Master jedes Gerät einzeln ansprechen und 
dessen Konfiguration erfragen. Dass ist dann um Welten efizienter, als 
die Wurstelei, wenn sich die Slaves beim Master melden, ggf. warten, 
u.s.w.

Gruß, Stefan


---

von Reinhard R. (reinhardr)


Lesenswert?

Vorausgesetzt die RS485 Transceiver tolerieren Buskollisionen ohne dabei 
physischen Schaden zu nehmen, wobei es dann egal ist dass die 
Datenintegrität im Kollisionsfall nicht gewährleistet ist, gibt es noch 
eine andere Möglichkeit, nämlich eine Baumsuche.
Dazu unterteilt der Master den Adressbereich in 2 Hälften und fordert 
alle Devices in der einen Hälfte auf sich zu melden. Sinnvollerweise 
werden die dann mit 0x00 oder 0xFF antworten damit im Falle kleinerer 
Unterschiede im Timings die Transceiver nur minimal belastet werden. 
Wenn sich dann zumindest ein Device meldet, halbiert der Master rekursiv 
den Adressbereich immer wieder und fragt nocheinmal nach, bis er die 
genaue Adresse eines Devices gefunden hat. Wenn er nichts gefunden hat 
wechselt er in den nächsten Bereich auf der gleichen Hierarchiestufe 
bzw. geht wieder eine Stufe nach oben.
Auf diese Art skaliert die Anzahl der notwendigen Abfragen linear mit 
der Adressbreite und der Anzahl der vorhandenen Devices. Das Verfahren 
ist also, zumindest bei großen Adressräumen, effizienter als alle 
Adressen der Reihe nach abzuprüfen.

Gruß
Reinhard

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.