Go Down

Topic: Brauche mal Hilfe (Regensensor hat Priorität vor Zeitschaltuhr) (Read 421 times) previous topic - next topic

0815rudi

Hallo,
bin neu eingestiegen in die Arduino Welt und hab schon ein wenig gebastelt.
Komme irgendwie nicht weiter.Brauche eine Rasen Bewässerungssteuerung über Zeit und Regensensor.
Hab mir mal zu Testzwecke zwei Codes zusammen gebastelt, was auch vom Ablauf funktioniert.
Einmal ne Zeitschaltuhr mit RTC und nen Regensensor.
Wie bekomme ich es hin, dass der Regensensor Vorrang zur Zeitschaltuhr hat.
Sozusagen, sollte, wenn es Zeit wird zu Wässern, die Schaltausgänge vom Regensensor blockiert werden.
Ist es trocken, gehts im Rhytmus weiter.
Wie muss ich das schreiben?
Hab mich zwar bisher so beholfen, dass ich per Relaisschaltung, die Spannung der anderen Relais blockiere, aber ne Software Lösung wäre komfortabler.
Hier der Sketch:

0815rudi

Code: [Select]
#define EIN LOW
#define AUS HIGH

int rainsense= 0; // analog sensor input pin 0
int led= 10; // digital output pin 10
int countval= 0; // counter value starting from 0 and goes up by 1 every second

struct schaltRelais_t{
  byte pin;
  int ein1; int aus1;
  int ein2; int aus2;
  int ein3; int aus3;
  int ein4; int aus4;
  int ein5; int aus5;


};

// Hier die Relais-Pins definieren mit Ein- und Ausschaltzeiten
schaltRelais_t schaltRelais[5]={
  {9, 1902, 1906, 1610, 1611},  // Regner am Pool
  {8, 1602, 1603, 1554, 1556}, // Regner Große Fläche
  {7, 1603, 1604, 1731, 1732}, // Regner Terrasse
  {5, 1605, 1606, 1735, 1740}, // Regner Strasse
};

void relaisSchaltenNachZeit(int thishour, int thisminute)  
// Schaltet die Zeitschaltuhr ein und aus und setzt den Ausgang entsprechend
{
  boolean state;
  // Aus der aktuellen Zeit eine Schaltzeit bilden
  int thisTime= thishour*100+thisminute;
  // Alle Schaltzeiten durchgehen, falls eine davon EIN sagt, einschalten
  for (int i=0;i<sizeof(schaltRelais)/sizeof(schaltRelais_t);i++)
  {
    state=AUS;  // Amnahme: Es sei nichts geschaltet
    if (
       (thisTime>=schaltRelais[i].ein1 && thisTime<schaltRelais[i].aus1)||
       (thisTime>=schaltRelais[i].ein2 && thisTime<schaltRelais[i].aus2)||
       (thisTime>=schaltRelais[i].ein3 && thisTime<schaltRelais[i].aus3)||
       (thisTime>=schaltRelais[i].ein4 && thisTime<schaltRelais[i].aus4)||
       (thisTime>=schaltRelais[i].ein5 && thisTime<schaltRelais[i].aus5)
       )
    {  
    state=EIN;
    }
    if (digitalRead(schaltRelais[i].pin)!=state) // Falls geschaltet werden soll
    { // ein paar Debug-Ausgaben machen
      Serial.print("Relais ");
      Serial.print(i+1);  // Relais-Index zählt ab 0, einfach 1 dazuzählen
      Serial.print(": ");
      if (state==EIN) Serial.println("EIN"); else Serial.println("AUS");
    }
    digitalWrite(schaltRelais[i].pin, state); // Schaltzustand setzen
  }
}  



#include <Wire.h>
// I2C Adresse der RTC ist 0x68 für DS1307 und DS3231
#define RTC_I2C_ADDRESS 0x68

int jahre,monate,tage,stunden,minuten,sekunden;
// wochentag bleibt in diesem Test-Sketch unberücksichtigt

void rtcReadTime(int &jahre, int &monate, int &tage, int &stunden, int &minuten, int &sekunden)
// aktuelle Zeit aus RTC auslesen
{
// Reset the register pointer
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
  Wire.requestFrom(RTC_I2C_ADDRESS, 7);
  // A few of these need masks because certain bits are control bits
  sekunden    = bcdToDec(Wire.read() & 0x7f);
  minuten     = bcdToDec(Wire.read());
  stunden     = bcdToDec(Wire.read() & 0x3f);  // Need to change this if 12 hour am/pm
  /*wochentag   = */bcdToDec(Wire.read());
  tage        = bcdToDec(Wire.read());
  monate      = bcdToDec(Wire.read());
  jahre       = bcdToDec(Wire.read())+2000;  
}

