LED mit Verzug in Abhängigkeit eines Lüfters an- und ausschalten

Guten Abend,

ich habe einen Lüfter (5V) an ein Arduino Nano Board angeschlossen, der regelmässig alle 10s für 5 Sekunden angeschalten werden soll. Zusätzlich dazu soll eine LED mit Vorwiderstand mit einem Verzug von 2s nach Einschalten des Lüfters aktiviert werden und 2 Sekunden nach Ausschalten des Lüfters deaktiviert werden.

Ich habe den ganzen Abend mit Versuchen verbracht - leider ohne das gewünschte Ergebnis. Nachfolgend meine vier Versuchsvarianten. Eine Korrektur beziehungsweise Aufklärung was hier falsch läuft würde mir sehr helfen.

Achja, falls es wichtig ist: Später soll der Lüfter nicht regelmässig an-und ausschalten sondern von der gemessenen Temperatur eines Sensors getriggert werden. Was aber absolut gleich bleibt sind die 2 Sekunden Verzug, mit denen die LED dem Status des Lüfters folgen soll.

Vielen Dank und gute Nacht :slight_smile:

const int Luefter = 9;                                       
const int LED = 5;                                       

unsigned long LuefterPreviousTime = 0;    
const long LuefterInterval = 10000;  
const long LuefterTime = 5000;

unsigned long LEDMerkerON = 0;
unsigned long LEDMerkerOFF = 0;
const long LEDVerzug = 2000;


void setup() {

  Serial.begin(9600);         
  
  pinMode(Luefter, OUTPUT);      
  digitalWrite(Luefter, LOW);       

  pinMode(LED, OUTPUT);      
  digitalWrite(LED, LOW);       
             }

void loop() {


 //Serial.println(String("LuefterPreviousTime: ") + String(LuefterPreviousTime));
 //Serial.println(String("LEDMerkerON: ") + String(LEDMerkerON));
 //Serial.println(String("LEDMerkerOFF: ") + String(LEDMerkerOFF));

    if (millis() - LuefterPreviousTime > LuefterInterval){     
      digitalWrite(Luefter, HIGH);
      LEDMerkerON = millis();
      LuefterPreviousTime = millis();}                          
    if (millis() - LuefterPreviousTime > LuefterTime){       
      digitalWrite(Luefter, LOW); 
      LEDMerkerOFF = millis();}

   if (LEDMerkerON + LEDVerzug <= millis()){
      digitalWrite (LED, HIGH);}
   if (LEDMerkerOFF + LEDVerzug <= millis()){
      digitalWrite (LED, LOW);}
                                                                                                               
}

--> LED und Lüfter laufen nicht synchron. Beispielsweise aktiviert die LED bevor der Lüfter überhaupt erstmals loslegt. Das kann nicht stimmen. Der Lüftertakt stimmt aber.

const int Luefter = 9;                                       
const int LED = 5;                                       

unsigned long LuefterPreviousTime = 0;    
const long LuefterInterval = 10000;  
const long LuefterTime = 5000;

unsigned long LEDMerkerON = 0;
unsigned long LEDMerkerOFF = 0;
const long LEDVerzug = 2000;


void setup() {

  Serial.begin(9600);         
  
  pinMode(Luefter, OUTPUT);      
  digitalWrite(Luefter, LOW);       

  pinMode(LED, OUTPUT);      
  digitalWrite(LED, LOW);       
             }

void loop() {


 //Serial.println(String("LuefterPreviousTime: ") + String(LuefterPreviousTime));
 //Serial.println(String("LEDMerkerON: ") + String(LEDMerkerON));
 //Serial.println(String("LEDMerkerOFF: ") + String(LEDMerkerOFF));

    if (millis() - LuefterPreviousTime > LuefterInterval){     
      digitalWrite(Luefter, HIGH);
      LEDMerkerON = millis();
      LuefterPreviousTime = millis();
      if (LEDMerkerON + LEDVerzug <= millis()){
      digitalWrite (LED, HIGH);}}                          
    if (millis() - LuefterPreviousTime > LuefterTime){       
      digitalWrite(Luefter, LOW); 
      LEDMerkerOFF = millis();
      if (LEDMerkerOFF + LEDVerzug <= millis()){
      digitalWrite (LED, LOW);}}
                                                                                                      
}

--> Die LED aktiviert sich gar nicht (der Lüftertakt ist korrekt).

const int Luefter = 9;                                       
const int LED = 5;                                       

unsigned long LuefterPreviousTime = 0;    
const long LuefterInterval = 10000;  
const long LuefterTime = 5000;

unsigned long LEDMerkerON = 0;
unsigned long LEDMerkerOFF = 0;
const long LEDVerzug = 2000;


