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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.