Forum: Mikrocontroller und Digitale Elektronik Arduino: readADC: den Wert Speichern und per SPI "verteilen"


von P. Smit (Gast)


Lesenswert?

Hallo,

ich habe folgendes Problem:

Ich möchte mit einem Arduino Nano eine Spannung messen. (0-5V) -> INT 
0...1023 (10bit), so viel ist mir klar.

Ich möchte 20 verschiedene Spannungen messen (schon in digits 
gerechnet): 50, 100, 150, ..., 950, 1000. Diese sind aber logischerweise 
nie genau 50 oder 100 sonder schwanken immer um +-10 digits.

Zu jeder der 20 gemessenen Spannungen soll ein unterschiedlicher Befehl 
über den SPI-Bus an ein Modul geschickt werden. Bsp:

Umess = 0,505V -> 103 digits (Bereich 93 - 113) -> 7A2 soll über SPI 
raus.
Umess = 1,481V -> 302 digits (Bereich 292 - 312) -> 8DF soll über SPI 
raus.

Wie kann ich das einfach implementieren? Da die Spannungen ja in einem 
Bereich schwanken möchte ich, dass erst ein neuer Befehl über SPI 
gesendet wird, wenn die Spannung in einen anderen Bereich kommt. 
Ansonsten sendet mein Arduino nämlich unendlich oft den gleichen Befehl 
per SPI, obwohl der Wert immer noch im gleichen Bereich ist.

Nochmals: Es soll nur dann ein Befehl gesendet werden, wenn die Spannung 
von einem der 20 Bereiche in einen anderen springt.

Vielen Dank und beste Grüße
P. Smits

von PittyJ (Gast)


Lesenswert?

Mittelwertfilter über eine gewissen Anzahl an Samples. Und erst wenn der 
Mittelwert stimmt, den Befehl senden.
Gibt auch ein noch ein paar andere Filter, sich einfach mal in die 
Problematik einlesen.

von Karl H. (kbuchegg)


Lesenswert?

P. Smit schrieb:

> Wie kann ich das einfach implementieren? Da die Spannungen ja in einem
> Bereich schwanken möchte ich, dass erst ein neuer Befehl über SPI
> gesendet wird, wenn die Spannung in einen anderen Bereich kommt.

Dann musst du eben feststellen, in welchem Bereich sich dein Messwert 
gerade befindet.
Wenn es einen einfachen mathematischen Zusammenhang in den Bereichen 
gibt, dann kann man den meist gewinnbringend benutzen. Zb seinen die 
Bereiche (ich geh jetzt nur bis 100 um das Prinzip zu verdeutlichen)
1
   0 ..  14    Bereich 0
2
  15 ..  29    Bereich 1
3
  30 ..  44    Bereich 2
4
  45 ..  59    Bereich 3
5
  60 ..  74    Bereich 4
6
  75 ..  89    Bereich 5
7
  90 .. 105    Bereich 6
Der Zusammenhang besteht offenbar daran, dass jeder Bereich genau 15 
mögliche Zhalenwerte umfasst. Um aus einem Messwert, sagen wir mal 48, 
auszurechnen in welchen Bereich er fällt, genügt es also, denn Messwert 
durch 15 (ganzzahlig) zu dividieren
1
  Messwert sei 48
2
3
     48 / 15 -> 3
4
5
  D.h. der Messwert fällt in den Bereich 3

ein Blick in die Tabelle zeigt, dass das auch richtig ist.

Du merkst dir, für welchen Bereich du zuletzt einen Messwert übertragen 
hast. Und solange weitere Messwerte in denselben Bereich fallen, gibst 
du einfach nichts aus.
1
uint8_t letzterBereich = 255;   // kann sich aus den Daten nicht ergeben
2
3
...
4
5
void loop()
6
{
7
  uint16_t wert;
8
  uint8_t bereich;
9
10
  wert = readADC( ... );
11
  bereich = wert / 15;
12
13
  if( bereich != letzterBereich ) {
14
    wert per SPI ausgeben
15
    letzterBereich = bereich;
16
  }
17
}

von Mick (Gast)


Lesenswert?

Gerade etwas zu spät, aber mein Code würde ziemlich gleich aussehen:
1
#define BANDWEITE 10
2
int gesendeteSpannung = 0; //Platzhalter für die aktuell gesendete Spannung
3
4
void loop(){
5
  int spannung = (analogRead(A0) / BANDWEITE) * BANDWEITE;    //10er Schritte 0,10,20,30
6
  if(spannung != gesendeteSpannung){  //nur senden, wenn Spannung geändert
7
     //hier die Logik für SPI
8
     gesendeteSpannung = spannung;
9
  }
10
}

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.