void setup() {

  Serial.begin(9600);         
  
  pinMode(Luefter, OUTPUT);      
  digitalWrite(Luefter, LOW);       

  pinMode(LED, OUTPUT);      
  digitalWrite(LED, LOW);       
             }

void loop() {


 //Serial.println(String("LuefterPreviousTime: ") + String(LuefterPreviousTime));
 //Serial.println(String("LEDMerkerON: ") + String(LEDMerkerON));
 //Serial.println(String("LEDMerkerOFF: ") + String(LEDMerkerOFF));

    if (millis() - LuefterPreviousTime > LuefterInterval){     
      digitalWrite(Luefter, HIGH);
      LEDMerkerON = millis();
      LuefterPreviousTime = millis();
      if (Luefter == HIGH && LEDMerkerON + LEDVerzug <= millis()){
      digitalWrite (LED, HIGH);}}                          
    if (millis() - LuefterPreviousTime > LuefterTime){       
      digitalWrite(Luefter, LOW); 
      LEDMerkerOFF = millis();
      if (Luefter == LOW && LEDMerkerOFF + LEDVerzug <= millis()){
      digitalWrite (LED, LOW);}}
                                                                                                      
}

--> Auch hier bleibt die LED komplett inaktiv (der Lüftertakt ist wieder korrekt).

const int Luefter = 9;                                       
const int LED = 5;                                       

unsigned long LuefterPreviousTime = 0;    
const long LuefterInterval = 10000;  
const long LuefterTime = 5000;

unsigned long LEDMerkerON = 0;
unsigned long LEDMerkerOFF = 0;
const long LEDVerzug = 2000;


void setup() {

  Serial.begin(9600);         
  
  pinMode(Luefter, OUTPUT);      
  digitalWrite(Luefter, LOW);       

  pinMode(LED, OUTPUT);      
  digitalWrite(LED, LOW);       
             }

void loop() {


 //Serial.println(String("LuefterPreviousTime: ") + String(LuefterPreviousTime));
 //Serial.println(String("LEDMerkerON: ") + String(LEDMerkerON));
 //Serial.println(String("LEDMerkerOFF: ") + String(LEDMerkerOFF));

    if (millis() - LuefterPreviousTime > LuefterInterval){     
      digitalWrite(Luefter, HIGH);
      LEDMerkerON = millis();
      LuefterPreviousTime = millis();}                          
    if (millis() - LuefterPreviousTime > LuefterTime){       
      digitalWrite(Luefter, LOW); 
      LEDMerkerOFF = millis();}

   if (Luefter == HIGH && LEDMerkerON + LEDVerzug <= millis()){
      digitalWrite (LED, HIGH);}
   if (Luefter == LOW && LEDMerkerOFF + LEDVerzug <= millis()){
      digitalWrite (LED, LOW);}
                                                                                                               
}

--> leider das gleiche Ergebnis wie 2) und 3).

Hast Du den Lüfter direkt an den Arduino Ausgang geschaltet oder verwendest Du einen Transistor zur Ansteuerung des Motors?

Grüße Uwe

Hallo Uwe,

ist ja doch noch jemand wach! Ich habe den (2pin) Lüfter direkt ans board gehängt (zusätzlich noch eine Freilaufdiode). Ich habe das Ganze aber ebenso mit einer zweiten LED+Vorwiderstand (statt des Lüfters) ausprobiert - weil das sollte ja eigentlich keine Rolle fürs Sketchprinzip spielen oder?

Viele Grüße
Carola

probier mal so:
(ungetestet)

const byte Luefter = 9;
const byte LED = 5;

unsigned long LuefterPreviousTime = 0;
const unsigned long LuefterInterval = 10000;
const unsigned long LuefterTime = 5000;
const unsigned long LEDVerzug = 2000;

unsigned long LEDPreviousTime;


void setup() {
  Serial.begin(9600);
  pinMode(Luefter, OUTPUT);
  digitalWrite(Luefter, LOW);
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);
}

void loop() {
  //Serial.println(String("LuefterPreviousTime: ") + String(LuefterPreviousTime));
  //Serial.println(String("LEDMerkerON: ") + String(LEDMerkerON));
  //Serial.println(String("LEDMerkerOFF: ") + String(LEDMerkerOFF));


  // dummy schalten - "Blink"
  unsigned long currentMillis = millis();
  if (digitalRead(Luefter) == HIGH && currentMillis - LuefterPreviousTime > LuefterTime) {
    Serial.print(F("Lüfter aus"));
    digitalWrite(Luefter, LOW);
    LuefterPreviousTime = currentMillis;
    LEDPreviousTime = currentMillis;  // eigentlich wollte ich hier einen "Aus-Trigger" machen, aber wir brauchen nur den Timestamp
  }
  else if (digitalRead(Luefter) == LOW && currentMillis - LuefterPreviousTime > LuefterInterval) {
    {
      Serial.print(F("Lüfter ein"));
      digitalWrite(Luefter, HIGH);
      LuefterPreviousTime = currentMillis;
      LEDPreviousTime = currentMillis;
    }
  }

  // lass die LED einfach dem Lüfterstatus folgen
  if (millis() - LEDPreviousTime > LEDVerzug) {
    if (digitalRead(Luefter) != digitalRead(LED))
    {
      Serial.println(F("LED folgt Lüfter"));
      digitalWrite(LED, digitalRead(Luefter));
    }
  }
}

