Guten Abend zusammen,
ich bin gerade über ein Problem bei mir gestolpert, bei dem ich nicht
weiß wie ich das lösen kann. Das Problem liegt vermutlich an bei der
Bildung eines gleitenden Mittelwerts.
Und zwar habe ich einen Sollwert 0-1023 welcher mit dem map Funktion vom
Arduino auf einen 8 Bit Wert 0-255 abbilden soll.
Den Sollwert gebe ich vor und die 0-255 gehen an ein Digitales Poti.
Der Wert vom Digitalen Poti wird dann über den ADC eingelesen und dann
in bestimmten Zeitintervallen um 1 erhöht. Das Problem was ich nun habe
ist das meine Erhöhung um 1 ab einem Sollwert von ~400 im rauschen des
Digi Potis untergeht und dann über meinen gleitenden Mittelwert
rausgemittelt wird.
Das Poti wird dann nicht mehr erhöht.
in der Variable "DigitalPoti" steckt der über 16 Werte gemittelte
eingelesen wert vom Digital Poti. Wenn ich das +1 auf +2 ändere dann
funktioniert es, aber ich hätte es gerne mit der +1 Erhöhung
hinbekommen, aber ich stehe da irgendwie auf dem Schlauch.
Franky schrieb:> if (millis() > myTimeout8ADC + myTimer8ADC ) { /7 Alle 100ms> myTimer8ADC = millis();> ADC_Werte_konvertieren();> }
Schon hier geht es nach einiger Zeit schief. Da hat jetzt nichts mit
deinem ADC zu tun, aber guck dir mal an, wie man millis() verwenden
muss, damit soetwas nicht plötzlich scheinbar hängt.
Stichwort: überlaufsichere Verwendung von millis()
Warum liest du die Einstellung des digitalen Potis analog zurück?
Du kannst dir doch einfach den zuletzt eingestellten Wert merken und
dann dazu die 1 addieren (anstatt auf den zurück gelesenen Wert).
Wolfgang schrieb:> Stichwort: überlaufsichere Verwendung von millis()
oh das Checke ich gleich mal, ich hatte da schonmal etwas drüber
gelesen, aber ich dachte das wäre nur interessant wenn man lange
laufzeiten mit millis "messen" möchte. bei mir sinds nur 0,1s bis 3s.
Stefan ⛄ F. schrieb:> Warum liest du die Einstellung des digitalen Potis analog zurück?
mhm, das verstehe ich nicht ganz, ich wollte mit dem einlesen und
mitteln des Potiwerts eine "saubere" Kurve hinbekommen, weil ich
wirklich den realen Wert dann für die weitere Verwendung habe. Oder ist
das keine gute Idee?
Lothar M. schrieb:> Ein Dejavu: Beitrag "Re: Arduino -> Digital Poti -> Wert über ADC wieder> einlesen"
Ja, aus diesem Beitrag hatte ich teile von meinem Code hergenommen vor
Allem die Mittelwertbildung war da ganz gut erklärt, das schien mir da
ein ähnliches Problem zu sein, Aber ein Lösungsansatz konnte ich da
nicht herauslesen :(
Franky schrieb:> das schien mir da ein ähnliches Problem zu sein
Die Lösung war damals schon bitterer Murks. Nochmal dranrum murksen
macht das nicht besser.
> im rauschen des Digi Potis
Sei dir sicher: das Ding rauscht in deiner Schaltung sicher am
wenigsten.
Mein Vorschlag: du zeigst deine Hardware mit Bauteilnamen und
Tybezeichnungen in einem Schaltplan und beschreibst, was da passieren
soll. Und darauf basierend schauen wir zusammen, wie eine brauchbare
Lösung aussehen würde.
Lothar M. schrieb:> Mein Vorschlag: du zeigst deine Hardware mit Bauteilnamen und> Tybezeichnungen in einem Schaltplan und beschreibst, was da passieren> soll. Und darauf basierend schauen wir zusammen, wie eine brauchbare> Lösung aussehen würde.
Okay, vielen Dank, das mache ich parat. :-)
Franky schrieb:> oh das Checke ich gleich mal, ich hatte da schonmal etwas drüber> gelesen, aber ich dachte das wäre nur interessant wenn man lange> laufzeiten mit millis "messen" möchte.
Nein, das Problem tritt genauso bei kurzen Zeiten auf - allerdings erst
einige Zeit nach dem letzten Reset des µC.
[c]
map(DigitalPoti, 0, 1023, 0, 256)) - 1);
[\c]
Mal 2 Fragen:
Ist es Absicht dass so ein krummer Faktor (3,984435797665) verwendet
wird?
Und wenn nein, warum nimmt man dafür eine map Funktion die aus 4
Additionen, 1 Multiplikation und 1 Division besteht anstatt 2 Mal rechts
schieben?
MaNi schrieb:> Ist es Absicht dass so ein krummer Faktor (3,984435797665) verwendet> wird?
Tatsache, das war ein Tippfehler. da muss natürlich 255 stehen!
Stefan ⛄ F. schrieb:> Warum liest du die Einstellung des digitalen Potis analog zurück?
Ich habe das nun angepasst und Speicher mir den wert in eine Variable ab
und erhöhe diese dann, das scheint zu funktionieren. Ich weiß nicht
genau warum ich in meinem Kopf gedacht habe das es mit dem rückgelesenen
wert besser wäre :D
Wolfgang schrieb:> Stichwort: überlaufsichere Verwendung von millis()
So jetzt begebe ich mich mal diesem Problem, das war mir irgendwie nicht
bewusst das das ein Problem gibt. Aber ich schaue mir mal an was da das
Problem ist. Vielen Lieben Dank auf Jeden fall schon einmal
Franky schrieb:> So jetzt begebe ich mich mal diesem Problem, das war mir irgendwie nicht> bewusst das das ein Problem gibt.
Es dauert aber lang, bis du dieses spezielle Problem hast. Und dessen
Behebung wird deinen Fehler nicht beheben. Dadurch wird nur dein
Programm an irrelevanter Stelle besser.
Zeichne lieber mal den Schaltplan und mach ein paar Fotos vom Aufbau,
statt deine Zeit mit solchen Übersprungshandlungen zu verplempern.
https://dorsch.hogrefe.com/stichwort/uebersprung-uebersprungshandlung
Lothar M. schrieb:> Es dauert aber lang, bis du dieses spezielle Problem hast. Und dessen> Behebung wird deinen Fehler nicht beheben.
Nichts ist lästiger als Fehler, die nur selten unter unklaren
Bedingungen auftreten - insbesondere, wenn ein Programm tagelang
(scheinbar) problemlos läuft und plötzlich seinen Dienst versagt, obwohl
es vorher doch sooh gut lief.
Lothar M. schrieb:> Zeichne lieber mal den Schaltplan und mach ein paar Fotos vom Aufbau,> statt deine Zeit mit solchen Übersprungshandlungen zu verplempern.
Den Schaltplan habe ich schonmal einscannen können. Ich hoffe das es
dadurch etwas klarer wird. Ein Foto vom Aufbau ist gerade nicht möglich,
keine Kamera/Smartphone zur Hand.
Aber es ist ganz rudimentär auf einer Lochraster Platine aufgebaut. Der
Ausgang des OPs geht eine Dimmbare LED Beleuchtung an meiner Bar, diese
möchte im Eingang 0-5V sehen.
Lothar M. schrieb:> Es dauert aber lang, bis du dieses spezielle Problem hast. Und dessen> Behebung wird deinen Fehler nicht beheben. Dadurch wird nur dein> Programm an irrelevanter Stelle besser.
Wenn ich das richtig verstanden habe dann tritt dort ein Problem nach
ca. 50 Tagen des Programmstarts auf, weil der Timer dann überläuft. Mir
ist noch nicht ganz bewusst warum das bei mir ein Problem ist, weil ich
ja nur ganz kurze intervalle habe.
Du willst also anhand einer Potistellung eine Spannung von 0-5V
ausgeben?
Dafür reicht ein Poti alleine.
Wenn du noch mehr Leistung benötigst von mir aus ein OP o.ä.
Leistungsstufe.
Aber für was genau brauchst du einen uC und einen digitalen Poti?
MaNi schrieb:> Aber für was genau brauchst du einen uC und einen digitalen Poti?
Guten Abend,
Das "Sollwert"-Poti ist momentan nur zum Manuellen spielen. Später würde
ich gerne die LEDs Faden lassen und für das hoch und runterfahren würde
ich gerne den Arduino benutzen. =)
Franky schrieb:> Später würde ich gerne die LEDs Faden lassen
Dann mach es doch wie alle anderen auch.
Nimm eine PWM und steuere entweder die LEDs über einen MOSFET oder
Transistor an.
MaNi schrieb:> Dann mach es doch wie alle anderen auch.
Der Rest existiert doch schon ;-) ich möchte mir nur mit dem Digital
Poti eine Spannung von 0V-5V erzeugen.
Es läuft ja auch schon größtenteils alles. Ich hatte halt das Problem
mit dem gleitenden Mittelwert.
Franky schrieb:> Das "Sollwert"-Poti ist momentan nur zum Manuellen spielen. Später würde> ich gerne die LEDs Faden lassen und für das hoch und runterfahren würde> ich gerne den Arduino benutzen. =)
0..5V bekommt man mit einen D/A-Wandler hin. MCP4725 gibt es günstig als
Chinaplatinchen, die passende A*-Library ist ebenfalls kalglos
auffindbar.
Franky schrieb:> ich möchte mir nur mit dem Digital Poti eine Spannung von 0V-5V> erzeugen.
Das kannst du aber mit einer PWM und einem Tiefpass um Welten einfacher
und weniger fehleranfällig.
Franky schrieb:> Es läuft ja auch schon größtenteils alles.
Das bezweifle ich.
Du schreibst die ganze Zeit vom Mittelwert, aber bist du dir zu 100%
sicher dass jeder Wert den du in das Poti schreiben möchtest auch
wirklich an dessen Ausgang so umgesetzt wird?
Was für einen Wert bekommt denn digitalPotWrite, wenn DigitalPoti == 0
ist:
Franky schrieb:> Ich hatte halt das Problem mit dem gleitenden Mittelwert.
Ich verstehe ehrlich gesagt nicht warum du den überhaupt bildest.
Mach eine Steuerung.
Sollwert stellen. Und wenn nicht gerade die Welt untergeht, dann stimmt
der Wert innerhalb der Toleranzen.
Wolfgang schrieb:> obwohl es vorher doch sooh gut lief.
Ja, daran arbeiten wir gerade. Und als "Abfallprodukt" kann man dann das
mit den millis() auch noch richten.
Franky schrieb:> Den Schaltplan habe ich schonmal einscannen können.
Mit Typbezeichnungen meinte ich die Bestellbezeichnungen der Bauteile,
so dass man sich ggfs. mal das Datenblatt dazu ansehen kann.
MaNi schrieb:> Dafür reicht ein Poti alleine.
Das sollte doch im Grunde nicht allzu schwierig zu verstehen sein: bei
diesr Anwendung muss die Potistellung deshalb nicht "zurückgelesen"
werden, weil man sie mit einem Stellwert eindeutig selber festlegen
kann.
Franky schrieb:> Den Sollwert gebe ich vor und die 0-255 gehen an ein Digitales Poti.> Der Wert vom Digitalen Poti wird dann über den ADC eingelesen und dann> in bestimmten Zeitintervallen um 1 erhöht.
Ein Programm, das genau das macht, sieht so aus:
Hier wird also einfach jeweils nach der "Wartezeit" der nächsthöhere
Wert zum Poti geschickt. Das wars, dafür ist kein ADC nötig, ich kenne
die "Potistellung" ja ganz genau.
Manfred schrieb:> 0..5V bekommt man mit einen D/A-Wandler hin.
Oder sogar mit der PWM-"Analogausgabe" des Andruiden. Wobei der ADC
anerkanntermaßen das Mittel der Wahl ist.
BTW: diese map() Funktion im "Originalprogramm" kann ganz leicht duch 1
Minute Nachdenken und ein "/4" ersetzt werden. Ich bekomm da fast die
Krätze ans Auge, wenn man so eine einfache Rechung, die der Compiler in
zwei Assemblerbefehlen abhandeln kann, in eine umständliche Funktion
packt...
Lothar M. schrieb:> Ich bekomm da fast die> Krätze ans Auge, wenn man so eine einfache Rechnung, die der Compiler in> zwei Assemblerbefehlen abhandeln kann, in eine umständliche Funktion> packt...
Die Rechnung bzw. Wertebereich (0 bis 1023 / Zweierpotenz) ist ein
Sonderfall.
Ansonsten hat map() schon seine Berechtigung. Implementiert sie doch die
"Lineare Interpolation", welche im Grunde ein übliches/häufig
verwendetes Pattern ist.
Es ist hier also nicht das Problem, dass man das "in eine umständliche
Funktion packt", sondern dass es offensichtlich eine
einfachere/schlichtere Möglichkeit gibt.
Die Funktion selber ist ok.
Das in eine Funktion zu packen auch wohl.
Das man es "besser" implementieren könnte, insbesondere, wenn man
Annahmen über die Wertebereichen treffen kann, ist auch wohl war.
EAF schrieb:> Die Rechnung bzw. Wertebereich (0 bis 1023 / Zweierpotenz) ist ein> Sonderfall.
Aber eben hier im Thread der einzig relevante "Normalfall". Und wenn man
sich die Probleme manchmal näher anschaut, dann kann man mit solchen
"Sonderfällen" viele Aufgaben lösen. Nur muss man dafür halt ein wenig
"binär" und "maschinennah" denken.
> Das man es "besser" implementieren könnte
Mal angenommen, man möchte einen 8-Bit Wert mit dem ADC einlesen, dann
muss man nur den ADC richtig verwenden, dann liefert der schon den
passenden 8-Bit Wert zurück und es muß gar nichts skaliert werden. Dazu
muss man allerdings die verwendete Hardware kennen. Und das sollte für
einen Embedded-Programmierer, der ja unmittelbar an der Hardware
programmiert, selbstverständlich sein.
Franky schrieb:> digitalPotWrite( ((map(DigitalPoti, 0, 1023, 0, 256)) - 1));
Doppelt ärgerlich ist dann noch, dass in dieser Zeile mindestens 2
Fehler drin
sind die durch einen einfachen >> 2 nicht aufgetreten wären:
* Falsche Skalierung (1024/257) habe ich oben ja schon erwähnt.
* "Unterlauf" bei DigitalPoti == 0
Lothar M. schrieb:> Und das sollte für> einen Embedded-Programmierer, der ja unmittelbar an der Hardware> programmiert, selbstverständlich sein.
Ich halte deine Erwartungshaltung **hier** für überzogen.
Denn ganz offensichtlich ist Franky noch kein erfahrener
Embedded-Programmierer.
Aber das kann ja noch werden....
Wenn ich da auch noch meine Zweifel habe, denn die Reaktion auf die
Millis Problematik lässt schon auf hinderliches Beharrungsvermögen
schließen.
Lothar M. schrieb:> Mal angenommen, man möchte einen 8-Bit Wert mit dem ADC einlesen, dann> muss man nur den ADC richtig verwenden, dann liefert der schon den> passenden 8-Bit Wert zurück und es muß gar nichts skaliert werden.
Ja, aber so einfach denkt heute kaum noch jemand. In der Firma werde ich
immer für meine einfachen Lösungsansätze gefeiert.
Warum kann der Nachwuchs das nicht mehr? Vielleicht, weil die Menschen
immer weniger mit einfachen Lösungen aufwachsen.
Manche können ohne Thermomix scheinbar nicht einmal mehr einen Eintopf
kochen. Andere können sich nicht vorstellen, dass die Menschen schon vor
hunderten Jahren Kleidung trugen, die der heutigen sehr ähnlich ist. Als
ob man ohne App nur Bärenfelle und Kartoffelsäcke verarbeiten könnte.