Hilfe bei Lichtsteuerung

Hallo,
ich habe mir an den letzten zwei Nachmittagen meine erste kleine Arduino Anwendung gebastelt bzw. zusammengebastelt. Eine automatische Lichtsteuerung für die Küche:

Mit Hilfe eine Bewegungssensor und eines Lichtsensors wird eine LED Leiste eingeschaltet. Treffen alle Bedingungen zu (Bewegung + Lichtstärke) werden die LEDs auf einen einstellbaren Wert hochgedimmt. Bleibt das Signal vom Bewegungsmelder aus, werden die LEDs wieder auf einen festen Wert runtergedimmt. Dieser Zustand wird mehrere Sekunden gehalten bevor die LEDs dann auf null gedimmt werden. Die Anfangslichtstärke der LEDs kann man per Potentiometers (später Taster) einstellen. Ebenso, ab welcher Lichtstärke die Automatik startet.

Meine zwei Probleme die ich noch habe:

A) Ab dem Zeitpunkt in dem kein Signal mehr vom Bewegungssensor kommt und die LEDs runtergedimmt werden, reagiert die Schaltung nicht mehr auf ein erneutes Signal vom Bewegungsmelder. Das heißt dass die bestehende Schleife bis zum Schluß durchgezogen wird →
LEDs werden runtergedimmt->mehrere Sekunden warten->LEDs werden auf null gedimmt
Schön wäre es aber, bei einer erneuter Bewegung in der Zeit, dass die LEDs wieder auf die einstellbare volle Helligkeit springen. Wie kann man das realisieren, Interrupt?

B) Wie geschrieben kann man mit einen Poti die Anfangshelligkeit der LEDs einestellen. Nur leider passiert das nicht im gleichen Moment sondern erst wenn die Schleife neu beginnt. Schön wäre es wenn sich die Helligkeit sofort ändert. Muss man hier die Schleife abbrechen oder liege ich mit meinen Lösungsansätzen komplett falsch?

Viele Grüße

Sketch:

const int mosfetPin = 9;               // setze Pin für den Mosfet/LED
const int motionPin = 2;               // setze Pin für den Bewegungssensor
const int lightPin = A7;               // setze Pin vom Helligkeitssensor
const int potiPin = A2;                // setze Pin vom Potentiometer
const int potiPinB = A4;               // setze Pin vom zweiten Potentiometer
int lightValue = 0;              // Wert vom Lichtsensor wird auf Null gesetzt
int motionStatus;                // Variable - letzter Status vom Bewegungssensor
int motionValue;                 // Variable - Status vom Bewegungssensor
int lightSens = potiPin;         // Variable "lightSensitivity" dem Wert vom Potentiometer zuweisen
      


void setup() 
{
  Serial.begin(9600);                     // Serielle Übertragung starten
  pinMode (mosfetPin, OUTPUT);            // "mosfetPin" als Output belegen
  motionStatus = digitalRead(motionPin);  // Variable "motionStaus" dem Wert vom Bewegungssensor zuweisen
}

void loop() 
{
  Serial.println(analogRead(potiPinB));
  lightValue = analogRead(lightPin);      // Variable "lightValve" dem Wert des Helligkeitssensors zuweisen
  lightSens = analogRead(potiPin); // Variable "lightSensitivity" dem Wert des Potentiometer zuweisen
  if (lightValue < lightSens)      // Loop startet erst wenn der Wert des Helligkeitssensors kleiner ist als der des Potentiometers
  {
    int startBright = analogRead(potiPinB)/4;
    motionValue = digitalRead(motionPin); // Variable "motionValve" dem aktueller Status des Bewegungssensor zuweisen
    if (motionValue != motionStatus)      // Loop startet erst wenn sich der Wert des Bewegungssensors wieder geändert hat
   {
       // Variable Anfangshelligkeit der LEDs
      if(motionValue == HIGH)
      { for(int fadeValue = 0 ; fadeValue <= startBright; fadeValue +=5) // fadet LEDs vom analogen Wert 0 auf einstellbaren Wert 
        analogWrite(mosfetPin, fadeValue);    
        delay(30);                         
      }                        
    
        
    else
    {
      for(int fadeValue = startBright ; fadeValue >= 11; fadeValue -=5) 
      {
        analogWrite(mosfetPin, fadeValue);   // dimmt LEDs vom analogen Wert 255 zu 12
        Serial.println("Licht AN");
        delay(30);                          
      }                            
    
      
    delay(10000);              // Zehn Sekunden warten bevor LEDs auf 0 gedimmt werden
      
      for(int fadeValue = 12 ; fadeValue >= 0; fadeValue -=1) // dimmt LEDs vom analogen Wert 12 zu 0
      {
        analogWrite(mosfetPin, fadeValue); 
        //Serial.println("Licht AUS");      
        delay(30);              
      }
                               
    }    // Ende else Bedingung
   }    // Ende if Bedingung "(motionValue != motionStatus)"            
  motionStatus = motionValue;   // neuen Status des Bewegungssensors speichern
        
 }     // Ende if Bedingung "(lightValue < lightSensitivity)"
}      // Ende void loop

