LDR doppelbestimmung gegen Fehlmessung

ich hab folgenden Code für eine Hühnerklappe in Verwendung. Nun will ich aber beim LCR eine Doppelbestimmung bzw über z.B.: 5Minuten machen damit nicht wenn kurzzeitig Licht auf diesen trifft, der Motor nicht gleich hochfährt. Wie könnte ich das am Besten lösen.

Danke

int eingang = A0; //LCR PIN
int LCR = 0;
#define Relais1_OPEN 6    //MOTOR fährt hoch 
#define Relais2_CLOSE 7   //MOTOR fährt runter
//#define Relais3 8
//#define Relais4 9

#define PIN_BUTTON_CLOSE 12   //Endschalter geschlossen                 
#define PIN_BUTTON_OPEN 13    //Endschalter geöffnet
int tasterstatus_tag = 0;
int tasterstatus_nacht = 0;

void setup()
{
  pinMode(PIN_BUTTON_CLOSE, INPUT_PULLUP);           
  pinMode(PIN_BUTTON_OPEN, INPUT_PULLUP);
  pinMode (Relais1_OPEN, OUTPUT);
  pinMode (Relais2_CLOSE, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
       LCR = analogRead(eingang);
       Serial.print("LCR: ");
       Serial.println(LCR);
    
 tasterstatus_tag = digitalRead(PIN_BUTTON_OPEN);
 tasterstatus_nacht = digitalRead(PIN_BUTTON_CLOSE);
 if (LCR < 500 && tasterstatus_tag != 1)  // <500 = Tag
 
  {
    digitalWrite (Relais1_OPEN, HIGH);
    digitalWrite (Relais2_CLOSE, LOW);
  }
 if (LCR < 500 && tasterstatus_tag == 1)
 {
    digitalWrite (Relais1_OPEN, LOW);
    digitalWrite (Relais2_CLOSE, LOW);
  }


  if (LCR > 500 && tasterstatus_nacht != 1)  // <500 = Tag
  
  {
    digitalWrite (Relais2_CLOSE, HIGH);
    digitalWrite (Relais1_OPEN, LOW);
  }

  if (LCR > 500 && tasterstatus_nacht == 1)
    {
    digitalWrite (Relais1_OPEN, LOW);
    digitalWrite (Relais2_CLOSE, LOW);
  }
}

die variable LCR nur alle 5 Sekunden verändern.
Aber nicht direkt mit dem analogRead sondern wenn analogRead kleiner als LCR ist, dann veringerst LCR um 1 und wenn LCR > als analogRead ist erhöhst LCR um 1.

So glättet sich LCR ein wenig und einzelne ausreißer sind nicht gleich dramatisch.

Damit es am Anfang nicht ganz so lange dauert dass du ca im aktuellen Bereich bis, könntest du die LCR einmalig im setup() mit analogRead setzen.

weiß nicht ganz wie du das meinst, bzw. wie ich das im Code anpassen soll. :confused:

Hi

Annahme: Bei wachsender Dunkelheit/unterschreiten der Helligkeit die Uhrzeit merken (millis) und zufahren (die Hüher sind bis dato selbstständig rein gegangen - oder es war nicht dunkel genug).
Wenn die Helligkeit nun die Hell-Schwelle überschreitet, wird sich die aktuelle Uhrzeit nicht erneut gemerkt - wenn der Abstand groß genug ist, Klappe auf.

So fährt die Klappe sofort zu, wenn's dunkel genug ist aber nur verzögert auf - die Helligkeit muß für die Wartezeit dauerhaft anliegen - eine kleine Abschattung und die Wartezeit beginnt von Neuem.

MfG

Programmieren: Problem in kleinere Einzelprobleme aufteilen.
So lange, bis man die Einzelprobleme gelöst bekommt.
Zumindest einen Versuch darfst Du starten!

konzept Unklar oder Umsetzung?

die Umsetzung würde ca so beginnen, mal ohne 5 sekunden Verzögerung:

statt

LCR = analogRead(eingang);

halt:

  int aktuell = analogRead(eingang); // eine temporäre lokale variable die wir dann wieder wegschmeißen
  if (aktuell>LCR) LCR++;
  else if (aktuell<LCR) LCR--;

das saust natürlich auch bei jedem loop durch, daher sollst das analog "BlinkWithoutDelay" halt nur alle paar Sekunden machen oder am Ende vom loop ein schmutziges delay()

Hi

Mein Ansatz:

/*
Forensketch Hühnerklappe
https://forum.arduino.cc/index.php?topic=687331.msg4622521#msg4622521
Auf Uno/Nano:
Der Sketch verwendet 588 Bytes (1%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 14 Bytes (0%) des dynamischen Speichers, 2034 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
 */

const uint16_t helldunkelgrenze=517;  //LDR-Wert bei Wunsch-Helligkeit
const byte pinldr=A0; //LDR Spannungsteiler, LDR an Plus-Seite
const uint32_t wartedunkel=(uint32_t)60*1000; //Millisekunden Wartezeit

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  static uint32_t lastmillis=0;  
  static bool sollzu=false;
  uint32_t aktmillis=millis();
  
  uint16_t messwert=analogRead(pinldr);
  if (messwert<helldunkelgrenze){
//    lastmillis=0; // Bullshit ... DAS muss 'in die Hose gehen' - sorry
    lastmillis=aktmillis;
    sollzu=true;
  }else if (sollzu && aktmillis-lastmillis>wartedunkel){
    sollzu=false;
  }
  if (sollzu){
    //Aktion, wenn Klappe zufahren soll
  }else{
    //Aktion, wenn Klappe auffahren soll
  }
}

