Forum: Mikrocontroller und Digitale Elektronik Arduino -> Digital Poti -> Wert über ADC wieder einlesen


von Lars (Gast)


Lesenswert?

Guten Morgen zusammen,

ich versuche mich gerade an einer kleinen Spielerei mit dem Arduino 
einem Digital Poti(10 bit/1024 Stufen) und dem ADC des Arduinos.

Ich teile einem Poti über den Arduino mit das es sich, über x sekunden 
auf den Wert 500 stellen soll. Ich möchte diesen Wert nun wieder über 
den Arduino einlesen und sobald 500 erreicht ist soll er stehen bleiben.

Das ganze hochfahren usw. klappte auch, aber natürlich schwankt der 
eingelesen wert so zwischen 496 und 504, so das mein Programm die ganze 
zeit denkt er hätte 500 noch nicht erreicht.

Dann dachte ich mich ich setze mir eine Grenze von +-8 Digits wann der 
Arduino erkennen soll das der Wert erreicht ist, aber irgendwie hab ich 
da Murks programmiert ;-) denn mit meiner "Grenze" von 8 Digit hab ich 
lediglich erreicht das schon bei 492 den wert erreicht hat und dann dort 
schwankt :D.

Wie löse ich das am Besten? wo ist mein Denk Fehler? Unten anbei sind 
meine 3 Routinen zum Erhöhen, Verkleinern oder zum Erkennen des 
erreichten Wertes


DigitalPoti = Eingelesener Poti Wert (0-1023)
Sollwert = 500

GrenzeUnten = 8

GrenzeOben = 8
1
if (DigitalPoti < (Sollwert - GrenzeUnten)) { *Wert erhöhen und Wert nicht erreicht* }
2
3
if (DigitalPoti > (Sollwert + GrenzeOben)) { *Wert verkleinern und Wert nicht erreicht* }
4
5
if ( !(DigitalPoti < (Sollwert - GrenzeUnten)) && !(DigitalPoti > (Sollwert + GrenzeOben)) && WertErreicht == false   ) { *Wert erreicht* }

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Filtern, filtern, filtern.
Bilde Mittelwerte aus den Werten des ADC und verringere so das 
Bitflimmern. Dann kannst du schrittweise dein Fenster verkleinern.

von Lars (Gast)


Lesenswert?

Stimmt Filtern tue ich das gar nicht hinter "DigitalPoti" steht direkt 
der eingelesene ADC Wert.

Huuuuhm. Interessant. Das teste ich gleich mal darüber hatte ich mir gar 
keine Gedanken gemacht. Mal etwas einlesen. Gibt es ne Faustformel Wie 
viele eingelesene Werte ich in wieviel Zeit ich berücksichtigen sollte?

von beo bachta (Gast)


Lesenswert?

Matthias S. schrieb:
> Bilde Mittelwerte aus den Werten des ADC und verringere so das
> Bitflimmern.

Vielleicht auch mal in sich gehen und die Schaltung prüfen ob
nicht da auch noch was zu filtern wäre.

Daher:

Lars schrieb:
> Wie löse ich das am Besten?

Erst mal Schaltung zeigen wenn man nicht weiter kommt.

von beo bachta (Gast)


Lesenswert?

Lars schrieb:
> so das mein Programm die ganze
> zeit denkt er hätte 500 noch nicht erreicht.

So ganz stabil auf (z.B.) 500 wirst du es nie bekommen da
eine Schwankung um +-1 immer vorhanden sein wird wegen der
Quantisierung des Wandlers.

von beo bachta (Gast)


Lesenswert?

beo bachta schrieb:
> So ganz stabil auf (z.B.) 500 wirst du es nie bekommen

Genau genommen wird dein Wert entweder zwischen 499 und 500
oder zwischen 500 und 501 schwanken, wenn sonst alles
höchstmöglich stabil bleibt.

von Jens M. (schuchkleisser)


Lesenswert?

Die beiden IFse sind falschrum.

