ADC mit Raspberry Pi kontinuierlich auslesen

Gast #5934638
Guten Abend zusammen,


ich habe einen Raspberry PI 3 B+, welcher einen A/D-Wandler über SPI 
ausliest. Die SPI-Verbindung taktet mit knapp 16MHz das sind etwa 1MSps 
die vom ADC pro Sekunde erhalten werden (Das zu Sampelnde Signal ist 
rel. hochfrequet weshalb tatsächlich 1MSps benötigt werden). Aufgrund 
der Geschwindigkeit übernimmt der automatische DMA Controller das 
Auslesen (dieser springt bei der BCM2835 Library, die ich verwende 
automatisch bei über 96 gesendeten Bytes an).


Um eine möglichst lange Messdauer zu erreichen, übergebe ich der SPI 
Schnittstelle ein möglichst langes Array, damit dieses vom ADC mit den 
Messwerten gefüllt wird und an mich zuück geliefert wird. Das Problem 
ist allerdings, dass die Messung dann nur etwa ein paar Sekunden dauert 
und ich gerne längere Zeiträumen abdecken will. Gibt es eine Möglichkeit 
das so zu lösen, dass der ADC quasi kontinuierlich (15-20 Sekunden 
beispielsweise) das Signal sampeln kann? Dabei darf es jedoch auf keinen 
Fall zur Unterbrechung des Samplings kommen.

Der Befehl an den ADC sieht derzeit wie folgt aus
Code

    char tx0[8200000] = {};
    char rx[] =  {};
    bcm2835_spi_transfernb(tx0,rx,samples);

Vielen Dank schon einmal vorab für eure Hilfe :)
Gast #5934781
Du muesst deinen Treiber so umprogrammieren das der DMA mit mehren 
Buffern arbeitet. Dann fuellt der DMA einen Buffer und den anderen 
leerst du gerade.

Ausserdem muss der DMA einen IRQ liefern der jedesmal zuschlaegt wenn 
der Buffer voll ist und sehr schnell den neuen Transfer aufsetzt.

Mit Mikrocontrollern ist sowas moeglich. Ob es auch mit dem Linuxkernel 
moeglich ist weiss ich nicht, wuerde es aber erwarten weil das ja auch 
in anderen Bereichen (Audio/Video-Ausgabe) gebraucht wird.

Olaf
Gast #5934833
Also ich denke nicht das es mit dem Linux Kernel da ein Problem gibt, 
deine Netzwerk Verbindung läuft ja auch schneller.
Es hängt einzig und allein an den Fähigkeiten des Entwicklers. Wenn du 
im User Space bist ist deine Anwendung tendenziell etwas langsamer wie 
wenn du einen Kernel Treiber schreibst.
Jedoch sollte deine Strategie nicht sein ein möglichst langes Array zu 
verwenden, sondern lieber eine Strategie zum Puffern und weitergeben von 
Daten. Also eine Art streaming implementieren, zum Beispiel könntest du 
bei den ganzen SDR Anwendungen schauen wie die das machen. Schliesslich 
kommen die ja auch mit mehr als 1Msps klar und rechnen dann noch auf den 
Daten.

DMA, Double buffering, circular buffer, streaming, coroutines, 
asynchronous I/O könntest du mal als weitere Schlüsselwörter zur Suche 
verwenden.

Was ich mich Frageist, was soll es werden. Eine dauerhafte Beobachtung 
oder reicht es den RAM voll laufen zu lassen und dann die Daten weg zu 
schreiben?
Für den Anfang könntest du ja mal probieren mehrere Arrays anzulegen und 
dann einfach den spi Befehl mehrfach wiederholen, oder einfach ein Array 
aus Arrays bauen und mit einer Schleife drüber laufen bis du deine 2O 
Sekunden hast. Wahrscheinlich nicht schön aber könnte reichen.

Interessant wäre zu wissen wie viel Byte pro Sample übertragen werden 
und ob es Overhead gibt? Relativ Hochfrequent ist ein guter Witz, was 
ist denn die erwartete höchste Signalfrequenz die du messen möchtest?

Mit deinem Array festgelegter Länge solltest du ja auch in der Lage sein 
auszurechnen wie lange du Daten aufzeichnen kannst, etwa ein paar 
Sekunden ist eine schlechte Angabe.

Ich gehe mal von einem 16bit ADC, wegen der 16MHz zu 1MSPS Beziehung 
aus, es könnte evtl Sinnvoll sein einen MC dazwischen zu setzen der 
deinen langsamen aber kontinuierlichen Datenstrom aufzeichnet und dann 
am besten per DMA in Blöcken schneller weiter gibt z.B. könntest du dann 
eine gpio Pin setzen wenn wieder ein Datensatz zur Abholung bereit 
steht. So kannst du trotz Raspi CPU Auslastung einen sauberen Datenstrom 
sicherstellen.


Wäre schön etwas von der Lösung später auch wieder hier zu sehen.
#5935015
Hat das SPI im Rπ einen RX Buffer? Normalerweise gibt es sowas. Dann 
gehst du periodisch hin, guckst ob was in diesem Buffer steht und liest 
es aus. Dann wartest du wieder. Mit Python kann ich so ganz ohne DMA 12 
MBit von einem FT2232H UART lesen, dauerhaft.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 7 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.