Nicht enthalten die die eigentliche Hühnerklappe/Endschalter/whatever
Bei Unterschreitung der Helligkeit wird sofort die Zufahrt eingeleitet, bei Überschritung wird eine Wartezeit - gewartet.
Der LDR (wieso eigentlich LCR?) wird nonstop ausgelesen, um jede Abdunklung mit zu bekommen und nicht nur alle paar Sekunden den aktuellen Wert - Das kann unglücklich nämlich gerade dann messen, wenn's kurz Aufblitzt.

MfG

Edit
Das lastmillis=0 durch =aktmillis getauscht - man muß Sich schon die aktuelle Uhrzeit merken - 'tschuldigung :confused:

Hi

Nicht, wenn 2x Aufblitzen erkannt wird - dann ist Das für den Arduino '2x Hell -> auf die Tür'.
Der zeitliche Ablauf fehlt ja total, wenn man nur alle paar Sekunden ganz kurz die Augen aufblinzelt.
Ob's in der Zwischenzeit nun hell oder dunkel war - diese Information fehlt.
Für den Moment reicht ein Blitzlicht und im 5-Sekundentakt kommt man mit Uralt-Fotoapparat so auch durch unbekanntes Terrain - und auf den Fotos wirst Du später sehen, daß es Immer, wann Du geschaut hast, hell war.

(mit einem Handy nicht zu vergleichen - Das leuchtet ja schon eine Stunde vorher herrum, bevor das Foto letztendlich gemacht wird).

MfG

Zugegeben: Man wird diese 5-Sekunden-Sprünge nur schwer einhalten können, um die Steuerung auszuhebeln - aber Es ist dann halt nicht 'durchgehend hell' gefordert, sondern nur 'alle 5 Sekunden hell für 3 Minuten'. - oder so.
Programmtechnisch ist 'immer hell' aber weder ein Problem, noch komplizierter - im Gegenteil - man braucht auch eine Wartezeit, dieses Mal bis die nächste Messung statt findet, aber zusätzlich auch einen Zähler, Der die erfolgreichen Messungen mitzählt.
Und hat dann doch nur 'nicht Alles'.

hab das jetzt so eingebaut. aber wo definiere ich dann meine zwei Endschalter?

const uint16_t helldunkelgrenze=517;  //LDR-Wert bei Wunsch-Helligkeit
const byte pinldr=A0; //LDR Spannungsteiler, LDR an Plus-Seite
const uint32_t wartedunkel=(uint32_t)60*1000; //Millisekunden Wartezeit

#define Relais1_OPEN 6    //MOTOR fährt hoch 
#define Relais2_CLOSE 7   //MOTOR fährt runter
//#define Relais3 8
//#define Relais4 9

#define PIN_BUTTON_CLOSE 12   //Endschalter geschlossen                 
#define PIN_BUTTON_OPEN 13    //Endschalter geöffnet
int tasterstatus_tag = 0;
int tasterstatus_nacht = 0;