Ich hätts mit
1
IF Istwert > (Sollwert + Halbesfenster) THEN Kleiner();
2
ELSE IF Istwert < (Sollwert - Halbesfenster) THEN Groesser();
3
ELSE WertErreicht();
probiert.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Lars schrieb:
> Wie löse ich das am Besten?
Na, zum Glück hast du nicht "am Einfachsten" gefragt. Für "am Besten" 
musst du dich aber mit Regelungstechnik beschäftigen.

> aber natürlich schwankt der eingelesen wert so zwischen 496 und 504
Warum schwankt der? Mit welcher Verteilung schwankt der? Ist das 
Rauschen oder schwingt dein Regler?

Lars schrieb:
> Mal etwas einlesen.
Ins Thema Regelungstechnik. Denn du willst irgendwas auf den Sollwert 
500 regeln, dein Poti ist das Stellglied dafür und der ADC bringt den 
Istwert. Dein Ziel ist es, trotz Störeinflüssen die Regeldifferenz auf 0 
zu bringen:
https://de.wikipedia.org/wiki/Regeldifferenz

> Gibt es ne Faustformel Wie
> viele eingelesene Werte ich in wieviel Zeit ich berücksichtigen sollte?
Kommt drauf an, wie schnell die zu regelnde Strecke ist.

: Bearbeitet durch Moderator
von MaWin (Gast)


Lesenswert?

Lars schrieb:
> Wie löse ich das am Besten?

Gar nicht gucken.

Nach x Sekunden hat das Poti den Wert 500, so wie programmiert, das ist 
der Vorteil von deterministischen Verfahren.

Was soll das überhaupt für ein merkwürdiges Digitalpoti sein mit 
automatischem slope ?

von Lars (Gast)


Lesenswert?

beo bachta schrieb:
> Vielleicht auch mal in sich gehen und die Schaltung prüfen ob
> nicht da auch noch was zu filtern wäre.

Ich lese mir das mal grad mit dem Mittelwert durch. Das ist ja nicht 
verkehrt die Messwerte etwas zu glätten :D.

beo bachta schrieb:
> Erst mal Schaltung zeigen wenn man nicht weiter kommt.

Hust - Schaltung ist noch etwas kraut und Rüben. Mir ging es auch 
vorerst um meine eventuelle vermurkste Programmierung, weil ich da 
irgendwie nen Knoten hatte.

von beo bachta (Gast)


Lesenswert?

Lars schrieb:
> Schaltung ist noch etwas kraut und Rüben.

Wenn die Schaltung "scheisse" ist dann kannst du ewig mitteln
bis du einen stabilen Wert bekommst.
Du solltest auf beiden Seiten für saubere Verhältnisse sorgen:
Hartware und Weichware.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Lars schrieb:
> Hust - Schaltung ist noch etwas kraut und Rüben.
Ja, du musst ja auch nicht deinen Drahtverhau zeigen, sondern einfach 
nur den Schaltplan. Dann sieht man schon, ob die grundlegende Idee 
überhaupt taugt...

von Lars (Gast)


Angehängte Dateien:

Lesenswert?

Lothar M. schrieb:
> Ja, du musst ja auch nicht deinen Drahtverhau zeigen, sondern einfach
> nur den Schaltplan. Dann sieht man schon, ob die grundlegende Idee
> überhaupt taugt..

beo bachta schrieb:
> Lars schrieb:
>> Schaltung ist noch etwas kraut und Rüben.
>
> Wenn die Schaltung "scheisse" ist dann kannst du ewig mitteln
> bis du einen stabilen Wert bekommst.
> Du solltest auf beiden Seiten für saubere Verhältnisse sorgen:
> Hartware und Weichware.

Guten Morgen zusammen,

ich habe mal meinen Schmierpapier Schaltplan schnell abgezeichnet damit 
es was ordentlicher aussieht. Das wollte ich euch dann doch nicht 
zumuten ;-).
So sieht der Schaltplan aus.
Die +-12V kommen aus einem Labornetzteil und werden am Eingang noch mit 
100uF und 100nf.

