Hallo,
ich möchte einen AVR an einen Raspberry anbinden und überlege wie ich
das Ganze am besten (Zuverlässigkeit und (Programmier-)Aufwand) löse.
Die Geschwindigkeit der Datenübertragung ist nicht wirklich der
begrenzende Faktor, 50 KBit/s reichen absolut aus.
Bislang dachte ich einfach den AVR über einen ganzen Port mit den GPIOs
des Raspberry zu verbinden und die Kommunikation über 2 Extraleitungen
(Strobe vom RPi und Busy vom AVR) zu steuern. Da ich eigentlich nur
Daten zum AVR schicken wollte, schien mir das der leichteste Weg zu
sein.
Falls ich aber doch mal was in die andere Richtung Senden will, müsste
ich entweder einen zweiten Port opfern oder mir nochmal Gedanken machen,
wie ich bidirektional über den einen Datenport kommunizieren kann.
Von daher kam ich auf die Idee das man den AVR ja auch über SPI, I²C
oder UART anbinden könnte.
Darum meine Frage, was haltet ihr, unter Berücksichtigung der begrenzten
Hardwarefähigkeiten von RPi (kein Clock Stretching) und AVR (schlechter
SPI-Slave), für die beste Möglichkeit?
>Darum meine Frage, was haltet ihr, unter Berücksichtigung der begrenzten>Hardwarefähigkeiten von RPi (kein Clock Stretching) und AVR (schlechter>SPI-Slave), für die beste Möglichkeit?
UART.
H.Joachim S. schrieb:> Jo, UART. Und ein nettes Protokoll dazu.> Was macht der AVR als Empfänger denn mit den 50kBit? Fällt mir gerade> nichts ein.
Bit Bang für Servos und Schrittmotoren, 50kBit/s waren eher als
Hausnummer gedacht. Geht weniger um die Datenmenge sondern darum das
schnell die Puffer gefüllt werden wenn nötig.
Also bislang 3:0 für UART.
UART sollte auf beiden Seiten die einfachste Lösung sein.
Serielles I/O auf Linux ist (fast) trivial, und sollte auf der Seite vom
AVR, sofern man die eingebaute UART nimmt, auch einfach sein.
Die Latenz des Busses hängt zwar mit der Baudrate zusammen, aber
prinzipiell ist die Bandbreite von der Latenz (eigentlich) unabhängig.
Eine Leitung/Protokoll kann auch nur mit 1B/s gefahren werden, sofern
das Bit mit geringer Verzögerung übertragen wird. UART ist natürlich
eine Zeit-Synchronisierte Schnittstelle. Bei SPI gibt der Master ja
den Takt vor, da müssen dann nur die Shiftregister auf dem Slave
schnell genug mithalten können.
Zeitkritische Sachen im einstelligen Millisekunden-Bereich oder darunter
würde ich nicht direkt über UART laufen lassen. Zumindest nicht wenn
ein Linux auf der anderen Seite dahinter hängt, wohl möglich noch
mit einem Python-Script oder so.
Aber ich nehme mal an, dass für die zeitkritischen Sachen der AVR dann
da ist und nur "langsam" neue Kontroll-Kommandos erhalten soll?
EDIT: Grammatik
UART.
Der AVR sollte vorzugsweise ein Baudratenquarz erhalten, z.B.
14,7456MHz.
Für die UART spricht auch die höhere Störsicherheit, da jedes Bit 3*
abgetastet wird.
Der AVR kann 3 Bytes puffern, der RPi kann DMA, also ist auch ein
Datenverlust kaum zu befürchten.
Robin R. schrieb:> Zeitkritische Sachen im einstelligen Millisekunden-Bereich oder darunter> würde ich nicht direkt über UART laufen lassen. Zumindest nicht wenn> ein Linux auf der anderen Seite dahinter hängt, wohl möglich noch> mit einem Python-Script oder so.> Aber ich nehme mal an, dass für die zeitkritischen Sachen der AVR dann> da ist und nur "langsam" neue Kontroll-Kommandos erhalten soll?
Das war der Plan, nachdem ich leider feststellen musste das der
Raspberry auch mit RT-Kernel nicht in der Lage ist die GPIOs exakt genug
anzusteuern, egal ob man diese mit BCM-lib, wiringPI oder nativ mit C
anspricht. Python würde ich für sowas garnicht anfassen.
Peter D. schrieb:> UART.> Der AVR sollte vorzugsweise ein Baudratenquarz erhalten, z.B.> 14,7456MHz.> Für die UART spricht auch die höhere Störsicherheit, da jedes Bit 3*> abgetastet wird.> Der AVR kann 3 Bytes puffern, der RPi kann DMA, also ist auch ein> Datenverlust kaum zu befürchten.
Stimmt, da war ja was mit dem UBRR^^. Hatte nach den FPGAs komplett
verdrängt das man ja den Teiler bei den AVRs nicht beliebig einstellen
kann.
Muss mal sehen ob ich den Raspberry nicht auf glatte Baudraten
einstellen kann, ansonsten entweder Baudraten Quarz oder schauen ob mir
max. 38.400@16MHz reicht.
Aber ist die SPI auf dem AVR echt so grottig das keiner das Ding
empfiehlt? Dachte eigentlich SPI wäre die erste Wahl für sowas...
Tim T. schrieb:> Aber ist die SPI auf dem AVR echt so grottig das keiner das Ding> empfiehlt? Dachte eigentlich SPI wäre die erste Wahl für sowas...
bei I2C und SPI gilt es immer noch die 3,3V zu 5V Hürde zu nehmen, der
Atmel und der PI haben beide keine OC.
Wer den Atmel mit 8 MHz versorgt kann locker auf 3,3V gehen
UART wäre auch meine Wahl, entweder bei 2 Spannungen per MAX dazwischen,
oder einfacher SerienR 470 Ohm und Schottky Diode nach 3,3V oder AVR
auch auf 3,3V
Ein AVR als I2C-Slave wird bei üblichen Bitraten nicht um Clock
Stretching herum kommen, was der RPi nicht richtig beherrscht. Wenn man
es nicht eilig hat und auf dem µC für I2C eine ausreichen kurze
Interrupt-Latenz garantiert, dann kann man aber beispielsweise auf 10
kHz I2C Takt runter.
Der Entwickler des SPI-Moduls der AVRs hatte beim Design vom Slave-Modus
nicht wirklich seinen besten Tag. Bei anderen µCs als AVR kann das
besser aussehen, besonders wenn die DMA können.
Bleibt UART, je nach Versorgungsspannung des AVR mit oder ohne
Pegelwandler. Das Linux vom RPi lauscht in Standardkonfiguration
allerdings an der UART auf ein Terminal, was die Sache ein wenig
behindert. Da muss man das System etwas anpassen (Stand RPi 1 vor 2
Jahren):
/boot/cmdline.txt: console=ttyAMA0,115200 rauswerfen
/etc/inittab: Zeile mit ttyAMA0 mit # auskommentieren
Eine serielle Notfallkonsole hat man dann natürlich keine mehr. Wenn man
sich netzwerkseitig aussperrt, dann sollte man Tastatur und Monitor
parat haben.
H.Joachim S. schrieb:> Der Raspi hat doch mehr als eine UART? Glaub ich zumindest...
Mindestens der erste RPi hatte das nicht und mit dem hatte ich das
gemacht.
A. K. schrieb:> Ein AVR als I2C-Slave wird bei üblichen Bitraten nicht um Clock> Stretching herum kommen, was der RPi nicht richtig beherrscht. Wenn man> es nicht eilig hat und auf dem µC für I2C eine ausreichen kurze> Interrupt-Latenz garantiert, dann kann man aber beispielsweise auf 10> kHz I2C Takt runter.
Hmm, dann kann man es auch fast lassen. Rein Interessehalber, wenn ich
mehrere AVR-I²C-Slaves am Bus betreiben würde, würde jedesmal die Arbeit
aller AVRs unterbrochen auch wenn die Nachricht nur für einen Knoten ist
und die ISR ausgelöst?
> Der Entwickler des SPI-Moduls der AVRs hatte beim Design vom Slave-Modus> nicht wirklich seinen besten Tag. Bei anderen µCs als AVR kann das> besser aussehen, besonders wenn die DMA können.
Scheint, nach allem was ich sonst noch darüber gelesen habe, wohl
wirklich bescheiden nutzbar zu sein.
> Bleibt UART, je nach Versorgungsspannung des AVR mit oder ohne> Pegelwandler. Das Linux vom RPi lauscht in Standardkonfiguration> allerdings an der UART auf ein Terminal, was die Sache ein wenig> behindert. Da muss man das System etwas anpassen (Stand RPi 1 vor 2> Jahren):>> /boot/cmdline.txt: console=ttyAMA0,115200 rauswerfen> /etc/inittab: Zeile mit ttyAMA0 mit # auskommentieren
Ja, der Teil ist klar. Glaube bis auf den RPi 3 ist das auch so
geblieben, dann war auf ttyAMA0 das Bluetooth Interface, dort ist die
(immernoch einzige) UART dann auf ttyS0.
> Eine serielle Notfallkonsole hat man dann natürlich keine mehr. Wenn man> sich netzwerkseitig aussperrt, dann sollte man Tastatur und Monitor> parat haben.
In Zeiten von USB-Unifying Donglen und HDMI sollte das kein Problem mehr
sein.
Danke schonmal für die ganzen Antworten, hat mir schon jede Menge Zeit
gespart in der ich mich mit I²C und SPI rumgeschlagen hätte...
Tim T. schrieb:> Rein Interessehalber, wenn ich> mehrere AVR-I²C-Slaves am Bus betreiben würde, würde jedesmal die Arbeit> aller AVRs unterbrochenAVRs mit vollständigem I2C Modul ignorieren, was nicht an sie adressiert
ist. Ebenso die mit slave-only Modul wie ATtiny841. Beim USI ist das
etwas anders, da die Adresserkennung in Software erfolgt.
Es wäre auch ein Szenario denkbar, in dem der AVR mit niedrigem Takt
angesprochen wird, andere Slaves aber mit hohem Takt. Es ist die
Verzögerung des Protokolls durch den Interrupt-Handler, die ggf. Clock
Stretching nötig macht.
Tim T. schrieb:> Rein Interessehalber, wenn ich> mehrere AVR-I²C-Slaves am Bus betreiben würde, würde jedesmal die Arbeit> aller AVRs unterbrochen auch wenn die Nachricht nur für einen Knoten ist> und die ISR ausgelöst?
Du verwechselst da was, bei I2C wird immer nur ein Slave adressiert und
nur der muß seinen Interrupt behandeln. Er muß sich dabei auch nicht
beeilen, da automatisch SCL auf low gezogen wird. Und der Master kriegt
erst den "fertig"-Interrupt, wenn SCL wieder auf high geht.
D.h. das Clock-Stretching muß vom Master unterstützt werden, sobald die
Slaves MCs sind.
Die AVR-UART kann auch adressiert werden, dazu muß die UART in den 9-Bit
Mode gesetzt werden. Und dann muß nur die adressierte UART die Bytes
lesen.
Peter D. schrieb:> D.h. das Clock-Stretching muß vom Master unterstützt werden, sobald die> Slaves MCs sind
Ist im RPi zwar vorgesehen, aber falsch implementiert. Hardwarefehler.
Wenn man µCs als Slaves an den RPi hängt, dann müssen die schnell genug
reagieren, oder es gibt Mist. Soweit ich weiss gilt das für alle diese
Broadcom SoCs.
http://www.advamation.de/technik/raspberrypi/rpi-i2c-bug.html
Peter D. schrieb:> Tim T. schrieb:>> Rein Interessehalber, wenn ich>> mehrere AVR-I²C-Slaves am Bus betreiben würde, würde jedesmal die Arbeit>> aller AVRs unterbrochen auch wenn die Nachricht nur für einen Knoten ist>> und die ISR ausgelöst?>> Du verwechselst da was, bei I2C wird immer nur ein Slave adressiert und> nur der muß seinen Interrupt behandeln. Er muß sich dabei auch nicht
Das ist eben die Frage wie das jeweils gemacht wird, ist wohl bei den
USIs so das jeder nen Interrupt bekommt.
> beeilen, da automatisch SCL auf low gezogen wird. Und der Master kriegt> erst den "fertig"-Interrupt, wenn SCL wieder auf high geht.> D.h. das Clock-Stretching muß vom Master unterstützt werden, sobald die> Slaves MCs sind.
Klar, leider war nur der ASIC Mensch vom Broadcom etwas doof und
maskiert den SCL lediglich, sobald der SCL vom Slave losgelassen wird
geht er, falls noch was von der Highpegel-Zeit übrig sein sollte, sofort
hoch und kann dadurch eine zu kurze High-Pegeldauer, die nicht von den
Slaves erkannt werden, generieren.
>> Die AVR-UART kann auch adressiert werden, dazu muß die UART in den 9-Bit> Mode gesetzt werden. Und dann muß nur die adressierte UART die Bytes> lesen.
Ja, hatte da irgendwann mal was gelesen; 9. Bit ist bei Adressen gesetzt
und bei Daten gelöscht oder sowas.
Tim T. schrieb:> und AVR (schlechter SPI-Slave)
wieso soll der AVR ein schlechter SPI Slave sein? Was gibts da für
Probleme?
Ich habe auch bald vor, den RPi an den AVR mit SPI anzubinden.
Max M. schrieb:> Tim T. schrieb:>> und AVR (schlechter SPI-Slave)>> wieso soll der AVR ein schlechter SPI Slave sein? Was gibts da für> Probleme?> Ich habe auch bald vor, den RPi an den AVR mit SPI anzubinden.
Am knackigsten hat es peda hier zusammengefasst:
Beitrag "Re: Atmel SPI = Müll?"
Max M. schrieb:> OK, dann also UART?
Ist zu empfehlen.
> Brauche ich dazu einen stabilen externen Takt? Habe einen Tiny2313 mit> int. Clock aktiv.
Jein. Die generelle Aussage dazu wird sein, dass du einen Baudraten
Quarz dafür brauchst, allerdings mit etwas Finetuning (OSCCAL -
Calibration Byte - Seite 160) am internen Takt, geht das auch mit dem
internen RC-Oszillator. Aber das Ganze ist dann immer etwas Exemplar,
Temperatur und Spannungsabhängig.
> Würde damit UART zum RPi gehen?
Der 2313 hat nur ein USI, keine "richtige" U(S)ART; geht natürlich
trotzdem bidirektional, also ja.
Tim T. schrieb:> Der 2313 hat nur ein USI, keine "richtige" U(S)ART
Nein, der 2313 ist einer der verhältnismäßig wenigen Tinys, der eine
Hardware-UART besitzt. Übrigens gleichermaßen auch die engen
Verwandschaft 2313A und 4313.
c-hater schrieb:> Tim T. schrieb:>>> Der 2313 hat nur ein USI, keine "richtige" U(S)ART>> Nein, der 2313 ist einer der verhältnismäßig wenigen Tinys, der eine> Hardware-UART besitzt. Übrigens gleichermaßen auch die engen> Verwandschaft 2313A und 4313.
Hast natürlich recht, der 2313 hat neben dem USI auch noch einen echten
USART. War da beim Wort Tiny wohl etwas zu vorschnell.