Hey, ich arbeite momentan mit dem Rapsberry Pi Model 3b+. Viel Erfahrung habe ich mit dem Pi noch nicht. Vorher habe ich mit Mikrocontrollern programmiert. Um mit dem Pi in C programmieren zu können habe ich mir Geany als IDE eingerichtet. Damit ich in C auf den Pi zugreifen kann habe ich mir wiringPi installiert. Das hat bisher auch ganz gut funktioniert. Ich würde gern ein sinusförmiges Signal messen. Dazu habe ich mir, bisher nur auf der Steckplatine wohlgemerkt, einen MCP3004 besorgt und diesen an den PI via SPI angeschlossen. Das ansprechen und auslesen der Daten funktioniert ebenfalls. Wenn ich mir jedoch die Daten im zeitlichen Verlauf ansehe ist das alles Andere, aber kein Sinus. Ich möchte gern, dass der Pi in äquidistanten Zeitabschnitten sich die Daten vom MCP3004 abholt und diese speichert. Bei einem µC würde ich das ganze über einen Timer interrupt laufen lassen. Geht sowas auch beim Pi? Wie kann ich dem Pi in C sagen, dass er nach einer festen Zeit wieder den MCP3004 ansprechen soll. Danke :)
:
Bearbeitet durch User
St. D. schrieb: > Siehe https://de.wikipedia.org/wiki/Abtastrate > und https://de.wikipedia.org/wiki/Nyquist-Frequenz Ich hab vergessen zu erwähnen, dass es sich um die feste Frequenz von 50 Hz handelt.
Wie liest du denn aus? Heir mal ein Beispielcode: https://raspberrypi.stackexchange.com/questions/27388/sampling-on-the-pi-using-mcp3004 Wenn du damit die selben 200Hz erreichst, reicht das grade so für ein 50Hz Signal.
Hast du beachtet, dass die Eingangsspannung nicht unter 0V und nicht über VCC des ADC gehen darf? Wie sehen denn deine Daten im zeitlichen Verlauf aus?
Alex G. schrieb: > Wie liest du denn aus? > > Heir mal ein Beispielcode: > https://raspberrypi.stackexchange.com/questions/27388/sampling-on-the-pi-using-mcp3004 > > Wenn du damit die selben 200Hz erreichst, reicht das grade so für ein > 50Hz Signal. Ich lese die ganzen Daten über den "Treiber" von WirinPi aus. Dort werden über eine Funktion die Daten angefragt. In der Funktion ist auch die Kommunikation über SPI geregelt. WiringPi nutzt da eine Funktion namens wiringPiSPIDataRW. Eigentlich möchte ich gern diese Funktion zyklisch anspringen, also mindestens mit 100 Hz, um das Abtasttheorem nicht zu verletzen. In der Zwischenzeit würde ich gern andere Sachen machen.
Stefan S. schrieb: > Hast du beachtet, dass die Eingangsspannung nicht unter 0V und > nicht > über VCC des ADC gehen darf? > > Wie sehen denn deine Daten im zeitlichen Verlauf aus? Ja habe ich. Mein Sinus hat einen Offset. Die Daten sehen durcheinander aus. Manchmal ist im Zeitverlauf ein Sinus erkennbar und manchmal nicht. Das spricht für mich, dass zwischendurch andere Sachen erledigt.
Hab Quatsch geschrieben. Die vierfache Abtastrate reicht ehr nicht aus um nen brauchbaren Sinus dar zu stellen. Jedenfalls nicht durchs direkte Anzeigen. Du solltest es mit einem C(++) Programm versuchen denn Python ist halt suboptimal für Echtzeit-Zeug. Narben Johnny schrieb: > Die Daten sehen durcheinander aus. Manchmal ist im Zeitverlauf ein Sinus > erkennbar und manchmal nicht. Das spricht für mich, dass zwischendurch > andere Sachen erledigt. Naja, das wirst du wohl auf einem Raspberry Pi unter Linux nie ganz weg bekommen denn da laufen einige Hintergrund-Threads drauf die jederzeit deinen kurz unterbrechen dürfen. Du kannst dem etwas entgegen steuern indem du dein Program maximale Priorität zuweist. Für ein Oszilloskop taugt das ganze allerdings trotzdem nicht. In welcher Programmiersprache ist deine Software geschrieben? Gib uns mehr Infos!
:
Bearbeitet durch User
Alex G. schrieb: > In welcher Programmiersprache ist deine Software geschrieben? Bitte nochmal lesen ;) Narben Johnny schrieb: > Um mit dem Pi in C programmieren zu können habe ich mir Geany als IDE > eingerichtet. Damit ich in C auf den Pi zugreifen kann habe ich mir > wiringPi installiert. Das hat bisher auch ganz gut funktioniert. Im Anhang ein Ausschnitt wie die Daten aussehen, wenn ich mit höchster Prio messe.
Hast Recht :) Trotzdem wäre allerdings der Code nett. Die Werte auf der X Achse sind ja die indices der Messpunkte, nicht Zeit (soweit ich das sehe). Hast du also eine Methode um sicherzustellen dass z.B alle 0.5 Mikrocsekunden ein neuer Wert erfasst wird? oder werden einfach so viele Werte erfasst wie möglich in einer Endlosschleife? Alternativ, lass einen Zeit-Zähler (am besten nanosekundenbereich) mitlaufen und zeichne dann einen grafen wo die Zeit auf der X-Achse ist indem du zu jedem Messpunkt auch den Zeitpunkt abspeicherst.
:
Bearbeitet durch User
Ich habe noch ein paar Tipps: Schau dir mal wiringPI unt Interrups an http://wiringpi.com/reference/priority-interrupts-and-threads/ Schau dir mal pigpio an, das ist bei Raspian schon dabei. Dort speziel "callbacks at timed intervals" http://abyz.me.uk/rpi/pigpio/index.html
Nach ein paar Recherchen sieht mein Sinus jetzt auch aus wie ein Sinus. Um eine Art "timer gesteuerten Interrupt" zu bekommen kann man folgendes machen: Man stellt an einem Pin eine feste PWM-Frequenz ein (idealerweise in der Frequenz wie oft man seine ISR anhüpfen möchte). Anschließend triggert man die interne ISR von wiringPi auf diesen Pin und sagt, wenn der Pin low oder high ist, dann spring in meine ISR. Quellcodemäßig kann das so aussehen:
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <stdint.h> |
4 | #include <string.h> |
5 | #include <time.h> |
6 | |
7 | #include <wiringPi.h> |
8 | #include <softPwm.h> |
9 | |
10 | void ISR(void) |
11 | {
|
12 | if(digitalRead(2) == 0){ |
13 | digitalWrite(2, HIGH); |
14 | }
|
15 | else{ |
16 | digitalWrite(2, LOW); |
17 | }
|
18 | }
|
19 | |
20 | int main() |
21 | {
|
22 | wiringPiSetup(); |
23 | |
24 | pinMode(0,OUTPUT); |
25 | |
26 | pinMode(2,OUTPUT); |
27 | |
28 | digitalWrite(0,LOW); |
29 | |
30 | digitalWrite(2,LOW); |
31 | |
32 | wiringPiISR(0, INT_EDGE_RISING, &ISR); |
33 | |
34 | softPwmCreate(0,0,20); |
35 | |
36 | softPwmWrite(0,17); |
37 | |
38 | while(1){ |
39 | |
40 | }
|
41 | }
|
WiringPi kann die PWM-Frequenz in vielfache von 100µs einstellen.
1 | softPwmCreate(0,0,20); //sagt eine PWM-Frequenz von 20*100µs=2ms |
2 | int softPwmCreate (int pin, int initialValue, int pwmRange); |
3 | softPwmWrite(0,17); //sagt, dass Pin 0 1,7ms an ist, als high |
4 | wiringPiISR(0, INT_EDGE_RISING, &ISR); //hier springt er nach void ISR(void) |
Ein guter workaround. Das Ergebnis seht ihr im Anhang.
Dein "neuer" Sinus sieht aber immer noch wie geschätzt aus ... 50Hz und ein Rpi schafft das nicht ? überleg dir mal das ganze mit einem kleine uC zu sampeln und "offline" die Daten an de Rpi zu übertragen. damit könntest du mit viel höheren Abtastraten arbeiten. Natürlich kannst du dann nicht in realtime an die daten ran... was ist denn die applikation?
soundos schrieb: > Dein "neuer" Sinus sieht aber immer noch wie geschätzt aus ... > 50Hz und > ein Rpi schafft das nicht ? > > überleg dir mal das ganze mit einem kleine uC zu sampeln und "offline" > die Daten an de Rpi zu übertragen. damit könntest du mit viel höheren > Abtastraten arbeiten. > > Natürlich kannst du dann nicht in realtime an die daten ran... > > was ist denn die applikation? Geschätzt kann man in der Tat sagen, denn die ISR wird nicht immer mit 500 Hz angesprungen, sondern mit + -, je nachdem, was das OS gerade macht. Fraglich ist ebenfalls, ob der Sinus gemessen werden muss oder, ob es reicht einfach nur den RMS-Wert aus dem Spitzenwert zu errechnen. Dennoch müsste man da den Sinus samplen. Ich werde die Sache noch einen gewissen Grad vorantreiben und schauen, ob es die Anwendung auf dem Pi realisierbar ist, denn es kommen noch anderen Komponenten dazu, die gemessen werden müssen. Diese sind zwar nicht so zeitkritisch, aber sie müssen auch gemessen und gespeichert werden. Wenn nicht dann steige ich auf einen µC um. Dort lässt sich einiges auch viel besser programmieren und da kann ich mir einen Timer aufbauen nicht sowas geschätztes wie beim Pi. Die Kontrolle über die Hardware ist dort ebenfalls besser. Es ist dennoch eine gute Erfahrung gewesen sich mit dem Pi auseinanderzusetzten. Die Temperatur im Kühlschrank ließe sich ganz gut mit dem Pi messen, aber zeitkritische Dinge dann nur auf dem Baremetal.
Hmm, du könntest noch die andere Methode versuchen die ich vorgeschlagen habe: Endlosschleife aber mit Zeit-Tracking. Damit ist vieleicht eine noch deutlich höhere Abtastrate drin und Verzögerungen haben viel weniger schlechten Einfluss.
:
Bearbeitet durch User
soundos schrieb: > Dein "neuer" Sinus sieht aber immer noch wie geschätzt aus ... 50Hz und > ein Rpi schafft das nicht ? So schlecht ist die Qualität doch gar nicht. Ich habe dem Bild mal einen idealen Sinus überlagert. Mit einer höheren Abtastfrequenz oder einer besseren Interpolation (sin(x)/x statt linear) würden auch die unschönen Zacken verschwinden. Allerdings ist die Abtastfrequenz etwas niedriger als das Zehnfache der Sinusfrequenz. Die Abtastfrequenz liegt also etwas unter 500Hz, oder die Sinusfrequenz etwas über 50Hz.
Yalu X. schrieb: > Allerdings ist die Abtastfrequenz etwas niedriger als das Zehnfache der > Sinusfrequenz. Die Abtastfrequenz liegt also etwas unter 500Hz, oder die > Sinusfrequenz etwas über 50Hz. Wohl eher letzteres. Der Sinus stammt aus einem Funktionsgenerator und wie ich schon oben beschrieben habe schwankt die Zeit des "Timers", da das Linux auch noch ein wenig mitspielen möchte.
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.