LDR gesteuerten DC Motor zusätzlich mit Blynk schalten

Grüß Euch,

ich habe eine Hühnerklappe welche mit einem 12 V DC Motor über 2 Wechselrelais mit einem Particle Argon und LDR gesteuert wird.
Die Automatik funktioniert einwandfrei, ich möchte jedoch die Klappe auch im Notfall z.B. mit Blynk oder einem Taster steuern.

Sollte so aussehen:
Klappe bei Tag durch LDR offen - mit Taster oder Blynk umschalten von Automatik auf Handbetrieb und schließen ohne das sie beim nächsten Loop durch LDR wieder geöffnet wird.
Und umgekehrt wieder auf Automatik umstellen.

Ein 2. Projekt Garagentor nur mit Blynk klappt auch einwandfrei.
Was ich trotz intensiver Suche im Netz nicht schaffe ist die Kombination LDR Automatik plus Blynk
und Taster. Ich war Mechatroniker ,habe aber nur wenig Erfahrung mit Arduino Programmierung.
Habe zwar als Pensionist viel Zeit zum Lernen aber ich hoffe das ihr mir behilflich seid. Vielleicht hat jemand ein fertiges Beispiel, ich habe leider nichts Passendes gefunden. Oder Tipps wie man das Ganze richtig kombiniert. Danke schon mal im Voraus.

Mein Sketch

//28.06.2020 Funktionierende Version mit LDR


const byte Sensor = A0;      // Pin A0 wird Constant als Sensor bezeichnet
const byte Relais1 = D0;     // Pin D0 wird Constant als Relais1 bezeichnet
const byte Relais2 = D1;     // Pin D1 wird Constant als Relais2 bezeichnet
const byte Ledgreen = D2;    // Pin D2 wird Constant als Ledgreen bezeichnet
const byte Ledred = D3;      // Pin D3 wird Constant als Ledred bezeichnet


int Messwert = 0;                   // Zum Abfragen des Sensor Messergebnises
int Tag = 1500;                     // Messwert Klappe öffnen
int Nacht = 150;                    // Messwert Klappe schliesen
byte Merker01 = 0;                  // Zum merken des aktuellen Status
unsigned long Zeitablauf = 0;       // Zeitabfrage Sensormessung
const unsigned long Pause = 5000;  // 1 Minute Ablaufzeit, Sensormessung in Millisekunden)

//-------------------------------------------------------------------------------------------------------------
void setup()
{

  pinMode(Sensor, INPUT);       // Pin A0 für Input aktivieren
  pinMode(Relais1, OUTPUT);     // Pin D0 für Output aktivieren
  pinMode(Relais2, OUTPUT);     // Pin D1 für Output aktivieren
  pinMode(Ledgreen, OUTPUT);    // Pin D2 für Output aktivieren
  pinMode(Ledred, OUTPUT);      // Pin D3 für Output aktivieren
}
//-------------------------------------------------------------------------------------------------------------
void loop()
{
  //-----------Sensor abfragen--------------------------------------------
  if (millis() - Zeitablauf >= Pause)           // Prüfen ob 60 Sekunden abgelaufen sind
  {
    Messwert = analogRead(Sensor);              // Pin von Sensor abfragen
     
  if (Messwert >= Tag)                         // Ist Messwert größer als Vorgabe für Klappe auf?
      {
      digitalWrite(Relais1, LOW);
      digitalWrite(Relais2, HIGH);
      digitalWrite(Ledred, LOW);
      digitalWrite(Ledgreen, HIGH);
      Particle.publish("Klappe offen", String(Messwert), PRIVATE);
      }
    if (Messwert <= Nacht)                         // Ist Messwert kleiner als Vorgabe für Klappe zu?
      {
      digitalWrite(Relais1, HIGH);
      digitalWrite(Relais2, LOW);
      digitalWrite(Ledred, HIGH);
      digitalWrite(Ledgreen, LOW);
      Particle.publish("Klappe zu", String(Messwert),PRIVATE);
      }
      Zeitablauf = millis();                   // Zeitablauf neu starten
  }
  
}