der erste Abschnitt sollte den Lüfter ein/ausschalten

der zweite Abschnitt macht dann Zeitgesteuert die LED. Dabei habe ich mir gedacht egal wie die Zeitstempel + Delay sind, lass die LED einfach dem Lüfter folgen.

Das wäre eigentlich ein schönes Beispiel um auf Objektorientierung umzubauen, wäre dann nicht so verworren...

Hallo noiasca,

ich habs getestet - und es funktioniert ganz wunderbar :grinning:

Dein Ansatz, die LED einfach dem Lüfterstatus mit der unter "Verzug" festgelegten Konstante folgen zu lassen finden ich super leicht verständlich.

Ob das weniger verworren ist wenn man den Sketch gemäss den Guidelines von objektorientiertem Programmieren umbaut (habe da gerade mal ins Thema reingegoogled) hängt vermutlich auch damit zusammen, inwieweit man Kenntnisse von dieser "Programmierphilosophie" hat. Ich finde deinen Sketch jedenfalls nicht verworren und du hast mir sehr geholfen!

Vielen Dank und Grüße
Carola

also so ein Objekt ist schnell mal hingeschrieben.
Ich habe mir gedacht, dass Ventilator und LED eine "Gruppe" bilden (die LED ist ja abhängig vom Ventilator) - also ein Objekt mit zwei Pins.
Dann brauchst einen setter der wie ein digitalWrite angewendet wird.
Und eine Methode, die die Zeitsteuerung übernimmnt.
Das wars eigentlich.

Dann den Dummy zum Ansteuern hab ich wieder altmodisch prozedural gemacht (weil du den ja eh wegwirfst).
Ähnlich kann man aber auch eine Temperatursteuerung machen.

Wenn die Leute hier wissen, welche Art von Temperatursensor du verwenden willst, dann kann man vermutlich auch die Tempsteuerung sauber mit OOP machen.

/*
  Lüfter (5V) an ein Arduino Nano Board,
  der regelmässig alle 10s für 5 Sekunden angeschalten werden soll.
  Zusätzlich dazu soll eine LED mit Vorwiderstand mit einem Verzug von 2s nach Einschalten des Lüfters aktiviert werden
  und 2 Sekunden nach Ausschalten des Lüfters deaktiviert werden.

  https://forum.arduino.cc/index.php?topic=724243.0
  by noiasca
*/

class Output                                  // a class for an output object with two output pins
{
  private:
    const byte ventPin;                       // pin for fan (master)
    const byte ledPin;                        // pin for a delayed LED (slave)
    uint32_t previousMillis = 0;              // timestamp for LED
    const unsigned long ledDelay = 2000;
  public:
    Output(byte ventPin, byte ledPin) : ventPin(ventPin), ledPin(ledPin) {}  // the constructor with initialization list

    void begin()                       // to be called in setup()
    {
      pinMode(ventPin, OUTPUT);
      digitalWrite(ventPin, LOW);
      pinMode(ledPin, OUTPUT);
      digitalWrite(ledPin, LOW);
    }

    void setVent(byte newState)         // compareable to a "digitalWrite" but also sets a timestamp
    {
      Serial.print(F("vent newState=")); Serial.println(newState);
      digitalWrite(ventPin, newState);
      previousMillis = millis();        // jede Schaltung "resetted" den Timestamp für die LED
    }

    void tick()                         // checks if the LEDs need to be switched, call periodically in loop()
    {
      if (millis() - previousMillis > ledDelay) {
        if (digitalRead(ventPin) != digitalRead(ledPin))
        {
          Serial.println(F("LED folgt Lüfter"));
          digitalWrite(ledPin, digitalRead(ventPin));
        }
      }
    }
};

//Output myOutput(9, 5); // ventilator pin, led pin
Output myOutput(6, 5); // ventilator pin, led pin   //ich habe andere Pins

