Initialisierung von Lichtsensor blockiert die Schleife

Hallo zusammen,

ich habe eine Kleine Lampe entwickelt bei der ein Timer abläuft sobald sie auf einem Untergrund steht. Sollte die Lampe stromlos sein, Soll der Timer ab dem Punkt der Stromunterbrechung weiterlaufen. Aus diesem Grund speichere ich den Status zwischen. Das Problem ist, dass die Lampe nach dem Neustart erst angehoben werden muss damit die Lampe weiter läuft. Sie soll aber sofort nachdem der Strom ausgefallen ist weiter laufen. Ich bin jetzt nicht der Programmierprofi und der Code ist sicher nicht das gelbe vom Ei. Kann mir Jemand einen Tip geben wie ich es hin bekomme, dass die Lampe nach Stromausfall so weiter läuft? Das ganze läuft aus einem Wemos D1 Hier der Code:

#include <NeoAnimationFX.h>
#include <EEPROM.h>
#include <BH1750FVI.h>
#define numPixels 16
#define PIN 2 //GPIO3

BH1750FVI myLux(0x23);


uint32_t lastUpdate = 0;

#ifdef ESP8266
typedef  NeoPixelBrightnessBus<NeoGrbFeature, Neo800KbpsMethod> NEOMETHOD; //uses GPIO3/RX
#endif
#ifdef ESP32
typedef  NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32I2s1800KbpsMethod> NEOMETHOD;
#endif

NEOMETHOD strip(numPixels, PIN); // PIN is ignored for ESP8266
NeoAnimationFX<NEOMETHOD> myPixelRef(strip);
int addr = 0;
int i=0,r=0,g=0,b=0,z=1,f=1,fz=0; // Farbe des LED Ring
long lastModeT = 0; // interne Variable


long minuten; //Hier Zeit einstellen
long case1=3; // Zeit Stick 1 in Minuten
// long case2=40; // Zeit Stick 2 in Minuten
// long case3=1; // Zeit Sick 3 in Minuten
int timer;// interne Variable
int wert = 10;//Lux sensibilitaet
int zwischen;

void EEPROMWriteInt(int p_address, int p_value)
 {
 byte lowByte = ((p_value >> 0) & 0xFF);
 byte highByte = ((p_value >> 8) & 0xFF);

 EEPROM.write(p_address, lowByte);
 EEPROM.write(p_address + 1, highByte);
 }

//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
unsigned int EEPROMReadInt(int p_address)
 {
 byte lowByte = EEPROM.read(p_address);
 byte highByte = EEPROM.read(p_address + 1);

 return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
 }



void setup() {
 Wire.begin();
myLux.powerOn();
myLux.setContLowRes();
myPixelRef.service();
myPixelRef.init();
 myPixelRef.setBrightness(255);
 myPixelRef.setColor(r,g,b);
 myPixelRef.start();
 myPixelRef.clear();
 myPixelRef.setMode(i);
 
 zwischen = EEPROMReadInt(addr);
 
if(zwischen > 0)  // Zwischenspeicher Wert laden
{
 timer = zwischen;
 i=3;
 f=1;
 myPixelRef.init();
 myPixelRef.setBrightness(255);
 myPixelRef.setColor(r,g,b);
 myPixelRef.start();
 myPixelRef.clear();
 myPixelRef.setMode(i);
  }
else
{
 timer = 0;
 
}



 EEPROM.begin(512);
/*  myPixelRef.init();
 myPixelRef.setColor(r,g,b);
 myPixelRef.start();
*/  
 

 
 


 
}

void pixelmode() // 1 Sekunden Timer
{
  myPixelRef.service();
  if (millis() - lastModeT > 1000) {
  if(myLux.getLux() < wert){
  lastModeT = millis();
  timer++;
  EEPROMWriteInt(addr, timer); 
  EEPROM.commit();
  EEPROM.end();
  }
 }
}

void lux()
{
    if((myLux.getLux() < wert) || (timer > 0)) // Sensor Ausgabe Lampe auf Fahrzeug
 {
   if(timer < minuten*60){
   i=3;
   }
   if(timer >= minuten*60){
   timer=minuten*60;
   f=0;
   EEPROMWriteInt(addr, 0); 
   EEPROM.commit();
   EEPROM.end();
   i=1;//Rot Blinken
   }
 }
   if(myLux.getLux() > wert)// Sensor Ausgabe Lampe nicht auf Fahrzeug
 {
     
     if(timer >= minuten*60){
     f=fz+1; 
     i=0; //Nur An 
     }
     timer=0;
     EEPROMWriteInt(addr, timer); 
     EEPROM.commit();
     EEPROM.end();
     f=1;
     i=0; //Nur An         
 }

}

