Spannungsabhänge PWM Steuerung

Hallo,
erst mal vorweg: dies ist mein erster Versuch ein auf einen Arduino hochspielbares "Programm" zu schreiben, bitte steinigt mich nicht gleich wenn ich daneben liege...

Mit dem Programm möchte ich einen IRLML2502, abhängig von der Spannung die an seinem Eingang anliegt, ansteuern. Je höher die Spannung, desto breiter soll der duty cycle werden.

Ein paar Details sind mir, trotz lesen vieler tuturials, leider noch nicht klar, - ich habe die Fragen als Kommentare in den Sketch eingefügt.

//fehlen hier #incudes?

const int sensorPin = 0; // pin Nr muss angepasst werden
const int analogOutPin = 9; // pin Nr muss angepasst werden

int outputValue = 0;
int sensorValue = 0;
int spannung = 0;
int rememberV = 0

void setup() {
//MUSS hier etwas stehen?
}

void loop() {

sensorValue = analogRead(sensorPin); //Spannung messen (Spannungsteiler für 20V)
if (spannung < 200) spannung = 0; // Spannung auf null setzen wenn Spannung < 3,9V
rememberV = spannung;
if (spannung > rememberV) outputValue ++1;
if (spannung < rememberV) outputValue --1;
if (spannung == 0) outputValue = 0;
if (outputValue > 255) outputValue = 255
analogWrite(analogOutPin, outputValue); //geht auf Mosfet als Verstärker

delay(200); //läuft die PWM Ausgabe währent des delays weiter oder wird sie auch unterbrochen?

}

Das ganze soll auf einen Nano oder Mini, das sollte gehen denke ich...

//fehlen hier #incudes?

nein

//MUSS hier etwas stehen?

nein

//läuft die PWM Ausgabe währent des delays weiter oder wird sie auch unterbrochen?

der PWM wert ist schon ja geschrieben, also bleibt der Wert bis zum nächsten überschreiben

if (spannung < 200) spannung = 0; // Spannung auf null setzen wenn Spannung < 3,9V
spannung wird immer < 200 sein!

Was möchtest du denn mit dem Projekt machen? Vielleicht hilft die Info bei der Lösungsfindung....

Und schmeiss bitte das Delay raus :wink:

Hast du den Sketch schon mal getestet ?

Ich vermute, der funktioniert nicht, da die "if-Anweisungen" irgendwie nicht sinnig erscheinen.

Auch wird die Variable "Spannung" anfangs nicht gefüllt, dadurch ergibt sich für mich keinen Sinn.

0V ist auch schon mit < 3,9V abgedeckt...

Du kannst, wenn sich der Ausgang schnell anpassen soll einfach eine mapping Funktion nehmen um die Werte des analogen Eingangs direkt in ein PWM umzuwandeln. Da bist du mit 2 Zeilen fertig.

Soll eine Trägheit mit rein, speicherst du die Ausgabe des gemappten Wertes und läßt dann, wie du es schon beschrieben hast, den Zielwert langsam nachführen, dass dann aber ohne delay.... mal ins unreine geschrieben:

//hier mapping;
if (millis() - Zeitmarke > Intervall)
{ Zeitmarke = millis();
if (gemappterWert > Zielwert) { Zielwert++;}
if (gemappterWert < Zielwert) { Zielwert--; }
}
analogWrite(LEDPin, Zielwert);

natürlich mußt du die Variablen vorher noch deklarieren...

Guten Morgen
und erst mal: Danke für die Infos.

Ich möchte mit der Schaltung die mögliche Leistungsentnahme an einem (kleinen) Windrad regeln. Wenn Euch interessiert woran ich (wir) so tüfteln...: www.daswindrad.de
Das Problem bei den Windrädern ist, dass die Leistungskurve des Rotors nicht zur Leistungskurve eines Generators past.
Weil die Last (z.B. bei Batterieladung) fast immer mehr haben möchte als der Rotor liefern kann muss irgendwie begrenzt werden wie viel Strom fließt.

@ HotSystems
Du hast recht, spannung bleibt ja immer 0.
Hab nach dem rüberkopieren aus den Beispielen vergessen die Variable anzupassen.

//läuft die PWM Ausgabe währent des delays weiter oder wird sie auch unterbrochen?
der PWM wert ist schon ja geschrieben, also bleibt der Wert bis zum nächsten überschreiben

Das ist schon klar, ich wollte wissen ob der PWM Pin auch wärend des Delays weiterarbeitet oder ob er auch Pause macht.

