Hallo zusammen, ich würde gerne einen Raspberry Pi mit einem oder mehreren ATmegas als verteiltes System betreiben, realisiert über SPI. Der Raspberry als Master würde den ATmegas Befehle erteilen und Rückgabewerte empfangen - quasi eine light-Version eines verteilten Systems. Ein Befehl könnte als remote-Aufruf einer C-Funktion realisiert werden, ggf auch als Kommunikation über (virtuelle) Register, wie bei Sensoren (z.B. BME280). Sahnetüpfelchen wäre die Redefinition der Arduino Serial-Libary mit Verwendung dieses Kanals statt UART. Das spart Leitungen, außerdem könnte man bei geschickter Programmierung dann Serial.Write() auch im Interrupt verwenden. Problem: die unzähligen Tutorials im Internet schieben 1-2 Bytes über die Leitung. Man freut sich, wenn eine LED leuchtet oder ein Byte zurückkommt. Die Libraries für dedizierte Sensoren machen letztlich auch nicht viel mehr. Was fehlt, ist eine Art OSI-Modell für SPI. Kennt da jemand was in diese Richtung? Würde ungern das Rad neu erfinden. Alles ist willkommen, was mehr tut als nur 1 oder 2 Bytes zu schieben. Grund für SPI: Verbindung ist bereits vorhanden, da ich die ATmegas darüber mit avrdude auf dem Raspberry Pi programmiere. Das Projekt könnte natürlich auch über I2C oder UART realisiert werden, aber die Problematik bleibt die gleiche. Gruß, Felix
:
Verschoben durch Admin
Wenn du mit "die ATmegas" diese in mehrzahl meinst hast du erstmal der problem mit dem Chip-Select signal mit dem die die einezelen salves geziehlt aktivieren/deaktivieren musst. Da kommen ganz schnell eine ganzer büschel an leitungen zustande. I2C kennt dagegen z.B. sowas wie Adressierung wenn mehrere Geräte gleichzeitig dran hängen. Und UART(RS232/RS428) wird interessant wenn die Leitung mehr als einige cm haben soll usw. Kommt also sehr genau darauf an was du tatsächlich machen willst und was dafür am geeignetzten ist. "Ist schon da" ist da eher ein schlechter Ratgeber (zumal selbst hierfür noch einiges fehlen dürfte).
Es kommt drauf an wie weit verteilt. SPI ist elektrisch ungünstig, weil es taktsynchron ist und viele Leitungen hat. Ich würde einen bestehenden Bus verwenden, dazu mal nach Feldbus googlen. Wozu das Rad neu erfinden?
Name: schrieb: > Es kommt drauf an wie weit verteilt. Nicht sehr weit verteilt. Die Geräte sitzen in einem Gehäuse, vielleicht 10-20 cm Leitung. Eigentlich habe ich auch nur einen ATmega verbunden, würde es nur gerne für die Zukunft offen lassen. Bzw. soll sich der SPI-Bus auch für weitere Sensoren oder Displays nutzen lassen. Den Hardware-Aspekt würde ich gerne erstmal beiseite lassen. Die SPI-Probleme lassen sich lösen. Daisy-chaining wäre möglich, da ich ja selbst die ATmega-Slaves konzipiere. Dann hat Mikrochip z.B. beim MCP23008 ein ganz interessantes Konzept, bei dem auch für SPI eine Geräte-Adresse verwendet wird. Ist mir aber egal, denn momentan reicht erstmal eine 1:1 Verbindung und Umstieg auf ein anderes Bussystem wäre ja jederzeit möglich. Mir geht es um "höherwertige Protokolle" auf einem Bus. Was gibt es da? Gefunden habe ich https://github.com/openmv/openmv-arduino-rpc, einen recht flexiblen Ansatz in diese Richtung. Würde ich wohl weiter verfolgen. Ist mir allerdings schon fast zu flexibel. Wenn mir jemand sagt, schau Dir Projekt XY an, da ist Dein Beispiel schon realisiert, dann wäre ich dankbar.
Irgend W. schrieb: > "Ist schon da" ist da eher ein schlechter > Ratgeber Grundsätzlich absolut richtig. Wenn es um wirklich viele Geräte geht, größere Entfernung, Funkverbindung etc. , dann werde ich wohl umdenken müssen. Nun ist es aber so, dass ich einen Versuchsaufbau habe, bei dem die SPI-Verbindung da ist und funktioniert. Das würde ich gerne nutzen, um das Softwareproblem "höherwertiges Protokoll" zu lösen, denn dieses besteht ja bei allen Verbindungen. Es bringt mir wenig, jetzt die Hardware zu optimieren und den Usecase "LED einschalten" für 100 LEDs in Australien stabil zu kriegen. Dann bastele ich noch Monate weiter und bin beim Problem der verteilten Programmierung keinen Schritt weiter gekommen.
ATmega als SPI Slave ist schon mal keine gute Idee. Ansonsten ist das schöne am OSI-Modell ja, daß das in Schichten aufgebaut ist. Da musst du nur die Transportschicht auf SPI umstricken ;) Oliver
:
Bearbeitet durch User
Beitrag #6567606 wurde von einem Moderator gelöscht.
Felix schrieb: > Was fehlt, ist eine Art OSI-Modell für SPI. Das fehlt sicher nicht. SPI bildet die unterste Ebene der Kommunikation ab. Du kannst fast jedes höhere Protokoll damit nutzen. Es braucht kein höheres Protokoll nur für SPI. Ob SPI hier aber sinnvoll ist, steht auf einem anderen Blatt.
Beitrag #6567625 wurde von einem Moderator gelöscht.
Oliver S. schrieb: > ATmega als SPI Slave ist schon mal keine gute Idee. Warum? Das wird oft in Foren behauptet. Aber einen stichhaltigen Beleg dafür habe ich noch nicht gefunden.
Felix schrieb: > Oliver S. schrieb: >> ATmega als SPI Slave ist schon mal keine gute Idee. > > Warum? Das wird oft in Foren behauptet. Aber einen stichhaltigen Beleg > dafür habe ich noch nicht gefunden. Warum probierst du es nicht einfach aus? Du behauptest viel und bist sehr von allem überzeugt. Das TU es einfach. Programmierung eines SPI Slave ist eben eine Nummer schwieriger als ein Master. Man muss die Zustände besser im Auge haben und man muss ständig Daten bereit halten, falls der Master etwas lesen möchte. Natürlich kannst du zwischen einem Pi und einem ATMega alles per SPI machen. Nur es ist nicht optimal und du wirst einiges rumprobieren müssen. Als erstes wäre zu prüfen ob ein verteiltes System notwendig ist. Der Aufwand und die Komplexität steigen schnell. Ohne Not würde ich das nicht machen. Einen ATMega als Subcontroller für spezielle Aufgaben lässt sich noch gut machen. Ein eher allgemein gehaltenes verteiltes System nicht mehr. Dafür gibts auch kein Kochrezept. Etablierte höhere Protokolle tun auch nicht alles für dich. Du kannst damit vielleicht Adressierung und Fehlererkennung und Retry usw. realisieren. Aber am Ende überträgst du immer noch Bytes und was die bedeuten wirst du dir selbst ausdenken und ausprogrammieren müssen. Also bitte bitte bitte, wenn du denkst du bist der coole Frood und kannst das und weißt das besser, dann mach doch einfach und laber hier nicht rum.
:
Bearbeitet durch User
Felix schrieb im Beitrag #6567625: > Immerhin ist der SPI-Bus der vom > ATmega-Hersteller vorgesehene Bus zur Programmierung des Chips. Nein, das ist natürlich nicht der Fall. Zur Programmierung benutzt man ISP, das ist was anderes als SPI und insbesondere auch kein Bus (höchstens, wenn man RST im Sinne von CS benutzt). Bei vielen AVR8 sind (neben CS, was sowieso nie passt) auch die anderen Anschlüsse nicht identisch. Bei den Tinys sind MOSI und MISO getauscht, bei einigen Megas liegen sie sogar auf völlig anderen Pins als SPI. Sprich: du hast absolut keine Ahnung, davon aber eine ganze Menge...
Beitrag #6569176 wurde von einem Moderator gelöscht.
c-hater schrieb: > Nein, das ist natürlich nicht der Fall. Zur Programmierung benutzt man > ISP, das ist was anderes als SPI... > > Sprich: du hast absolut keine Ahnung, davon aber eine ganze Menge... Tut mir leid, bin noch relativer Einsteiger beim ATmega. Hatte mich halt auf Atmels Datasheet vom ATmega328p verlassen, die gleich auf einer der ersten Seiten schreiben "The on-chip ISP flash allows the program memory to be reprogrammed in-system through an SPI serial interface..." Dank Deines Rates weiß ich jetzt also, dass das falsch ist, vielen Dank für die Hilfe.
Cyblord -. schrieb: > Also bitte bitte bitte, wenn du denkst du bist der coole Frood und > kannst das und weißt das besser, dann mach doch einfach und laber hier > nicht rum. Möchte ich natürlich sein und deswegen bastele ich daran weiter statt noch mehr zu schreiben. Bisher läuft der ATmega sehr gut als SPI-Slave, aber halt nur Byte-für-Byte. Werde das wie oben angedeutet aufbohren. Falls es jemand inhaltlich interessiert, hier zwei recht vielversprechende Projekte dazu: https://simplerpc.readthedocs.io/en/latest/ https://github.com/openmv/openmv-arduino-rpc Wenn was bei rauskommt, werde ich das Ergebnis vorstellen.
Beitrag #6569963 wurde vom Autor gelöscht.
Wenn du schon du schon von "höherwertiges Protokoll" sprichst, warum nimmst du nicht einfach nen W5100? Dann hast du dein SPI und kannst auch viele andere Geraete ansprechen. Dann kannst du frei UDP,TCP, raw MAC oder raw IP machen. CAT5/6/7 Kabel bekommst du wie Sand am Meer und die sind auch guenstig. All deine Probleme waeren geloest. Dann koenntest du sogar dieses "IoT" relativ einfach umsetzen ^^
:
Bearbeitet durch User
Oliver S. schrieb: > ATmega als SPI Slave ist schon mal keine gute Idee. Schon SPI an sich ist zur Kommunikation zwischen unabhängigen Modulen ungeeignet. Und besonders dann, wenn einer ganz naiv "erst" mit SPI ein Kommando an einen Slave schickt, und sofort "danach" die Antwort vom Slave abholen will. Denn dann wird 1. der ganze Bus nur halbduplex gefahren und 2. muss der Slave "in kürzester Zeit" a) das Kommando abholen, b) das Kommando auswerten und c) das Ergebnis zur Übertragung bereitstellen. "In kürzester Zeit" bedeutet hier bei den meisten Anfängerentwürfen "nur 1 SPI-Taktzyklus". Ein brauchbarer Bus zur Übertragung von Daten zwischen zwei "intelligenten" Geräten ist ein RS232, RS422 oder RS485 Bus. Die ersten beiden sind sogar vollduplex.
Lothar M. schrieb: > Schon SPI an sich ist zur Kommunikation zwischen unabhängigen Modulen > ungeeignet. Das stimmt sicherlich, nur sind meine Module nicht wirklich unabhängig. Vielleicht habe ich mein Szenario nicht präzise genug dargestellt. Ich möchte das Problem ja gar nicht allgemein lösen, d.h. Kommunikation und Jobverteilung zwischen beliebig vielen autonomen Modulen in einem physikalisch verteilten Netz. Ich möchte einen Raspberry Pi Zero für ein Robotics-Project als Steuerung nutzen. Mit seinem WLAN kann er gut kommunizieren, sein Betriebssystem erlaubt mir die Installation von allerlei nützlichen Tools. Um ihn zu entlasten und echtzeitfähiger zu machen, habe ich ihm eine Platine mit einem ATmega als Unterkontroller aufgesteckt. Der ATmega steuert die Motoren und fragt deren Hall-Sensoren ab. PI und ATmega sind per SPI verbunden, weil ich das zur Programmierung des ATmega nutze. Deswegen die Idee, den SPI-Bus gleich zum Datenaustausch zu nutzen - der Datenaustausch ist bisher nicht befriedigend gelöst. Die Lösung würde ich gerne so bauen, dass noch ein zweiter oder vielleicht dritter ATmega als Unterkontroller eingebaut werden kann. Das Duplex-Problem werde ich mit getrennten Schreib/Lese-Puffern lösen und das Protokoll zum Datenaustausch so gestalten, dass Warten möglich ist (Software-Handshaking). Der Master würde also nicht sofort die Antwort erwarten, sondern erstmal eine Reihe von Nullen akzeptieren. In einem SPI-Taktzyklus brauchen dann nur die Puffer gelesen oder beschrieben zu werden. RS232 bzw. der serielle Port wäre auch eine Möglichkeit. Ich könnte damit den ATmega auch programmieren, wenn ich einen Bootlader verwende. Allerdings ist mir hier nicht klar, wie ich einen zweiten ATmega reinbringen könnte. Ganz allgemein habe ich gerade die Befürchtung, dass mir interrupt-gesteuerte Kommunikation die Messung der Hall-Sensoren kaputt machen könnte. Für die Sensoren muss ich 80µs auflösen können, gemessen per Pin-Interrupt. Wenn ich diese Interrupts durch höher priorisierte Kommunikations-Interrupts unterbreche, ist die Messung kaputt. Umgekehrt würde ein hoch priorisierter Mess-Interrupt den Kommunikations-Interrupt stören. Hier wäre ein Kommunikationsverfahren besser, das ich ohne Interrupt in der Loop-Routine machen kann. Könnte ein Argument gegen SPI sein...
Philipp B. schrieb: > warum nimmst du nicht einfach nen W5100? Weil für meinen Anwendungsfall (siehe letzter Beitrag) die Integration dieses Chips die Komplexität des Gesamtaufbaus übersteigen würde. Im allgemeinen Fall wäre das aber in der Tat eine gute Empfehlung. Sorry, falls ich mein Problem nicht präzise genug beschrieben habe.
100Ω W. schrieb: > Warum nimmst du nicht einfach Modbus? Das ändert erst mal wenig. Modbus arbeitet mit virtuellen Registern, die man lesen und schreiben kann. So arbeiten viele SPI Slaves auch. Das ist ohne großen Aufwand realisiert. Löst das Problem des TE aber auch nicht.
Zu den Schwachpunkten der AVRs gehört dessen SPI-Modul. Traditionell hat es zwar einen vom Shift-Register getrennten Receive-Buffer, aber keinen Transmit-Buffer. Antworten an den Master kann der Slave also nur in Pausen zwischen den Byte-Transfers ins Shift-Register schreiben. Der Master muss folglich das worst-case Timing des AVR bei der Reaktion auf SPI-Transfers in sein eigenes Zeitverhalten einrechnen.
:
Bearbeitet durch User
Felix schrieb: > der Datenaustausch ist bisher nicht befriedigend gelöst. Genau das ist das Problem bei Anfängern, sie stellen sich eine zuverlässige Kommunikation popeleinfach vor. Erfahrene Programmierer nehmen mehrere MCs erst dann, wenn es wirklich nicht anders geht. Felix schrieb: > Ganz allgemein habe ich gerade die Befürchtung, dass mir > interrupt-gesteuerte Kommunikation die Messung der Hall-Sensoren kaputt > machen könnte. Diese Befürchtung ist voll berechtigt. Und genau deshalb ist SPI-Slave bei den AVRs ganz großer Mist. Nimm I2C, das streckt automatisch den Takt, solange der Slave nicht bereit ist. Der Slave kann also alle wichtige Echtzeit ohne Rücksicht auf die Kommunikation machen. Der Slave kann auch temporär sein I2C disablen, dann kriegt der Master ein NACK auf die Adresse. Der Master weiß also immer, ob ein Transfer geklappt hat. Ganz im Gegensatz zum SPI. Felix schrieb: > Der Master würde also nicht sofort die > Antwort erwarten, sondern erstmal eine Reihe von Nullen akzeptieren. Der Master liest aber keine Nullbytes, sondern Mumpitz, wenn der Slave nicht schnell genug ist. Der Slave kriegt ein Kollisionsbit, wenn er erst im Transfer das Sendebyte schreibt. Nur kann sich der Master dafür nichts kaufen. Er muß durch höhere Protokolle den Mumpitz erkennen, alles nochmal anfordern und hoffen, daß es diesmal klappt.
Peter D. schrieb: > Der Master liest aber keine Nullbytes, sondern Mumpitz, wenn der Slave > nicht schnell genug ist. SPI ist zur Kommunikation zwischen 2 softwaregesteuerten Modulen ungünstig, weil der Master dem Slave (s)einen externen Takt bzw. Zyklus aufzwingt. Der Slave muss also immer für einen Empfang bereit sein, gleich auch noch passende Sendedaten bereithalten und so seine eigentliche "Echtzeitarbeit" für die Kommunikation unterbrechen. Bei einer simplen Hardwarekomponente wie einem Schieberegister, das jederzeit angesteuert werden kann, ist SPI aber ein toller Bus ohne viel Protokolloverhead: SS# aktivieren und lostakten. Einfacher geht es kaum.
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Der Slave muss also immer für einen Empfang bereit sein, > gleich auch noch passende Sendedaten bereithalten und so seine > eigentliche "Echtzeitarbeit" für die Kommunikation unterbrechen. Das ist DER zentrale Kern überhaupt, den man als Anfänger meist nur schwer nachvollziehen kann. Man denkt, der SPI ist doch bidirektional, jeder Teilnehmer kann lesen und schreiben. Die Synchronisierung der Datenhaltung zwischen den Teilnehmern wird zum Hauptproblem. Ein übergeordnetes Kommunikationsprotokoll kann genau das nicht lösen, da die Anwendungsfälle zu unterschiedlich sind. Ein wirklich schönes Protokoll für eine Multiprozessorarchitektur ist CAN, da muss man sich in der Anwendungsebene schon mal weniger um die eigentliche Kommunikation kümmern. Mittlerweile in vielen CPUs drin und einfach handzuhaben.
Peter D. schrieb: > Nimm I2C, das streckt automatisch den Takt, solange der Slave nicht > bereit ist. Bei den RasPis funktioniert das leider nicht. Bug. Mindestens nicht bei den Versionen 1 und 2. Ob das bei den neuen behoben ist, weiss ich nicht.
:
Bearbeitet durch User
(prx) A. K. schrieb: > Bei den RasPis funktioniert das leider nicht. Der Meinung bin ich auch. Bis zu meinen SPI-Versuchen hatte ich I2C im Einsatz. Es hat leidlich funktioniert, war aber nie absolut stabil. Außerdem kann der ATmega dann nicht selber als Master agieren um I2C-Sensoren einzubinden. Deswegen will ich davon weg.
Felix schrieb: > Oliver S. schrieb: >> ATmega als SPI Slave ist schon mal keine gute Idee. > Warum? Das wird oft in Foren behauptet. Aber einen stichhaltigen Beleg > dafür habe ich noch nicht gefunden. Den AVRs fehlt der DMA. SPI ist eigentlich eine gute Schnittstelle, die hohe Datenraten ermöglicht, wo I²C, CAN usw. lange nicht mitkommen. Das Problem ist eben, wie einige hier schon geschrieben haben, dass die Daten auch im richtigen Moment geliefert werden können müssen. So wie ich das kenne, sendet der Master einen (Lese-) Befehl mit ein paar Byte, darin ist auch die Datenlänge zum Lesen kodiert. Der Master wartet dann eine feste Zeit, bis er die Lesevorgänge startet. In dieser Zeit muss der Slave seinen Interrupt ausführen, den Befehl dekodieren, die Daten im RAM bereitstellen und den DMA darauf konfigurieren. Wenn der Master dann zum Lesen lostaktet, kümmert sich der DMA um den Datennachschub. Die Zeit die der Master wartet zwischen Lesebefehl und Lesevorgang, richtet sich eben danach, wie lange der Slave für die Datenbereitstellung braucht. Also wenn deine Messung einen Interrupt mit höherer Priorität hat (Interrupt-Prioritäten gibts beim AVR auch nicht), spielt die auch in die Wartezeit rein. Eine ADC-Messung anzustoßen sollte aber in ein paar Takten vonstatten gehen und auch die Ergebnisse in einen Puffer wegzuschreiben geht schnell, nur muss man das Anstoßen und Auslesen dann in getrennten Interrupts durchführen und kann nicht im Interrupt blockierend auf das Ergebnis warten. D.h. insgesamt setzt das auf der Slaveseite eine genaue Planung des Aufbaus und der Latenzen voraus. Prinzipiell finde ich es immer gut, sich an anspruchsvollere Themen zu wagen.
Maxe schrieb: > So wie ich das kenne, sendet der Master einen (Lese-) Befehl mit ein > paar Byte, darin ist auch die Datenlänge zum Lesen kodiert. Der Master > wartet dann eine feste Zeit, bis er die Lesevorgänge startet. Genau diese "Warten" ist Murks. Ein gutes SPI-Protokoll sendet jetzt z.B. ein 16-Bit langes Kommando und bekommt gleichzeitig 16 Bit vom vorherigen Kommando als Antwort zurück. Der AD7490 ist ein gutes Beispiel dafür (siehe Screenshot). Dann nutzt man wenigstens ansatzweise die volle Bandbreite des Busses aus.
(prx) A. K. schrieb: > Zu den Schwachpunkten der AVRs gehört dessen SPI-Modul. Traditionell hat > es zwar einen vom Shift-Register getrennten Receive-Buffer, aber keinen > Transmit-Buffer. Antworten an den Master kann der Slave also nur in > Pausen zwischen den Byte-Transfers ins Shift-Register schreiben. Der > Master muss folglich das worst-case Timing des AVR bei der Reaktion auf > SPI-Transfers in sein eigenes Zeitverhalten einrechnen. Habe ich nicht ganz verstanden. Ich schreibe als Slave entweder Nullen zurück (wenn der Puffer leer ist) oder übertrage den Puffer Byte-für-Byte. Das mache ich direkt im Interrupt, schreibe also sofort nach Auslesen von SPDR das Sendebyte in SPDR. Laut Datasheet sollte es auch umgekehrt gehen, dann sollte also nichts mehr schief gehen: The slave may continue to place new data to be sent into SPDR BEFORE reading the incoming data. The last incoming byte will be kept in the buffer register for later use. Ich habe es ausprobiert: Ab einer bestimmten Baudrate (etwa 115200) gibt es den zu erwartenden Bitsalat, darunter läuft es absolut stabil. Auf der physikalischen Ebene habe ich also keine Probleme, außer Zeitkonflikte mit meiner Messung (was natürlich ein ko-Kriterium sein könnte).
Felix schrieb: > Das mache ich direkt im Interrupt, schreibe also sofort > nach Auslesen von SPDR das Sendebyte in SPDR. Und du hast dafür genau so viel Zeit, bis der Master das nächste Taktsignal liefert. Wenn das immer reicht - kein Problem. Sobald du zu spät dran bist, weil ein anderer Interrupt schneller dran war, ist das SPDR blockiert und der Master kriegt sein eigenes Byte retour.
:
Bearbeitet durch User
Felix schrieb: > Habe ich nicht ganz verstanden. Ich schreibe als Slave entweder Nullen > zurück (wenn der Puffer leer ist) oder übertrage den Puffer > Byte-für-Byte. Und woher weiß der Master ob die Nullbytes nun nicht vielleicht Nutzdaten sind? Du brauchst mindestens einen Header vor den Nutzdaten.
Felix schrieb: > Ab einer bestimmten Baudrate (etwa 115200) gibt es den zu erwartenden > Bitsalat Wenn ich SPI höre, dann denke kommen mir Taktraten um und über 2MHz in den Sinn. Der obige AD7490 kann z.B. bis zu 20MHz. Dort ist der SPI zuhause und dort gehört er hin. > darunter läuft es absolut stabil. Das ist sowas wie "immer" und "nie". Solche Begriffe verwende ich nur überaus ungern und wenn ich mir wirklich sicher bin. Weißt du sicher, warum es einen Bitsalat gibt, wenn es mal nicht "absolut stabil" läuft? Denn nur, wenn du das sicher weißt, kannst du wissen, dass es "absolut stabil" laufen wird.
:
Bearbeitet durch Moderator
Felix schrieb: > Das mache ich direkt im Interrupt Genau das ist der Knackpunkt, Du mußt rechtzeitig in den Interrupt kommen und den Prolog abgearbeitet haben. Es dürften also keine weiteren Interrupts enabled sein, bzw. es muß genug Zeit vom Master gewartet werden, um diese abzuarbeiten. Felix schrieb: > Ich habe es ausprobiert: Ja aber nur, wenn Deine Applikation sonst nichts weiter zu tun hat. Z.B. wenn man den SCK auf 1kHz runter setzt, dann hat der Slave ein Zeitfenster von 500µs, um andere Interrupts zu beenden und das SPI-Register zu füllen.
Felix schrieb: > (prx) A. K. schrieb: >> Bei den RasPis funktioniert das leider nicht. > > Der Meinung bin ich auch. http://www.advamation.de/technik/raspberrypi/rpi-i2c-bug.html
Eine Sammelantwort > Du brauchst mindestens einen Header vor den Nutzdaten. Das ist eingeplant. Nutzdaten werden eine Transaktionsnummer bekommen (um die Antwort zuordnen zu können), Längenangabe und mit einer Checksum enden. > Weißt du sicher, warum es einen Bitsalat gibt, wenn es mal nicht "absolut stabil" läuft? Nicht wirklich genau. Wenn das mit der Checksum fertig ist, kann ich einen Massentest machen. Bisher kann ich es nur auf Basis von wenigen hundert Byte und ohne weitere Interrupts sagen. Werde es aber auch nochmal mit dem Oszilloskop ansehen, z.B. einen Ausgabepin im Interrupt toggeln und mit SCLK vergleichen. Bzw. mal überschlagen, wie lang der Code der Interrupt-Routine dauert. >Wenn ich SPI höre, dann denke kommen mir Taktraten um und über 2MHz in den Sinn Mein ATmega läuft mit 8MHz (wegen 3.3V Spannung). Aber der Unterschied ist in der Tat groß. Da habe ich noch keine Erklärung... Clock-Divider sollten nicht gesetzt sein. > wenn man den SCK auf 1kHz runter setzt, dann hat der Slave ein Zeitfenster von 500µs, Damit muss ich noch experimentieren, mit dem Zusammenspiel Messung und Kommunikation habe ich noch keine Erfahrung. Was ich mich dazu frage: Welches Kommunikationsverfahren würde mir denn bei diesem Problem helfen? I2C und USART sind vielleicht nicht so Ressourcen-intensiv, aber da kommen ja auch Interrupts, nur nicht so oft. Ob mir so ein Interrupt ständig in die Messung reingrätscht oder nur manchmal, ist dann auch fast egal. Ideal wäre ein Kommunikationsverfahren, das ganz ohne Interrupts auskommt (da ich sie wohl beim ATmega nicht priorisieren kann).
Lothar M. schrieb: > Maxe schrieb: >> So wie ich das kenne, sendet der Master einen (Lese-) Befehl mit ein >> paar Byte, darin ist auch die Datenlänge zum Lesen kodiert. Der Master >> wartet dann eine feste Zeit, bis er die Lesevorgänge startet. > Genau diese "Warten" ist Murks. > > Ein gutes SPI-Protokoll sendet jetzt z.B. ein 16-Bit langes Kommando > und bekommt gleichzeitig 16 Bit vom vorherigen Kommando als Antwort > zurück. Der AD7490 ist ein gutes Beispiel dafür (siehe Screenshot). In Hardware, ja. Aber bei einem Mikrocontroller als Slave bleibt das Problem das gleiche, also dass dieser bis zum nächsten Befehl die Daten vorbereiten muss. Das gilt aber letztlich für jede Schnittstelle, der Teilnehmer muss ja erst wissen, was die Gegenstelle von ihm verlangt, bevor er antworten kann. Der einzige Unterschied beim SPI ist, dass das Timing vom Master vorgegeben wird. > Dann nutzt man wenigstens ansatzweise die volle Bandbreite des Busses aus. Da gehts doch gar nicht drum? Ein Raspi soll mittels angestöpseltem Mikrocontroller echtzeitfähig gemacht werden, ich denke SPI bietet sich da durchaus an. UART wäre einfacher, ist aber langsamer.
Nachtrag: Und gerade bei mehreren Slaves kann der Master die Wartezeit bis die Antwort bereit ist, sinnvoll nutzen: Er schickt allen Slaves der Reihe nach den Befehl und holt anschließend jeweils die Daten der Reihe nach ab.
Es könnte sinnvoll sein, die vom Master alle an einen Slave gesendeten Bytes stets von denen unterscheiden zu können, die vom Slave zurück kommen können. Dadurch wird erkennbar, dass ein Master sein eigenes Geschwätz retourniert bekommt, statt der gewünschten Antwort.
:
Bearbeitet durch User
Man muss eine grundsätzliche Registerarchitektur durchziehen. D.h. die Applikation kann jederzeit (das muss entsprechend gesynct oder gelockt werden), Daten in beliebige "Register" schreiben und daraus lesen. Ein SPI Handler reagiert auf Anfragen des Masters und liest und schreibt diese Register die anhand einer Adresse spezifiziert werden. Damit kann der SPI Interrupt schnell genug sein, und er arbeitet immer gleich und kümmert sich nicht um Zustände der Applikation. Auch muss er die Daten nicht erst beschaffen oder berechnen. Für den Fall dass ein Register gerade gelockt ist, muss ein Fehler übermittelt werden und der Master kann es nochmal versuchen.
Maxe schrieb: > Er schickt allen Slaves der Reihe nach den Befehl und holt anschließend > jeweils die Daten der Reihe nach ab. Genau das "erst Schreiben und später Lesen" ist ja das Unsinnige, denn dadurch ist der Bus bestenfalls zur Hälfte "ausgelastet", weil der Bus immer nur Hablduplex verwendet wird, denn es ist zu jedem Zeitpunkt der Übertraung eine der beiden Leitungen unnötig, weil sie zu diesem Augenblick keine brauchbare Information überträgt. Der eigentliche Witz am SPI ist das gleichzeitige Schreiben und Lesen: mit jeder Taktflanke wird zugleich 1 Bit gesendet und 1 Bit empfangen. Wenn man das nicht braucht oder keinen Vorteil daraus gewinnen kann, dann nimmt man besser einen anderen Bus.
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Der eigentliche Witz am SPI ist das gleichzeitige Schreiben und Lesen. > Wenn man das nicht braucht oder keinen Vorteil daraus gewinnen kann, > dann nimmt man besser einen anderen Bus. Richtig. In diesem Fall würde sich I2C eher anbieten. Dann hat man auch gleich Adressierung und spart sich Leitungen. Das Registerkonzept kann man hingegen genau gleich implementieren.
:
Bearbeitet durch User
>Ein Raspi soll mittels angestöpseltem >Mikrocontroller echtzeitfähig gemacht werden Dann solltest Du auch die übliche Vorgehensweise (TM, James Bond) nutzen: Der PI koordiniert, verteilt Aufgaben und wartet die Ergebnisse ab. Die µC machen die ganze Echtzeitarbeit. Somit ist das erste Kriterium, nichts zeitkritisches über die Kommunikation laufen zu lassen. Wenn Du zb eine Regelung brauchst, ist die komplett im Slave (µC) gelöst. Der Pi schickt nur den Sollwert hin. Und das nicht zyklisch, sondern wenn nötig. Abfragen macht er, wenn er etwas wissen will. Die Antwort erfolgt dann "zeitnah". Das dasrf im Pi keinierlei Probleme auslösen. Sollte es auch nicht, denn es wird ja nichts zeitkritisches gemacht. (also zb Istwerte nur angezeigt und Sollwerte verstellt) Für diese Art Kommunikation würde ich wegen bereits erklärter Nachteile weder SPI noch I2C ansetzen. Mein erster Gedacnke wäre seriell: RS232 oder RS422/485 je nach Länge der Kabel und nötiger/gewünschter Datenrate. Das Protokoll wäre so designed, das die Datenmenge pro Übertragung (natürlich immer nur zu einem Slave) variable Längen hat. Das Protokoll könnte etwa so aussehen: Byte0: Adresse_des_Partners Byte1: eigene_Adresse (nötig für evtl. Antwort) Byte2: Länge der dann folgenden Nutzdaten Byte3..N: Nutzdaten ByteN+1: Prüfsumme (Nutzdatenlänge Null wäre somit denkbar, dann würden vier Bytes übertragen) Die Zieladresse als erstes erlaubt Dir (bei den AVRs) den MultiProcessorCommunicationMode zu nutzen. Da wird schon etwas per Hardware wegefiltert und Deine Empfangsrouting muss nur die Adresse prüfen und die Bytes, die wirklich für einen selbst sind. (alle anderen werden durch die Hardware verworfen). Dann kann per state machine ( also nebenbei neben dem Echtzeitteil) in aller Ruhe die Meldung ausgewertet, die ANtwort zusammengebaut und dem Sendepuffer übergeben werden. Das ist ein vernünftiger Ansatz. Aber unterschhätze den nicht.
Matthias L. schrieb: So langsam leckt das Forum Blut :-) > Der PI koordiniert, verteilt Aufgaben und wartet die Ergebnisse ab. Die > µC machen die ganze Echtzeitarbeit. Genauso ist das geplant, d.h. Notaus/Reset, Drehen, Geradeausfahrt mit Stoppbedingung, Positionsabfrage und Echolot wären Funktionsaufrufe. Damit würde der Raspberry die übergeordnete Regelung vorgehen mit Fernziel Kartenerstellung und -auswertung. Der ATmega macht Motorregelung, Hallsensorauswertung und Abfrage Infrarotsensoren autonom inklusive eventuellem Notstopp. Kommunikation ist also Prio2 gegen Messung und Steuerung. > Für diese Art Kommunikation würde ich wegen bereits erklärter Nachteile > weder SPI noch I2C ansetzen. Mein erster Gedacnke wäre seriell: RS232 > oder RS422/485 je nach Länge der Kabel und nötiger/gewünschter > Datenrate. SPI-Nachteile wurden genannt. Die Kabellänge beträgt aktuell 5 cm, das ist keine Problemquelle. Aus meiner Sicht ungelöste Probleme bei USART: Einbinden eines weiteren ATmegas und die Tatsache, dass auch USART Interrupts auslöst. Die Messung wird potentiell also auch gestört, nur seltener. > Das Protokoll könnte etwa so aussehen: Geplant ist für Funktionsaufruf durch Master: Transaktions-ID (für Zuordnung Rückruf), Registeradresse (jede aufrufbare Funktion wird virtuell gegen ein Register gebunden beim Setup), Datenlänge, Payload, Checksum. Das ist recht statisch, die ISV-Routine kann also das Ende der Nachricht leicht erkennen. Das eigentliche Parsen und Aufrufen wird dann aus dem Puffer in der loop gemacht. Nach Beendigung sendet der Slave ein kurzes Acknowledge mit Transaktions-ID und Antwort-Payload im Erfolgsfall, bei Checksum-Fehler die Bitte um Wiederholung. Das ganze ginge auch in Rückrichtung, d.h. Call durch den Slave, einfach in den gerade laufenden Traffic hinein (Konsequenz: Master muss alle paar Mikrosekunden pollen). Hier würde ich eine Device-ID vorsehen. Unsicher bin ich beim Senden der eigenen Device-ID. Muss ein Empfänger wissen, von wem die Nachricht kommt? Potentiell wohl schon... Ja, das wird wohl ein großes Projekt. Aber dank Corona sind die Abend frei...
Felix schrieb: > Es hat leidlich funktioniert, war aber nie absolut stabil. > Außerdem kann der ATmega dann nicht selber als Master agieren um > I2C-Sensoren einzubinden. Deswegen will ich davon weg. I2C ist per se vollständig multimasterfähig. Nur ist die Implementierung im AVR dazu leider nicht fehlerfrei. Mit nur einem Master funktioniert das aber auch beim AVR stabil, wenn man es richtig macht, Oliver
>Die Kabellänge beträgt aktuell 5 cm mal von den WOrt "aktuelL" abgesehen: Spielt keine Rolle. SPI oder I2C finde ich für Dein Problem weniger geeignet. >Einbinden eines weiteren >ATmegas und die Tatsache, dass auch USART Interrupts auslöst. Die >Messung wird potentiell also auch gestört, nur seltener. Die Priorität muss auf der Echtzeitaufgabe liegen. Somit würde diese nur für den Empfang der (für ihn bestimmten) Bytes unterbrochen. Und hier gibt es eine zulässige Reaktionszeit von einem Byte ggü einem Bit bei SPI. Denn das empfangene Byte muss nur aus dem UDR raus, bis das nächste fertig empfangen wurde. Weitere Aktionen sind im Interrupt nicht nötig. >Transaktions-ID (für Zuordnung Rückruf), Registeradresse ... Das wären bereits Nutzdaten nach meinem Beispiel. >die ISV-Routine kann also das Ende der Nachricht leicht erkennen Würde ich nicht machen. Das sollte rein durch die ANzahl der empfangenen Zeichen (deshalb wird die Länge weit vorn mitgeteilt) und einem Timeout geschehen. Das ist universeller wenn Du später Erweiterungen an einer Stelle machst. So brauchen die anderen nicht angefasst zu werden. >Das eigentliche Parsen und Aufrufen wird dann aus dem Puffer in der loop >gemacht.Nach Beendigung sendet der Slave ein kurzes Acknowledge mit >Transaktions-ID und Antwort-Payload im Erfolgsfall, Richtig, weniger Prio als die Echtzeit. >bei Checksum-Fehler die Bitte um Wiederholung. .. oder anderen Fehlern einfach ein ErrorCOde verschieden GOOD zurücksenden (*) >Das ganze ginge auch in Rückrichtung, Klar. Ein Slave kann auch von allein einen Transmit anstossen (der Sendetreiber muss natürlich warten bis der Bus frei ist). > d.h. Call durch den Slave, einfach in den gerade laufenden Traffic hinein Hä? siehe "muss auf Bus frei warten" >(Konsequenz: Master muss alle paar Mikrosekunden pollen). Er muss sowieso empfangsbereit sein, denn er will ja hören. Alle µs? Kenne den Pi nicht, aber ich würde ich einen UART-Rx-Interrupt erwarten. >Hier würde ich eine Device-ID vorsehen. Unsicher bin ich beim Senden der >eigenen Device-ID. Muss ein Empfänger wissen, von wem die Nachricht kommt? >Potentiell wohl schon... Das ist die von mir genannte eigenen Adresse, die als zweites übertragen wird. DIese wird als Zieladresse bei der ANtwort eingesetzt. (*) Somit würde ich das so machen: Byte0: Adresse_des_Partners Byte1: eigene_Adresse (nötig für evtl. Antwort) Byte2: ErrorCode Byte3: Länge der dann folgenden Nutzdaten Byte4..N: Nutzdaten ByteN+1: Prüfsumme Ist ein Empfang fehlerhaft, erfolgt eine negative Antwort: [0-Destination] ... [1-Source] ich selbst [2-ErrorCode] Wert (verschieden Null), der den Fehlergrund angibt [3- Länge Nutzdaten] NULL Diese/Solche vier Bytes wären somit das kleinste zulässige Telegram.
Felix schrieb: > Tut mir leid, bin noch relativer Einsteiger beim ATmega Ja, das ist genau das Problem. Du hast einfach die falsche Hardware ausgesucht. Schau mal wie die Profis es machen. Z.B. in der Automobilindustrie. Oder bei Baumaschinen. Oder in der Industrieautomation. Überall wird für so etwas CAN eingesetzt, und zwar aus gutem Grund: - CAN ist relativ fix - bis 1MBit, bei CAN-FD noch deutlich mehr. - CAN ist deterministisch - heißt also man kann vorher wissen, wie sich ein System verhält - CAN macht sehr viel in Hardware, was Du anderswo in Software machen musst. Beispielsweise Warten bis der Bus frei ist. Prüfsummen erzeugen und vergleichen. Pakete bestätigen. Usw usw. Alles ohne Prozessoraufwand. - CAN funktioniert. Das Zeugs ist seit 1990 millionenfach verbaut worden. Willst DU Dir anmaßen, klüger als die Profis zu sein? Also: Als Master schlage ich einen Beaglebone vor. Der hat zwei CAN-Controller integriert. Ja, es gibt auch welche, die man am SPI anschließen kann. Die chipinternen haben aber viel weniger Overhead und kommen mit hoher Buslast besser zurecht. Als Slaves nimmst Du z.B. Teensy 3.2. Die haben erstens einen viel leistungsfähigen Controller, CAN in Hardware eingebaut, und können trotzem per Arduino-IDE programmiert werden, wenn Du meinst, das unbedingt zu brauchen. Und trotzdem kann der noch 5V-Signale ab. Du brauchst jeweils noch Transceiver. Das sind kleine 8-Pinner, die den Analogteil einer CAN-Schnittstelle darstellen. Je nachdem, wie schnell und wie lang Dein CAN-Bus sein soll, gibts verschiedene Transceiver. Wenn Du 3.3V UND 5V zur Verfügung hast, ist der MCP2562 eine gute Wahl. Für ein reines 3.3V-System wäre z.B. der TCAN332 eine gute Wahl. Für CAN gibts einen Haufen Literatur. Für CAN gibts dann verschiedene High-Level-Protokolle wie CAN-Open, Devicenet, J1939 usw. Das sollte Deine Corona-Zeit durchaus füllen. fchk
> Zu den Schwachpunkten der AVRs gehört dessen SPI-Modul. Traditionell hat > es zwar einen vom Shift-Register getrennten Receive-Buffer, aber keinen > Transmit-Buffer. Dürfte sich rumgesprochen haben, dass dieses Problem bei neueren gelöst ist. Mehrere INT-Prio, DMA (FIFOs) fehlen dem AVR dennoch.
MCUA schrieb: >> Zu den Schwachpunkten der AVRs gehört dessen SPI-Modul. Traditionell hat >> es zwar einen vom Shift-Register getrennten Receive-Buffer, aber keinen >> Transmit-Buffer. > Dürfte sich rumgesprochen haben, dass dieses Problem bei neueren gelöst > ist. Deshalb schrieb ich "traditionell".
MCUA schrieb: > Mehrere INT-Prio, DMA (FIFOs) fehlen dem AVR dennoch. Nö, die AVR128/64/32Dyy haben immerhin zwei echte Interrupt-Prioritäten, das dürfte für die allermeisten Anwendungen völlig ausreichend sein (mir hat i.A. eigentlich sogar die klassische eine praktisch immer gereicht). DMA haben sie aber tatsächlich nicht.
> Nö, die AVR128/64/32Dyy haben immerhin zwei echte Interrupt-Prioritäten,
Ja, man muss ws. nochmal 20 Jahre warten, bis welche dazu kommen.
Mit 2 Prio kann man nicht viel machen.
Lothar M. schrieb: > Der obige AD7490 kann z.B. bis zu 20MHz. Dort ist der SPI zuhause und > dort gehört er hin. Da wird er übrigens auch schnell mal problematisch, wenn man ihn denn wirklich als Bus aufsetzen will. Ich habe da schon mal unter die hochgebogenen Pins eines 144pinnigen Cortex-M7 noch 0201-Serienterminierungs-Widerstände eingelötet, weil der erste Entwurf das Thema ignoriert hatte. Allerdings war das SPI auf dem Board eben nicht mehr klassisch Punkt-zu-Punkt, sondern es hingen mehrere Devices dran, bis hin zum Controller, der selbst (mit zwei verschiedenen SPIs) beide Seiten bedient hat.
MCUA schrieb: > Mit 2 Prio kann man nicht viel machen. Also ich konnte mit der klassischen einen eigentlich schon so ziemlich alles machen, was unterkam und nicht von vorherein zu "groß" für einen AVR8 aussah...
Jörg W. schrieb: > Lothar M. schrieb: >> Der obige AD7490 kann z.B. bis zu 20MHz. Dort ist der SPI zuhause und >> dort gehört er hin. > Da wird er übrigens auch schnell mal problematisch, wenn man ihn denn > wirklich als Bus aufsetzen will. Ja, da ist es hilfreich, wenn man bedenkt, dass da dann doch so langsam HF anfängt. Und auch, welchen Zinnober um einzelne mm bei PCI mit seinen gerade mal 33MHz gemacht wurde. > Ich habe da schon mal unter die hochgebogenen Pins eines 144pinnigen > Cortex-M7 noch 0201-Serienterminierungs-Widerstände eingelötet Schön, dass es sowas gibt, nicht wahr? Und sooo arg viele Beine sind es ja nicht... ;-)
Lothar M. schrieb: > Und sooo arg viele Beine sind es ja nicht... ;-) Zum Glück nur zwei: SCLK und MOSI. ;-) Aber man biegt diese Pins natürlich keine 32mal … Gab ganz witzige Effekte: der Bus ist noch auf ein paar Mini-Stecker von JST rausgeführt, damit man zum Debuggen einen Logic Analyzer dran hängen kann. Mit LA funktionierte das System besser als ohne. :o Am Ende landete am SCLK-Anschluss des Debug-Steckers noch ein kleiner Snubber.
Jörg W. schrieb: > Ich habe da schon mal unter die hochgebogenen Pins eines 144pinnigen > Cortex-M7 noch 0201-Serienterminierungs-Widerstände eingelötet Ich hab da auch schon schlechte Erfahrungen mit der Störempfindlichkeit von SPI machen müssen. Bei I2C wird die slew-Rate begrenzt und die Eingänge gefiltert. Und bei der UART erfolgt eine Dreifachabtastung mit Majoritätslogik. Dadurch sind beide deutlich störsicherer als SPI.
Peter D. schrieb: > Bei I2C wird die slew-Rate begrenzt und die Eingänge gefiltert. Schon dadurch, dass der Anstieg nur durch Pull-Ups erfolgt … aber wenn man schneller werden will als nur 100 oder 400 kHz, ist das eben nicht mehr ganz so einfach mit dem Begrenzen der slew rate. Ansonsten volle Zustimmung zu den Statements weiter oben: SPI mit einem Controller als Slave ist alles andere als optimal. SPI funktioniert gut, wenn ich hintendran ein Schieberegister habe oder andere Hardware, die mir einen Takt später auf der Rückleitung die Antwort liefern kann. Eine CPU braucht notgedrungen ein paar Takte, bis sie eine solche Antwort bereitstellen kann.
Klopp CAN in die Tonne. Der ist gut fur Autos, die maximlae Packetlaenge ist 6 Bytes oder so.
SPI auf seinen 5 cm Laenge zu stoeren halte ich fuer sehr schwierig, ausser mit EMV. Die Idee mit mehreren CPUs auf einem Board ist Muell. Das wird so nie was. Falls man Hardware funktionaittaet auslagern moechte, dann in ein FPGA.
Matthias L. schrieb: >> d.h. Call durch den Slave, einfach in den gerade laufenden Traffic hinein > > Hä? siehe "muss auf Bus frei warten" War zu kurz geschrieben. Ich meinte die Situation, in der ein Slave dran ist und mangels Daten im Puffer nur Nullen sendet. In diesem Moment könnte er von sich aus einen Call initiieren und in den Datenstrom aus Nullen einschieben. >>(Konsequenz: Master muss alle paar Mikrosekunden pollen). >Alle µs? Nein, das war unüberlegt. Wenn keine Antwort aussteht, würde Pollen durch den Master vielleicht alle 50-100 Millisekunden reichen
Frank K. schrieb: > Ja, das ist genau das Problem. Du hast einfach die falsche Hardware > ausgesucht. > > Schau mal wie die Profis es machen Technisch ein sehr guter Rat und die Aufstellung der CAN-Hardware finde ich hilfreich, danke dafür. Die Frage ist nur, wie setze ich Deinen Tipp um? Ich schreibe das mal ausführlich, weil das für sehr viele Profi-Tipps an Amateure gilt. Ich betreibe das als Hobby ohne das Ziel einer Vermarktung. Dabei stehe ich aktuell vor folgenden Herausforderungen: - Lernen über Mikrocontroller, serielle Busse und Elektronik - Hardware-Design des Roboters - Software-Design des Roboters wie Fahrprogramme, Karten etc. - Design eines höheren Kommunikationsprotokolls zwischen ATmega und Raspberry Das kann ich mit meiner aktuellen Hardware erstmal sinnvoll weiterführen. Wahrscheinlich ist SPI ungeeignet, dann kann ich auf USART umsteigen, wird mich nur einen Abend kosten. Dabei würde ich dann auch mal mit dem MCP2562 experimentieren, ist mit knapp 90 Cent ja keine Investition. Natürlich werde ich den Karren trotzdem an die Wand fahren, wahrscheinlich in dem Moment, wo ich einen zweiten ATmega einsetzen will. Oder eine höhere Geschwindigkeit brauche. Dann bin ich mit meinen 4 Punkte oben weiter und würde auf den Beagle-Bone (oder Alternativen) mit CAN-Bus-Unterstützung zurückkommen. Alles, was ich bis dahin gelernt und gebaut habe, kann ich weiternutzen, es ist also kein "Waste". Die 12 Euro für den Raspberry Zero und die 2,50 Euro für den ATmega haben sich dann bezahlt gemacht. Ein direktes Umsetzen Deines Tipps heute würde mich das zehnfache vom aktuellen Setup kosten, ich könnte die große Community rund um Arduino und Raspberry nicht mehr nutzen und ich stände wieder ganz am Anfang mit einer mir unbekannten Hardware. Umsetzen werde ich Deinen Tipp also erstmal nicht in Richtung Hardwarekauf, sondern in Richtung Verständnis einer sinnvollen Zielarchitektur. Das gleiche gilt für Pandurs Tipp von eben mit FPGAs. Sicher auch sinnvoll, nur wenn ich all diesen Tipps (hinter denen verschiedene Engineering-Schulen stehen) direkt nachgehe, dann drehe ich mich im Kreis und komme nirgendwo an.
> Bei I2C wird die slew-Rate begrenzt und die Eingänge gefiltert.
I2C zählt nicht, ist schnarchlangsam.
Auch UART (grade bei den meisten uCs) ist sehr langsam.
MCUA schrieb: > I2C zählt nicht, ist schnarchlangsam. Der ist mit seinen "üblichen" 400kHz immer noch schneller, als das, was derzeit auf dem SPI von Felix läuft, denn Felix schrieb: > Ich habe es ausprobiert: Ab einer bestimmten Baudrate (etwa 115200) gibt > es den zu erwartenden Bitsalat, darunter läuft es absolut stabil. MCUA schrieb: > I2C zählt nicht, ist schnarchlangsam. Siehe auch https://www.i2c-bus.org/fastmode/ MCUA schrieb: > Auch UART (grade bei den meisten uCs) ist sehr langsam. Grade bei uCs ist der UART nicht mal soo arg langsam. Man darf dann eben nicht die aus der Telegrafensteinzeit stammenden "Standard-Baudraten" verwenden, sondern solche, die der µC gut kann. Und dann waren z.B. schon mit den alten 8051 bei DMX512 lockere 250kBit/s drin.
:
Bearbeitet durch Moderator
> I2C zählt nicht, ist schnarchlangsam.
Wenn man einer Schnecke einen "Fast"-Modus verpasst wird es auch nicht
viel schneller.
Das I2C-Protokoll lässt prinz. keine hohen Raten zu.
> Auch UART (grade bei den meisten uCs) ist sehr langsam.
UART kann (prinz.) bis einige Gbps gehen, nur eben bei fast jedem uC
nicht.
MCUA schrieb: > UART kann (prinz.) bis einige Gbps gehen, nur eben bei fast jedem uC > nicht. Naja, 1 MBaud sind bei Controllern meist noch problemlos möglich, mit einem FTDI geht das sogar noch über UART in Richtung PC. Bei Controllern kann man außerdem meist noch einen "synchronen" Modus fahren. Da bleibt zwar immer noch das blöde UART-Framing (anders als bspw. die Z80-SIO das vor Jahrzehnten konnte), aber man braucht das 16fache oversampling der normalen UART nicht mehr.
Bevor man die Bardraten hochreibt sollte man sich vergewaertigen dass man auf der anderen Seite Intrrupts erzeugt. Das ist ja gut, wenn der auch Zeit hat. Und eher nicht, wenn nicht. zB ist ein SPI Interrupt bei hoher Taktrate sinnlos. Ein Byte rauszuschieben datert 8 clocks oder so. Ein Interrupt macht mal ein Push von allen Registern, und nachher nochmals ein Pop von allen Registern. Bei 16 Registern waeren das dann schon 32 clocks, bedeutet mehr als Clock -Viertel ist nichts fuer den SPI in diesem Betrieb. Ein 8 facher NOP waere passender. Ohne Interrupts.
:
Bearbeitet durch User
Pandur S. schrieb: > Ein 8 facher NOP waere passender. Stattdessen das ready-Flag zu testen, ist noch sinnvoller.
Pandur S. schrieb: > wenn nicht. zB ist ein SPI Interrupt bei > hoher Taktrate sinnlos. Ein Byte rauszuschieben datert 8 clocks oder so. > Ein Interrupt macht mal ein Push von allen Registern, und nachher > nochmals ein Pop von allen Registern. Bei 16 Registern waeren das dann > schon 32 clocks, bedeutet mehr als Clock -Viertel ist nichts fuer den > SPI in diesem Betrieb. Ein 8 facher NOP waere passender. Ohne > Interrupts. Nur der Neugier halber, denn mir würden für meinen Fall auch 9600 Baud reichen: Welche sinnvolle Anwendung kann man damit bauen? Das bedeutet ja, dass pausenlos ein Loop läuft, der entweder von sich aus genau taktet oder halt das Ready-Flag liest. Dann bleibt gerade noch Zeit ein paar IO-Pins zu lesen oder zu setzen und das wars. Vielleicht geeignet als Konverter, serial nach parallel. DA-Wandler gibt es nicht auf dem ATmega. Was bleibt als Einsatzmöglichkeit?
Felix schrieb: > Welche sinnvolle Anwendung kann man damit bauen? Allerlei Peripherie, die man schnell "befüllen" will: Funk-Transceiver, Frequenzwort für DDS-ICs, Flash-Speicher, … you name it. Man kann auch simple 74HC595 dranhängen und mit einem langen Schieberegister sackweise parallele IO-Pins (bspw. für eine LED-Matrix) ansteuern.
Pandur S. schrieb: > Klopp CAN in die Tonne. Der ist gut fur Autos, die maximlae Packetlaenge > ist 6 Bytes oder so. 8 Bytes, plus 29-Bit ID. Und? Ich habe darüber u.A. ein Eventlog von zig KB Länge ausgelesen. Man braucht dafür etwas Protokoll obendrauf, spart sich aber untenrum viel Arbeit.
MCUA schrieb: > I2C zählt nicht, ist schnarchlangsam. Kommt auf die Ansprüche an. Schneller als schnell genug bringt nichts.
Felix schrieb: > Ein direktes Umsetzen Deines Tipps heute würde mich das zehnfache vom > aktuellen Setup kosten, ich könnte die große Community rund um Arduino > und Raspberry nicht mehr nutzen und ich stände wieder ganz am Anfang mit > einer mir unbekannten Hardware. Der Pi ist eine Linux-Maschine. Das, was Du da siehst, ist das Linux. Das ist in Prinzip das gleiche Linux wie auf einem PC. PC-Linux-Software kannst Du zu großen Teilen einfach neu compilieren, und sie laufen auf Deinem Pi. Der Beaglebone ist auch eine Linux-Maschine. Der hat sogar die gleiche Architektur (armhf). Du kannst die meisten Programme vom Beaglebone einfach so auf dem Pi laufen lassen, und umgekehrt. Es sei denn, sie nutzen den Closed-Source Binärcode von der Pi Foundation - dann hängen sie in der Fliegenfalle. Gleiches gilt für die Coprozessoren beim Beaglebone. Das Linux selber kümmert sich um den Großteil der Hardwareunterschiede. Der Rest sind Details (wie baue ich mir eine SD-Karte? Wie konfiguriere ich die GPIO-Pins?) Daher ist zu Deinem Argument zu sagen: "sachlich falsch". Lerne Linux (auf welcher Plattform auch immer), nicht Raspberry. Und der Teensy wird auch mit der Arduino-IDE programmiert. Da kümmert sich das Arduino-System um die Unterschiede. Es gibt sogar von Arduino selber Boards mit ARM-Prozessor. fchk
>> Ein 8 facher NOP waere passender. > Stattdessen das ready-Flag zu testen, ist noch sinnvoller. Da sieht man wie schlecht es um den AVR steht, wenn NOPs schon besser sind! An eine Schnitte gehören ein paar FIFOs (und weiter DMA), da brauchts keinen INT alle 8 Bits.
MCUA schrieb: > Da sieht man wie schlecht es um den AVR steht, wenn NOPs schon besser > sind! Quark. NOPs sind _nicht_ besser, höchstens fauler (für den Programmierer). Macht kein Mensch so. > An eine Schnitte gehören ein paar FIFOs (und weiter DMA), da brauchts > keinen INT alle 8 Bits. Das hilft bei SPI in aller Regel rein gar nicht. Je nach Gerät hast du noch irgendwelchen Firlefanz drumrum zu machen (bspw. festzulegen, während welcher Perioden das Select-Signal gezogen und wann wieder losgelassen werden muss), dass das mit üblichen DMA-Logiken nicht handhabbar ist. BTDT (nicht AVR, sondern verschiedene ARMs, auch deren "intelligentes" Select-Signal brachte es nicht). DMA ist gut für Dinge, wo man in regelmäßigen Abständen oder langen Blöcken viele ansonsten gleichartig gelagerte Daten bearbeiten muss.
:
Bearbeitet durch Moderator
> Das hilft bei SPI in aller Regel rein gar nicht.
Quark. Was heisst hier in aller Regel?
Die Tiefe der FIFOs (wenn man welche hat) kann man steuern.
Bei 16 Bytes Tiefe ist es ein INT (oder DMA-Req.) nicht alle 1 Byte
sondern alle 16 Bytes. Macht Faktor 16, den die CPU mehr Zeit (zu
rechnen) hat, bis sie wieder unterbrochen wird.
Hat man weniger Bytes kann man (muss man aber nicht) auch weniger
einstellen (dann wird die INT-Rate nat. umso grösser).
MCUA schrieb: > Bei 16 Bytes Tiefe ist es ein INT (oder DMA-Req.) nicht alle 1 Byte > sondern alle 16 Bytes. Wenn ich aller 8 µs 4 Bytes vom Gerät abholen muss (also vier Nullbytes senden) und dabei vorher ein passendes Kommando (3 Bytes) hinsenden (nicht zu vergessen, das Select-Handling um all diese Bytes herum), dann hilft mir der FIFO was? Ein FIFO hilft nur bei einem längeren Datenstrom wirklich. SPI-Geräte sind viel zu verschieden für solch pauschale Aussagen.
Der FIFO kann ja auch senden, nicht nur empfangen. Der kann also mal 16 Bytes rausbuttern, das auch lesen. (\CS muss auch nicht nach jedem Byte geschaltet werden) Das Schema funkt. genauso auch bei anderen Schnittstellen (sofern die auf Bitebene schnell genug sind)
MCUA schrieb: > \CS muss auch nicht nach jedem Byte geschaltet werden Nicht nach jedem, aber vor jedem Block eingeschaltet und nach dem Block ausgeschaltet. Die meisten Peripherals brauchen das als Synchronisation. Da aber das CS-Handling halt nicht durch das normale SPI-Datenregister erfolgt, passt das alles nicht so recht in ein DMA-Schema. Klar, wenn man nur einmal ein Kommando senden muss und dann /CS aktiv bleiben darf, um hin und wieder da mal was abzuholen, dann passt das. Lohnt aber eigentlich nur, wenn die periphere Daten(bereitstellungs)rate das limitierende ist. Wenn es die Bustaktrate ist (weil das Gerät seinen Blurb an Daten sowieso rumliegen hat), dann kann die CPU auch gleich solange warten. Nur, wenn die CPU-Geschwindigkeit sehr viel höher als die SPI-Rate ist, würde sich dort FIFO oder DMA lohnen, sofern die CPU mit den übrigen Zyklen auch wirklich was anderes tun kann. (Wenn sie nur auf das "DMA ready"-Bit warten muss, kann sie auch gleich selbst pollen.)
Das "CS-Handling" ist aber nicht der Rede wert, wenn es nur 1x je Block ein-aus-geschaltet wird. Die Hardware kann das machen, das kostet keine CPU-Zeit. Und wenn die CPU "gleich solange warten" soll, stimmt sowiso schon was nicht. Das ist vertrödelte (blockierende) Zeit (egal ob mit NOPs oder irgent welche Abfragen). Die Grenze ist sozusagen die CPU-INT-Leistung. CPU schafft nur eine bestimmte Anzahl ISRs/s. (es fallen ja min schon min. ca 5..8 CPU-Clks an, nur bis der INT überhaupt mal angenommen wird (von ContextSwich ganz zu schweigen). Solange man (rel. weit) unter dieser CPU-INT-Belastung ist, geht das.
MCUA schrieb: > Das "CS-Handling" ist aber nicht der Rede wert, wenn es nur 1x je Block > ein-aus-geschaltet wird. Sag ich ja: lohnt sich bestenfalls nur bei langen Blöcken. > Die Hardware kann das machen, das kostet keine CPU-Zeit. Dir sind scheinbare noch nicht genügend verschiedene SPI-Geräte über den Weg gelaufen. Wie ich oben schrieb: die Hardware hat schlicht keine Ahnung, an welchen Stellen sie /CS ziehen und an welchen wieder loslassen muss, wenn man da erst irgendwelche Kommandos runterschreiben muss (die nicht nur aus einem Byte bestehen). Dann kann das nur die Software machen. > Und wenn die CPU "gleich solange warten" soll, stimmt sowiso schon was > nicht. Wenn sie die Daten an der Stelle braucht und sowieso nichts weiter tun kann als Däumchen zu drehen, dann könnte sie sich bestenfalls noch schlafen legen. Wenn nur ein paar Byte zu holen sind (und das dann auch mit 20 MHz SPI-Takt), lohnt das aber auch nicht. Sleep/wakeup hat auch Overhead.
MCUA schrieb: > Das "CS-Handling" ist aber nicht der Rede wert, wenn es nur 1x je Block > ein-aus-geschaltet wird. Wenn das Wörtchen "wenn" nicht wär... > Die Hardware kann das machen "Wenn" sie es denn überhaupt kann. Bei den allerwenigsten SPI-Implementierungen in µC kann der SPI-Automat aber die Steuerung des Busses komplett selbständig machen. Ich habe hier ein System mit 3 SPI-Bussen und 16 Slaves, die im ms-Takt alle mit unterschiedlichem Takt, variabler Wortbreite, mehreren SPI-Mode und änderndem CS-Timing angefahren werden wollen. Da ist nichts mit "das macht die CPU per DMA nebenher". Diese SPI-Teilnehmer werden unabhängig von der CPU mit einem FPGA bedient, in dem ein Automat eine Anweisungsliste mit all den Einstellungen durchackert und dann rechtzeitig zum nächten Tick die empfangenen Daten der 16 Slaves bereitstellt. Denn der Witz ist eben, dass ein SPI-Bus eben meist nur die physikalische Verbindung zwischen zwei Geräten ist, und das "Übertagungsprotokoll" schon beim Timing der Ansteuerung beginnt. Beim SPI habe ich u.U. bei 4 Teilnehmern 4 komplett unterschiedliche Ansteuersequenzen mit völlig unterschiedlichen SPI-Register-Einstellungen. Man braucht neben dem Oszilloskop auch die Datenblätter zum Timing jedes Bausteins um die Qualität der Übertragung zu kontrollieren. In den allermeisten anderen Bussen muss man sich um das Timing nicht kümmern, weil das in der Busspezifiktation festgelegt ist und sich alle daran zu halten haben. Bei RS232 mit 96008N1 kann jeder mit einem Oszilloskop ohne Wissen um die Teilnehmer kontrollieren, ob die Übertragung so überhaupt funktionieren kann.
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Diese SPI-Teilnehmer werden unabhängig von der CPU mit einem FPGA > bedient Wenn man das so braucht, auf jeden Fall eine elegante Lösung. Wenn man das FPGA noch direkt vom Controller aus konfiguriert, hat man trotzdem noch eine komplett per Software änderbare Lösung. ;-) Ganz so schlimm war's bei uns zum Glück nicht, aber genügend SPI-Spaß habe ich in meinem aktuellen (und auch vorherigen) Job allemal gehabt …
> Dir sind scheinbare noch nicht genügend verschiedene SPI-Geräte über den > Weg gelaufen. Mehr als du denkst. Ausserdem gibt es keine SPI-Geräte, nur SPI-ICs. > Denn der Witz ist eben, dass ein SPI-Bus eben meist nur die > physikalische Verbindung "Den" SPI-Bus gibt es überhaupt nicht. Klar kann die Schnittstellen-Hardware (zugegeben nicht Jede) auch das bisschen \CS-Steuerung übernehmen. Und wenn man unterschiedliche Timing/Grössen-Anforderungen hat, kann/soll man das auch auf mehrere Busse aufteilen (sofern man dazu die Schnittst. hat). Bloss, FIFOs die man nicht hat, kann man auch nicht benutzen.
MCUA schrieb: > Klar kann die Schnittstellen-Hardware (zugegeben nicht Jede) auch das > bisschen \CS-Steuerung übernehmen. Woher bitte soll die eigentlich wissen, um welche Bytegrenzen herum sie das Signal schalten soll? Genau daran scheiterte es bei uns selbst bei solchen Controllern, die das angeblich in Hardware könn[t]en.
>> Klar kann die Schnittstellen-Hardware (zugegeben nicht Jede) auch das >> bisschen \CS-Steuerung übernehmen. > Woher bitte soll die eigentlich wissen, um welche Bytegrenzen herum sie > das Signal schalten soll? Muss ich das wirklich beantworten?
MCUA schrieb: >>> Klar kann die Schnittstellen-Hardware (zugegeben nicht Jede) auch das >>> bisschen \CS-Steuerung übernehmen. >> Woher bitte soll die eigentlich wissen, um welche Bytegrenzen herum sie >> das Signal schalten soll? > Muss ich das wirklich beantworten? Naja: genau das war eins der Probleme, weshalb die "automatischen" CS-Handler der ARM-SPI-Units nicht funktioniert haben. Sie können so schlecht die Datenblätter der Peripheriebausteine lesen.
SPI ist hauptsächlich dazu gedacht, dumme Slaves anzusteuern, wie IO-Register, ADC/DAC, LED-Treiber usw. Daher sind die Slave-Implementierungen vieler MCs nur ungenügend durchdacht. Soll aber ein MC dochmal Slave sein, wird oft folgendes Protokoll verwendet: Adreßbyte, Befehlsbyte, Dummybyte, Daten ... In der Zeit des Dummybytes kann der Slave dann das Kommando auswerten und entsprechend Daten lesen oder bereitstellen.
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.