PWM Steuerung Pumpe im laufenden Betrieb

Guten Tag,

ich möchte mit einem Mosfet meine 12V Aquarienpumpe via PWM steuern. Die Pumpe soll in Intervallen AN und AUS sein. Ich möchte später direkt am Poti während des Betriebs die Pumpgeschwindigkeit einstellen können. Da die Funktionalität in einen größeren Gesamtsketch eingebunden ist möchte ich das ganze ohne delay() sondern mit millis() realisieren.

Hier mein Aufbau - mein verwendeter MOSFET ist ein IRLZ44N, die Diode eine N4007, der Widerstand hat 10kOhm, der Poti ebenfalls linear 10kOhm, die Pumpe verträgt 12V und zieht ca. 0,6A, mein Netzteil liefert 12V und bis zu 2,5A, mein µC ist ein Arduino Nano und ist via USB an den PC angeschlossen (später wenn alles fertig ist wird er separat mit Strom versorgt):

Und hier mein kleiner sketch (alles was mit dem seriellen Monitor zu tun hat spielt im finalen sketch keine Rolle, kommt raus und dient hier nur der Kontrolle während des Aufbaus. Auch die gewählten Pumpintervalle sind nur beispielhaft. Zum Ausprobieren benötige ich möglichst viel AN):

const int Pump = 6;
const int PumpPoti = A0;
//int Pumpspeed;

int PumpPotiValue = 0;                                      
int PumpSpeed = 0;
unsigned long MarkerPump = 0;                               
const long IntervalPump = 60000;                           
const long PumpTime = 50000;                                

void setup()
{
  Serial.begin(9600);                                         
  pinMode (Pump, OUTPUT);
  analogWrite (Pump, 0);
}
void loop()
{  

  if (millis() - MarkerPump > IntervalPump)                 
  {
    PumpPotiValue = analogRead(PumpPoti);
    PumpSpeed = map(PumpPotiValue, 0, 1023, 0, 255);   
    analogWrite (Pump, PumpSpeed);                                
    Serial.println(PumpSpeed);

    MarkerPump = millis();                                 
  }
  if (millis() - MarkerPump > PumpTime)                     
  {
    analogWrite (Pump, 0);                                 
  }

}

--> Der sketch funktioniert, die Pumpe läuft und der MOSFET wird nicht heiss, alles gut ABER:

Was nicht funktioniert ist, die Pumpgeschwindigkeit während die Pumpe läuft, zu verändert. Lediglich für den nächsten Zyklus übernimmt das Programm den in der Zwischenzeit am Poti neu eingestellten Wert. Jeweils zu Beginn der folgenden Kondition wird die Pumpegeschwindigkeit aktualisiert:

if (millis() - MarkerPump > IntervalPump)

Auch folgende Adaption des loops bringt keine Besserung/Änderung:

void loop()
{
  PumpPotiValue = analogRead(PumpPoti);
  PumpSpeed = map(PumpPotiValue, 0, 1023, 0, 255);        

  if (millis() - MarkerPump > IntervalPump)                 
  {
    analogWrite (Pump, PumpSpeed);                                
    Serial.println(PumpSpeed);

    MarkerPump = millis();                                 
  }
  if (millis() - MarkerPump > PumpTime)                     
  {
    analogWrite (Pump, 0);                                 
  }

}

Weiss jemand weiter und kann mir sagen was ich ändern muss um die Pumpgeschwindigkeit während einer AN Phase quasi "live" ändern zu können?

Vielen Dank und Grüße,
Carola

Hi,
Du hast beides ( Pumpe an und aus schalten und Drehzahl regeln) in einer Funktion (loop).
Lass nur das Drehzahl regeln im loop und gib an und aus in eine eigene Funktion welche Du nach Ablauf von xx millis aufrufst.

1 Like
const int Pump = 6;
const int PumpPoti = A0;