Der Schaltplan im Anhang, ich hoffe ich habe habe es so richtig gemacht.

Grüße aus Kärnten
Rudolf

Du bestimmst 2 Betriebsmodi: Automatisch und manuell.
Bei manuell noch 2 Zustände Auf und Zu.
Die Betriebsmodi speicherst Du in einer Variablen und daraus wird also eine Endlicher Automat.
Grüße Uwe

Hallo Uwe,

danke erstmal für die Antwort. Also ich muss erstmal lernen wie das geht. Bis jetzt habe ich meistens Beispiele angepasst. Vielleicht kannst du oder jemand der Lust dazu hat ein solches posten und ich beiße mir dann in Ruhe die Zähne daran aus.
Grüße Rudolf

Hi

Du kapselst einfach Deine jetzige IF (quasi die ganze loop() )und lagerst Das in die Funktion automatik(); aus.
Dann kommt in loop() nur eine
IF (automatikbetrieb){
automatik();
}else{
//manueller Kram
}

Wie bekommst Du die Hühner dazu, vor Deinem manuellen verschließen das Innere aufzusuchen?
Dann noch eine OT-Frage:
Meines Wissen ist der Mechatroniker ein eher neuer Beruf (Mischung Kabelaffe/Schlosser) - zumindest gab's Das zu meiner Lehrzeit (im letzten Jahrtausend - wenn dort auch eher am Ende) noch nicht - wie schafft's man Da zum Pensionist?
(oder besser: wie schaffe ich Das auch :wink: )

MfG

Hallo postmaster-ino,

danke für deinen Tipp, werde mich umgehend damit beschäftigen.

Die manuelle Funktion ist nur für dafür gedacht um z.B. bei Arbeiten im Stall die Vögel auszusperren oder wichtiger, Abends wenn welche vergessen haben das Schlafenszeit ist und im Garten herumirren manuell zu öffnen und die Tierchen hineinzujagen.
Beim alten System ( ein paar Relais, ein Scheibenwischermotor, 2 Endschalter, zeitschaltuhr) habe ich einfach nur den Strom ausgeschalten und die Klappe händisch geöffnet und fixiert.
Eigentlich ist das Ganze eher so das ich angefangen habe mich mit Arduinos usw. zu beschäftigen und bis jetzt mein Garagentor mit Blynk am Handy bediene, den Füllstand meiner Heizöltanks und der Regenwasserzisterne mit Ultraschallsensoren abfrage und wiederum mit Blynk und Thingspeak ausgebe usw.

Mit dem Beruf Mechatroniker hast recht, hab eigentlich auch vor Urzeiten Elektriker gelernt und mit 45 bei Mechatronic als Schrauber angefangen und mich zum Servicemanager hochgekämpft. Wir haben in erster Linie Sondermaschinen für die Halbleiterindustrie gebaut. Bin also kein waschechter Mechatroniker.

Ah ja, Pension - bin 62 und seit 7 Jahren Zuhause.
Auf meine Art willst du es aber garantiert nicht schaffen, mein Arbeitsleben hat der Lungenkrebs beendet.
Rechte Seite komplett entfernt, Chemo und den ganzen Sch… aber bis jetzt überlebt.

Hoffe ich darf noch lästig sein wenn ich nicht weiterkomme.

Grüße
Rudolf

Hallo,

Nur mit der Betriebsat Hand/Auto wird das aber eventuell auch noch nicht das werden was Du willst.

Annahme es ist Hell Klappe wurde durch den LDR auf gefahren.Jetzt willst Du sie mauell schliessen. Du schaltest also auf manuell und machst sie zu. Anschliessend schaltest Du auf Auto zurück, damit sie abends auch automatisch zu geht und du das nicht vergisst. Damit geht sie dann jetzt aber leider wieder auf.

Eigendlich musst du dir ein Signal bilden das dann einmalig kommt wenn der LDR von dunkel auf hell wechselt und umgekehrt. Also die Änderung(Flanke ) des LDR auswerten. Dann kannst Du dir die Betriebsart sparen und jederzeit mit den Handtastern auf und zu fahren.