void rtcWriteTime(int jahre, int monate, int tage, int stunden, int minuten, int sekunden)
// aktuelle Zeit in der RTC speichern
{
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);
  Wire.write(decToBcd(sekunden));    // 0 to bit 7 starts the clock
  Wire.write(decToBcd(minuten));
  Wire.write(decToBcd(stunden));      // If you want 12 hour am/pm you need to set
                                   // bit 6 (also need to change readDateDs1307)
                                  
  Wire.write(decToBcd(0)); // Wochentag unberücksichtigt
  Wire.write(decToBcd(tage));
  Wire.write(decToBcd(monate));
  Wire.write(decToBcd(jahre-2000));
  Wire.endTransmission();  
}

byte decToBcd(byte val) // Hilfsfunktion zum Lesen/Schreiben der RTC
// Convert decimal number to binary coded decimal
// Hilfsfunktion für die Echtzeituhr
{
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)  // Hilfsfunktion zum Lesen/Schreiben der RTC
// Convert binary coded decimal to decimal number
// Hilfsfunktion für die Echtzeituhr
{
  return ( (val/16*10) + (val%16) );
}


int getIntFromString (char *stringWithInt, byte num)
// input: pointer to a char array
// returns an integer number from the string (positive numbers only!)
// num=1, returns 1st number from the string
// num=2, returns 2nd number from the string, and so on
{
  char *tail;
  while (num>0)
  {
    num--;
    // skip non-digits
    while ((!isdigit (*stringWithInt))&&(*stringWithInt!=0)) stringWithInt++;
    tail=stringWithInt;
    // find digits
    while ((isdigit(*tail))&&(*tail!=0)) tail++;
    if (num>0) stringWithInt=tail; // new search string is the string after that number
  }  
  return(strtol(stringWithInt, &tail, 10));
}  


void setup()
{
  Wire.begin();       // initialisiert die Wire-Library
  Serial.begin(9600); // Serielle Kommunikation starten
  while (!Serial);    // wait for serial port to connect. Needed for Leonardo only
  Serial.println("\r\nZeitschaltuhr- und Kurzzeittimer-Demo Sketch");
  Serial.println("Coded by jurs for German Arduino Forum.");
  Serial.println("Jede Minute wird die aktuelle Zeit im 'Seriellen Monitor' angezeigt.");
  Serial.println("Ebenso alle Ein- und Ausschaltungen und die Kurzzeittimer-Aktion");
  Serial.println();
  Serial.println("Du kannst die Zeit mit einem 'set' Befehl im 'Serial Monitor' neu setzen.");
  Serial.println("\r\nBeispiel:");
  Serial.println("set 28.08.2013 10:54\r\n");
  for (int i=0;i<sizeof(schaltRelais)/sizeof(schaltRelais_t);i++)
  {
    digitalWrite(schaltRelais[i].pin,AUS);
    pinMode(schaltRelais[i].pin,OUTPUT);
    pinMode (led, OUTPUT); // REGEN
    pinMode(rainsense, INPUT);
  }  
}


void behandleSerielleBefehle()
{
  char linebuf[30];
  byte counter;
  if (Serial.available())
  {
    delay(100); // Warte auf das Eintreffen aller Zeichen vom seriellen Monitor
    memset(linebuf,0,sizeof(linebuf)); // Zeilenpuffer löschen
    counter=0; // Zähler auf Null
    while (Serial.available())
    {
      linebuf[counter]=Serial.read(); // Zeichen in den Zeilenpuffer einfügen
      if (counter<sizeof(linebuf)-1) counter++; // Zeichenzähler erhöhen
    }
    // Ab hier ist die Zeile eingelesen
    if (strstr(linebuf,"set")==linebuf) // Prüfe auf Befehl "set" zum Setzen der Zeit
    { // Alle übermittelten Zahlen im String auslesen
      tage=getIntFromString (linebuf,1);
      monate=getIntFromString (linebuf,2);
      jahre=getIntFromString (linebuf,3);
      stunden=getIntFromString (linebuf,4);
      minuten=getIntFromString (linebuf,5);
      sekunden=getIntFromString (linebuf,6);
    }
    else
    {
      Serial.println("Befehl unbekannt.");
      return;
    }
    // Ausgelesene Werte einer groben Plausibilitätsprüfung unterziehen:
    if (jahre<2000 || monate<1 || monate>12 || tage<1 || tage>31 || (stunden+minuten)==0)
    {
      Serial.println(linebuf);
      Serial.println("\r\nFehlerhafte Zeitangabe im 'set' Befehl");
      Serial.println("\r\nBeispiel:");
      Serial.println("set 28.08.2013 10:54\r\n");
      return;
    }
    rtcWriteTime(jahre, monate, tage, stunden, minuten, sekunden);
    Serial.println("Zeit und Datum wurden auf neue Werte gesetzt.");
  }
}


