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!!
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
[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.
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
---
@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 ..
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.
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
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
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
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
---
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