Heinz

Hallo Heinz,

das funktioniert schon. :wink:

Beispiel: Tag - Klappe automatisch offen, umschalten auf Handbetrieb- Klappe manuell schließen.

Ich erledige meine Arbeiten im Stall - umstellen auf Automatik - LDR meldet hell - Klappe geht wieder auf - oder bleibt zu wenn es dunkel ist.
Zum Umschalten reicht ein Ein/Aus Schalter. Und zum öffnen oder schließen ein Taster.
Bin gerade dabei den Taster optimal zu entprellen, (weis noch nicht wie ich das im Sketch besser einbaue). Im Moment eine einfache Lösung mit delay welche aber nicht optimal ist. Dann poste ich alles ( Fritzing Schaltplan, Sketch und Fotos, eventuell Video ) nochmal auf Github. Muss aber erst schauen wie das geht, hab ich noch nie gemacht. Wenn jemand Tipps hat wie ich mein Projekt ( falls es interessant ist) für andere zur Verfügung stellen kann nur her damit. Vorerst mein neuer Sketch im Anschluß.

Inzwischen habe ich mich dank dem Tipp von postmaster-ino das erstemal mit Funktionen beschäftigt und bin jetzt soweit das es nach meiner Vorstellung mit einem Testaufbau funktioniert.
Danke postmaster-ino.

Ah ja, ich diskutiere gerne darüber wann meine Hühner schlafengehen aber ich denke in diesem Forum sollten wir über Programmierung reden bevor uns ein Admin rügt.

Und als hilfesuchender Newby freut man sich natürlich eher über Tipps die einen weiterbringen.

Verbesserungsvorschläge herzlich willkommen.
Gruß
Rudolf

const byte Sensor = A0;      // Pin A0 wird Constant als Sensor bezeichnet
const byte Relais1 = D0;     // Pin D0 wird Constant als Relais1 bezeichnet
const byte Relais2 = D1;     // Pin D1 wird Constant als Relais2 bezeichnet
const byte Ledgreen = D2;    // Pin D2 wird Constant als Ledgreen bezeichnet
const byte Ledred = D3;      // Pin D3 wird Constant als Ledred bezeichnet
const byte Switchauto = D4;  // Pin D4 wird Constant als Tasterauf bezeichnet
const byte Ledyelow = D5;    // Pin D5 wird Constant als Ledyellow bezeichnet
const byte Manbutton = D6;     // Pin D6 wird Constant als Manbutton bezeichnet


int Messwert = 0;                   // Zum Abfragen des Sensor Messergebnises
int Tag = 1500;                     // Messwert Klappe öffnen
int Nacht = 150;                    // Messwert Klappe schliesen
unsigned long Zeitablauf = 0;       // Zeitabfrage Sensormessung
const unsigned long Pause = 1000;  // 1 Minute Ablaufzeit, Sensormessung in Millisekunden)

bool rel1an = false;
bool rel2an = false;

//-------------------------------------------------------------------------------------------------------------
void setup()
{

  pinMode(Sensor, INPUT);       // Pins für INPUT oder OUTPUT sktivieren
  pinMode(Relais1, OUTPUT);     
  pinMode(Relais2, OUTPUT);    
  pinMode(Ledgreen, OUTPUT);    
  pinMode(Ledred, OUTPUT);  
  pinMode(Ledyelow, OUTPUT); 
  pinMode(Switchauto, INPUT);    
  pinMode(Manbutton,INPUT);    
    
  

}
//-------------------------------------------------------------------------------------------------------------
void loop(){

       digitalWrite(Ledyelow, LOW);
    if(digitalRead(Switchauto) == HIGH){    // Ist schalter auf Hand- oder Automatikbetrieb
        
        hand();                             // gehe zu Funktion Handbetrieb
        }
    else
        automatic();
        }
