Forum: Mikrocontroller und Digitale Elektronik SpiDev mit zwei Slaves


von Lukas (Gast)


Lesenswert?

Hallo zusammen,

ich möchte mit einem Raspberry Pi 4 über SPI mit zwei ADCs 
kommunizieren. Dazu haben ich folgenden Beitrag gefunden:

Beitrag "[Python] SPI Kommunikation zweier Slaves"

So wie in diesem Beitrag geantwortet wurde, muss ich nach Variante a 
vorgehen. Ist das so richtig? Oder gibt es eine andere Möglichkeit den 
CS von CS_0 zu CS_1 umzuschalten, ohne die Kommunikation davor zu 
beenden?

Weiter ist die Frage, ob es eine andere Möglichkeit (also ohne SpiDev) 
gibt die SPI zwischen dem Raspberry Pi und den zwei ADCs aufzubauen?

Vielen Dank für eure Antworten.

von Frank K. (fchk)


Lesenswert?

Lukas schrieb:

> So wie in diesem Beitrag geantwortet wurde, muss ich nach Variante a
> vorgehen. Ist das so richtig? Oder gibt es eine andere Möglichkeit den
> CS von CS_0 zu CS_1 umzuschalten, ohne die Kommunikation davor zu
> beenden?

Wenn Du nur eine SPI-Einheit hast, d.h. SCK, MISO und MOSI an zwei 
Devices führst, dann darf immer nur ein CS zur Zeit aktiv sein. Das 
heißt, die aktuelle SPI-Transaktion muss beendet sein, bevor eine neue 
beginnt.

Ein Pi 4 hat aber zwei SPI-Einheiten, jede mit eigenen SCK, MISO, MOSI 
und CS-Leitungen. Die sind voneinander unabhängig und können 
gleichzeitig genutzt werden.

> Weiter ist die Frage, ob es eine andere Möglichkeit (also ohne SpiDev)
> gibt die SPI zwischen dem Raspberry Pi und den zwei ADCs aufzubauen?

Beziehst Du das auf Python, oder allgemein?

fchk

von Lukas (Gast)


Lesenswert?

Vielen Dank für die schnelle Antwort.

 >Ein Pi 4 hat aber zwei SPI-Einheiten, jede mit eigenen SCK, MISO, MOSI
 >und CS-Leitungen. Die sind voneinander unabhängig und können
 >gleichzeitig genutzt werden.

Dafür muss ich dann mit mehreren Tasks arbeiten?

 >Beziehst Du das auf Python, oder allgemein?

Die Frage ist auf Python bezogen

von Frank K. (fchk)


Lesenswert?

Lukas schrieb:
> Vielen Dank für die schnelle Antwort.
>
>  >Ein Pi 4 hat aber zwei SPI-Einheiten, jede mit eigenen SCK, MISO, MOSI
>  >und CS-Leitungen. Die sind voneinander unabhängig und können
>  >gleichzeitig genutzt werden.
>
> Dafür muss ich dann mit mehreren Tasks arbeiten?

Der Begriff "Tasks" wird in Unix nicht verwendet. Du kannst getrennte 
Prozesse verwenden, oder mehrere Threads innerhalb eines Prozesses.

Ich benutze Python zu wenig, deswegen kann ich keinerlei 
Python-spezifische Fragen beantworten. Ich weiß jetzt nicht, ob Deine 
Bibliotheksfunktionen blockieren (d.h. erst den Transfer durchführen und 
dann zurückkehren), oder ob es auch nicht blockierende Versionen gibt 
(die einen Transfer starten, dann sofort zurückkehren, und der Transfer 
ist dann irgendwann fertig). Wenn es nicht blockierende Funktionsaufrufe 
gibt, kannst Du das auch irgendwie innerhalb eines Threads machen. Mit 
mehreren Threads oder Prozessen wirds aber einfacher und 
übersichtlicher.

fchk

: Bearbeitet durch User
von Lukas (Gast)


Lesenswert?