void setup(){
  Serial.begin(9600);                                         
  pinMode (Pump, OUTPUT);
  analogWrite (Pump, 0);
}
void loop(){  
    analogWrite (Pump, analogRead(PumpPoti)/4);                                 
  }

Hallo

probier mal diesen Sketch aus. Über das Poti wird die Fördermenge eingestellt.

const int Pump = 6;
const int PumpPoti = A0;
int PumpPotiValue = 0;
int PumpSpeed = 0;
int pumpOnOff;
unsigned long markerPump = 0;
const long IntervalPump = 60000;
const long PumpTime = 50000;

void setup()
{
  Serial.begin(9600);
  pinMode (Pump, OUTPUT);
  analogWrite (Pump, 0);
}
void loop()
{
  if (millis() - markerPump > IntervalPump)
  {
    markerPump = millis();
    pumpOnOff = pumpOnOff ? LOW : HIGH;
  }
  pumpOnOff ? analogWrite(Pump, map(analogRead(PumpPoti), 0, 1023, 0, 255)) : analogWrite(Pump, 0);
}

Oder soll die das Pumpintervall einstellbar sein?
Oder beides ?
Dann fehlt noch ein zweites Poti.

1 Like

Ich bezweifle daß die Pumpe in allen möglichen Ansteuerungen (1%-100%PWM) anläuft. Bei langsamen Drehzahlen muß mit 100% angefahren werden und dann auf die gewünschten Drehzahl ansenken.
Grüße Uwe

herbk

Hi,
Du hast beides ( Pumpe an und aus schalten und Drehzahl regeln) in einer Funktion (loop).
Lass nur das Drehzahl regeln im loop und gib an und aus in eine eigene Funktion welche Du nach Ablauf von xx millis aufrufst.

Meinst du mit einer eigenen void Funktion? Kannst du bitte mal ein Beispiel verlinken? Ich dachte das Auslagern in eigene void dient nur der besseren Übersicht im skecth und macht das Bearbeiten leichter.

kolaha

const int Pump = 6;
const int PumpPoti = A0;

void setup(){
  Serial.begin(9600);                                         
  pinMode (Pump, OUTPUT);
  analogWrite (Pump, 0);
}
void loop(){  
    analogWrite (Pump, analogRead(PumpPoti)/4);                                 
  }

Entspricht das nicht meiner gezeigten Alternative? Also Rausnehmen aus der if-condition? Ist das

analogWrite (Pump, analogRead(PumpPoti)/4); 

und das

PumpPotiValue = analogRead(PumpPoti);
PumpSpeed = map(PumpPotiValue, 0, 1023, 0, 255);   
analogWrite (Pump, PumpSpeed); 

nicht synonym?

Danke für eure Hilfe

Grüße
Carola

in einer Wasseruhr reguliere ich die Füllmenge durch die Dauer auf voll Last geschalteter Pumpe.

Hi, das stimmt auf jeden Fall, habe ich selbst schon bemerkt. Macht aber nichts, wenn PWM unter dem Schwellenwert liegt ist sie halt aus. Alles was ich möchte bzw. brauche ist, dass die Pumpe, während sie aktiv ist, mittelbar auf Veränderung des Potiwertes reagiert. Also in dieser Funktion hier:

 if (millis() - MarkerPump > IntervalPump)                
  {
[...]
}

paulpaulson

Hallo

probier mal diesen Sketch aus. Über das Poti wird die Fördermenge eingestellt.

[...]

Oder soll die das Pumpintervall einstellbar sein?
Oder beides ?
Dann fehlt noch ein zweites Poti.

Hallo und danke. Nein das Intervall muss ich erst einmal nicht anpassen. Es geht wirklich um eine Feinjustierung der Fördermenge, Strömungsgeschwindigkeit im laufenden Betrieb. Es ist ein Flussaquarium mit sich bildenen Schaumnestern. Da muss man schnell reagieren und den Wasserstrom drosseln können. AN/AUS ist relativ konstant. Da AN/AUS zudem vom Intervall her auch ziemlich groß ist (es sind mehrere Stunden dazwischen) kann ich nicht immer warten, bis das nächsten AN Intervall startet um den Effekt meines neu eingestellten Potiwertes zu sehen. Wie gesagt, die Pumpe sollte direkt auf Änderungen des Wertes ansprechen sofern sie läuft.