Dein Problem sind vermutlich die langen Delays. Ersetze die bitte durch eine Funktion ohne Delays. Siehe hier auch das Beispiel "BlinkWithoutDelay"

"Blink without delay" in allen Variationen ist dein Freund.

Wenn du diese Technik "blockierungsfreies Programmieren" verstanden hast und umsetzt, sin deine Probleme alle gelöst.

Deinen vorhandenen auf diese Technik umzuschreiben, geht nicht. Besser mit neuem Ansatz frisch ans Werk und neu programmieren.

ElEspanol: "Deinen vorhandenen auf diese Technik umzuschreiben, geht nicht. Besser mit neuem Ansatz frisch ans Werk und neu programmieren.

Wat? Neuschreiben? Weisst du was mich der für Nerven gekostet hat ;) Könntest du mal bitte ansatzweisse erklären warum das mit meinem Sketch nicht funtioniert, bzw. warum ich nicht einfach die Delays ersetzen kann?

Hallo edth,

programmieren lernt man nicht in einigen Stunden/Tagen/Wochen/Monaten. Das sollte jedem klar sein.

Ich schließe mich ElEspanol an. Lerne, bzw. schaue dir die Basics an, vorallem Blink Without Delay, dann sollte dir das ganze schnell klar werden, was an den delays kontraproduktiv ist.

Deine beiden Probleme liegen an deinem delay. Delay blockiert den Arduino und er wartet bis die Zeit abgelaufen wird. Immer über 10Sekunden. In der Zeit wird weder dein Poti noch Lichtsensor abgefragt.

30ms delay() für sich sieht nicht schlimm aus. Und ist es auch nicht zwangsläufig. Aber du musst beachten wie oft du dass in der Schleife machst. 100 mal sind schon 3 Sekunden in denen sonst nichts bearbeitet werden kann.

Hallo,

ich habe jetzt zumindest mal das zehn Sekunden Delay durch die Millis-Funktion ersetzt. Doch jetzt bleibt die LED nachdem sie runtergedimmt ist entweder AN oder überspringt das dimmen und geht sofort aus wenn kein Signal mehr vom PIR Sensor kommt. Aber zumindest springt es bei erneuter Bewegung schonmal zurück zur Ursprungshelligkeit. Ein kleiner Fortschritt er mit Hoffnung gibt.

Video

im Video:
bei der 1. Bewegung geht die LED an aber geht sofort aus nachdem das PIR-Signal weg ist
bei der 2. Bewegung geht die LED an und dimmt, so wie es sein soll, runter nachdem das PIR-Signal weg ist
doch leider bleibt sie dann ewig an
bei der 3. Bewegung bei 1.

wo liegt mein Fehler?

 const int mosfetPin = 9;               // setze Pin für den Mosfet/LED
const int motionPin = 2;               // setze Pin für den Bewegungssensor
const int lightPin = A7;               // setze Pin vom Helligkeitssensor
const int potiPin = A2;                // setze Pin vom Potentiometer
const int potiPinB = A4;               // setze Pin vom zweiten Potentiometer
int lightValue = 0;              // Wert vom Lichtsensor wird auf Null gesetzt
int motionStatus;                // Variable - letzter Status vom Bewegungssensor
int motionValue;                 // Variable - Status vom Bewegungssensor
int lightSens = potiPin;         // Variable "lightSensitivity" dem Wert vom Potentiometer zuweisen
unsigned long previousMillis = 0;
const long interval = 10000; 
//const long fadetime = 5;
//int fadeValue = 5;