void automatic()                            // gehe zu Funktion Automatikbetrieb
    {


  //-----------Sensor abfragen--------------------------------------------
   if (millis() - Zeitablauf >= Pause)           // Prüfen ob vorgegebene Zeit abgelsufen ist
    {
    Messwert = analogRead(Sensor);              // Pin von Sensor abfragen
  if (Messwert >= Tag){                        // Ist Messwert größer als Vorgabe für Klappe auf?
      open();
      }
    if (Messwert <= Nacht){                         // Ist Messwert kleiner als Vorgabe für Klappe zu?
      close();
      }
      Zeitablauf = millis();                   // Zeitablauf neu starten
    }
}

void hand(){                                    //  Funktion Handbetrieb
  if(digitalRead(Switchauto) == HIGH){
      digitalWrite(Ledyelow, HIGH);
      handswitch();
          }
      else{
      digitalWrite(Ledyelow, LOW);
     }
   }
void open()  {
    digitalWrite(Relais1, LOW);
      digitalWrite(Relais2, HIGH);
      digitalWrite(Ledred, LOW);
      digitalWrite(Ledgreen, HIGH);
      Particle.publish("Klappe offen", String(Messwert), PRIVATE);
}
void close(){
    digitalWrite(Relais1, HIGH);
      digitalWrite(Relais2, LOW);
      digitalWrite(Ledred, HIGH);
      digitalWrite(Ledgreen, LOW);
      Particle.publish("Klappe zu", String(Messwert),PRIVATE);
}
void handswitch(){
    if(digitalRead(Manbutton) == HIGH){
     if(rel1an == true){
       rel1an = false;
       digitalWrite(Relais1, LOW);
       digitalWrite(Relais2, HIGH);
       digitalWrite(Ledgreen, HIGH);
       digitalWrite(Ledred, LOW);
      
     }else{
      rel1an = true;
      digitalWrite(Relais1, HIGH);
      digitalWrite(Relais2, LOW);
      digitalWrite(Ledgreen, LOW);
      digitalWrite(Ledred, HIGH);
      
     }
  }
  delay(250);
}