void farbwechsel() //Neuinitialisierung bei Modewechsel
{
 if(i != z)
 {
 myPixelRef.init();
 myPixelRef.setBrightness(255);
 myPixelRef.setColor(r,g,b);
 myPixelRef.start();
 myPixelRef.clear();
 myPixelRef.setMode(i);
 z=i;
 
 }
}

void loop() // Routinen aufrufen Endlosschleife
{
 lux();
 farbe();
 pixelmode();
 farbwechsel();
}

void farbe()
{
 if(f == 1) //tuerkis
 {
   r=64;
   g=224;
   b=208;
   fz=f;
   minuten=case1;
 }
/*  if(f == 2) //Gelb
 {
   r=255;
   g=255;
   b=0; 
   fz=f;
   minuten=case2;
 } */
/* if(f == 3)  // Aktivieren wenn Stick 3 dazu kommt
 {
   r=0;
   g=255;
   b=0;
   fz=f; 
   minuten=case3;
 } */
 if(f == 0)
 {
   r=255;
   g=0;
   b=0;
   
 }
 if(f > 2) // 2 auf 3 erhoehen wenn Stick 3 dazu kommt
 {
   f=0;
   i=0;
 }


 
}

(deleted)

djamp:
Hallo zusammen,

ich habe eine Kleine Lampe entwickelt bei der ein Timer abläuft sobald sie auf einem Untergrund steht. Sollte die Lampe stromlos sein, Soll der Timer ab dem Punkt der Stromunterbrechung weiterlaufen.

Wie soll der Timer weiterlaufen, wenn eine Stromunterbrechung vorhanden ist.
Ist da ein zusätzlicher Akku drin ?

Dann brauchen wir dringend dein Schaltbild.

Edit:
Ich habe versucht, deinen Sketch zu analysieren, leider ist der schwer zu lesen. Es sind massig unnötige Leerzeilen drin und dafür fehlen jegliche Kommentare. Das solltest du ändern, damit auch außenstehende den Sketch besser verstehen können.

void EEPROMWriteInt(int p_address, int p_value)

{
byte lowByte = ((p_value >> 0) & 0xFF);
byte highByte = ((p_value >> 8) & 0xFF);

EEPROM.write(p_address, lowByte);
EEPROM.write(p_address + 1, highByte);
}

Davon wird mir schon schwindelig...

Punkt 1:
Die EEPROM LIB bietet get und put um solchen Dinge abzuhandeln. Das muss man nicht händisch tun.

Punkt 2:
Was hier als int bezeichnet wird, ist kein int.
Merke: int ist hier 4 Byte groß und nicht 2.

 EEPROM.commit();

EEPROM.end();

EEPROM.end() ist ausreichend.

combie:
Was hier als int bezeichnet wird, ist kein int.

In einem int kann man in jedem Fall entweder 0 oder eine Zahl > 0 ablegen. Mehr scheint hier nicht gebraucht zu werden. Wobei allerdings

long minuten;

mich stutzen lässt.

Dass dir schwindlig wird, kann ich auch nachvollziehen.

Ich befasse mich nicht mit der Frage, weil globale Variable namens f, z und fz mir verleiden, zu raten was das soll.

In einem int kann man in jedem Fall entweder 0 oder eine Zahl > 0 ablegen. Mehr scheint hier nicht gebraucht zu werden.

Ja, das könnte man so tun, aber ob das dann auch wirklich klappt liegt am µC Type und ein klein wenig am Wetter.

Eigentlich sollte man solche Dinge so erledigen, dass einem weder ein Alignment, noch die Byteorder, als auch die int Größe keine Streiche spielen kann.

Ja, ich weiß, das ist eine Idealvorstellung und das Leben besteht eigentlich nur aus Kompromissen.

Peter-CAD-HST:
Moin djamp
Herzlich Willkommen im Forum.
Zeige mal deinen Schaltplan und Sketch, damit wir dir helfen können.
Dazu gehst du im Arduino IDE auf den Eintrag BEARBEITEN, klickst auf FÜR FORUM KOPIEREN und anschließend fügst du mit CTRL V den Sketch, richtig verpackt, auch nachträglich in den Forum Editor ein.
Und nicht vergessen vorher die Leerzeilen zu löschen und den Sketch zu formatieren.
Gruss Peter
take care

Hier habe ich das ganze mal kopiert, wie Du gesagt hast:

#include <NeoAnimationFX.h>
#include <EEPROM.h>
#include <BH1750FVI.h>
#define numPixels 16
#define PIN 2 //GPIO3


BH1750FVI myLux(0x23); // Initialisierung Lichtsensor


uint32_t lastUpdate = 0;


#ifdef ESP8266
typedef  NeoPixelBrightnessBus<NeoGrbFeature, Neo800KbpsMethod> NEOMETHOD; //uses GPIO3/RX
#endif
#ifdef ESP32
typedef  NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32I2s1800KbpsMethod> NEOMETHOD;
#endif