void setup() 
{
  Serial.begin(9600);                     // Serielle Übertragung starten
  pinMode (mosfetPin, OUTPUT);            // "mosfetPin" als Output belegen
  motionStatus = digitalRead(motionPin);  // Variable "motionStaus" dem Wert vom Bewegungssensor zuweisen
 
}

void loop() 
{
  Serial.println(analogRead(potiPinB));
  lightValue = analogRead(lightPin);      // Variable "lightValve" dem Wert des Helligkeitssensors zuweisen
  lightSens = analogRead(potiPin); // Variable "lightSensitivity" dem Wert des Potentiometer zuweisen
  if (lightValue < lightSens)      // Loop startet erst wenn der Wert des Helligkeitssensors kleiner ist als der des Potentiometers
  {
    int startBright = analogRead(potiPinB)/4;
    motionValue = digitalRead(motionPin); // Variable "motionValve" dem aktueller Status des Bewegungssensor zuweisen
    if (motionValue != motionStatus)      // Loop startet erst wenn sich der Wert des Bewegungssensors wieder geändert hat
   {
       // Variable Anfangshelligkeit der LEDs
     if(motionValue == HIGH)
      { for(int fadeValue = 0 ; fadeValue <= startBright; fadeValue +=5) // fadet LEDs vom analogen Wert 0 auf einstellbaren Wert 
        analogWrite(mosfetPin, fadeValue);    
        delay(30);                         
      }                       
        
    else
    {
      for(int fadeValue = startBright ; fadeValue >= 11; fadeValue -=5) 
      {
        analogWrite(mosfetPin, fadeValue);   // dimmt LEDs vom analogen Wert 255 zu 12
        Serial.println("Licht AN");
        delay(30);                          
      }                            
       unsigned long currentMillis = millis();
       if(currentMillis - previousMillis >= interval)
       {
               previousMillis = currentMillis;
               for(int fadeValue = 12 ; fadeValue >= 0; fadeValue -=1) // dimmt LEDs vom analogen Wert 12 zu 0
               {
                 analogWrite(mosfetPin, fadeValue); 
                 delay(30);              
               }
          
        } // Ende if Millis
                         
    }    // Ende else Bedingung
   
   }    // Ende if Bedingung "(motionValue != motionStatus)"   
            
  motionStatus = motionValue;   // neuen Status des Bewegungssensors speichern
       
 }     // Ende if Bedingung "(lightValue < lightSensitivity)"
}      // Ende void loop

Hallo edth,
ich habe mir mal einen Spass gemacht und einen Teil deines Sketches umgeschrieben. Hier nur der Teil für fade_up, den ich in eine Funktion ausgelagert habe und von der loop aus aufrufe. Schau es dir mal an, vielleicht kannst du es gebrauchen.

void loop()
{
  if(motionValue)
     fade_up();
}

void fade_up()
{
  static unsigned long millis_alt;
  if (millis() -millis_alt > 30)
    {for(static int fadeValue = 0 ; fadeValue <= startBright; fadeValue +=5) // fadet LEDs vom analogen Wert 0 auf einstellbaren Wert
        {analogWrite(mosfetPin, fadeValue);
        millis_alt = millis();
        Serial.println (fadeValue);
        }
    }
}

Ich habe das gleiche auf einem Attiny85 gemacht. Hier mal einfach so mein Programm

#define PIRIN 2
#define FET 0
#define PWMLOW 7
#define PWMHIGH 255
#define INTERVAL 60000

boolean State=false;
boolean lState=false;
byte pwmval=10;
byte pwmvalint=0;
unsigned long lmillis=0;
unsigned long lmillis2=0;


void setup(){
  pinMode(PIRIN,INPUT);
  pinMode(FET,OUTPUT);
}

void loop(){
  State=digitalRead(PIRIN);
  if (State==true){
    lmillis=millis();
    pwmval=PWMHIGH;  
    // State=false;
  }
  if (millis()-lmillis>=INTERVAL){
    pwmval=PWMLOW;
  }
  if (millis()-lmillis2>=20){
    if (pwmval<pwmvalint){
      pwmvalint=pwmvalint-1;
         }
    if (pwmval>pwmvalint){
      pwmvalint=pwmvalint+1;
    }
    lmillis2=millis();  
  }
  analogWrite(FET,pwmvalint);
}