void timer()    // dummy function to be replaced  by a temperature control
{
  const unsigned long LuefterInterval = 10000;
  const unsigned long LuefterTime = 5000;
  static unsigned long previousMillis = 0;   // static, weil die Variable nach Funktionsende weiter bestehen soll (für den nächsten Aufruf)
  static bool state = LOW;                   // gibt an, ob wir in der on oder off Phase sind
  unsigned long currentMillis = millis();    // aktueller Zeitstempel

  if (state == LOW && currentMillis - previousMillis > LuefterInterval)
  {
    state = HIGH;
    myOutput.setVent(state);
    previousMillis = currentMillis;
  }
  else if (state == HIGH && currentMillis - previousMillis > LuefterTime)
  {
    state = LOW;
    myOutput.setVent(state);
    previousMillis = currentMillis;
  }
}

void temperatureControl()                    // untested
{
  static bool state = LOW;                   // gibt an, ob wir in der on oder off Phase sind
  int raw = analogRead(A1);                  // read the sensor
  int temp = map(raw, 0, 1023, -40, 40);     // calculate temperature from raw value
  if (state == LOW && temp > 20)             // switch on if larger than 20 degrees
  {
    state = HIGH;
    myOutput.setVent(state);
  }
  else if (state == HIGH && temp < 15)       // switch off if lower than 15 degrees
  {
    state = LOW;
    myOutput.setVent(state);
  }
}

void setup() {
  Serial.begin(115200);
  myOutput.begin();
}

void loop() {
  timer();                 // Zeitsteuerung - später ersetzen durch Temperatursteuerung
  //temperatureContol();   // Beispiel für eine Temperatursteuerung
  myOutput.tick();         // dem Output Objekt periodisch ein wenig Zeit geben
}

Die Mächtigkeit von OOP wirst du lieben lernen, sobald du mehr als nur einen Pin ansteuerst und öfters das gleiche oder ähnliche machen willst. 6 Ventilatoren, 6 LEDs, die einen zeitgesteuert, die anderen temperaturgesteuert, einer manuell ... das sind mit Objekten nur mehr ein paar wenige Zeilen und der Code bleibt übersichtlich.

Du kannst besser auf den Scope von Variablen achten. Du vermeidest globale Variablen.

Auch der Loop bleibt übersichtlich: Sensoren einlesen und Zeitsteuerungen als Programmlogik. Die Objekte kümmern sich in kurz zugewiesenen Zeitscheiben ("tick") falls sie etwas zu tun haben. Auch stellen sie setter Methoden zur Verfügung, um von außen Einfluss nehmen zu können.

Du brauchst eine Transistor um den Lüfter Anzusteuern. Auf Dauer machst Du den Arduino kaputt.
Grüße Uwe

Hallo Uwe,

danke nochmal für den Hinweis - ich habe einen NPN Transistor hinzugenommen.

Und @noiasca - super anschauliches Beispiel und tolle Anregung für OOP (objektorientiertes Programmieren), danke!

Viele Grüße
Carola

danke nochmal für den Hinweis - ich habe einen NPN Transistor hinzugenommen.

Hoffe ein Basiswiderstand ist auch dabei.
Grüße Uwe

Hallo,
wenn Du den Temperatursensor dazu nimmst könntest Du auch nochmal über einen anderen Ansatz nachdenken und eine Ablaufsteuerung( Schrittkette, Zustandsautomat ) daraus machen. Allerdings liegen dann alle Zeiten hintereinander. Zustände wären dann z.B messen , Lüfteron, Ledon, Lüfteroff, LEDoff, warten.

Heinz

objektorientiertem Programmieren

OOP und Datenfluss orientiert.
incl. Hysterese für die Temperatur 2 Punkt Regelung.

#include <CombiePin.h>
#include <CombieTools.h>
#include <CombieTimer.h>
#include <CombieTypeMangling.h>

using namespace Combie::Millis;

using Led     = Combie::Pin::OutputPin<13>;
using Luefter = Combie::Pin::OutputPin<12>;



const byte temperaturSensor =  A0;
const int  obereSchwelle    = 780; // Schaltschwelle
const int  untereSchwelle   = 555; // Schaltschwelle

Combie::Tools::SchmittTrigger<int> st   {obereSchwelle,untereSchwelle};
Combie::Timer::RisingEdgeTimer     ton  {2_sec};  // steigende Flanke wird verzoegert
Combie::Timer::FallingEdgeTimer    toff {2_sec};  // abfallende Flanke wird verzoegert


void setup() 
{
  Led().init();
  Luefter().init();
}

void loop() 
{
  //Led() = toff = ton = Luefter() = not (st = analogRead(temperaturSensor));// heizen
  Led() = toff = ton = Luefter() = st = analogRead(temperaturSensor);// kühlen
}

CombieLib.zip (388 KB)

@michael_x
Ja, ich weiß...
Ist etwas dreist, diese Methode, die Dinge zu sehen....
:grin: :grin: :grin:

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