NEOMETHOD strip(numPixels, PIN); // PIN is ignored for ESP8266
NeoAnimationFX<NEOMETHOD> myPixelRef(strip);
int addr = 0;
int i=0,r=0,g=0,b=0,z=1,f=1,fz=0; // Farbe des LED Ring  I wählt den Neopixelmode
long lastModeT = 0; // interne Variable




long minuten; //Hier Zeit einstellen
long case1=3; // Zeit Stick 1 in Minuten
// long case2=40; // Zeit Stick 2 in Minuten
// long case3=1; // Zeit Sick 3 in Minuten
int timer;// interne Variable
int wert = 10;//Lux sensibilitaet
int zwischen;


void EEPROMWriteInt(int p_address, int p_value)
  {
  byte lowByte = ((p_value >> 0) & 0xFF);
  byte highByte = ((p_value >> 8) & 0xFF);


  EEPROM.write(p_address, lowByte);
  EEPROM.write(p_address + 1, highByte);
  }


//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
unsigned int EEPROMReadInt(int p_address)
  {
  byte lowByte = EEPROM.read(p_address);
  byte highByte = EEPROM.read(p_address + 1);


  return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
  }


void setup() {
  Wire.begin();
myLux.powerOn();
myLux.setContLowRes();
myPixelRef.service();
myPixelRef.init();
  myPixelRef.setBrightness(255);
  myPixelRef.setColor(r,g,b);
  myPixelRef.start();
  myPixelRef.clear();
  myPixelRef.setMode(i);
  
  zwischen = EEPROMReadInt(addr);
  
if(zwischen > 0)  // Zwischenspeicher Wert laden
 {
  timer = zwischen;
  i=3;
  f=1;
  myPixelRef.init();
  myPixelRef.setBrightness(255);
  myPixelRef.setColor(r,g,b);
  myPixelRef.start();
  myPixelRef.clear();
  myPixelRef.setMode(i);
  BH1750FVI myLux(0x23);
 }
 else
 {
  timer = 0;
  BH1750FVI myLux(0x23);
 }


EEPROM.begin(512);
/*  myPixelRef.init();
  myPixelRef.setColor(r,g,b);
  myPixelRef.start();
*/  
}


void pixelmode() // 1 Sekunden Timer
{
   myPixelRef.service();
   if (millis() - lastModeT > 1000) {
   if(myLux.getLux() < wert){
   lastModeT = millis();
   timer++;
   EEPROMWriteInt(addr, timer); 
   EEPROM.commit();
   EEPROM.end();
   }
  }
}


void lux()
{
     if((myLux.getLux() < wert) || (timer > 0)) // Sensor Ausgabe Lampe auf Fahrzeug
  {
    if(timer < minuten*60){
    i=3;
    }
    if(timer >= minuten*60){
    timer=minuten*60;
    f=0;
    EEPROMWriteInt(addr, 0); 
    EEPROM.commit();
    EEPROM.end();
    i=1;//Rot Blinken
    }
  }
    if(myLux.getLux() > wert)// Sensor Ausgabe Lampe nicht auf Fahrzeug
  {
      
      if(timer >= minuten*60) // Wenn Timer durchgezaehlt hat dann
{
      f=fz+1;  // Zwischenspeicher um neuen Wert in den Timer zu laden
      i=0; //Nur An 
   }
      timer=0;
      EEPROMWriteInt(addr, timer); 
      EEPROM.commit();
      EEPROM.end();
      f=1;
      i=0; //Nur An         
  }


}


void farbwechsel() //Neuinitialisierung bei Modewechsel
{
  if(i != z)
  {
  myPixelRef.init();
  myPixelRef.setBrightness(255);
  myPixelRef.setColor(r,g,b);
  myPixelRef.start();
  myPixelRef.clear();
  myPixelRef.setMode(i);
  z=i;  
  }
}


void loop() // Routinen aufrufen Endlosschleife
{
  lux();
  farbe();
  pixelmode();
  farbwechsel();
}


void farbe()
{
  if(f == 1) //tuerkis
  {
    r=64;
    g=224;
    b=208;
    fz=f;
    minuten=case1;
  }
/*  if(f == 2) //Gelb
  {
    r=255;
    g=255;
    b=0; 
    fz=f;
    minuten=case2;
  } */
 /* if(f == 3)  // Aktivieren wenn Stick 3 dazu kommt
  {
    r=0;
    g=255;
    b=0;
    fz=f; 
    minuten=case3;
  } */
  if(f == 0)
  {
    r=255;
    g=0;
    b=0;
  }
  if(f > 2) // 2 auf 3 erhoehen wenn Stick 3 dazu kommt
  {
    f=0;
    i=0;
  }
}