Grüße
Carola

Sie kann überhitzen.

Danke für die Warnung. Stimmt natürlich, der Zustand wäre aber (sofern ich sie "live" steuern kann) nur ganz wenige Sekunden. Das wird sie überleben :slight_smile:

Hallo,
du könntest mit Map () den Potiwert 0-100% auf 30-100% umskalieren. 30% ist sicher ein Wert bei dem die Pumpe sicher anläuft.

Heinz

Hi, super Idee, danke. Das werde ich machen denn dann bin ich komplett auf der sicheren Seite. Aktuell teste ich das mit einem kleinen 12V Lüfter.

Hi, ich habe versucht deinen Vorschlag umzusetzen & das folgendermaßen ausprobiert. Bringt aber leider auch keine Veränderung. Auch hier aktualisiert die Pumpe erst im nächsten Zyklus den via Poti (neu) zugewiesenen PWM-Wert:

const int Pump = 6;
const int PumpPoti = A0;

int PumpPotiValue = 0;                                      
int PumpSpeed = 0;
unsigned long MarkerPump = 0;                           
const long IntervalPump = 30000;                          
const long PumpTime = 25000;                             

void setup()
{
  Serial.begin(9600);                                        
  pinMode (Pump, OUTPUT);
  analogWrite (Pump, 0);
}
void loop()
{
  PumpPotiValue = analogRead(PumpPoti);
  PumpSpeed = map(PumpPotiValue, 0, 1023, 0, 255);     
  Pumping();

}

void Pumping() {
  if (millis() - MarkerPump > IntervalPump)                
  {
    analogWrite (Pump, PumpSpeed);                                
    Serial.println(PumpSpeed);
    MarkerPump = millis();                              
  }
  if (millis() - MarkerPump > PumpTime)                     
  {
    analogWrite (Pump, 0);                                 
  }

}

Auch diese Variante führt nicht zum gewünschten Ergebnis:

const int Pump = 6;
const int PumpPoti = A0;

int PumpPotiValue = 0;                                     
int PumpSpeed = 0;
unsigned long MarkerPump = 0;                               
const long IntervalPump = 30000;                          
const long PumpTime = 25000;                              

void setup()
{
  Serial.begin(9600);                                      
  pinMode (Pump, OUTPUT);
  analogWrite (Pump, 0);
}
void loop()
{
  PumpPotiValue = analogRead(PumpPoti);
  PumpSpeed = map(PumpPotiValue, 0, 1023, 0, 255);        
  if (millis() - MarkerPump > IntervalPump)               
  {
    PumpingON();
    MarkerPump = millis();
  }
  if (millis() - MarkerPump > PumpTime)                   
  {
    PumpingOFF();
  }

}

void PumpingON() {
  analogWrite (Pump, PumpSpeed);                                
  Serial.println(PumpSpeed);
}

void PumpingOFF() {
  analogWrite (Pump, 0);                                
}

Oder ich habe dich falsch verstanden? Sorry ich muss mir das alles selbst herleiten. Keine einschlägige Ausbildung vorhanden :sweat_smile: Letztendlich möchte ich eigentlich nur, dass sich das Konstrukt in der AN Phase exakt so verhält wie der Beispielsketch "AnalogInOutSerial".

Da gehts Dir nicht anders als mir...
Dir zu helfen ist für mich gerade auch der Versuch mich in einen Fremden Sketch einzudenken... :wink:

Ja, extra Funktion ist wegen der Übersichtlichkeit, - ich bin da ein Fan von. Bei den paar Code Zeilen geht es aber auch ohne.
Du fragst das Poti immer nur ab wenn (millis() - MarkerPump > IntervalPump)
hol die Poti abfrage direkt in den loop, dann sollte es schon gehen.