@MaHa76
das ganze soll (in MC geschwindikkeit gedacht) relativ langsam ablaufen, die 5 Messungen pro Sekunde die ich mit dem Delay (weshalb mögt ihr den eigentlich nicht?) erreichen möchte sind eigentlich schon overkill.

Die Variante mit dem "2 Zeilen Mapping" hatte durchdacht, ich bin aber der Meinung, dass das noch zu direkt ist.

wenn ich diesen Teil des Codes von Dir

if (millis() - Zeitmarke > Intervall)
{ Zeitmarke = millis();

richtig verstehe, dann erstetzt er das delay, - mal gucken ob ich das hinbekomme...

Genau- mit meinen Zeilen ersetzt du delay.... wenn du deine Spannung die du verfolgen willst auf 0 ... 255 mappst und für den Intervall 4 wählst würde die Steuerung einem Sprung der Spannung am Eingang in einer Sekunde folgen.

Kleineren Spannungsänderungen würde es entsprechend schneller nachlaufen können. Wenn du generell eine andere Dynamik willst- dass die Steuerung auf große schnelle Änderungen schnell reagiert und bei kleinen Änderungen träger reagiert, kannst du auch die Differenz von Zielwert zu gemappterWert als Wert für deinen Intervall nehmen - z.b. Intervall = 255/(Zielwert - gemappter Wert);

Spannendes Projekt übrigens :slight_smile:

enn du generell eine andere Dynamik willst- dass die Steuerung auf große schnelle Änderungen schnell reagiert und bei kleinen Änderungen träger reagiert, kannst du auch die Differenz von Zielwert zu gemappterWert als Wert für deinen Intervall nehmen - z.b. Intervall = 255/(Zielwert - gemappter Wert)

Das wäre die optimale Variante... Danke!

Spannendes Projekt übrigens

im Moment leider etwas eingeschlafen. Ich hoffe durch die Regelung wieder etwas Dynamik in die Geschichte zu bringen... :slight_smile:

Na dann schreibe mal mit den bisherigen Tipps einen Sketch und teste ihn- setze ihn dann mal direkt hier rein- dann schauen wir mal drüber...

herbk:
die 5 Messungen pro Sekunde die ich mit dem Delay (weshalb mögt ihr den eigentlich nicht?)

In deinem Fall ist es mit dem "delay" noch nicht kritisch.
Aber Grundsätzlich ist ein "delay" immer "blockierend" !

Während dieser Zeit ist der Controller zum "Nichtstun" verdammt. Er wird auf keinerlei Aktionen (Taster, Sensoren usw.) reagieren. Sobald du es mit der Funktion "millis" löst, reagiert der Controller auch in der "Wartezeit".

Guten Morgen,
dass ein den Programmablauf unterbricht hatte ich schon verstanden (deshalb ja auch die Frage ob die PWM Ausgabe auch unterbrochen wird).
Die Unterbrechung fand ich sogar hilfreich, weil ich davon ausgegangen bin (gehe ich immer noch..) dass ein Prozessor der nichts tut weniger Energie braucht als einer der arbeitet.

Dass es zum Energiesparen bessere Methoden gibt, habe ich mittlerweile aber auch gelesen. - Ist aber ein Thema das ich erst mal hinten anstelle...

Gestern Abend habe ich dann erst mal nnachgelesen was "millis" eigentlich ist/macht.
Dazu noch eine Frage: Kann/muss man millis eigentlich zurücksetzen?

@MaHa76

.... für den Intervall 4 wählst würde die Steuerung einem Sprung der Spannung am Eingang in einer Sekunde folgen.

Das verstehe ich nicht... weshalb erzeugt intervall 4 einen Zyklus von 1 Sekunde?

Ein Sprung von 0 aufmax sind bei der 8bit Auflösung des PWMs 255 Schritt. Je 4ms Sind dann 1020ms, als rund 1s.

Wenn du ein delay von 200ms einfügst würde der Prozessor etwaige Spannungsspitze nicht mal merken.

weil ich davon ausgegangen bin (gehe ich immer noch..) dass ein Prozessor der nichts tut weniger Energie braucht als einer der arbeitet.

Dann willst du den Prozessor in den Sleep schicken?
Im Deepsleep bleibt allerdings auch dein PWM stehen.

Nein: Delay() ist keine Stromsparmaßnahme.
Ob er in einer Warteschleife rum trampelt, oder was nützliches tut... egal...

Was nützliches wäre z.B. eine MPPT Regelung .
Das würde bei eurem Windrad Sinn machen.

Dazu noch eine Frage: Kann/muss man millis eigentlich zurücksetzen?

Häää....
Man kann, ist aber sinnfrei.
Nein muss man nicht.
Macht es selbstständig nach 49,X Tagen.

rememberV = spannung;
if (spannung > rememberV) outputValue ++1;
if (spannung < rememberV) outputValue --1;
if (spannung == 0) outputValue = 0;
if (outputValue > 255) outputValue = 255

Die ersten beiden if Anweisungen können doch so nie ausgelöst werden.

Das rememberV = spannung; muss doch danach kommen

MaHa76:
Ein Sprung von 0 aufmax sind bei der 8bit Auflösung des PWMs 255 Schritt. Je 4ms Sind dann 1020ms, als rund 1s.

Wenn du ein delay von 200ms einfügst würde der Prozessor etwaige Spannungsspitze nicht mal merken.

Du hast theoretisch recht, praktisch aber nicht. Es geht um Windräder. Die sind mechanisch träge, da kanns du nicht in ms enorme Beschleunigungen und Abbremsungen aufbauen. Windräder puffern Energie in der Masse. So tun das auch Kraftwerksgeneratoren. Dort ist einige Megawatt an Energie drin(ca 2% der Kraftwerksleistung).

Die Geschwindigkeitsveränderung und damit die Spannungserhöhung erfolgt also ziemlich träge. Hier sind 200ms durchaus akzeptabel. Wir haben keine schnellen Spannungsänderungen an Windrädern. Genauso sieht es bei Wärme aus. Dort ist auch eine große Trägheit in der Änderung.

Wenn du dann aber alle paar ms misst und den Regelkreis nachführst kann dir das ganze anfangen zu schwingen und viel größere Abweichungen erzeugen als nötig. Das kompensiert man dann meist mit PI-Reglern. Aber wieso ein Problem generieren, um das dann elegant zu lösen, wenn man das Problem vermeiden kann.

@Combi
Nicht so ganz, im Leerlauf eines Delay arbeitet zb der Adress und Datenbus garnicht. Es muss nichts geholt werden oder geschrieben. Grundsätzlich ändert sich der Stromverbrauch für jede Operation, mal ist es mehr mal weniger. Delay dürfte intern wohl wenig Bereiche ansprechen und daher den Stromverbrauch senken. Weder muss man die Busse ansprechen noch wird RAM oder Flash ausgelesen, das spart durchaus Strom. Am Akku macht sich 10% mehr Laufzeit sicherlich bemerkbar. Am Netzteil vermutlich den Aufwand nicht wert.

Es muss nichts geholt werden oder geschrieben.

Falsch!

Auch die Nops und Vergleiche müssen aus dem Flash geholt werden.
Die Daten für die Vergleiche stehen im Ram.
Die Busse laufen also unter Volldampf.
Auch die Timer und Taktgeneratoren arbeiten mit Volldampf.

Messe die Sache aus, und dann sage uns, über wie viel Promille Einsparung wir hier reden.

Hallo Chefin- daher mein Vorschlag dies dynamisch zu machen- kleinen Änderungen langsam zu folgen und großen schneller... mit einem festen delay verbaut man sich alle Chance zu reagieren.

Die Spannung einer Spannungsquelle ist nicht nur allein von der Spannungsquelle abhängig, sondern auch vom Verbraucher, von der abgerufenen Last. Da kann es schon Sinn machen darauf zu reagieren.

Edit: Nimm als Beispiel den Anlauf des Windrades- die Spannung geht von 0V auf *V... jetzt folgt die Regleung der Spannung alle 200ms um einen Schritt... ist bei max. also nach 40 sekunden.... Ist das sinnvoll?

//fehlen hier #incudes?Nein. Nur wenn du spezielle Libraries haben willst.

void setup() {
    //MUSS hier etwas stehen?
}

ja!
Hier musst du die Ein- und Ausgänge definieren.
Also:

void setup() {
    pinMode(sensorPin, INPUT);
    pinMode(analogOutPin, OUTPUT);
}
void loop() {

sensorValue = analogRead(sensorPin); //Spannung messen (Spannungsteiler für 20V)

ich nehme an, dass soll spannung = analogRead(sensorPin) sein?

if (spannung < 200) spannung = 0;  // Spannung auf null setzen wenn Spannung < 3,9V
rememberV = spannung;
if (spannung > rememberV) outputValue ++1;

das macht keinen Sinn.
Erst setzt du beide gleich, dann fragst du, ob einer größer ist!

if (spannung < rememberV) outputValue --1;
if (spannung == 0) outputValue = 0;
if (outputValue > 255) outputValue = 255

outputValue < 0 musst du auch abfangen.

analogWrite(analogOutPin, outputValue);  //geht auf Mosfet als Verstärker

delay(200);  //läuft die PWM Ausgabe währent des delays weiter oder wird sie auch unterbrochen?

delay ist schlechter Stil, aber in dem Zusammenhang funktioniert es.

Hallo zusammen,
erst mal noch mal Danke für die Korrekturen.

D.H. so sollte das erst mal funktionieren?

const int sensorPin = 0; // pin Nr muss angepasst werden
const int analogOutPin = 9; // pin Nr muss angepasst werden

int dutycycle = 0;
int spannung = 0;
int rememberV = 0;

void setup() {
pinMode(sensorPin, INPUT);
pinMode(analogOutPin, OUTPUT);
}

void loop() {

spannung = analogRead(sensorPin); //Spannung messen (Spannungsteiler für 20V)
if (spannung < 200) spannung = 0; // Spannungswert auf null setzen wenn Spannung < 3,9V
if (spannung > rememberV) dutycycle ++1;
if (spannung < rememberV) dutycycle --1;
if (spannung == 0) dutycycle = 0;
if (dutycycle > 255) dutycycle = 255;
rememberV = spannung;

analogWrite(analogOutPin, dutycycle); //geht auf Mosfet als Verstärker

delay(200);

An der "millis Version" bastle ich noch :wink:

@ Gunter

outputValue < 0 musst du auch abfangen.

Weshab? Die Spannung kann doch nicht <0 werden. (outputvalue hab ich auf dutycyle geändert damit es für mich übersichtlicher ist)

@MaHa76

Nimm als Beispiel den Anlauf des Windrades- die Spannung geht von 0V auf *V... jetzt folgt die Regleung der Spannung alle 200ms um einen Schritt... ist bei max. also nach 40 sekunden.... Ist das sinnvoll?

Ohne Last am Generator beschleunigt mein besster Rotor bei einer konstanten Windgeschwindigkeit von 3,5m/s in etwa 15 Sekunden so weit, dass eine Leerlaufspannung von ca. 4,5V am Generatorausgang (nach Gleichrichtung) anliegt, - für 20V unter Last bräuchte ich rund 40m/s Wind...

Damit die von Dir geschilderte Situation, von 0 auf 100% duty cycle in 40 Sekunden, entstehen könnte, bräuchten wir schon seeeehr schnell ansteigenden Wind... Ich leb in Mittelfranken, nicht in Florida..:smiley: :smiley:

Aber wie oben schon geschrieben: Eine dynamische Anpassung des entnehmbaren Stroms halte ich auch für die A Lösung.
Das wird aber erst der nächste Schritt, jetzt soll (wenn es so funktioniert) der "schlechte Stil" erst mal zeigen ob ich gedanklich (bei der Stromentnahmeregelung) überhaupt auf dem richtigen Weg bin...
Und zu tun hat der Nano eh nichts anderes... :wink:

herbk:
D.H. so sollte das erst mal funktionieren?

Nö.

Zwei Bitten:

  1. Wenn du Code postest, schliesse ihn in Code-Tags ein. (das Symbol </> oben links)
  2. Bevor du Code postest, lass ihn doch mal compilieren. (in der Arduino IDE der Haken oben links)

Dein jetziger Code ist nicht lauffähig.

ein Tip:
"dutycycle ++1" ist falsch.
entweder "dutycycle = dutycycle +1"
oder dutycycle += 1
oder dutycycle++

Dann sollte der Code laufen.

wegen Outputvalue < 0 abfangen.
ja, du hast recht.
Das sollte nie vorkommen.
Aber kann nie ausschliessen, das die Abfrage if (spannung < rememberV) dutycycle--; nicht vielleich doch irgendwann mal ein -1 liefert.
Es ist sicherer, das abzufangen. Und kostet nichts.

Was ich mich aber noch frage:
Was genau soll einentlich wie geregelt werden?

Aktuell sieht dein Algorithmus so aus:
immer wenn die Spannung steigt, wird der Dutycycle erhöht und umgekehrt.

Eine Regelung sieht aber meist so aus:
Ich habe einen Sollwert, vergleiche den mit den Istwert und ändere dann die Stellgröße.

z.B. so:

int U_Soll = 500;  
  if (spannung > U_Soll) dutycycle++;
  if (spannung < U_Soll) dutycycle--;