Die 10V werden über ein Referenz Modul erzeugt und daraus dann die 5V 
Referenz gemacht. Was mir dabei aufgefallen ist vermutlich ist es blöd 
wenn ich die Referenz Massen alle auf GND lege. Vielleicht sollte ich 
die seperat routen und die Masse an einem Bestimmten punkt zusammen 
legen. Ich wüsste da nur nicht wo die Massen zusammen gelegt werden 
sollten.

Ihr könnte ja mal drüber gucken und sagen was ihr davon haltet -
Viele Grüße

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Uups, naja, warum einfach, wenns auch kompliziert geht. Aber gut, du 
hast ja U1B als Puffer zum ADC, der könnte auch gleich noch filtern (aka 
integrieren). Aber warum so viel Hardware?

von Lars (Gast)


Lesenswert?

Matthias S. schrieb:
> Uups, naja, warum einfach, wenns auch kompliziert geht. Aber gut, du
> hast ja U1B als Puffer zum ADC, der könnte auch gleich noch filtern (aka
> integrieren). Aber warum so viel Hardware?

Ich wollte einfach mal mit OPs spielen die sind ja momentan einfach als 
Impedanz Wandler oder als Verstärker Faktor 2 geschaltet -> so kann ich 
mein Reales Poti (10V) und mein Digitales Poti (5V *2) direkt mit 
einander vergleichen.
Oder habe ich das ausser "kompliziert" etwas generell falsch gemacht?

Aber mit der Mittelwert Bildung ist mir glaub ich was lustiges passiert.
Und zwar will ich ja versuchen mit dem Digital Poti mit einer Rampe auf 
einen Soll-Wert zu fahren.

Vorher habe ich einfach den eingelesenen Analogwert vom Digital Poti 
genommen Habe dazu 1 addiert und habe diesen Wert wieder zum Poti 
gesendet. So hat der sich Stück für Stück erhöht. Zwar etwas am rauschen 
aber gut :D

