Forum: Mikrocontroller und Digitale Elektronik Sinus messen Raspberry Pi WiringPi


von Narben Johnny (Gast)


Lesenswert?

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 :)

von St. D. (st_d)


Lesenswert?


: Bearbeitet durch User
von Narben Johnny (Gast)


Lesenswert?

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.

von Alex G. (dragongamer)


Lesenswert?

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.

von Stefan S. (chiefeinherjar)


Lesenswert?

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?

von Narben Johnny (Gast)


Lesenswert?

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.

von Narben Johnny (Gast)


Lesenswert?

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.

von Alex G. (dragongamer)


Lesenswert?

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
von Narben Johnny (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Alex G. (dragongamer)


Lesenswert?

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
von Martin (Gast)


Lesenswert?

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

von Narben Johnny (Gast)


Angehängte Dateien:

Lesenswert?

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.

von soundos (Gast)


Lesenswert?

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?

von Narben Johnny (Gast)


Lesenswert?

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.

von Alex G. (dragongamer)


Lesenswert?

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
von Yalu X. (yalu) (Moderator)


Angehängte Dateien:

Lesenswert?

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.

von Narben Johnny (Gast)


Lesenswert?

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