Das Programm fadet bei Bewegung von 7=>255 PWMVal und nach 60s wieder von 255=>7

Gruß
DerDani

Hallo,
Danke für eure Hilfe, ganz besonders an ardubu und volvodani.

ardubu:
Hallo edth,
ich habe mir mal einen Spass gemacht und einen Teil deines Sketches umgeschrieben. Hier nur der Teil für fade_up, den ich in eine Funktion ausgelagert habe und von der loop aus aufrufe. Schau es dir mal an, vielleicht kannst du es gebrauchen.

Habe den Code versucht einzubinden und funktioniert auch, nur nicht ganz reibungslos, was aber sicher nicht am Code, sondern an meinem noch begrenzten Verständnis liegt. Trotzdem vielen lieben Dank. Was auch gut ist, ist dass ich jetzt weiß dass man Funktionen auslagern kann :wink:

volvodani:
Hier mal einfach so mein Programm

Spitze, das war echt’n feiner Zug von Dir, weiß gar nicht wie ich das wieder gut machen kann :wink: Dein Code läuft wie Sahne. Habe ihn nach meinen Bedürfnissen modifiziert und bin nun sehr zufrieden. Ich poste ihn trotzdem nochmal im Gesammten für andere.

Viele Grüße

const int mosfetPin = 9;       // digital pin used to connect the mosfet/LED
const int motionPin = 2;       // digital pin used to connect the motion sensor
const int lightPin = A7;       // analog pin used to connect the light sensor
const int potiPin = A2;        // analog pin used to connect the first potentiometer 
const int potiPinB = A4;       // analog pin used to connect the second potentiometer 
int lightValue;                // variable to read the value from the light sensor
int lightSens;                 // variable to read the value from the first potentiometer
int endBright = 0;             // variable to set the end brightness
int dimBright = 15;            // variable to set the dim brightness
int startBright;               // variable to set the start brightness (reads the value from the second potentiometer)
long intervalSD = 100000;       // variable to set the time (milliseconds) from start brightness to dim brightness
long intervalDE = 90000;        // variable to set the time (milliseconds) from dim brightness to end brightness
boolean State = false;         // variable to read the value from the motion sensor
byte pwmval=10;                // variable to save the valve for dimming
byte pwmvalint=0;              // variable to save the valve for dimming
unsigned long lmillis=0;       // variable to save the time for dimming
unsigned long lmillis2=0;      // variable to save the time for dimming


void setup(){
  pinMode(mosfetPin,OUTPUT);    // set mosfetPin (2) as an Output
  }

void loop(){

  lightValue = analogRead(lightPin);      
  lightSens = analogRead(potiPin);        
  if (lightValue < lightSens)             
  {
    startBright=analogRead(potiPinB)/4;
    State=digitalRead(motionPin);
    if (State==true){
      lmillis=millis();
      pwmval=startBright; 
    }
  
      if (millis()-lmillis>=intervalDE){
      pwmval=dimBright;
    }
    if (millis()-lmillis>=intervalSD){
      pwmval=endBright;
    }
  
    if (millis()-lmillis2>=15){
      if (pwmval<pwmvalint){
        pwmvalint=pwmvalint-1;
           }
      if (pwmval>pwmvalint){
        pwmvalint=pwmvalint+1;
      }
      lmillis2=millis(); 
    }
    analogWrite(mosfetPin,pwmvalint);
  }
}

Mein Verständnis von Open Source. Komplette Programme neu schreiben für andere würde ich nicht aber wenn man das schon mal gemacht hat warum nicht ins Forum kopieren. Kleine Programme lege ich gerne offen vor allem weil da "nichts" drin steht. Hauptsache du verstehst was da drin vor sich geht. Gruß DerDani

Da hast du wahr. Wenn man so wie ich noch am Anfang steht ist so ein fertiges Beispiel Gold wert für das weitere Verständnis. Ich sag mal ich hab das meiste verstanden. Auf jeden Fall fasziniert mich das Thema so sehr dass ich gerade angefangen habe ein Buch zu lesen.

Viele Grüße

Was auffällt:

int intervalSD = 100000;
int intervalDE = 90000;

Das passt nicht annähernd in einen int und auch nicht in unsigned int

gut aufgepasst ;) ...ist korrigiert