Und hier der Schaltplan dazu:


Ich mach das ganze eher als Hobby und nicht professionell. Entschuldigt auch die Fehler im Code aber ich hoffe ich kann mit Eurer Hilfe noch etwas lernen. Danke an alle die sich durch meinen Code mühen. Ich bin über jeden Tip oder Verbesserungen dankbar. Ich möchte auf einen Akku verzichten da das Gehäuse sehr klein ist und deswegen den Timer zwischenspeichern, um nach Stromausfall ca. 10 Sek während des Vorgangs den die "Eieruhr" "Stoppen" soll, an der letzten Stelle an der er stehen geblieben ist weiter zu zählen.

djamp:
ich habe eine Kleine Lampe entwickelt bei der ein Timer abläuft sobald sie auf einem Untergrund steht. Sollte die Lampe stromlos sein, Soll der Timer ab dem Punkt der Stromunterbrechung weiterlaufen. Aus diesem Grund speichere ich den Status zwischen. Das Problem ist, dass die Lampe nach dem Neustart erst angehoben werden muss damit die Lampe weiter läuft.

Also ich hab jetzt mehrfach drüber gelesen und denke ich weiss, was Du willst:

Das Gerät (lampe) startet einen Timer, sobald ein Zustand eingetreten ist (steht auf Untergrund). Nach Ablauf des Timer soll irgendwas passieren. (Das ist egal)
Wenn der Strom ausfällt (Lampe sromlos), wird der aktuelle TimerWert im EEprom gespeichert.
Wenn der Strom wiederkommt (Lampe startet) UND aus dem EEprom die RestTimerzeit gelesen wird, soll die Lampe für diese Restlaufzeit angehen.
Letzteres macht sie nicht.

Dein Code ist unübersichtlich und nicht kommentiert, um das zu erfassen.

Aber in dem Codestück:

if (zwischen > 0) // Zwischenspeicher Wert laden
  {
    timer = zwischen;
  .....

musst Du Deinem System noch sagen, wie er anfangen soll.
Denn sonst geht er als erstes im loop in lux() und holt sich da natürlich den Wert, den er aus dem Sensor liest.
Vermutlich wird hier in der Funktion:

  if (myLux.getLux() > wert) // Sensor Ausgabe Lampe nicht auf Fahrzeug

die Lösung liegen.

Aber wie schon gesagt, die Variablen global und dann nicht beschrieben, was die machen ist ...

Ich kann noch keinen Schaltplan sehen.
Wo hast du den abgelegt ?

HotSystems:
Ich kann noch keinen Schaltplan sehen.
Wo hast du den abgelegt ?

Weil ich auch nichts sehe....
Ich hab grad mal durch den Quelltext der Seite gewühlt...
Vielleicht:
https://www.bilder-upload.eu/bild-fdf7ac-1607131412.jpg

Das Ganze stammt aus dieser Zeile.

![](upload://gorNHY2N7loU3FQYKFRXb16lrE3.jpeg)

Heute ist wiedermal cdn.arduinoc.cc etwas gnätzig und verbastelt wird auch wieder mehr.
Möglicherweise ist das Bild auch gelöscht - K.A.; ich hab auch keines - Ich kann einige URL's nicht aufrufen.
Aber es brauchts auch nicht. - siehe mein Post oben.

my_xy_projekt:
Also ich hab jetzt mehrfach drüber gelesen und denke ich weiss, was Du willst:

Das Gerät (lampe) startet einen Timer, sobald ein Zustand eingetreten ist (steht auf Untergrund). Nach Ablauf des Timer soll irgendwas passieren. (Das ist egal)
Wenn der Strom ausfällt (Lampe sromlos), wird der aktuelle TimerWert im EEprom gespeichert.
Wenn der Strom wiederkommt (Lampe startet) UND aus dem EEprom die RestTimerzeit gelesen wird, soll die Lampe für diese Restlaufzeit angehen.
Letzteres macht sie nicht.

Dein Code ist unübersichtlich und nicht kommentiert, um das zu erfassen.

Aber in dem Codestück:

if (zwischen > 0) // Zwischenspeicher Wert laden

{
timer = zwischen;
.....



musst Du Deinem System noch sagen, wie er anfangen soll.
Denn sonst geht er als erstes im loop in lux() und holt sich da natürlich den Wert, den er aus dem Sensor liest.
Vermutlich wird hier in der Funktion:


if (myLux.getLux() > wert) // Sensor Ausgabe Lampe nicht auf Fahrzeug



die Lösung liegen.

Aber wie schon gesagt, die Variablen global und dann nicht beschrieben, was die machen ist ...

Genau so soll sie funktioneren. :wink:
Der Schaltplan wurde wohl gelöscht. Hier ist er nochmal: