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:
#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();
}
}
}
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
Für was brauch ich jetzt einen Ablaufplan?
Ich weiß, was passieren soll.
Kann es nur nicht umsetzen.
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.
void loop () {
if ( regenTest() ) {
// was bei Regen zu tun ist
} else {
relaisSchaltenNachZeit();
}
}
0815rudi:
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.
0815rudi:
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