RS485 Kommunikation Raspi <-> Arduino

  • Hallo zusammen,
    hier ensteht nach und nach eine Dokumentation über eine Kommunikation zwischen Raspberry Pi und Arduino über RS485. Ziel der ganze Sache ist es eine stabile Verbindung zwischen mehreren Arduinos/Raspberrys über eine längere Strecke sicherzustellen. In einem konkreten Fall, der ausgiebig getestet und hier vorgestellt wird geht es grundsätzlich um folgende Komponenten:


    - 3x Arduino Nano (+ TTL -> RS485 Modul | MAX485)
    - 1x Raspberry Pi 2 (+ RS485 USB Converter)
    - evtl. Pegelwandler für 5V->3.3V für GPIO Anwendung (Kommt später hinzu)


    Aktueller Stand des Aufbaus ist auf dem Fritzing Plan zu sehen, dieser wird laufende aktualisiert, wenn Änderungen vorgenommen werden. Das ganze wird über eine 2-Draht RS485 Verbindung realisiert, als Kommunikationsprotokoll ist MODBUS vorgesehen.


    [IMG:http://abload.de/img/rs485_steckplatinet4u5i.jpg]
    Das genaue Modul war nicht verfügbar, die Belegung des Chips sollte aber identisch sein. Die Anschlüsse DE+RE wurden gebrückt an den Arduino angeschlossen, der USB Converter am Raspberry Pi ist in wirklichkeit nur 2-polig!


    Dieses Projekt wird aktuell dreamshader und mir durchgeführt. Bei Interesse ist jede Beteiligung natürlich erwünscht, bitte wichtige Informationen an mich weiterleiten damit diese hier im Startpost dauerhaft aktualisiert werden können, damit eine schöne Dokumentation für jeden vollständig einsehbar ist!


    Gruß
    JumpY


    Stand: 01.04.2015


    Linksammlung: Diskussionsthread Übertragunsarten | Ergebnis: RS485

  • Ok,
    kurze Zusammenfassung:
    wie Du schon erwähnt hast, bietet sich hier der MODBUS an.
    Allerdings werden wir von dem wohl nicht viel brauchen ausser der Umschaltung senden/empfangen.


    Auf der RPi Seite heisst es zunächst mal: library installieren.

    Code
    1. sudo apt-get install libmodbus-dev


    Obiges Kommando sollte zusätzlich libmodbus5 installieren. Falls nicht, bitte auch libmodbus5 installieren.


    Dann wird in den meisten Informationsquellen ein Modbus-Monitor empfohlen.
    Hier habe ich QModbus verwendet. Lässt sich anstandslos auf dem RPi übersetzen.
    Allerdings benötigt QModbus Qt4, so dass auch das zuerst installiert werden muss:

    Code
    1. sudo apt-get install qt4-dev-tools libqt4-dev libqt4-core libqt4-gui


    //Anmerkung:
    libmodbus-dev, QModbus und die Qt4-libs können auch problemlos auf z.B. Ubuntu installiert werden.


    Nun, das erst mal als Anfang.
    Die Arduino-Seite und die ersten "Gehversuche" folgen ...


    cu,
    -ds-

  • Keine schlechte Idee.
    Aber warum RS485 ? Steckt da eine Idee dahinter oder nur Spieltrieb ?
    Ich hätte jetzt den Arduinos ein Ethernetshield verpasst. ( Netzwerker halt ;-) )

    Offizieller Schmier und Schmutzfink des Forum.
    Warum einfach wenn's auch schwer geht ?


    Kein Support per PN !
    Fragen bitte hier im Forum stellen. So hat jeder etwas davon.

  • Ich habe im ersten Thread den Link der Diskussion hinzugefügt, wo die Wahl auf RS485 gefallen ist. Ethernetshield wäre eine Möglichkeit gewesen, allerdings wusste ich nicht ob am ersten Einbauort Ethernet überall eingeplant ist. Das System (welches ich daraus mache), sollte möglichst flexibel sein und überall zum laufen zu bringen sein (Ethernet ist heute Stand der Technik, allerdings tatsächlich nicht überall verfügbar). Nun ist's halt RS485, wird aber sicherlich auch eine interessante Erfahrung die bislang nicht sonderlich bekannt sein sollte. (Zumindest nicht ausführlich und deutsch dokumentiert)


  • Nun ist's halt RS485, wird aber sicherlich auch eine interessante Erfahrung die bislang nicht sonderlich bekannt sein sollte. (Zumindest nicht ausführlich und deutsch dokumentiert)


    Jo, Danke für die Erklärung.
    Hatte vor etlichen Jahren mal öfters mit 485 zu tun, da hab ich mich viel um Barcodescanner gekümmert ( SICK CLV ). Die haben wir immer per 485 vernetzt, war noch zu Zeiten von Industrie 0.5 :D.
    Irgendwann kam dann, wie überall, die Profibus Baugruppe und alles war ganz einfach :wallbash:


    Resistent gegen Störungen. Für lange Leitungswege sicherlich eine gute Wahl.
    Muss mal schauen, ich hatte eine sehr gute Beschreibung des 485, mal sehen ob ich die noch im Datengrab habe.

    Offizieller Schmier und Schmutzfink des Forum.
    Warum einfach wenn's auch schwer geht ?


    Kein Support per PN !
    Fragen bitte hier im Forum stellen. So hat jeder etwas davon.

  • So, weiter gehts ...


    Im Prinzip ist das alles ganz einfach. Ich habe jetzt mal auf Ubuntu und dem Raspi die libmodbus-dev installiert und die Beispiele übersetzt.
    USB-RS485 Adapter in Raspi und Laptop, mit ca. 5m Zwillingslitze verbunden und schon laufen die Beispiele.
    Es funktioniert auch, wenn ich auf beiden Seiten minicom anwerfe. Aber jetzt kommt die Krux: ich kann nur vom Laptop zum Raspi Datens schicken, nicht umgekehrt ...


    Das hängt jetzt wohl damit zusammen, dass die Verbindung ja nur halbduplex ist und man zwischen Sende- und Empfangs-Modus umschalten muss.
    Wie gesagt, der Rest ist total easy ... einfach die UART Parameter abgleichen und schon flutscht die Sache.
    Ok, als nächstes wäre wohl der Arduino und die Suche nach der Umschaltmöglichkeit Sender/Empfänger dran.


    // Nachtrag:
    So eine Modbus-Lib kommt nicht in Frage. Der Regelfall sieht wohl so aus, dass die Modbus-Teilnehmer lediglich Bits und/oder Register-Inhalte austauschen. Da wir ein Protokoll zur Datenübermittlung benötigen reicht uns das nicht aus.


    Statt dessen habe ich -> hier <- eine RS485 Bibliothek ausgegraben, die ich im Moment auf Tauglchkeit teste.
    Der Arduino ist gar nicht so sehr das Problem. Beim Raspi weiß ich nicht wie ich den Modus umschalten kann. Da hängt das RS485-Modul ja über USB dran.


    Die Bibliothek ist es auf alle Fälle wert mal näher unter die Lupe genommen zu werden.
    Ini den Beispielen sind jedenfalls die Programme rs485_receive.cpp und rs485_send.cpp enthalten. Es sieht fast so aus als wären das genau die Sourcen, die wir hier benötigen.


    Nächster Schritt war jetzt also:
    die -> arduPi Library <- und die RS485-Library auf dem Raspi zu entpacken.
    Naja, und jetzt geht es drum dass sich die beiden unterhalten.


    Das ist jetzt mal der aktuelle Stand. So, JumpY ... während ich jetzt mal versuche den Raspi mit dem Arduino plaudern zu lassen kannst Du Dir mal überlegen wie die Kommunikation zwischen den beiden ablaufen soll (also das Protokoll).


    cheers,
    -ds-


    cu,
    -ds-

  • Hallo zusammen,
    ich musste mal eine kurze Auszeit nehmen ...


    Zum Thema Protokoll:
    ich wollte zunächst den Aufbau der Datenpakete so wie bei meiner Funkgeschichte machen, das ist aber wohl komplett oversized ;)


    Der Ablauf der Kommunikation dürfte so in etwa folgender sein:


    An einem Arduino wird ein RFID-Tag eingelesen. Der Arduino signalisiert diesen Vorgang an den Raspi, indem eine Leitung für einen kurzen Impuls von HIGH auf LOW (oder umgekehrt) geschaltet wird.


    Der Raspi sendet darauf hin an den entsprechenden Arduino (den er aufgrund der Leitung/des GPIO Pins identifizieren kann ) eine Sende-Anforderung über die RS485 Verbindung.


    Der Arduino wiederum schickt per RS485-Verbindung die eingelesene ID zum Raspi.


    So weit mal der Grund-Ablauf.


    Den Aufbau der Datenpakete kann imho relativ simpel gehalten werden und ich könnte ihn mir folgendermassen vorstellen:


    magic byte | length | crc8 | sender | receiver | telegram-type | data ...

    Die Daten werden binär (also ohne Konvertierung nach ASCII) übertragen. Das spart bis zu 50% Platz.
    telegram-type ist dann z.B. Quittung, Sende-Anforderung, Daten-Telegram, ...
    data wäre dann entsprechend ACK, NAK, SEND oder eben die ID.


    Jetzt ist die Frage ob und welche Quittungen wann verschickt werden.
    Mir ist noch unklar, wie ich aus der Software heraus die Umschaltung zwischen Senden und Empfangen bewerkstelligen kann. Da wir eine halbduplex-Verbindung haben, ist das mit dem hin- und hersenden nicht unbedingt ganz trivial.
    Einen CRC werden wir definitiv brauchen, denn der Transportlayer stellt lediglich die Parity-Funktion zur Verfügung.


    //EDIT:
    Bevor ich es vergesse: jetzt wäre Dein Input gefragt, JumpY ...
    Wie ist das - benötigt eine Lesestation eine Quittung ok, nicht ok (also Zugang oder nicht)?
    Was passiert mit fehlerhaft übertragenen Telegrammen ... ignorieren, neu anfordern, ...



    Fortsetzung folgt ...



    cheers,
    -ds-


  • Soweit richtig. Es gibt allerdings 2 Möglichkeiten wie das genau umgesetzt wird, ich beschreibe den Vorgang auf beide Arten:
    Variante 1:
    Jemand hält einen RFID Tag an die Lesestation, welche einer der Arduinos bildet. Dieser setzt sofort sobald ein Tag in Reichweite ist einen Ausgang auf HIGH. In diesem Moment erkennt der Pi dies (GPIO), und sendet ein Datenpaket an diesen speziellen Arduino. Das Datenpaket hat nur die Funktion das Senden des Arduinos freizugeben, der Arduino antwortet an den Pi die Kennung des RFID-Tags in Reichweite. Der Pi prüft, ob diese Nummer eine Zulassung zur Öffnung hat (Abgleich Textdatei / "Datenbank") und antwortet mit Ja oder Nein. Der Arduino entriegelt die Tür. Anschließend loggt der Pi folgendes in eine Textdatei (Zugriffslog): Uhrzeit | Türkennung | RFID Kennung | Name des Chipbesitzers. Falls der Zugriff verweigert wird, notiert der Pi dies in eine andere Datei!
    Variante 2:
    Jemand hält einen RFID Tag an die Lesestation, welche einer der Arduinos bildet. Dieser setzt sofort sobald ein Tag in Reichweite ist einen Ausgang auf HIGH. In diesem Moment erkennt der Pi dies (GPIO), und sendet ein Datenpaket an diesen speziellen Arduino. Das Datenpaket enthält ALLE gültigen RFID-Kennungen um die Tür zu öffnen, der Arduino gleicht seinen gelesenen Key mit denen ab, die er durch den Pi erhalten hat. Wenn eine Übereinstimmung besteht, öffnet er die Tür, ansonsten bleibt die Tür zu. Als Antwort sendet der Arduino den genutzten Key an den Pi.
    Hier endet die Kommunikation, das loggen übernimmt wieder der Pi genau wie oben.


    Der Unterschied daran ist, dass nur einmal alle Keys übermittelt werden und der Arduino sofort arbeiten kann. Bei Variante 1 müsste der Arduino erst den Key senden, welchen der Pi prüft und das Ergebnis zurücksenden. Ich vermute, dass Variante 2 schneller ist, allerdings nur dann, wenn wirklich alle Keys in einem Paket gesendet werden können. Da bist du gefragt, dazu kann ich nichts sagen. Es wird sich in diesem Anwendungsfall um ~10Keys handeln, das System sollte allerdings für alle Leute die das gerne nutzen möchten erweiterbar sein, ich weiß nicht wieviel möglich ist..



    Jetzt ist die Frage ob und welche Quittungen wann verschickt werden.


    Die Sache mit der Quittung richtet sich nach den obigen Varianten. Wenn der Arduino den Keyvergleich macht, benötigt man keine Quittung, ansonsten natürlich schon.



    Mir ist noch unklar, wie ich aus der Software heraus die Umschaltung zwischen Senden und Empfangen bewerkstelligen kann. Da wir eine halbduplex-Verbindung haben, ist das mit dem hin- und hersenden nicht unbedingt ganz trivial.


    Ist es nicht so, dass alle Empfänger die Pins RE+DE auf LOW gesetzt haben müssen, der Sender auf HIGH? Ich glaube verstanden zu haben, dass danach die Unterscheidung gemacht wird ob Receive oder Transmit aktiv sein soll, wenn dem so ist, wäre es auf den Arduinos "leicht umzusetzen". Wie das mit dem Pi ausschaut weiß ich nicht, die haben diese "Pins" ja nicht, vielleicht gibts da intern aber was zu schalten?



    Bevor ich es vergesse: jetzt wäre Dein Input gefragt, JumpY ...
    Wie ist das - benötigt eine Lesestation eine Quittung ok, nicht ok (also Zugang oder nicht)?
    Was passiert mit fehlerhaft übertragenen Telegrammen ... ignorieren, neu anfordern, ...


    Fehlerhafte Telegramme.. Da weiß ich auch noch nichts genaues, am besten wäre es diese erneut anzufordern, also dafür eine bestimmte Nachricht festzulegen, welche die letzte Anfrage erneut anfordert. Ich weiß nicht wie warscheinlich so etwas passieren wird, vielleicht kann man das auch vernachlässigen?


    Das war's von mir, ich hoffe das war verständlich :)

  • Hi JumpY,


    hm, da sagt der Softie in mir: das ist inkonsequent und eine suboptimale Idee ...


    Warum? Nun, der Arduino hat die Aufgabe, eine ID zu lesen, diese an seine Leitstelle zu übermitteln und dann entsprechend der Antwort die Tür zu entriegeln oder eben nicht. Somit haben wir hier eine klare Aufgaben-Verteilung, die auch mit mehreren Instanzen funktionieren sollte.


    Im anderen Fall bekommen wir mehrfach Probleme. Angenommen, die ID ist nicht bekannt ... da müsste dann eine Verwaltung der IDs her, welche bereits auf den speziellen Arduino übermittelt wurden, um einen Restabgleich durchzuführen. Dabei müsste zusätzlich berücksichtigt werden, ob der Arduino zwischenzeitlich neu gestartet wurde, und deshalb evtl. einen Komplettabgleich benötigt.
    Hinzu kommt, dass der Arduino wesentlich langsamer ist als ein RPi und zudem über keinen Datenspeicher verfügt. Die IDs müssten also alle im RAM gehalten (da hat der aber nur 2kbyte) oder im Flash (der ist ebenfalls begrenzt und das dauert) gespeichert werden.
    Hinzu kommt die Übertragungrate ... bis jetzt kann ich zumindest nicht sagen, wie schnell wir über die RS485 fahren können. Die meisten Beispiele liegen so bei 4800/9600 Bit/s.
    Der Arduino ist halt nun mal kein Rechenknecht sondern als µController für spezielle, einfache Aufgaben konzipiert.
    Deshalb würde ich das auf die erste Variante beschränken - was in meinen Augen duchaus auch Sinn macht.




    ....
    Ist es nicht so, dass alle Empfänger die Pins RE+DE auf LOW gesetzt haben müssen, der Sender auf HIGH? Ich glaube verstanden zu haben, dass danach die Unterscheidung gemacht wird ob Receive oder Transmit aktiv sein soll ...
    ...


    Das ist mir klar ;) ...
    Allerdings überlege ich gerade, wie ich das an einem USB->RS485 Konverter realisiere ...
    Da hab' ich ja nur die serielle Schnittstelle des CH341 oder was auch immer das für ein Chip ist.


    cu,
    -ds-

  • Hallo,
    alles klar, wenn dem so ist dann wird das so gemacht. Also Variante 2, der Pi macht die Arbeit.


    Zu dem USB->RS485 Konverter werde ich mir dann auch nochmal ein paar Sachen durchlesen wie man das erkennen kann, wird aber ja auf Software herauslaufen. Da der Pi Master ist, darf der ja alles bestimmen. Vielleicht einfach Zeitabhängig machen, also generell ist er im Schreibmodus, sobald er sein Paket übermittelt hat, Softwareseitig auf Read umschwenken und dabei einen Counter starten. Wenn nach X Sekunden niemand geantwortet hat, wieder in Write gehen. So könnte man zumindest ausschließen, dass er keine Möglichkeit des Sendens hat, allerdings wäre die Lösung eher unschön :(

  • Nun, ich hoffe ja, dass der USB->RS485 Konverter nach dem Prinzip "keep it simple" funktioniert und beim Schreiben bzw. Lesen die Leitungen entsprechend setzt.
    Jetzt muss ich erst noch ein bisschen Hardware basteln ... dann geht's weiter


    // Noch was: was sind das für RFID Leser, die Du hast?
    Es geht darum, wie die angesteuert werden. SPI oder UART ...


    cu,
    -ds-

  • Aktuell liegen folgende beiden RFID-Reader vor. Welches am Ende eingesetzt wird ist noch nicht ganz klar, ich glaube aber das es das simple RDM6300 wird. Das wird aber erst bei Vorführung enschieden, welches demjenigen besser gefällt wo der Ersteinsatz stattfindet.


    1) Seeedstudio RDM6300 : http://www.seeedstudio.com/depot/datasheet/RDM630-Spec..pdf
    2) MFRC-522 : Gerade kein Datenblatt zur Hand, http://image.dhgate.com/albu_5…der-ic-card-proximity.jpg das ist das Teil

  • So, jetzt hab' ich mal ein bisschen was gebastelt um mehrere Arduinos als Slaves einzusetzen.
    Dann werden wir mal sehen, wie das mit der Kommunikation funktioniert und ob die USB-Teile wie erwartet (oder besser erhofft) arbeiten.


    Ich spiele mit dem Gedanken evtl. doch das Modbus-Protokoll zu verwenden. Das hätte den Vorteil, dass wir uns mit dem ganzen Datenhandling nicht rumschlagen müssen und z.B. auf dem Arduino die Kommunikation komplett selbstständig von der Modbus-Klasse im sketch erledigt würde.
    Hintergrund ist, dass ich eine Funktion zum Lesen mehrerer Register auf einmal entdeckt habe. Da könnte der Slave z.B. die Register 0 bis 7 mit der Id des Tags füllen und dem Raspi den Lesevorgang signalisieren. Der liest dann per Modbus-API diese Register aus und setzt, abhängig von der Gültigkeit, ein anderes Register des Slave. Und der kann dann summen oder nicht ;) ...


    So einen MFRC-522 habe ich übrigens hier. Der ist aber noch original verpackt und bisher unbenutzt.
    War wohl irgendwie Gedankenübertragung nach dem Motto "zwei Deppen ein Gedanke" ;)
    Den werde ich dann wohl auch mit einbinden in die Testerei ...


    Nun, jetzt bin ich erst mal gespannt ob das alles so funktioniert, wie ich mir das vorstelle ...


    Ich halt' Dich/Euch auf dem Laufenden ....
    cu,
    -ds-

  • Sehr gut, das höre ich gerne!


    Wie schon gesagt, du bist derjenige der sich in die Protokolle eingearbeitet hat & kannst auch entscheiden welches genommen wird, denke du triffst dafür schon die richtige Wahl ;)


    Wie gesagt, das MFRC-522 ist für die etwas höherwertigen RFID-Tags, im Prinzip ist das aber alles das gleiche. Wenn man eine ID manuell versenden kann, funktionierts ja auch nach dem auslesen dies zu übermitteln. Solltest du was am laufen haben, bitte die Codes nicht verlieren, für die Auslesegeräte habe ich verschiedenstes Codesachen, da muss ich auch noch entscheiden welche davon die beste/sinnvollste ist :)


    Viel Erfolg!
    JumpY


  • ... Solltest du was am laufen haben, bitte die Codes nicht verlieren, für die Auslesegeräte habe ...
    ...


    Ich hab' den RC-522 gerade mal fertig zusammengelötet. Meintest Du lauffähige sketches für den Leser?
    Die hebe ich sowieso auf ... ich denke, wenn das Ding funktioniert nehme ich das mit in meine Sammlung auf ;)


    //EDIT:
    Hast Du -> diese <- Lib auch schon entdeckt? Ich gehe zwar mal davon aus, aber schaden kann der Link nicht :) ...
    Da ist auch ein Beispiel für einen Türöffner dabei ...


    Noch ein kleiner Nachschlag: o.g. Library hat bei mir mit dem RC-522 auf Anhieb funktioniert. Im Gegensatz zum RDM630 wird der RC-522 über SPI angesteuert. Da wir auf dem Arduino schon eine Menge mit RS232 zu tun haben, ist mir das sympatischer, als der RDM630, der auch wieder eine rs232 benötigt. Ausserdem hat der RDM630 noch eine spezielle Geschichte mit diesem Wiegand-Interface ... keep it simple - das wäre ein weiterer Pluspunkt für den RC-522.


    Der DumpInfo-sketch dürfte anfangs am interessantesten sein.
    Jeder Transponder hat ja eine UID (also eine eindeutige Seriennummer) mit 5 Byte Länge. Allerdings verbirgt sich hinter den Transpondern ja ein Speicherchip mit z.B. 1 kByte Kapazität. Das heisst, Du könntest auch Deine eigenen IDs vergeben.
    Meine Frage jetzt: was benutzt Du als Id?
    Das ist jetzt nicht sooo dringend, aber die Info brauchen wir für die Anzahl der Register für den sketch bzw. das Programm auf dem RPi, der die ja dann lesen muss.
    Ach ja: -> dieser Link <- ist vielleicht ganz interessant zum Thema RFIDs.




    cu,
    -ds-


  • //EDIT:
    Hast Du -> diese <- Lib auch schon entdeckt? Ich gehe zwar mal davon aus, aber schaden kann der Link nicht :) ...
    Da ist auch ein Beispiel für einen Türöffner dabei ...


    Das hatte ich bislang nicht, weil ich mich eher mit dem RDM630 auseinander gesetzt habe und nur getestet habe ob das RC-522 funktioniert. Danke für den Link ;)



    Allerdings verbirgt sich hinter den Transpondern ja ein Speicherchip mit z.B. 1 kByte Kapazität. Das heisst, Du könntest auch Deine eigenen IDs vergeben.
    Meine Frage jetzt: was benutzt Du als Id?


    Da bislang noch nicht klar ist, welches System wirklich zum Einsatz kommt, habe ich mich auf die ID konzentriert. Die Tags für RDM630 haben keinen beschreibbaren Bereich, weswegen nur die ID genutzt werden kann, bei dem anderen System könnte man die ID oder den Speicherbereich nutzen, dass erhöht zumindest die Sicherheit des Systems. Generell genügt aber dabei auch die normale ID, für eine höhere Sicherheit sollte man bei jedem Lesevorgang eine neue Prüfzahl setzen und diese in's Tag schreiben. Also jedesmal ID+XXXX (4-Stelliger Code z.B.) abfragen & bei erfolgreicher Öffnung diesen Code durch eine neue Zufallszahl ersetzen und in den Tag schreiben (wenn das alles schnell genug funktioniert). Ich denke wir sollten uns aber zunächst nur auf die ID beschränken, da eine Änderung vorzunehmen sollte ja möglich sein, oder?


    Ich denke allerdings weiterhin, dass derjenige der das System als erstes von mir bekommt, sich für die Variante mit dem RDM630 entscheiden wird, aber es soll ja möglichst universell einsetzbar sein, für die anderen hier ;)

  • Ok, das mit dem RFID-Teil gehört im Grunde nicht hierher und war nur als Hinweis am Rand gedacht.
    Ich habe da zu wenig Ahnung von RFID Transpondern und deren Einsatz, allerdings kommt mir der Name Mifare bekannt vor.
    Was schliesslich da zum Einsatz kommt musst Du dann entscheiden. Allerdings kann ich mit einem RDM630 leider nicht dienen.
    Ok, ich denke, das ist evtl. mal Thema für einen eigenen/neuen Thread ... und damit verlassen wir mal den OT-Bereich wieder ;) ...


    cu,
    -ds-

  • Kurzer Zwischenstand:
    Ich habe jetzt den sketch SimpleModbusSlave aus der -> Library SimpleModbus <- umgestrickt damit statt des Hardware-Serial-Ports eine Software-Serial-Instanz verendet werden kann.
    Hintergrund ist, dass es - um den Arduino zu flashen - notwendig ist, den RS485-Adapter abzustecken. Das ist etwas mühselig, vor allem, weil später evtl. keine Möglichkeit besteht, so einfach umzustecken.


    Die modifizierte Lib hänge ich mal als Anhang hier dran.
    Der RS485-Adapter ( ein solcher -> hier <- ) ist folgendermassen verdrahtet:

    Code
    1. Vcc -> +5V
    2. GND -> Masse
    3. DI -> Pin #9
    4. RO -> Pin #8
    5. DE -> Pin #2
    6. RE -> Pin #2


    Mit dem Modbus-Monitor ( das ist der -> hier <- ) ist es dann möglich, die "Register" des Arduino auszulesen. Hier steht später die UID des Transponders.


    ja ... hm ... mehr fällt mir im Moment nicht ein.
    Macht jedenfalls schon mal einen positiven Eindruck :) ...


    cu,
    -ds-

  • Nächster Schritt ...


    //EDIT: Achtung!

    Ihr benötigt die rfid-Lib von Miguel Balboa, die ihr -> hier <- herunterladen könnt.


    im beigefügten sketch ist jetzt das Auslesen eines Transponders mit einem MFRC-522 Lesemodul mit eingebunden.
    Einen Schaltplan liefere ich noch nach. An dieser Stelle nur kurz die textuelle Beschreibung der Verdrahtung, falls es jemand nicht erwarten kann.
    Der RS485-Adapter ( ist immer noch der aus dem Beitrag weiter oben, nur die Verdrahtung hat sich geändert ) ist folgendermassen angeschlossen:

    Code
    1. Vcc -> +5V
    2. GND -> Masse
    3. DI -> Pin #8
    4. RO -> Pin #7
    5. DE -> Pin #3
    6. RE -> Pin #3


    Der Mifare-Leser wird so verdrahtet:

    Code
    1. SDA -> Pin #10
    2. SCLK -> Pin #13
    3. MOSI -> Pin #11
    4. MISO -> Pin #12
    5. IRQ -> Pin #2
    6. GND -> GND
    7. RST -> Pin #9
    8. 3V3 -> 3.3V


    Ich habe in diesem Fall einen UNO verwendet, der zudem alle Pins mehrfach herausgeführt hat, weil da die Verdrahtun etwas unkomplizierter ist und er zudem 3V3 liefert.
    Es sollte aber mit einem Sketchboard als "Verteiler" und einer Spannungsquelle für die 3V3 auch mit einem anderen Arduino funktionieren.


    Ablauf im sketch:
    Das Auslesen eines Transponders löst einen Interrupt aus. Dieser wird jetzt nur genutzt um ein Flag zu setzen, dass eine neue UID eingelese wurde. Die eingelesene UID der Karte kann 4, 7 oder 10 Byte lang sein und wird mit einigen anderen Werte jetzt in die Modbus-Register (16 Bit) übertragen, die folgendermassen aufgebaut sind:

    Code
    1. Position 0: ein Flag, das anzeigt dass eine neue Id in den Registern steht
    2. Position 1: die Länge der enthaltenen UID
    3. Position 2 - 11: die max. 10 Werte der UID
    4. Position 12: ein Flag das anzeigt, ob der Master die UID bereits gelesen hat
    5. Position 13: ein Flag, das anzeigt, ob die eingelesene UID ok ist
    6. Position 14: ein Flag das der Master setzt, wenn der Türöffner betätigt werden soll


    Mit dem Monitor qmodbus (siehe einen Beitrag vorher) kann jetzt eine eingelesene UID abgerufen werden.
    Damit wäre zunächst mal die erste Grundfunktionalität auf der Arduino-Seite erledigt.
    Es kommen allerdings noch folgende Punkte auf die TODO-Liste bzw. sie bedürfen noch der Klärung:

    • Auslösen des Interrupt auf dem Raspi,
    • Berücksichtigen der Flags die der Master setzt


    Nächster Schritt ist jetzt das Anbinden des Raspi mittels modbus-Library an das RS485-Netzwerk ( welches dann schon mal aus drei Teilnehmern besteht ;) ).


    Achtung! Ihr braucht die Library aus dem Beitrag vorher.


    //EDIT: Verdrahtung des Lesers war fehlerhaft ... danke JumpY


    cu,
    -ds-

  • Und weiter geht's ;) ...


    ich habe jetzt ein Programm für den Raspi erstellt, das sich als Master am RS485-Bus anmeldet, die Register des Slabe (Arduino) ausliest und einige Register ändert.
    Voraussetzung: die libmodbus muss installiert sein. Verwendet habe ich die aktuellste Version (3.1.2 vom 10.02.2015), die ihr als Source -> hier <- oder bei github -> hier <- herunterladen könnt. Auf github liegt eine ZIP-Datei namens libmodbus-master.zip.
    Und dann benötigt ihr noch einen USB->RS485-Adapter wie z.B. -> diesen <- hier.

    Das Bauen der Library ist ziemlich simpel. Entpackt das Archiv mit

    Code
    1. pi@raspberrypi ~ $ tar xvf libmodbus-3.1.2


    bzw. beim ZIP-Archinv mit

    Code
    1. pi@raspberrypi ~ $ unzip libmodbus-master.zip.


    wechselt dann in das Verzeichnis

    Code
    1. pi@raspberrypi ~ $ cd libmodbus-3.1.2


    und ruft dann das Konfigurationsscript auf

    Code
    1. pi@raspberrypi ~/RS485_MODBUS/libmodbus-3.1.2 $ ./configure


    Wenn nach Beenden des scripts die Ausgabe


    erscheint, habt ihr erst mal alles richtig gemacht :) ...


    Jetzt mit make:


    die Library erzeugen und anschliessend mit sudo make install:


    installieren. Wenn jetzt im Verzeichnis /usr/local/lib folgende Dateien:

    Code
    1. pi@raspberrypi ~/RS485_MODBUS/libmodbus-3.1.2 $ ls -l /usr/local/lib/*modbus*
    2. -rwxr-xr-x 1 root staff 919 Apr 9 02:58 /usr/local/lib/libmodbus.la
    3. lrwxrwxrwx 1 root staff 18 Apr 9 02:58 /usr/local/lib/libmodbus.so -> libmodbus.so.5.1.0
    4. lrwxrwxrwx 1 root staff 18 Apr 9 02:58 /usr/local/lib/libmodbus.so.5 -> libmodbus.so.5.1.0
    5. -rwxr-xr-x 1 root staff 114648 Apr 9 02:58 /usr/local/lib/libmodbus.so.5.1.0
    6. pi@raspberrypi ~/RS485_MODBUS/libmodbus-3.1.2 $


    und im Verzeichnis /usr/local/include diese Include-Dateien und Verzeichnisse:


    vorhanden sind - gratuliere - dann ist alles ok gelaufen.
    Ladet euch jetzt den Source für den Raspi-Modbus-Master in z.B. Euer Home-Verzeichnis herunter, steckt den USB->RS485 Adapter am Raspi an und überprüft mit dmesg:

    Code
    1. pi@raspberrypi ~/RS485_MODBUS $ dmesg
    2. ...
    3. [988403.925355] usb 1-1.2.3.4: new full-speed USB device number 9 using dwc_otg
    4. [988404.028808] usb 1-1.2.3.4: New USB device found, idVendor=1a86, idProduct=7523
    5. [988404.028850] usb 1-1.2.3.4: New USB device strings: Mfr=0, Product=2, SerialNumber=0
    6. [988404.028871] usb 1-1.2.3.4: Product: USB2.0-Serial
    7. [988404.030916] ch341 1-1.2.3.4:1.0: ch341-uart converter detected
    8. [988404.045856] usb 1-1.2.3.4: ch341-uart converter now attached to ttyUSB0
    9. pi@raspberrypi ~/RS485_MODBUS $


    auf welche Gerätedatei ihr für die Verbindung zugreifen müsst.
    Wenn ihr nichts am sketch geändert habt, dann sollten die Schnittstellen-Parameter auf 9600 Baud, even Parity, 8 Datenbits und 2 Stoppbits stehen.
    Im Raspi-Code werden diese Werte ebenfalls verwendet, falls ihr nichts daran verändert habt.
    Am Anfang des Source-Codes findet ihr folgende Anweisungen die die Schnittstelle betreffen:

    Code
    1. #define MODBUS_DEV "/dev/ttyUSB0"
    2. #define MODBUS_BAUD 9600
    3. #define MODBUS_PARITY 'E'
    4. #define MODBUS_DATABITS 8
    5. #define MODBUS_STOPBITS 2


    Ändert ggf. das Device auf den Namen, den ihr mit dmesg angezeigt bekommen habt. Soltet ihr im sketch die Schnittstellen-Parameter geändert haben, dann führt die entsprechenden Änderung auch im Raspi-Source durch.
    Jetzt könnt ihr das Programm mit

    Code
    1. pi@raspberrypi ~ $ cc -o RaspiRFIDModbus RaspiRFIDModbus.c -I/usr/local/include/modbus -I/usr/local/include/libmodbus -lmodbus


    übersetzen und anschliessend mit

    Code
    1. pi@raspberrypi ~ $ ./RaspiRFIDModbus


    aufrufen.
    Wenn jetzt alles passt, solltet ihr eine Ausgabe ähnlich wie:


    Wie ihr seht stehen alle ausgelesenen Register auf 0.
    Jetzt lest einen Transponder ein und ruft das Programm anschliessend zweimal auf:


    Zweimal deshalb, damit die Änderungen die das Master (Raspi) an den Registern vornimmt sichtbar werden. Die Register 12, 13 und 14 sollten nach dem Aufruf des Programms auf 1 geändert sein. Ihr könnt allerdings auch den Modbus-Monitor qmodbus verwenden, um die Änderungen zu sehen.


    Nun, das war es auch schon ...
    Ich hoffe jetzt, mir ist kein gröberer Schnitzer beinm Schreiben dieses Beitrags unterlaufen. Falls noch
    Fragen offen sind, einfach melden ...


    Als Nachtrag noch eine wichtige Erkenntnis:
    das Handling der Kommunikation wird komplett von der libmodbus übernommen. Die Befürchtungen, das mit dem USB-Adapter nicht hinzubekommen (wegen des HIGH/LOW-Handshake) waren also unnötig.


    Wie gesagt: Schaltplan wird noch nachgeliefert und die fehlenden Funktionen im sketch (siehe Beitrag vorher) müssen noch ausdiskutiert resp. implementiert werden.
    Ich bleib' jedenfalls dran und halte Euch auf dem Laufenden.


    cu,
    -ds-