Hallo Rudolf,
bitte drücke in Deiner IDE mal die Tastenkombination [CTRL] + [T] (teilw. auch als [STRG] + [T] gekennzeichnet.
das formatiert den Programmcode etwas übersichtlicher, vor allem die Klammer-Blöcke werden dadurch besser nachvollziebar.
So ist der Code sehr schwer zu lesen, vorallem ist sehr schwer zu sehen, wo ein Klammerblock beginnt und wo er endet.
Lade dann bitte den Formatierten Programmcode frisch hoch. Du kannst das auch als Edit Deines Posts machen, in dem Du den Code bereits zeigst.

LG Stefan

Hallo Stefan.

danke für die Info. Ich arbeite ja mit einem Particle Argon und der Particle IDE. Auserderm habe ich, wie man sieht, nicht wirklich Erfahrung was richtiges formatieren von Codes angeht.
Im Moment habe ich meinen Sketch sowieso irgendwie versaut. Das meiste hat ja schon gut funktioniert aber jetzt macht das Ding nichts mehr richtig.
Sobald ich weiter bin gibt es wieder Infos.
Ich möchte natürlich soviel als möglich lernen und keiner der Anwender sein die einen verwurstelten Code hier posten und nach Hilfe rufen.
Am besten mit einem voll funktionierenden Sketch als Antwort.
Bin der learning by doing Typ aber wenn ich im Netz keine Antworten finde freue ich mich natürlich über jede Hilfe.
Werde die Arduino IDE instalieren und mich damit beschäftigen und den aktuellen Sketch posten.
Ich denke dann bin ich darauf angewiesen was zurückkommt.
Ich hoffe dann auf Antworten wie " Hier hast du das oder das vergessen, Dieser Teil gehört nicht dahin sondern da... usw.

Grüße Rudolf

Hallo Rudolf,
es tut mir leid, dass ich Dir keine konstruktivere Hilfe war. Ich habe dich deshalb auf die Formatierung hingewiesen, weil ich beim ersten Drüberschauen bei deinem Code, an einigen stellen eine falsch gesetzte '}' klammer vermutete, die einen Lauffehler des Programmcodes auslöst. mir ist es sehr schwer gefallen, ja fast unmöglich gewesen den Lauf deines codes nachzuverfolgen. Daraufhin habe ich Deinen Code dann erstmal runtergeladen, und in meiner IDE eingefügt, damit ich die Formatierung anpassen konnte. Erst dann hab ich feststellen können, dass zumindest die Klammersetzung für die Blöcke doch in Ordnung ist.
Leider konnte ich mir deinen Code danach nicht weiter ansehen und analysieren, da ich anderbeitige pflichten zu erfüllen hatte.
Also habe ich Dir den Hinweis wegen der Formatierung hinterlassen, weil dieser Hinweis sonst garantiert von einem anderen Forenuser/Helfer gekommen wäre. Ich hatte gehofft, dass wenn Du das machst, andere Helfer sich eher die Zeit nehmen, sich Deinen Code genauer anzusehen, um dir dann Zielführende Hinweise zu geben.

Es tut mir leid, dass ich nicht die Zeit hatte, mir Dein Problem genauer anzusehen, un ich Dich deshalb enttäuschen musste.

LG Stefan

Hallo Stefan,
dein Hinweis war gut. Hat mich auf die Idee gebracht die Arduino IDE zu installieren und mir das ganze da anzuschauen.
Gefällt mir gut.
Zwar kann ich in der Arduino IDE den Code nicht überprüfen da logischerweise die Pins bei meinem Particle anders bezeichnet sind aber das mit der automatischen Formatierung geht z.B. in der Particle IDE nicht.
Übrigens hatte ich wirklich auf etwas mehr an Tipps die mich weiterbringen von anderen Usern gehofft aber etwas war zumindest dabei.
Und das nicht Alle auf Antworten reagieren ist wohl in Foren so üblich.
Jedenfalls habe ich es geschafft, :slight_smile: :slight_smile: es funktioniert so wie ich es mir vorgestellt habe.
Automatikbetrieb mit verschiedenen Zeiten zum Öffnen und Schließen, umschalten auf Handbetrieb, mit einem Taster händisch öffnen oder schließen, wieder umschalten auf Automatik und alles läuft bestens wieder über den LDR.

Hier der von der Arduino IDE formatierte Code, ob er von der Programmierung her so korrekt ist weis ich nicht aber es funktioniert.
Über Verbesserungsvorschläge von Profis freue ich mich natürlich.
Grüße
Rudolf

/*
  Automatische Hühnerklappe mit LDR Sensor und Umschaltung auf Handbetrieb
  Umschalten Hand / Automatik erfolgt mit einem Schalter
  Öffnen und Schließen im Handbetrieb mit einem Taster
  Öffnen und Schließen im Automatikbetrieb mit LDR
  Helligkeit zum Schließen und Öffnen getrennt einstellbar
*/

const byte Sensor = A0;      // Pin A0 wird Constant als Sensor bezeichnet
const byte Relais1 = D0;     // Pin D0 wird Constant als Relais1 bezeichnet
const byte Relais2 = D1;     // Pin D1 wird Constant als Relais2 bezeichnet
const byte Ledgreen = D2;    // Pin D2 wird Constant als Ledgreen bezeichnet
const byte Ledred = D3;      // Pin D3 wird Constant als Ledred bezeichnet
const byte Ledyelow = D4;    // Pin D7 wird Constant als Ledyellow bezeichnet
const byte Switch = D5;  // Pin D4 wird Constant als Tasterauf bezeichnet
const byte Button1 = D6;  // Pin D4 wird Constant als Tasterauf bezeichnet

unsigned long Zeitablauf = 0;       // Zeitabfrage Sensormessung
const unsigned long Pause = 30000;  //  Ablaufzeit, Sensormessung in Millisekunden)
int Messwert = 0;                   // Zum Abfragen des Sensor Messergebnises
int Tag = 1500;                     // Messwert Klappe öffnen
int Nacht = 150;                    // Messwert Klappe schliesen
byte Merker01 = 0;                  // Zum merken des aktuellen Status

//Variablen zum speichern der Zustände
int KlappenStatus = HIGH;          //der Klappen-Status
int Button1Status;              //zum zwischenspeichern des aktuellen Klappen-Status
int letzterButton1Status = LOW; //zum zwischenspeichern des letzten Klappen-Status

//long ist ein Datentyp für große Zahlen; unsigned bedeutet, dass nur positive Zahlenwerte angenommen werden können.
unsigned long letzteAenderung = 0;  //der letzte Zeitpunkt, an dem eine Änderung stattfand
unsigned long warten = 50;           //Pause, die nach Klappen-Aktion folgen soll


//-------------------------------------------------------------------------------------------------------------
void setup()
{
  Serial.begin(9600);           // Öffnet die serielle Schnittstelle bei 9600 Bit/s:
  pinMode(Sensor, INPUT);       // Pins für INPUT/OUTPUT aktivieren
  pinMode(Relais1, OUTPUT);
  pinMode(Relais2, OUTPUT);
  pinMode(Ledgreen, OUTPUT);
  pinMode(Ledred, OUTPUT);
  pinMode(Button1, INPUT);

  pinMode(Switch, INPUT);
  pinMode (Ledyelow, OUTPUT);
  digitalWrite(Ledyelow, KlappenStatus);    //Klappe erst einmal anschalten
}
//-------------------------------------------------------------------------------------------------------------


void loop() {

  int switchState = digitalRead(Switch);    // Status Switch Hand/Automatik abfragen
  Serial.println(switchState);
  delay(10);                                // delay für Stabilisierung
  if (switchState == HIGH)                  // Wenn Schalter ist ein
  {
    hand();    // Handbetrieb
    digitalWrite(Ledyelow, HIGH);
  }
  if (switchState == LOW)                   // Wenn Schalter ist aus
  {
    automatic();                            // Automatikbetrieb
    digitalWrite(Ledyelow, LOW);
  }
}
void automatic() {

  if (millis() - Zeitablauf >= Pause)     // Prüfen ob vorgegebene Zeit abgelaufen ist
  {
    Messwert = analogRead(Sensor);        // Pin vom Sensor abfragen
    if (Messwert >= Tag) {                // Ist Messwert größer als Vorgabe für Klappe auf?
      open();
    }
    if (Messwert <= Nacht) {              // Ist Messwert kleiner als Vorgabe für Klappe zu?
      close();
    }
    Zeitablauf = millis();                // Zeitablauf neu starten
  }
}

void hand()  {

  //aktuellen Klappen-Messwert lesen
  int gelesen = digitalRead(Button1);

  //...Wenn der Klappen-Status sich geändert hat (durch drücken oder auch prellen)
  if (gelesen != letzterButton1Status) {
    // setze den Timer zurück
    letzteAenderung = millis();
  }

  if ((millis() - letzteAenderung) > warten) {
    //Der aktuell-gelesene Wert kann nun als zuverlässig angesehen werden, da dieser länger als 50ms vorliegt.
    if (gelesen != Button1Status) {  //falls sich der Status verändert hat...
      Button1Status = gelesen;       //...setze diesen als buttonStatus

      //...und verändere den Klappe-Status, falls der Knopf gedrückt wurde
      if (Button1Status == HIGH) {
        if (KlappenStatus == HIGH) {
          KlappenStatus = LOW;
          close();
        } else {
          KlappenStatus = HIGH;
          open();
        }
      }
    }
  }

  //Setze den neuen Klappen-Status
  digitalWrite(Ledyelow, KlappenStatus);

  //merke Dir für den nächsten Loop, was der aktuelle ButtonStatus ist.
  letzterButton1Status = gelesen;
}

void open()  {
  digitalWrite(Relais1, LOW);
  digitalWrite(Relais2, HIGH);
  digitalWrite(Ledred, LOW);
  digitalWrite(Ledgreen, HIGH);
  Particle.publish("Klappe offen", String(Messwert), PRIVATE);
}
void close() {
  digitalWrite(Relais1, HIGH);
  digitalWrite(Relais2, LOW);
  digitalWrite(Ledred, HIGH);
  digitalWrite(Ledgreen, LOW);
  Particle.publish("Klappe zu", String(Messwert), PRIVATE);
}

Hallo Rudolf,

danke für die Rückmeldung, und herzliche Gratulation zu Deinem Erfolg. Danke auch, dass Du den korrigierten Code hier engestellt hast, das kann wiederum anderen helfen, die vlt. ein ähnliches Problem Haben.

Ich wünsche Dir weiterhin viel Erfolg.

LG Stefan

Hallo Stefan,

hoffe mein Experiment hilft anderen die sich auch damit auseinandersetzen.
Habe es gerade geschafft die Klappe auch mit Blynk am Handy zu steuern.

2 Buttons -
1x als Schalter zum umstellen Hand / Automatik
1 x als Taster für Pin 6 (Button1) zum öffnen/schließen.

Also im Testaufbau macht das Ding jetzt fast schon das was ich will.
Ohne Blynk im Sketch:
Automatik = ok.
Manuelle Bedienung = ok.
Mit Blynk im Sketch:
Automatik = ok.
Bedienung mit Blynk am Handy = ok.
Aber jetzt funktioniert der mechanische Switch zum umstellen auf Hand nicht mehr.

Offenbar wird die manuelle Funktion jetzt von Blynk im Sketch blockiert, ohne Blynk passt alles.
Da komme ich im Moment nicht weiter. Bitte um Hilfe.

Hier nochmal der Sketch mit Blynk.

// This #include statement was automatically added by the Particle IDE.
#include <blynk.h>
//********************************************************************
/*
  Automatische Hühnerklappe mit LDR Sensor und Umschaltung auf Handbetrieb
  Umschalten Hand / Automatik erfolgt mit einem Schalter
  Öffnen und Schließen im Handbetrieb mit einem Taster
  Öffnen und Schließen im Automatikbetrieb mit LDR
  Helligkeit zum Schließen und Öffnen getrennt einstellbar
*/

const byte Sensor = A0;      // Pin A0 wird Constant als Sensor bezeichnet
const byte Relais1 = D0;     // Pin D0 wird Constant als Relais1 bezeichnet
const byte Relais2 = D1;     // Pin D1 wird Constant als Relais2 bezeichnet
const byte Ledgreen = D2;    // Pin D2 wird Constant als Ledgreen bezeichnet
const byte Ledred = D3;      // Pin D3 wird Constant als Ledred bezeichnet
const byte Ledyelow = D4;    // Pin D7 wird Constant als Ledyellow bezeichnet
const byte Switch = D5;  // Pin D4 wird Constant als Tasterauf bezeichnet
const byte Button1 = D6;  // Pin D4 wird Constant als Tasterauf bezeichnet

unsigned long Zeitablauf = 0;       // Zeitabfrage Sensormessung
const unsigned long Pause = 30000;  //  Ablaufzeit, Sensormessung in Millisekunden)
int Messwert = 0;                   // Zum Abfragen des Sensor Messergebnises
int Tag = 1500;                     // Messwert Klappe öffnen
int Nacht = 150;                    // Messwert Klappe schliesen
byte Merker01 = 0;                  // Zum merken des aktuellen Status

//Variablen zum speichern der Zustände
int KlappenStatus = HIGH;          //der Klappen-Status
int Button1Status;              //zum zwischenspeichern des aktuellen Klappen-Status
int letzterButton1Status = LOW; //zum zwischenspeichern des letzten Klappen-Status

//long ist ein Datentyp für große Zahlen; unsigned bedeutet, dass nur positive Zahlenwerte angenommen werden können.
unsigned long letzteAenderung = 0;  //der letzte Zeitpunkt, an dem eine Änderung stattfand
unsigned long warten = 50;           //Pause, die nach Klappen-Aktion folgen soll

// Blynk Aut Code ********************************
char auth[] = "***hier den Blynk Auth Code einfügen***";
//************************************************

//-------------------------------------------------------------------------------------------------------------
void setup()
{
  Serial.begin(9600);           // Öffnet die serielle Schnittstelle bei 9600 Bit/s:
  pinMode(Sensor, INPUT);       // Pins für INPUT/OUTPUT aktivieren
  pinMode(Relais1, OUTPUT);
  pinMode(Relais2, OUTPUT);
  pinMode(Ledgreen, OUTPUT);
  pinMode(Ledred, OUTPUT);
  pinMode(Button1, INPUT);

  pinMode(Switch, INPUT);
  pinMode (Ledyelow, OUTPUT);
  digitalWrite(Ledyelow, KlappenStatus);    //Klappe erst einmal anschalten

  // Blynk Setup ******
  Blynk.begin(auth);
  //*******************
}
//-------------------------------------------------------------------------------------------------------------


void loop() {

  // Blynk loop ***************
  {
    Blynk.run();
  }
  //**************************


  int switchState = digitalRead(Switch);    // Status Switch Hand/Automatik abfragen
  Serial.println(switchState);
  delay(10);                                // delay für Stabilisierung
  if (switchState == HIGH)                  // Wenn Schalter ist ein
  {
    hand();    // Handbetrieb
    digitalWrite(Ledyelow, HIGH);
  }
  if (switchState == LOW)                   // Wenn Schalter ist aus
  {
    automatic();                            // Automatikbetrieb
    digitalWrite(Ledyelow, LOW);
  }
}
void automatic() {

  if (millis() - Zeitablauf >= Pause)     // Prüfen ob vorgegebene Zeit abgelaufen ist
  {
    Messwert = analogRead(Sensor);        // Pin vom Sensor abfragen
    if (Messwert >= Tag) {                // Ist Messwert größer als Vorgabe für Klappe auf?
      open();
    }
    if (Messwert <= Nacht) {              // Ist Messwert kleiner als Vorgabe für Klappe zu?
      close();
    }
    Zeitablauf = millis();                // Zeitablauf neu starten
  }
}

void hand()  {

  //aktuellen Klappen-Messwert lesen
  int gelesen = digitalRead(Button1);

  //...Wenn der Klappen-Status sich geändert hat (durch drücken oder auch prellen)
  if (gelesen != letzterButton1Status) {
    // setze den Timer zurück
    letzteAenderung = millis();
  }

  if ((millis() - letzteAenderung) > warten) {
    //Der aktuell-gelesene Wert kann nun als zuverlässig angesehen werden, da dieser länger als 50ms vorliegt.
    if (gelesen != Button1Status) {  //falls sich der Status verändert hat...
      Button1Status = gelesen;       //...setze diesen als buttonStatus

      //...und verändere den Klappe-Status, falls der Knopf gedrückt wurde
      if (Button1Status == HIGH) {
        if (KlappenStatus == HIGH) {
          KlappenStatus = LOW;
          close();
        } else {
          KlappenStatus = HIGH;
          open();
        }
      }
    }
  }

  //Setze den neuen Klappen-Status
  digitalWrite(Ledyelow, KlappenStatus);

  //merke Dir für den nächsten Loop, was der aktuelle ButtonStatus ist.
  letzterButton1Status = gelesen;
}

void open()  {
  digitalWrite(Relais1, LOW);
  digitalWrite(Relais2, HIGH);
  digitalWrite(Ledred, LOW);
  digitalWrite(Ledgreen, HIGH);
  Particle.publish("Klappe offen", String(Messwert), PRIVATE);
}
void close() {
  digitalWrite(Relais1, HIGH);
  digitalWrite(Relais2, LOW);
  digitalWrite(Ledred, HIGH);
  digitalWrite(Ledgreen, LOW);
  Particle.publish("Klappe zu", String(Messwert), PRIVATE);
}

Grüße Rudolf