Okay, danke Dir!

von N. M. (mani)


Lesenswert?

Was für ADCs möchtest du denn verwenden?
Sind die nicht Mainline?

von Lukas (Gast)


Lesenswert?

> Was für ADCs möchtest du denn verwenden?

ADC128S022

Mein Ziel ist die beiden ADCs möglichst schnell nacheinander abzufragen. 
Aus diesem Grund möchte ich die Kommunikation nicht jedes mal schließen 
und wieder neu öffnen.

von Frank K. (fchk)


Lesenswert?

Lukas schrieb:

> Mein Ziel ist die beiden ADCs möglichst schnell nacheinander abzufragen.
> Aus diesem Grund möchte ich die Kommunikation nicht jedes mal schließen
> und wieder neu öffnen.

Wenn nacheinander reicht, dann hänge einfach den ersten ADC an SPI0 
(GPIO 8-11) und den zweiten an SPI1 (GPIO 18-21), öffne beide, und lass 
sie geöffnet. Das wird funktionieren. Wenn Du das später optimieren 
willst, kannst Du dann immer noch mit Threads usw anfangen und beide 
parallel betreiben.

fchk

von Lukas (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

leider ist bei der Umsetzung mit SPI 0 und SPI 1 ist folgendes Problem 
aufgetreten:

Das SCLK Signal von SPI 0 stimmt nicht mit dem SCLK Signal von SPI 1 
überein, wobei das SCLK Signal von SPI 0 richtig ist. Die Clock- 
Frequenz kann ich bei SPI 0 und SPI 1 ändern.

Den Verlauf der Signale habe ich angehängt.

Das Interface für die SPI 1 habe ich mit dem Befehl dtoverlay in der 
config.txt freigeschaltet.

Ich verwende in beiden Fällen den Befehl xfer2().

Kann mir jemand dieses Verhalten erklären?

Vielen Dank für Eure Antworten.

von Falk B. (falk)


Lesenswert?

Lukas schrieb:
> LogicAnalyzer.png

Hast du mal dein Bild angeschaut und über das Thema Lesbarkeit 
reflektiert?

von Vancouver (Gast)


Lesenswert?

Wenn man jetzt in dem Bild etwas erkennen könnte...


> Das SCLK Signal von SPI 0 stimmt nicht mit dem SCLK Signal von SPI 1
> überein, wobei das SCLK Signal von SPI 0 richtig ist.

Was bedeutet "stimmt nicht überein"? Warum müssen die beiden SCLKs 
übereinstimmen?
Es gibt bei SPI die beiden Parameter CPOL und CPHA (->Google), die du 
evtl. einstellen musst.

Falls es wirklich auf die Performance ankommt, wirst du nicht drumherum 
kommen, einen Kerneltreiber für die ADCs zu schreiben, der das ganze 
SPI-Handling selbstständig abwickelt (bzw, vielleicht gibt es den auch 
schon). Das Python-Programm fragt dann nur die Werte ab, ohne sich um 
den SPI-Kram zu kümmern.

Das Userspace-SPI ist nicht so wirklich performant. Das habe ich 
gemerkt, als ich versucht habe, ein SPI-TFT-Display auf diese Weise 
anzusteuern. Letztlich habe ich einen Kerneltreiber geschrieben, anders 
ging da nichts.

von Gustl B. (gustl_b)


Lesenswert?

Lukas schrieb:
> Das SCLK Signal von SPI 0 stimmt nicht mit dem SCLK Signal von SPI 1
> überein,

Muss das denn so sein? Das sind doch zwei getrennte Interfaces. Ob die 
Kommunikation passt kannst du mit dem Datenblatt das ADCs abgleichen. 
Wenn du #CS dauerhaft auf Low legen willst was bei diesem ADC geht, dann 
ist Seite 7 relevant. Du kannst SCLK dauerhaft toggeln lassen, musst 
aber die Parameter einhalten. Also minimal 0,8 MHz, maximal 3,2 MHz für 
den Takt, ...

von Wolfgang (Gast)


Lesenswert?

Lukas schrieb:
> Mein Ziel ist die beiden ADCs möglichst schnell nacheinander abzufragen.

Der Abfragezeitpunkt ist normalerweise ziemlich egal. Entscheidend ist, 
dass bei soetwas die Abtastung idealerweise gleichzeitig statt findet. 
Der ADC128S022 ist dafür allerding nicht geeignet, weil die 
Track&Hold-Steuerung zeitlich fest an den Clock der SPI Kommunikation 
gekoppelt ist.

Bei dem ADC128S022 bleibt dir wohl nur eine sequentielle 
Abtastung/Übertragung. Wenn das in separaten Tasks statt finden soll - 
viel Spaß bei der Synchronisation.

von Lukas (Gast)


Angehängte Dateien:

Lesenswert?

Sorry für die schlechte Qualität des Bildes. Ich habe zwei neue Bilder 
angehängt.

Die Kommunikation mit der SPI 0 funktioniert. Deshalb habe ich die SPI 1 
genau gleich konfiguriert (zwei identische ADCs). Aus diesem Grund 
erwarte ich die gleichen Signale, insbesondere das SCLK Signal.

Wie auf den beiden Bilder zu sehen ist, stimmen diese jedoch nicht 
miteinander überein. Daraus schließe ich, dass die Konfiguration der SPI 
1 nicht vollständig durchgeführt wurde.

Deshalb meine Frage, ob jemand schon mit der SPI 1 von dem Raspberry Pi 
gearbeitet hat und mir Tipps geben kann.

Viele Grüße

von Gustl B. (gustl_b)


Lesenswert?

Etwas zu wenige oder zu viele Takte. Außerdem ist da Pause dazwischen.

Das steht alles schön im Datenblatt auf Seite 7 oben und in Kapitel 
7.3.1 Seite 15.

: Bearbeitet durch User
von Gustl B. (-gb-)


Lesenswert?

Gustl B. schrieb:
> oder zu viele Takte

Und genau das sieht man auch wunderbar im zweiten Bildchen SPI_1.PNG, in 
dem das MOSI eigentlich MISO heißen müsste.
Jedenfalls kommen die gesetzten LSBs am Ende der ersten 24 Takte, bei 
den zweiten 24 Takten liegen sie schon weiter vorne und im 3. 24 Clock 
"Burst" bekommst du sogar zweimal Daten, nämlich vom 2. Burst und vom 3. 
Burst.

Wenn du #CS Low hältst, dann sollte die SCLK durchgehend toggeln, ohne 
Pause. Alle 16 Takte kommen dann Daten. Wenn du eine Pause machen 
möchtest, keine Ahnung ob das erlaubt ist, dann immer nach 16 Takten.

von Lukas (Gast)


Lesenswert?

Okay, ich habe mich nicht klar genug ausgedrückt, mein Fehler.

Einschalten von SPI 1 nach 
https://blog.stabel.family/raspberry-pi-4-device-tree/
1
dtoverlay = spi1-1cs

überprüfen mit ls \dev\spi*

-> Ausgabe von /dev/spidev1.0 -> spi wurde freigeschalten


Die Anleitung habe ich von 
https://www.sigmdel.ca/michel/ha/rpi/dnld/draft_spidev_doc.pdf
1
spi = spidev.SpiDev()
2
spi.open(0,0)
3
spi.max_speed_hz = 1000000
4
spi.bits_per_word = 8
5
spi.mode = 0b00
6
7
spi_1 = spidev.SpiDev()
8
spi_1.open(1,0)
9
spi_1.max_speed_hz = 1000000
10
spi_1.bits_per_word = 8
11
spi_1.mode = 0b00
12
13
Answer_1 = spi.xfer2([0,CH0,0,CH1,0,CH2,0,CH3,0,CH4,0,CH5,0,CH6,0,CH7,0])
14
Answer_2 = spi_1.xfer2([0,CH0,0,CH1,0,CH2,0,CH3,0,CH4,0,CH5,0,CH6,0,CH7,0])
15
16
spi.close()
17
spi_1.close()

SPI 0 => Funktioniert, d.h. Es werden pro Channel zwei Datenpakete mit 
jeweils 8 Bit gesendet.

Problem:
SPI 1 Funktioniert nicht. Zwei Dingen fallen bei dem Betrachten der 
Signale auf:

1. Der Signalverlauf von dem SCLK Signal (SPI 0) stimmt nicht mit dem 
Signalverlauf von dem SCLK_1 Signal (SPI 1) überein. Warum?

2. Der Master sendet über den MOSI_1 die Channelauswahl. Somit wird 
zumindest ein Teil der Funktion xref2() ausgeführt.

Die Frage ist jetzt: Warum bekomme ich bei der gleichen Konfiguration 
zwei unterschiedliche Signalverläufe von SCLK?

Hoffe das Problem ist jetzt etwas verständlicher geworden.

Vielen Dank für Eure Antworten.

von Gustl B. (-gb-)


Lesenswert?

Lukas schrieb:
> SPI 0 => Funktioniert, d.h. Es werden pro Channel zwei Datenpakete mit
> jeweils 8 Bit gesendet.

Was bedeutet "funktioniert" genau? Bekommst du korrekte Abtastwerte? In 
Bild SPI_0.PNG ist bei MISO teilweise gar kein Bit gesetzt, liegen die 
Eingänge auf Masse?

Lukas schrieb:
> 1. Der Signalverlauf von dem SCLK Signal (SPI 0) stimmt nicht mit dem
> Signalverlauf von dem SCLK_1 Signal (SPI 1) überein. Warum?

Naja, der stimmt schon grob überein. Was nicht stimmt sind die Pausen.

SPI_0 toggelt SCLK 16x8 Mal = 128 Takte
SPI_1 toggelt SCLK 5*24 + 1x8 Mal = 128 Takte

Woran das liegt weiß ich nicht, aber:
Du kannst an deinen zweiten ADC auch nochmal die SCLK vom 1. ADC 
anschließen. Ja, ist nicht sauberes Design, aber bei der Frequenz sehr 
wahrscheinlich egal.
Genauso kannst du auch MOSI vom 1. ADC gleich mit an den 2. ADC 
anschließen. Du musst dann nur das zweite MISO korrekt erfassen.

Lukas schrieb:
> Die Frage ist jetzt: Warum bekomme ich bei der gleichen Konfiguration
> zwei unterschiedliche Signalverläufe von SCLK?

Ich sehe keinen Fehler in deinem Code, aber ich weiß auch aus Erfahrung, 
dass diese Library oft grauenhaft schlecht sind. Wie das hier ist weiß 
ich nicht.

Lukas schrieb:
> Hoffe das Problem ist jetzt etwas verständlicher geworden.

Ja, ist es.

von Lukas (Gast)


Lesenswert?

Gustl B. schrieb:
> Was bedeutet "funktioniert" genau? Bekommst du korrekte Abtastwerte? In
> Bild SPI_0.PNG ist bei MISO teilweise gar kein Bit gesetzt, liegen die
> Eingänge auf Masse?

Ja genau, habe zum Testen eine DC- Spannung an den Channel angelegt. In 
dem Bild SPI_0 liegen die Eingänge auf Masse.

Gustl B. schrieb:
> Woran das liegt weiß ich nicht, aber:
> Du kannst an deinen zweiten ADC auch nochmal die SCLK vom 1. ADC
> anschließen. Ja, ist nicht sauberes Design, aber bei der Frequenz sehr
> wahrscheinlich egal.
> Genauso kannst du auch MOSI vom 1. ADC gleich mit an den 2. ADC
> anschließen. Du musst dann nur das zweite MISO korrekt erfassen.

Vielen Dank für den Tipp, werde das morgen probieren.

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