So mit meiner Mittlerbildung:
(von der Seite: 
https://42project.net/drei-methoden-zur-filterung-von-verrauschten-adc-messungen-mit-dem-arduino/#lightbox/1/)

Wird ja der laufende Mittelwert über 16 Werte gebildet wenn ich nun den 
Mittelwert nehme und 1 addiere und dann wieder zum Poti sende, dann wird
ja quasi nur 1/16tel der 1 auf den Poti wert addiert und das wird quasi 
wieder rausgemittelt :D
Dat hatte ich mir etwas anders vorgestellt :D oder wende ich das falsch 
an ?




const int RunningAverageCount = 16;               // Anzahl der in den 
Laufenden-Mettelwert aufgenommenen Messungen
float RunningAverageBuffer[RunningAverageCount];
int NextRunningAverage;
1
 
2
void loop()
3
{
4
  float RawTemperature = MeasureTemperature();
5
 
6
  RunningAverageBuffer[NextRunningAverage++] = RawTemperature;
7
  if (NextRunningAverage >= RunningAverageCount)
8
  {
9
    NextRunningAverage = 0; 
10
  }
11
  float RunningAverageTemperature = 0;
12
  for(int i=0; i< RunningAverageCount; ++i)
13
  {
14
    RunningAverageTemperature += RunningAverageBuffer[i];
15
  }
16
  RunningAverageTemperature /= RunningAverageCount;
17
 
18
  delay(100);
19
}

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Lars schrieb:
1
   float RunningAverageTemperature = 0;
Soso, Fließkommaberechnungen auf einem 8-Bit-Boliden. Und der 
Ausgangswert ist dazu noch ein Integer. Hut ab, das ist eine Leistung.
Mein Tipp: ich würde da einfach den Integerwert vom ADC filtern, Dann 
brauche ich kein float. Und wenn ich schon unbedingt die Tempertur 
filtern will, dann würde ich die auf 1/10 Grad in Integer packen: wenn 
im Integerwert 321 steht, dann ist die Temperatur 32,1 Grad. Dann spart 
man sich die Rechenzeit und die Probleme mit der eingeschränktenn 
Mantisse von Floatzahlen.
1
   for(int i=0; i< RunningAverageCount; ++i)
2
   {
3
     RunningAverageTemperature += RunningAverageBuffer[i];
4
   }
5
  RunningAverageTemperature /= RunningAverageCount;
"RunningAverage" ist aber eine eher unglückliche Übersetzung für 
"gleitender Mittelwert". Der Engländer schreibt da eher "Moving 
Average". Und dafür gibt es wesetnlich weniger aufwendige Rechenwege. Du 
musst z.B. nicht jedesmal alles aufsummieren, sondern nur den ältesten 
Wert abziehen und den Neuesten draufaddieren.

> So mit meiner Mittlerbildung: (von der Seite: ...
Das "Expotentialfilter" dort hat auch was.

> Dat hatte ich mir etwas anders vorgestellt
Das Konzept ist halt schon ein wenig wirr.

> Und zwar will ich ja versuchen mit dem Digital Poti mit einer Rampe auf
> einen Soll-Wert zu fahren.
Dann macht das doch einfach.
Du weißt doch, welchen Zielwert dein Poti haben soll. Und du weißt, 
welchen Wert du selbst zuletzt rausgeschrieben hast. Also musst du 
einfach diese beiden Werte miteinander vergleichen und dann den 
"Rausschreibewert" zum Zielwert hinführen.
Und der Witz: da ist kein ADC beteiligt, denn der Potiwert muss nicht 
zurückgelesen werden, weil du immer genau weißt, welchen Wert das Poti 
gerade hat.

Ich wiederhole es noch einmal: so wie du es machen willst, MUSST du dich 
mit Regelungstechnik und im speziellen Fall mit P- oder besser 
PI-Reglern auseinandersetzen. Man kann dem Kind vielleicht einen anderen 
Namen geben, es bleibt aber trotzdem so.

Und generell: wenn man aus einem µC eine Spannung ausgeben will, dann 
nimmt man einen DAC. Der kann das viel besser als so ein Poti.

: Bearbeitet durch Moderator
von Wolfgang (Gast)


Lesenswert?

Lars schrieb:
> Vorher habe ich einfach den eingelesenen Analogwert vom Digital Poti
> genommen Habe dazu 1 addiert und habe diesen Wert wieder zum Poti
> gesendet. So hat der sich Stück für Stück erhöht.

Bei der Referenzspannung für den ADC hast du in der Initialisierung 
hoffentlich die interne Referenz abgeschaltet (REFS=0, Kap 23.9.1 ADMUX 
im Datenblatt des ATmega328).
Wieso verwendest du die +5V_Ref als Versorgungsspannung für den 
Digitalteil des Potis (VDD)?
Als Puffer bei dynamischer Belastung durch den ADC sollte ein 
Kondensator an A1 nicht fehlen.

von Lars (Gast)


Lesenswert?

Lothar M. schrieb:
> Soso, Fließkommaberechnungen auf einem 8-Bit-Boliden. Und der
> Ausgangswert ist dazu noch ein Integer. Hut ab, das ist eine Leistung.
> Mein Tipp: ich würde da einfach den Integerwert vom ADC filtern, Dann
> brauche ich kein float. Und wenn ich schon unbedingt die Tempertur
> filtern will, dann würde ich die auf 1/10 Grad in Integer packen: wenn
> im Integerwert 321 steht, dann ist die Temperatur 32,1 Grad. Dann spart
> man sich die Rechenzeit und die Probleme mit der eingeschränktenn
> Mantisse von Floatzahlen.

Jau, das mit der Fließkommaberechnung scheint nicht so toll auf dem 
kleinen Nano zu sein. der braucht da knapp 3ms für. Ich hatte das auch 
einfach so kopiert gehabt.
Da scheint auch irgendwie ein Fehler in der Mittelwert Berechnung zu 
sein
und zwar wenn ich den ADC Wert von A0 einlese
float RawTemperatureA0 = analogRead(A0);
dann bekomm ich manchmal nach der Mittelwert bildung bei der Ausgabe auf 
den Seriellen Monitor ein "Overflow" wert für die Float variable.

Also das mit Float ist irgendwie merkwürdig.
Meinst du mit der Integerfilterung ich nehme ~8x die Roh Daten aus dem 
ADC(10bit) und teile die dann durch 8 um immer im Integer Rahmen zu 
bleiben ?
Diese "Temperatur variablen" die da rein gekommen sind nur wegen der 
Website so benannt ich hab keine Temperatur


Wolfgang schrieb:
> Bei der Referenzspannung für den ADC hast du in der Initialisierung

Die Ref Spannung beim ADC ist abgeschaltet und kann extern versorgt 
werden.

von Lars (Gast)


Lesenswert?

Lars schrieb:
> Da scheint auch irgendwie ein Fehler in der Mittelwert Berechnung zu
> sein

Ha da scheint irgendwo ein Faktor 2 drin zu sein - Ich lese als Roh 
Daten 1000 ein und nach der Mittelwert Bildung hab ich nur noch 500 als 
wert

von Lars (Gast)


Lesenswert?

Lars schrieb:
> Ha da scheint irgendwo ein Faktor 2 drin zu sein - Ich lese als Roh
> Daten 1000 ein und nach der Mittelwert Bildung hab ich nur noch 500 als
> wert

Kommando zurück :D der Fehler lag bei mir

Es gibt einen Unterschied zwischen den beiden :D scheisse hab ich dafür 
lang gebraucht ^^
1
RunningAverageBufferA0[NextRunningAverage] = RawA0;
2
RunningAverageBufferA1[NextRunningAverage++] = RawA1;
3
4
oder
5
RunningAverageBufferA0[NextRunningAverage++] = RawA0;
6
RunningAverageBufferA1[NextRunningAverage] = RawA1;

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Lars schrieb:
> scheisse hab ich dafür lang gebraucht ^^
An so einer Stelle freut man sich dann, wenn man einen funktionierenden 
Debugger hat.

Den Rest meines Posts, im Besondern den Abschnitt mit "du brauchst für 
diese Rampe keinen ADC" hast du aber auch gesehen und verstanden?

von Lars (Gast)


Lesenswert?

Lothar M. schrieb:
> Den Rest meines Posts, im Besondern den Abschnitt mit "du brauchst für
> diese Rampe keinen ADC" hast du aber auch gesehen und verstanden?

Lothar M. schrieb:
> Du weißt doch, welchen Zielwert dein Poti haben soll. Und du weißt,
> welchen Wert du selbst zuletzt rausgeschrieben hast

Jau, die Fehlersuche von meinem Letzten Post hatte etwas mehr zeit in 
anspruch genommen. Nun wollte ich mich an deinen 2ten Ansatz wagen.

So ganz hab ich das noch nicht nachvollzogen.

Meinst du das in etwas so?
Ich lege meinen Sollwert auf 200 fest
und wenn mein Digital Poti bei 10 startet erhöhe ich das jede x Sekunden 
um 1 bis ich bei 200 angekommen bin?

Interessant, wenn ich jetzt so darüber nachdenke, warum hab ich das 
nicht vorher schonmal ausprobiert ? ;-) mhm Gute Frage.

Ich vermute ich war irgendwie davon ausgegangen, das wenn ich bei dem 
Poti sage "stell dich mal auf 200" das ich das auch noch kontrollieren 
sollte.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Lars schrieb:
> Meinst du das in etwas so?
Ja.

> Ich vermute ich war irgendwie davon ausgegangen, das wenn ich bei dem
> Poti sage "stell dich mal auf 200" das ich das auch noch kontrollieren
> sollte.
Warum sollte das nötig sein?
Ich kontrolliere da nichts. Ich (bzw. der entsprechende Softie) gebe 
z.B. dem DAC den Befehl: gib umgerechnet 5V aus. Und dann tut er das. 
Höchstens, irgendwer schließt den Ausgang kurz oder macht sonstige 
Dummheiten oder die Steuerung ist kaputt. Aber das ist mir egal, weil es 
eben kein Problem meines DAC ist. Das funktioniert weltweit tadellos 
mehrfach in zigtzehnausenden Steuerungen.

: Bearbeitet durch Moderator
von Lars (Gast)


Lesenswert?

Lothar M. schrieb:
> Warum sollte das nötig sein?

Ja stimmt da hast natürlich recht. wenn ich dem sage stell dich auf den 
Wert, dann muss ich in einer funktionierenden Welt natürlich auch davon 
ausgehen das das passt ;).