void loop()
{
  char buffer[30];
  static unsigned long lastMillis;
  static int lastMinute;
  int stunden, minuten, sekunden, dummy;
  if (millis()-lastMillis>1000) // nur einmal pro Sekunde
  {
    lastMillis=millis();
    rtcReadTime(dummy, dummy, dummy, stunden, minuten, sekunden);
    if (minuten!=lastMinute) // die aktuelle Minute hat gewechselt
    {
      lastMinute=minuten;
      snprintf(buffer,sizeof(buffer),"%02d:%02d Uhr",stunden,minuten);
      Serial.println(buffer);
      relaisSchaltenNachZeit(stunden,minuten);
    }
   {
    int rainSenseReading = analogRead(rainsense);
   Serial.println(rainSenseReading); // serial monitoring message
   delay(500);// rain sensing value from 0 to 1023.
   // from heavy rain - no rain.
   if (countval <= 450){
      Serial.print("Heavy rain");
      digitalWrite(led, HIGH);  //raise an alert after x time
       }
   //raining for long duration rise buzzer sound
   // there is no rain then reset the counter value
   if (rainSenseReading <450){
      countval++; // increment count value
   }
   else
   if (rainSenseReading >451)
   { // if not raining
      digitalWrite(led, LOW); // turn off buzzer
      countval = 0; // reset count to 0
   }
  behandleSerielleBefehle();
   }
  }
}

Klaus_ww

Ich habe Deinen Code nicht gelesen, aber einen Tipp für Dich: male Dir ein Ablaufdiagramm auf, das hilft ungemein. Und ich bin sicher, Du wirst erkennen woran es hakt.

Und wenn nicht: dann wieder hier vorbeikommen. Mit dem Ablaufplan  :)
Freizeit-Programmierer mit moderatem Ehrgeiz besseren Code zu schreiben.

0815rudi

Für was brauch ich jetzt einen Ablaufplan?
Ich weiß, was passieren soll.
Kann es nur nicht umsetzen.

michael_x

Hab deinen Code nur überflogen, und frage mich, warum du es genau anders herum machst?
In loop() wird auf jeden Fall erstmal relaisSchaltenNachZeit aufgerufen (mit direkter Ausgabe), und dann auf "Regen" getestet. Das muss beides nicht sein.

Wofür if und else gut sind, scheinst du ja zu wissen.

Einfache Fragen werden auch besser an einfachen Beispielen erörtert, statt an großen Komplett-Sketchen.

Code: [Select]
void loop () {
  if ( regenTest() ) {
    // was bei Regen zu tun ist
  } else {
     relaisSchaltenNachZeit();
  }
}

HotSystems

Für was brauch ich jetzt einen Ablaufplan?
Ich weiß, was passieren soll.
Kann es nur nicht umsetzen.
Weil ein Anfänger mit einem Ablaufplan einen besseren Überblick über den eigentlichen Ablauf bekommt und danach auch besser den Sketch erstellen kann.
Und damit fällt dir das Umsetzen leichter.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

gregorss

Für was brauch ich jetzt einen Ablaufplan?
Ich weiß, was passieren soll.
Kann es nur nicht umsetzen.
Naja, die blöde Sache ist, dass man Fehler, die man im Kopf nicht bemerkt hat, in einem Ablaufplan evtll. umso besser sieht. Ich bin erst durch einen Ablaufplan darauf gekommen, warum ich mir den Algorithmus nicht merken kann, obwohl der ziemlich einfach ist.

Arbeit ist mit Arbeit verbunden. Das ist blöd, kann aber auch was haben, denn was man aus dem Schädel hat, kann auf Papier noch ein bisschen reifen. Nimm wirklich jede Gelegenheit wahr, den Kopf für die wichtigen Sachen frei zu haben.

Gruß

Gregor
„Ich glaube, ich leg' mich noch mal hin", sagte das Bit.

Go Up