Hallo, ich habe zwei Geräte - einen Raspberry Pi und einen
Mikrocontroller, zwsichen denen ich Daten hin- und herschaufeln möchte.
Später sollen es mehrere Mikrocontroller sein.
Der Raspberry Pi hat an seinen 26 Pins 3 Schnittstellen
- SPI
- UART (seriell)
- I2C
I2C scheidet aus, weil der BCM2835-Baustein auf dem Raspberry Pi einen
Bug hat und das I2C nicht richtig umsetzt (Clock-Stretching-Problem).
SPI funktioniert zwar, aber ich benötige pro Bus-Slave eine CS-Leitung.
Wenn ich z.B. 6 Slaves adressieren möchte, gehen mir 6 IO-Pins verloren.
Deshalb wäre die Lösung mit I2C schöner gewesen, aber ich bekomme keine
einwandfreie Kommunikation mit I2C hin wegen dem
Clock-Stretching-Problem (Beitrag "Raspberry PI i2c-clock-stretching bug").
Ob der UART eine Lösung ist, weis ich noch nicht so genau, aber der hat
ja max. 115200 baud.
Könntet ihr mir ein paar Tipps geben, ob es noch andere Ansätze für eine
Kommunikation geben könnte (CAN-Bus scheidet auch aus).
Meine Idee wäre es jetzt, auf low-level-Ebene (dort können die Pins bis
etwa 20MHz angesteuert werden) selber eine Software-I2C-Schnittstelle zu
programmieren, aber irgendwie gefällt mir diese Lösung auch nicht.
Ich hab auch schon gegoogelt, und es gibt z.B. I2C-Slave to
SPI-Master-Bridgebausteine - haltet ihr das evtl. für eine Lösung, um
den Bug im Raspberry Pi zu umgehen?
Anfänger schrieb:
> SPI funktioniert zwar, aber ich benötige pro Bus-Slave eine CS-Leitung.> Wenn ich z.B. 6 Slaves adressieren möchte, gehen mir 6 IO-Pins verloren.
mit einem Hardware-Dekoder, z.B. 74HC138, kannst du mit 4 Pins bis zu 8
Slaves ansprechen und mit 5 Pins bis zu 16.
> Ob der UART eine Lösung ist, weis ich noch nicht so genau, aber der hat> ja max. 115200 baud.
ob da nicht mehr geht solltest du nochmal genauer untersuchen, der Pi
ist schliesslich kein PC. Und soo viel schneller wird normgerechtes I2C
auch nicht, 400kHz sind ja netto keine 400,000 Bits/s. Zum Ausgleich ist
UART einfacher zu programmieren.
I2C musst du sehr zuverlässig aufbauen. Nach einer verloren gegangenen
Flanke ist der Reset so umständlich - praktisch hilft da nur
Versorgungsspannung ausschalten. Bei SPI ist CS gleichzeitig Reset.
UART ist nur für Punkt zu Punkt Verbindungen konzipiert. Sollen mehrere
Geräte auf dem selben Kabel senden, musst du einige Verrenkungen machen.
eagle user schrieb:> mit einem Hardware-Dekoder, z.B. 74HC138, kannst du mit 4 Pins bis zu 8> Slaves ansprechen und mit 5 Pins bis zu 16.
Hmm, das ist klar mit den Hardware-Dekodern, nur muss ich ja dann auch
z.B. 8 Leitungen für 8 Slaves auf dem Bus mit verlegen. Ich kann dann
z.B. nicht einfach in einem Stecksystem zwei Einschübe vertauschen, es
steht dann ganz klar fest, zu welchem Einschub der entsprechende Slave
gehört. Man könnte dann vlt. eine Anfangsroutine ablaufen lassen, mit
der dann alle Slaves eindeutig identifiziert werden und dann
softwaremässig die CS-Leitungen zuordnen. Wäre eine Lösung. Aber ich
muss dann halt 8 CS-Leitungen durch mein System schleusen :-(
Wenn du so etwas zum ersten Mal machst, dürfte die übersichtlichste
Lösung die beste sein. Das zentrale Problem: Du weißt nicht, ob der
Fehler in der Hardware, in deiner Software oder im Linux steckt.
Bei SPI kann dein Programm beliebig langsam direkt die Port-Pins
ansprechen. Mit einem einfachen Multimeter kannst du kontrollieren, ob
alle Signale korrekt ankommen. Schon alleine weil die Fehlersuche
einfacher ist, würde ich für das erste Projekt mit einzelnen CS
Leitungen machen.
Etwas überraschende Frage.
Wieso Umweg über USB? Der Pi hat ja Pins die man direkt mit einen 3,3V
MC verbinden kann. Zusätzliche Chips kosten Geld. FTDI gibt es nicht für
Lochraster. Der Raspi-Prozessor ist zu langsam für zusätzlichen
Overhead. Und USB-Kabel brauchen mehr Platz als eine Backplane.
Welche Argumente sprechen dafür?
Noch einer schrieb:> Welche Argumente sprechen dafür?
Was auch noch dagegen spricht, ist die "Zuordnungsbarkeit" der
USB-Ports. Pro USB-Schnittstelle bekomme ich im /dev-Verzeichnis eine
neue Datei /dev/ttyUSB0... an dem Raspi hängen auch schon USB-Geräte wie
Maus, Tastatur etc. Man müsste dann auch wieder nach jedem Start alle
USB-Ports softwaremässig durchgehen und prüfen, an welchem USB-Port das
entsprechende Gerät hängt. Wahrscheinlich ginge das auch, aber irgendwie
umständlich.
Vielleicht könntest Du ja mal durchscheinen lassen um welche
Datenvolumina es geht und um welche Entfernungen.
Wir können aber auch raten...
Ein Wort zur Umgebung könnte auch nicht schaden. Es besteht immerhin ein
winziger Unterschied zwischen einer stark gestörten Industrieanwendung
und einem spielerischem Hobbyaufbau.
Auch wie sicher die Übertragung sein soll, ist manch einen Gedanken
wert.
Muss aber nicht sein.
So ein ähnliches Problem hatte ich auch mal.
Meine Lösung:
Bussystem mit 8 SPI Devices welche über eine 2 Draht Leitung selektiert
werden (Data und Clock). Auf jeder Platine habe ich einen kleinen Attiny
verbaut welcher für die Decodierung zuständig ist.
Beispiel:
Master sendet 0010 als Bitfolge (Data und Clock). Attiny welcher diese
Adresse hat setzt CS für das SPI Device auf Low. Alle anderen Attiny
setzen CS auf High.
Sendet der Master 0000 gehen alle CS auf High.
Funktioniert bisher ohne Probleme.
Nachteil: für jedes CS Device ist ein Attiny notwendig.
Noch einer schrieb:
> UART ist nur für Punkt zu Punkt Verbindungen konzipiert. Sollen mehrere> Geräte auf dem selben Kabel senden, musst du einige Verrenkungen machen.
UART an sich ist ja kein Problem, es kommt auf die Treiber an. Mit RS232
geht's ganz schlecht. Mit RS485 kostet es zusätzlich ein Driver Enable
Signal, das nicht ganz trivial ist. Mit einer Stromschleife geht's
einfach, kostet aber viele kleine Bauteile. Wenn man Potentialtrennung
braucht, lohnt sich der Aufwand evt. trotzdem.
Für diese Anwendung (mit genau einem Master) würde ich CAN-Treiber
vorschlagen. Die werden genau wie MAX232 ans UART angeschlossen, aber
man darf die Ausgänge der Treiber alle parallel schalten. Da vom Prinzip
her immer nur ein Gerät zur Zeit sendet, ist UART+CAN
selbstfunktionierend. Man kann auch je einen Treiberbaustein für Sendung
und Empfang spendieren und so ggf. den Durchsatz erhöhen. Nachteilig ist
der hohe Stromverbrauch, besonders, wenn man tatsächlich 2x120 Ohm
spendiert. Bei kurzen Kabeln geht's aber auch hochohmiger.
Noch einer schrieb:> Etwas überraschende Frage.> Wieso Umweg über USB? Der Pi hat ja Pins die man direkt mit einen 3,3V> MC verbinden kann.
Ja, scheinbar kann der UART ja aber nur 115,2kBaud.
Die Überlegung war, ob man trotz des Overhead von USB eine höhere
Datenrate hin bekommt.
>Zusätzliche Chips kosten Geld.
Ist das ein Massenprodukt wo es auf das bisschen ankommt? Was kostet
deine Zeit? Mit der Kabelvariante wo ich geschrieben habe steckst du es
an und legst los. Keine Platine designen/bestellen/löten/in betrieb
nehmen/Fehler suchen...
>FTDI gibt es nicht für Lochraster.
Wo steht die Anforderung?
>Der Raspi-Prozessor ist zu langsam für zusätzlichen> Overhead.
Das weis ich nicht. Ich hätte es mal ausprobiert.
>Und USB-Kabel brauchen mehr Platz als eine Backplane.
Wo steht die Anforderung?
> Welche Argumente sprechen dafür?
Schnell ausprobiert, noch erschwingliche kosten, mit RS485 ein
vernünftiger Treiber dahinter damit es auch ein paar Meter mehr sein
dürfen.
Vielen Dank für Eure vielen Tipps - mal eine Frage zu dem CAN-Bus.
Folgendes Szenario - ein Slave nimmt Messwerte auf - 1000 16bit-Werte
pro Sekunde. Diese Werte will ich an den RPi senden, man könnte das
Datenholen z.B. 10mal pro Sekunde machen.
Meine Erinnerung an den CAN-Bus ist, dass ich nur ein Kommando senden
kann und vorher den Slave adressieren muss.
I2C wäre für mich ideal, dort kann ich einfach machen:
<Slave_Adress>-<Command>-<Data>-<Data>...<Data>
Aber wegen dem Clock-Stretching klappt das nicht. Beim CAN-Bus hab ich
ja
<Slave_Adress>-<Command>-<Data> - ich kann immer nur einen Wert abholen
und muss dann immer wieder die Adresse mitsenden, umd das nächste
Datenpaket zu bekommen.
Mit SPI hab ich halt meine Probleme wegen der vielen CS-Leitungen. Das
Problem ist noch, wenn ich SPI auf dem RPi verwende und selbst mit einem
Portexpander arbeite, so sind doch die beiden CS-Pins blockiert.
Werner P. schrieb:> Sendet der Master 0000 gehen alle CS auf High.>> Funktioniert bisher ohne Probleme.>> Nachteil: für jedes CS Device ist ein Attiny notwendig.
Das gefällt mir ganz gut, da muss ich mal drüber nachdenken.
Kennt ihr vlt. eine bessere Alternative als einen RPi, der auch Linux
drauf hat und kein Clock-Stretching-Problem?
Du hast immernoch nicht beschrieben, was du eigentlich tun willst (oder
ich habe es beim Überfliegen überlesen). Ethernet ist gut. USB ist gut.
Wenn nicht, musst du mehr Informationen bringen.
Wenn ein I2C-Slave kein Clock-Stretching benutzt, kann es dir
schnurzpiepegal sein, ob der RPi das unterstützt oder nicht. Es gibt
genug Bausteine, die an einem RPi ganz wunderbar funktionieren. SPI
braucht pro Slave einen CS-Pin. Aber den kannst du auch nachrüsten, z.B.
mit einem PCF8574/A (oder was modernerem) am I2C des RPi.
Die klassische serielle Schnittstelle am PC schafft maximal 115,2
kBit/s, moderne USB-Seriell-Wandler schaffen deutlich mehr; je nach
Chipsatz bis zu 2 MBit/s.
Aber solange du nicht sagst, was du eigentlich möchtest, bleibt
eigentlich nur Ethernet.
Brauchste jetzt einen Standard oder isses egal ?
Wenn egal nimm einfach zwei Pins und einer ist mit #0 verbunden und #999
ist mit #0 verbunden.
Der Rest ist für Dich.
Onewire gibt's dann noch mit zwei Leitungen oder Du funkst dazwischen
...
Achja RSXYZ geht auch mit extra Chips oder per Software ...
S. R. schrieb:> Du hast immernoch nicht beschrieben, was du eigentlich tun willst (oder> ich habe es beim Überfliegen überlesen)
Hier steht es:
Anfänger schrieb:> Folgendes Szenario - ein Slave nimmt Messwerte auf - 1000 16bit-Werte> pro Sekunde. Diese Werte will ich an den RPi senden, man könnte das> Datenholen z.B. 10mal pro Sekunde machen.
Ne, das steht da nicht.
Da steht nicht:
- wieviele Slaves es gibt,
- wie weit voneinander die entfernt sind,
- wie kompliziert sie sein duerfen,
- wie wichtig die Daten sind,
- usw.
Also nimm Ethernet. Fertig.
Anfänger schrieb:> I2C wäre für mich ideal, dort kann ich einfach machen:>> <Slave_Adress>-<Command>-<Data>-<Data>...<Data>>> Aber wegen dem Clock-Stretching klappt das nicht.
Wieso soll das nicht klappen?
Weisst du überhaupt, was CLock-Stretching ist oder ist das wieder so
eine 'Ich hab mal gelesen, dass es da ein Problem gibt' Sache?
> Beim CAN-Bus hab ich> ja>> <Slave_Adress>-<Command>-<Data>
Beim CAN Bus hast du in erster Linie erst mal überhaupt keine
adressierbaren Slaves. DIe Idee hinter dem CAN Bus ist eine komplett
andere. Weg vom klassischen Master-Slave Prinzip und hin zu: jeder
plärrt auf dem Bus raus, welche Daten er anzubieten hat und wen auch
immer diese Daten interessieren, der kriegt sie. Auf einem CAN Bus
verkündet zb der Aussentemperatur Sensor alle paar Millisekunden, dass
es jetzt gerade draussen +8°C hat. Ob sich die Heizungssteuerung diesen
Wert holt oder die Rollosteuerung ist dem Temperatursensor egal, er
verkündet was er gemessen hat.
Das ist die Grundidee. Nicht die Adresse des Senders oder Empfängers ist
wichtig, sondern welche 'Datenfracht' ein CAN-Paket transportiert.
Das man damit wieder eine Master-Slave Kommunikation aufbauen kann ist
ein Nebenprodukt. Die eigentliche Idee bei CAN ist aber eine ganz
andere.
> Kennt ihr vlt. eine bessere Alternative als einen RPi, der auch Linux> drauf hat und kein Clock-Stretching-Problem?
Falsche Frage.
Hast du denn überhaupt einen I2C Teilnehmer, der Clock Stretching
betreibt? Die Mehrzahl wird dieses Feature nämlich gar nicht benutzen.
>ich habe zwei Geräte - einen Raspberry Pi und einen>Mikrocontroller, zwsichen denen ich Daten hin- und herschaufeln möchte.>Später sollen es mehrere Mikrocontroller sein.>Hast du denn überhaupt einen I2C Teilnehmer, der Clock Stretching>betreibt.
Er hat mindestens einen;)
Karl H. schrieb:> Wieso soll das nicht klappen?> Weisst du überhaupt, was CLock-Stretching ist oder ist das wieder so> eine 'Ich hab mal gelesen, dass es da ein Problem gibt' Sache?
Ich habe einen Logikanalyzer an den I2C-Bus gehängt und dann gesehen,
dass das Clock-Signal vom Slave entsprechend gehalten wird, wenn er noch
nicht fertig ist und dann kommt der RPi durcheinander.
Anfänger schrieb:> Ich habe einen Logikanalyzer an den I2C-Bus gehängt und dann gesehen,> dass das Clock-Signal vom Slave entsprechend gehalten wird, wenn er noch> nicht fertig ist und dann kommt der RPi durcheinander.
Und!? Magst Du uns vielleicht auch noch den Chip mitteilen!?
Anfänger schrieb:> ich habe zwei Geräte - einen Raspberry Pi und einen> Mikrocontroller
... und welchen?
Ist das der Chip, welcher das SCK hält? Wäre eine Alternative keine
Möglichkeit?
Und: Woher kommen die Daten? Welche Chips sind noch involviert? ...
Es ist echt nervig, alle Informationen häppchenweise auf Nachfrage zu
erhalten und solange um Dein Problem herum zu rätseln.
Anfänger schrieb:>> Also nimm Ethernet. Fertig.>> Das ist eine gute Idee,
Stand 5 Beiträge weiter oben auch schon ...
> verwendet ihr bei den Mikrocontrollern dann z.B.> Bauteil:>> http://www.reichelt.de/?ARTICLE=109722 ?
Ja, z.B.
Alternativ: SPI-Daisy-Chain. Sofern von den Bausteinen unterstützt.
(welche auch immer das dann sein mögen)
Und: Soll das ganze auf eine Platine oder wird das eine
Freiluftverdrahtung?
Gruß
Jobst
Jobst M. schrieb:> Und: Soll das ganze auf eine Platine oder wird das eine> Freiluftverdrahtung?
Jetzt eine "Freiluftverdrahtung", später soll das dann, wenn es
funktioniert, auch festgelötet werden, damit sich die Kabel dann nicht
mehr ablösen.
Anfänger schrieb:> Ja genau, das ist ein ARM STM32
Warum muss es diese Rakete sein?
Kann es evtl. am Programm liegen, dass der den SCK festklemmt?
Jobst M. schrieb:> Wäre eine Alternative keine Möglichkeit?>> Und: Woher kommen die Daten? Welche Chips sind noch involviert? ...
???????
> Es ist echt nervig, alle Informationen häppchenweise auf Nachfrage zu> erhalten und solange um Dein Problem herum zu rätseln.
...!
Anfänger schrieb:> Jetzt eine "Freiluftverdrahtung", später soll das dann, wenn es> funktioniert, auch festgelötet werden, damit sich die Kabel dann nicht> mehr ablösen.
Also Freiluftverdrahtung ...
> Gruß>> Jobst