Ach, das ich auch immer so kompliziert denken muss :D

von Lars (Gast)


Lesenswert?

Lothar M. schrieb:
> Ich kontrolliere da nichts.

So also insgesamt habe ich nun alle Verbesserungen eingepflegt, aber 
irgendwie bin ich noch nicht so zufrieden was den "Endwert" angeht das 
geht garantiert besser.

Ich gehe mal wieder von meinem Sollwert( eingelesener Real Potiwert mit 
gleitenden Mittelwert) 200 aus und das Digitalpoti startet bei 0. Das 
fährt nun pro Sekunde 1 weiter hoch. Jetzt kommt das Digital Poti bei 
200 an und die Rampe stoppt. Wenn sich jetzt Sollwert auf 201 ändert 
dann erhöht sich das Digitalpoti wieder um 1 und wenn wenn der Sollwert 
wieder auf 200 gemittelt ist dann verringert sich das Poti wieder um 1.

So wenn ich den Sollwert so blöd eingestellt hab das der immer zwischen 
201 und 200 schwankt dann zappelt auch die ganze zeit das Digital Poti 
hin und her.

Mit meinem Programm für eine obere und untere Grenze z.B. +- 3 hat das 
irgendwie nicht geklappt, denn dann hat das Digitalpoti halt schon bei 
197 aufgehört hochzulaufen, weil Sollwert-3 dann schon im "richtigen" 
Bereich liegt. ich würde das aber irgendwie gerne realisiert haben das 
das Digital Poti ERST! so nah wie möglich auf den Sollwert fährt und 
dann die Abweichung von +-3 geprüft wird so das es doch dann eigentlich 
viel genauer sein müsste.
Irgendwie komme ich da grad nicht drauf wie ich das realisieren kann
Oder habe ich da einen Denkfehler.