void setup()
{
  pinMode(PIN_BUTTON_CLOSE, INPUT_PULLUP);           
  pinMode(PIN_BUTTON_OPEN, INPUT_PULLUP);
  pinMode (Relais1_OPEN, OUTPUT);
  pinMode (Relais2_CLOSE, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  static uint32_t lastmillis=0; 
  static bool sollzu=false;
  uint32_t aktmillis=millis();
    
 tasterstatus_tag = digitalRead(PIN_BUTTON_OPEN);
 tasterstatus_nacht = digitalRead(PIN_BUTTON_CLOSE);
 
   uint16_t messwert=analogRead(pinldr);
  if (messwert<helldunkelgrenze){
    lastmillis=0;
    sollzu=true;
  }else if (sollzu && aktmillis-lastmillis>wartedunkel){
    sollzu=false;
  }

 if (sollzu)
 {
 digitalWrite (Relais1_OPEN, HIGH);
 digitalWrite (Relais2_CLOSE, LOW);
 }
 else
 {
   digitalWrite (Relais2_CLOSE, HIGH);
   digitalWrite (Relais1_OPEN, LOW);
 }
}

Hi

Die Benennung der Pins und Taster ist 'eigen'.
Definiert hast Du Diese - Du meinst ggf. eher 'baue ich Diese ein'?

  • #define gegen const byte tauschen - dann hat der Kompiler eine Chance, Das zu Prüfen und zu Optimieren.

Die Fahrt kannst Du Da starten, wo Du den Zustand sollzu setzt.

In der sollzu-IF fragst Du dann jeweils den entsprechenden Endschalter ab, wenn die Bewegung noch nicht gestoppt ist.
if (sollzu){
if (digitalRead(Relais_close)==_AN && Endtaster_ZU_betätigt){
ditigalWrite(Relais_close,_AUS);
}
}else{
if (digitalRead(Relais_open)==_AN && Endtaster_AUF_betätigt){
digitalWrite(Relais_open,_AUS);
}
}

knapp drüber
const bool _AN=LOW; //Relais zieht bei diesem Pegel an (LOW und false ist hier identisch)
const bool _AUS=!_AN;

Gleiches für den Taster-Zustand - wenn Du auf GND abfragst, wäre der aktive Zustand LOW.
Mit const bool Variable ist Das innerhalb einer Sekunde anpassbar.

MfG

Edit
Wenn Du mir zeigst, was Du zusammen gebracht hast (und man ein Fortschritt darin erkennen kann), zeige ich Dir, was ich bereits habe.

Edit 2
Da ich den Sketch bei mir 'Huehnerklappe_2' nennen musste, gab's wohl schon Mal Eine.
In meinem Sketch geschaut, den darin enthaltenen Link geklickt:
Huehnerklappe
Ist aber genau das Gleiche wie hier - mit dem gleichen Stand - 14 tage her.

(deleted)

Hi

Wobei Sich der Fuchs nicht an die Uhrzeit hält - Dem reicht's völlig, wenn's dunkel genug ist - auch das Federvieh orientiert sich beim nach Hause gehen an der Helligkeit.
An den Jurs-Sketch im Nachbar-Thread dachte ich auch schon - denke aber, daß wir hier mit der Helligkeit 'besser' fahren.

MfG

...ich versteh es einfach nicht wirklich.. :frowning:

jetzt passiert gar nichts mehr...

const uint16_t helldunkelgrenze=517;  //LDR-Wert bei Wunsch-Helligkeit
const byte pinldr=A0; //LDR Spannungsteiler, LDR an Plus-Seite
const uint32_t wartedunkel=(uint32_t)60*1000; //Millisekunden Wartezeit

const byte Relais_OPEN= 6;   //MOTOR fährt hoch 
const byte Relais_CLOSE= 7;  //MOTOR fährt runter

const byte Endtaster_ZU= 12;  //Endschalter geschlossen                 
const byte Endtaster_AUF= 13; //Endschalter geöffnet
int tasterstatus_tag = 0;
int tasterstatus_nacht = 0;

const bool _AN=LOW;  //Relais zieht bei diesem Pegel an (LOW und false ist hier identisch)
const bool _AUS=!_AN;

void setup()
{
  pinMode(Endtaster_ZU, INPUT_PULLUP);           
  pinMode(Endtaster_AUF, INPUT_PULLUP);
  pinMode (Relais_OPEN, OUTPUT);
  pinMode (Relais_CLOSE, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  static uint32_t lastmillis=0; 
  static bool sollzu=false;
  uint32_t aktmillis=millis();
    
  uint16_t messwert=analogRead(pinldr);
  if (messwert<helldunkelgrenze){
    lastmillis=0;
    sollzu=true;
  }else if (sollzu && aktmillis-lastmillis>wartedunkel){
    sollzu=false;
  }

 if (sollzu)
    {
   if (digitalRead(Relais_CLOSE)==_AN && Endtaster_ZU)
      {
      digitalWrite(Relais_CLOSE,_AUS);
      }
    }
else{
   if (digitalRead(Relais_OPEN)==_AN && Endtaster_AUF)
      {
      digitalWrite(Relais_OPEN,_AUS);
      }
     }
}[/codee]

lastmillis=aktmillis !!!

Wenn Du Dir als aktuelle Uhrzeit Null merkst, ist millis() (nahezu immer) größer als die Wartezeit.
Auch schaltest Du den Motor nicht AN, wo Du 'sollzu' änderst.
Solange Du den Motor nicht anschaltest, wird Der Sich auch nicht bewegen - und somit wird Der auch nicht an den Endschaltern abgeschaltet.
... Mal gucken, ob der Sketch überlebt hat ... hatten hier 3 Stunden Notstand (Stromausfall ... durchaus nützlich, in jedem Raum 12V liegen zu haben ... wenn's auch nicht für Flutlicht reicht) ...

oha ... habe Das gerade in meinem Sketch auch geändert ... sorry, da hatte ich Mist verzapft :confused:
Wir merken und 'wenn Alles gut ist' die aktuelle Uhrzeit - also aktmillis (oder eben millis() ).
Ich nehme aktmillis, weil so die Funktion millis() nur 1x ausgelesen werden muß und diese Uhrzeit für den ganzen loop()-Durchlauf gilt.
Wenn 'nicht Alles gut ist', prüfen wir, ob seit dem Letzten 'Alles ok' unsere Wartezeit vorbei ist - und erst dann schalten wir um.

/*
  Forensketch Hühnerklappe
  https://forum.arduino.cc/index.php?topic=687331.msg4622521#msg4622521
  Auf Uno/Nano:
Der Sketch verwendet 1198 Bytes (3%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 14 Bytes (0%) des dynamischen Speichers, 2034 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
*/
const uint16_t helldunkelgrenze = 517; //LDR-Wert bei Wunsch-Helligkeit
const byte pinldr = A0; //LDR Spannungsteiler, LDR an Plus-Seite
const uint32_t wartedunkel = (uint32_t)60 * 1000; //Millisekunden Wartezeit

const byte pinendtasteroben = 13;
const byte pinendtasterunten = 12;

const byte pinmotorhoch = 6;
const byte pinmotorrunter = 7;

const bool _pushed = LOW; //Pegel bei gedrückten Taster
const bool _AN = LOW;     //Pegel für aktives Relais

const bool _relased = !_pushed;
const bool _AUS = !_AN;

void setup() {
  //Ausgänge auf 'AUS' setzen und zu Ausgängen machen
  digitalWrite(pinmotorhoch, _AUS);
  digitalWrite(pinmotorrunter, _AUS);
  pinMode(pinmotorhoch, OUTPUT);
  pinMode(pinmotorrunter, OUTPUT);
  if (!_pushed) { //Taster schalten gegen GND?
    pinMode(pinendtasteroben, INPUT_PULLUP);
    pinMode(pinendtasterunten, INPUT_PULLUP);
    /* kann entfallen, da die Pins beim Reset eh INPUT sind
      else{
         pinMode(pinendtasteroben, INPUT);
         pinMode(pinendtasterunten, INPUT);
    */
  }
}

void loop() {
  static uint32_t lastmillis = 0;
  static bool sollzu = false;
  uint32_t aktmillis = millis();

  uint16_t messwert = analogRead(pinldr);
  if (messwert < helldunkelgrenze) {
    lastmillis = aktmillis;
    sollzu = true;
    digitalWrite(pinmotorhoch, _AUS);
    digitalWrite(pinmotorrunter, _AN);
  } else if (sollzu && aktmillis - lastmillis > wartedunkel) {
    sollzu = false;
    digitalWrite(pinmotorrunter, _AUS);
    digitalWrite(pinmotorhoch, _AN);
  }
  if (sollzu) {
    if (digitalRead(pinmotorrunter) == _AN && digitalRead(pinendtasterunten) == _pushed) {
      digitalWrite(pinmotorrunter, _AUS);
    }
  } else {
    if (digitalRead(pinmotorhoch) == _AN && digitalRead(pinendtasteroben) == _pushed) {
      digitalWrite(pinmotorhoch, _AUS);
    }
  }
}

MfG

PS: nur kompiliert, aber Das 'macht Er'.

Hallo
Danke für deine Bemühungen....
ich hab jetzt deinen Code 1zu1 übernommen und rübergespielt.

if (!_pushed) { //Taster schalten gegen GND?

Taster schalten auf GND.

Mit diesem Code passiert nun folgendes:
Ausgangszustand: Kein Taster ist gedrückt und LDR hat Tageslicht

Betätige ich nun den Endschalter unten fährt der Motor los. Der Motor bleibt aber nicht sehen wenn ich den Endschalter oben betätige.
Der Motor bleibt nur stehen wenns am LDR finster wird.

Hi

Dann hast Du _AN und _AUS genau falsch herum.
Die Endschalter schalten die Ausgänge auf _AUS - was eher eine Abschaltung auslösen sollte.
Wenn dabei der Motor AN geht, sind wir hier falsch herum.

Ändere das const bool _AN=LOW; -> =HIGH;

Das sollte dann 'anders herum' laufen, also Start/Stop anders, die Drehrichtung sollte bei _AUF aber auch schon Richtung EndschalterAUF gehen.

MfG

es klappt trotzdem nicht, hab jetzt einmal ein Foto von der Verkabelung gemacht vl. hilft ja das weiter oder ich hab da noch irgendwo einen Fehler :slight_smile:

@postmaster-ino bin ich ein hilfloser Fall ? :slight_smile:

r_robert:
@postmaster-ino bin ich ein hilfloser Fall ? :slight_smile:

Evtl....
Kann ich nicht bestätigen.

Meist ist es nur ein einziger Groschen, welcher fallen muss, damit es weiter geht.
Bis zum nächsten Aha-Effekt.
Eine ewige Kette....

Oha - eine Hutschinensteckdose nebst Netzteil :slight_smile:

Ob Du ein hoffnungsloser Fall bist - kA - aber zumindest könntest Du versuchen, den Fehler einzukreisen.
'Klappt nicht' - selbst mit dem Zusatz 'trotzdem' - ist keine fundierte Fehler-Beschreibung.

  • Startet der Motor, wenn der LDR abgedunkelt wird?
  • Startet der Motor, wenn der LDR beleuchtet wird?
  • Startet der Motor in die richtige Richtung, also zum dazu passenden Endtaster?
  • Stoppt der Motor, wenn der falsche Endtaster betätigt wird?
  • Stoppt der Motor beim richtigen Endtaster?
  • Startet der Motor bei einem der Endtaster? Wenn JA, in welche Richtung (zum Taster oder von weg?)
  • Stoppt dann der Motor, wenn der LDR beleuchtet/abgeschattet wird?

Du musst sämtliche Möglichkeiten einzeln durchprobieren, um dem Fehler auf die Spur zu kommen.

Ein klein Wenig beansprucht mich ein eigenes Arduino-Projekt ebenfalls - noch wehrt Er Sich aber gegen meine Ideen ...

MfG

  • Startet der Motor, wenn der LDR abgedunkelt wird?
    => ja aber nur solllange der Endschalter oben gedrückt wird. Richtung passt

  • Startet der Motor, wenn der LDR beleuchtet wird?
    => ja, ich muss den Endschalter unten drücken sobald ich ihn loslasse, hört er wieder auf

  • Startet der Motor in die richtige Richtung, also zum dazu passenden Endtaster?
    ja aber nur der wenn der LDR beleuchte ist...