Edit : Nein geht nicht, Du musst ja auch jedes mal schreiben...

Hast Du @paulpaulson Code mal probiert? sollte eigentlich auch gehen, aber wenn ich es richtig interpretiere sind da ein und aus immer gleich lang.

Na dann umso mehr danke für deine Tipps :slightly_smiling_face:!

Du fragst das Poti immer nur ab wenn (millis() - MarkerPump > IntervalPump)
hol die Poti abfrage direkt in den loop, dann sollte es schon gehen.

Nein, ist mittlerweile in beiden Alternativen im Main loop. Geschrieben wird der Wert aber, wie du ja auch schreibst, immer nur in der if (millis() - MarkerPump > IntervalPump) Unterfunktion (vielleicht liegt da ja das Problem). Während if (millis() - MarkerPump > PumpTime) gilt, wird ja automatisch PWM 0% geschrieben ohne Potiabfrage.

@paulpaulson Code ist schwierig für mich. Verstehe zB nicht was die Syntax ":" und "?" bedeutet und wird auf der Referenzseite auch nicht erklärt. Kann ich testen (und werde ich auch), wenn ich damit aber weiterarbeite wirds problematisch denn ich kann das ja nichts verändern (weil ich es nicht verstehe) :sweat_smile: Ich würds halt gerne mit den mir bekannten Funktionen basierend auf dem was ich bereits habe, umsetzen. Es klingt nämlich so einfach dass ich glaube dass das geht. Wir natürlich jeder ich weiss. Wenn es absolut nicht geht muss ich umdenken aber wie gesagt das Ganze kommt in einen existierenden sketch rein, der anderen Funktionen enthält.

Probier den mal:

const int Pump = 6;
const int PumpPoti = A0;
//int Pumpspeed;

int PumpPotiValue = 0;
int PumpSpeed = 0;
unsigned long MarkerPump = 0;
const long IntervalPump = 60000;
const long PumpTime = 50000;
byte pump_runs = 0;


void setup()
{
  Serial.begin(9600);
  pinMode (Pump, OUTPUT);
  analogWrite (Pump, 0);
}

void loop()
{
  PumpPotiValue = analogRead(PumpPoti);
  PumpSpeed = map(PumpPotiValue, 0, 1023, 50, 255);
 
  if (pump_runs == 1)
  {
    analogWrite (Pump, PumpSpeed);
    pump_runs = 0;
  }

  if (millis() - MarkerPump > IntervalPump)
  {
    analogWrite (Pump, PumpSpeed);
    Serial.println(PumpSpeed);
    pump_runs = 1;
    MarkerPump = millis();
  }
  if (millis() - MarkerPump > PumpTime)
  {
    analogWrite (Pump, 0);
    pump_runs = 0;
  }

}

Combie wird jetzt wieder sagen "zu viele if"... :laughing:

1 Like

Hallo

Es wird ein ternären Operator verwendet:

pumpOnOff ? analogWrite(Pump, map(analogRead(PumpPoti), 0, 1023, 0, 255)) : analogWrite(Pump, 0);

ist die C++ Version von

if (pumpOnOff ==HIGH) 
{
analogWrite(Pump, map(analogRead(PumpPoti), 0, 1023, 0, 255));
}
else
{
analogWrite(Pump, 0);
}

Man spart sich eine Menge Schreibarbeit damit.

2 Likes

Hallo herbk,

vielen Dank für deinen letzten Sketch - leider führt auch diese Variante nicht zum gewünschten Ergebnis.

Hallo paulpaulson,

vielen Dank für deinen sketch (siehe Post #4) - es funktioniert wunderbar. Ganz besonderen Dank für deine Nachhilfe/Übersetzung C++ --> Arduino Codesprache. Wäre ich selbst leider nicht drauf gekommen. Dank der Zusatzerklärung verstehe ich deinen Sketch und kann ihn bei mir verwenden und einbauen.

Danke allen für die Hilfe.

Grüße, Carola

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.