Vielen Dank schonmal für Eure Hilfen, Ihr seid Klasse.
Gruß,
Lars

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Lars schrieb:
> Wenn sich jetzt Sollwert auf 201 ändert
> dann erhöht sich das Digitalpoti wieder um 1 und wenn wenn der Sollwert
> wieder auf 200 gemittelt ist dann verringert sich das Poti wieder um 1.
Evtl. ein wenig provokant, aber einfach mal so gefragt: Wen juckts?

> So wenn ich den Sollwert so blöd eingestellt hab das der immer zwischen
> 201 und 200 schwankt dann zappelt auch die ganze zeit das Digital Poti
> hin und her.
Ja, klar. Das musst du dir mal verinnerlichen. Da hilft nichtmal eine 
endlos lange Mittelwertfilterung.

Lars schrieb:
> Mit meinem Programm für eine obere und untere Grenze z.B. +- 3 hat das
> irgendwie nicht geklappt, denn dann hat das Digitalpoti halt schon bei
> 197 aufgehört hochzulaufen
Dein Problem ist auch NICHT das Nachführen des Digipotwertes (das geht 
ja schon, solange alles ruhig ist), sondern dass der Mittelwert um 1 
zappelt.

Du musst also nur dafür sorgen, dass nicht jeder kleine Zappler am 
Drehpoti zu einer Änderung deines Digipotwertes sorgt. Dort im 
Beitrag "ADC-Werte entflackern" haben wir das mal 
diskutiert.

von Lars (Gast)


Lesenswert?

Lothar M. schrieb:
> Du musst also nur dafür sorgen, dass nicht jeder kleine Zappler am
> Drehpoti zu einer Änderung deines Digipotwertes sorgt. Dort im
> Beitrag "ADC-Werte entflackern" haben wir das mal
> diskutiert.

Konnte Gestern Abend nur mal gerade in den Thread reinschauen, aber das 
las sich interessant. Wer ich mich heute Abend wenn es wieder in den 
Bastel-Keller geht dransetzten und ausprobieren ;-). Danke für den Tipp

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.