Arduino Gewächshaussteuerung

Themabewertung:
  • 1 Bewertung(en) - 5 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Unilein
Fachgebiet Rauchentwicklung
*******

Beiträge: 758
Registriert seit: Apr 2014
Bewertung: 5
20.03.2015, 21:51

Heute war endlich mal Analyse angesagt.

Erstmal weiß ich jetzt, dass das Programm im µC einwandfrei funktioniert. Die Steuersignale für die Leistungsstufe werden ordentlich bereit gestellt und auch wieder abgeschaltet. Getestet habe ich das mit den neulich erworbenen Low-Current-LED's. Auf dem Bild kann man erkennen, dass ich im Prinzip die "Leuchtdiode" der Optokoppler durch diese LED's ersetzt habe und so festgestellt, dass diese angesteuert werden und auch leuchten. Das reicht also, um den Optokoppler zu bedienen.

   

Danach habe ich jeden einzelnen Optokoppler auf ein Steckbrett gepackt und dort mit einer einfachen Schaltung aus Widerstand, Diode, Optokoppler und zwei Batterien geprüft, ob diese noch funktionieren. Ich weiß jetzt, dass die Optokoppler in Ordnung sind. Sie entkoppeln und schalten einwandfrei.

Als nächstes habe ich die eigentliche Leistungsstufe getestet. Also geprüft, ob die Darlington-Transistoren vom Typ TIP122 noch heil sind. Dabei habe ich festgestellt, dass meine Freilaufdioden, die ich irgendwann später mal in die Schaltung eingesetzt hatte, falsch herum eingebaut sind und so zu einem Kurzschluß führen. Ich habe sie also wieder ausgebaut. Danach funktionierten alle Transistoren einwandfrei. Ich habe mir das Datenblatt des TIP122 noch einmal angesehen und dabei festgestellt, dass dieser bereits eine eingebaute Freilaufdiode hat. Somit kann ich auf die externen Dioden verzichten.

Die einzelnen Komponenten sind also in Ordnung.

Also die Optokoppler wieder eingebaut und die Schaltung eingeschaltet. Und schon geht's nicht. Es ist so, dass der Optokoppler offensichtlich auf der Schaltseite, also auf der Seite der TIP122 nicht korrekt versorgt wird und so keine Spannung an die Basis der TIP122 bringt.

Ich muss jetzt also herausfinden, warum beim Signal am Optokoppler der Transistor des Optokopplers, der die Basis des TIP122 versorgt, nicht funktioniert. Dazu muss ich mir noch einmal genau ansehen, wie das aktuell verdrahtet ist. Die Schaltung hat ja mal funktioniert, also habe ich, als ich den Spannungsregler eingebaut habe, mist gebaut.

Die Schaltung wird inzwischen mit 9 Volt (eigentlich sind es 8,4 Volt, weil ein Akku dran hängt) versorgt. Der Spannungsregler macht daraus 5,01 Volt. Prinzipiell ist das jetzt OK.

Jetzt muss ich nur noch den kleinen Fehler finden.

Gruß
Uni
-----

Wenn Du nicht weißt, wohin Du segeln willst, ist kein Wind richtig!
Zitieren
Unilein
Fachgebiet Rauchentwicklung
*******

Beiträge: 758
Registriert seit: Apr 2014
Bewertung: 5
21.03.2015, 17:32

Und weiter geht's.

Heute habe ich mir die Kopplung der Steuerung mit der Leistungsstufe über die Optokoppler nochmals angesehen und mir einen Wolf gemessen. Ich habe KEINE AHNUNG, warum die Optokoppler das Signal der Steuerung nicht auf die Leistungsstufe übertragen.

Also habe ich mir eine andere Lösung ausgedacht: Optokoppler raus und mit den Steuersignalen des µC direkt die TIP122 ansteuern. Zwischen den Pins des µC und der Basis des TIP122 sitzt noch eine Diode, die verhindert, dass aus der Leistungsstufe irgendwelche Spitzen auf den µC übertragen werden.

Und jetzt funktioniert's wieder! :-)


Dennoch: Am Programm muss ich nochmal arbeiten. Das gefällt mir aktuell noch nicht. Außerdem muss eigentlich noch so etwas wie ein Resetknopf her. Denn sonst muss ich das Gehäuse aufschrauben und den Akku abklemmen, wenn mal irgendwas nicht so läuft, wie es soll.
-----

Wenn Du nicht weißt, wohin Du segeln willst, ist kein Wind richtig!
Zitieren
Unilein
Fachgebiet Rauchentwicklung
*******

Beiträge: 758
Registriert seit: Apr 2014
Bewertung: 5
22.03.2015, 12:44

Grrrr! #++*#§$$"!§! <-- Fluch!

Die Schaltung läuft zwar jetzt, benötigt aber jetzt viel zu viel Strom. Folglich war der 9V Akku heute morgen (nach nur knapp 15 Stunden) leer. Das ist natürlich totaler Mist.
Mit Netzteil wäre das kein Problem, aber ich habe nun mal keine Steckdose in der Nähe. Ich könnte jetzt noch am Programm arbeiten und den µC in den Pausen zwischen den Bewässerungszyklen schlafen schicken. Da würde ich sicher einiges an Strom sparen. Das Display muss eigentlich auch nicht immer an sein. Das könnte ich im Programm auch noch regeln. Auch an der Leistungsstufe könnte ich noch Dinge verändern: Momentan werden die Leistungstransistoren über die Basis leitend gemacht. Und sie bleiben solange leitend, bis an der Basis keine Spannung mehr anliegt. Logischerweise braucht auch das Strom.

Die Alternative wären MOSFET's. Die benötigen lediglich einen Impuls um leitend und einen weiteren Impuls um wieder nicht-leitend zu werden. Dazu müsste aber das komplette Design der Schaltung überarbeitet werden. Und ganz ehrlich: Dazu habe ich aktuell keine Lust. Meine Gewächshaussteuerung ist jetzt mal in die Bastelkiste gewandert. Wenn ich mal wieder viel Lust habe, überdenke ich das Ganze noch mal.

LG
Uni
-----

Wenn Du nicht weißt, wohin Du segeln willst, ist kein Wind richtig!
Zitieren
tesacrep
Administrator
*******

Beiträge: 500
Registriert seit: Dec 2013
Bewertung: 2
20.06.2016, 20:51

Hey,

mal eine kurze "Zwischenfrage". Hast du überlegt damals bei dir Co2 oder Sauerstoff der Luft zu messen? Bin gerade am überlegen solche Sensorenin die Wetterstation zu integrieren doch leider sind diese verdammt teuer.


Grüße

tesacrep
Zitieren
Unilein
Fachgebiet Rauchentwicklung
*******

Beiträge: 758
Registriert seit: Apr 2014
Bewertung: 5
23.06.2016, 23:12

Nee. Das habe ich nie in Betracht gezogen. Macht vermutlich in meinem großen Gewächshaus auch keinen Sinn. Dann bekommt ja ständig Frischluft, sind ja Fenster drin

Gruß,
Uni

Gesendet von meinem SM-N910F mit Tapatalk
-----

Wenn Du nicht weißt, wohin Du segeln willst, ist kein Wind richtig!
Zitieren
Unilein
Fachgebiet Rauchentwicklung
*******

Beiträge: 758
Registriert seit: Apr 2014
Bewertung: 5
21.05.2017, 14:57

Hallo zusammen,

da jetzt bald wieder Sommer ist, möchte ich das Thema mal wieder aufgreifen. Meine Schaltung von damals habe ich noch und sie funktioniert auch. In diesem Sommer werde ich, wenn alles gut geht, ein neues Gewächshaus bauen. Und dort wird dann auch gleich eine passende Steuerung verbaut. Die notwendige Infrastruktur werde ich von Anfang an mit einplanen. Die Steuerung wird dann in etwa die werden, die ich mir damals gebaut habe.

@tesacrep: Läuft Deine Steuerung eigentlich noch?

Gruß
Uni
-----

Wenn Du nicht weißt, wohin Du segeln willst, ist kein Wind richtig!
Zitieren
tesacrep
Administrator
*******

Beiträge: 500
Registriert seit: Dec 2013
Bewertung: 2
23.05.2017, 23:02

Hey,


das klingt doch Prima.
Ja meine Steuerung "läuft" noch. Ich habe zwar ein indoor Gewächshaus und baue auch aktuell nichts an aber Theoretisch tut alles. Letztens hatte ich die Pläne das ganze zu erweitern. Prinzipiell ist ja auch ein Peltierelement vorgesehen zur Kühlung usw. Das konnte ich aber noch nicht einsetzten da mir ein passendes Netzteil Fehlt. Eigentlich wollte ich auch noch darüber Heizen aber dann könnte man die Luftfeuchtigkeit nicht so gut Steuern. Ach ja - UV LEDs bringen nix sondern verbrennen dir die Pflanzen. Ohne konnte ich bessere Ergebnisse erzielen.

So Rückblickend gibt es doch noch einiges zu Tun. Planst Du dein neues Projekt eigentlich größer?

Also mehr Sensoren und Steuermodule?


Grüße

tesacrep
Zitieren
Unilein
Fachgebiet Rauchentwicklung
*******

Beiträge: 758
Registriert seit: Apr 2014
Bewertung: 5
13.04.2019, 17:40

Hey ho!

Das Frühjahr ist da und ich habe im vergangenen Jahr zusammen mit meiner Frau ein neues Gewächshaus gebaut. Es liegt also nah, dass auch das Thema "Bewässerung" wieder hoch blubbert.

2017 habe ich an dem Thema, obwohl damals angekündigt, nicht gearbeitet. Da gab es andere Dinge zu tun.

Aber jetzt ist 2019... Gerade mal 5 Jahre nach dem Projektstart in 2014.  Big Grin  Big Grin

Ich habe mein Modul von damals aus dem Schrank gepopelt und einem kurzen Test unterzogen. Die Elektronik funktioniert noch. Die zum Modul gehörigen Ventil, die das Wasser in die richtige Richtung lenken, habe ich auch noch. Ob die noch einwandfrei funktionieren, muss ich noch testen.

Das Programm auf dem Mikrocontroller (ATMega168) hat einen kleinen Fehler. Wenn Ventil 1 auslösen soll, löst auch Ventil 2 aus. Da ist wohl eine Variable falsch angesprochen oder so. Das Programm muss ich mir also auch noch einmal ansehen.

Das Programm ist in C mit dem Visual Studio von Atmel (heute Microchip) geschrieben. Ich habe schon damals den Controller ohne Arduino benutzt.

Hier mal der Programmcode von damals:

 
/*
*  Gewächshausbewässerung
*
* Created: 01.07.2014 11:13:08
*  Author: Martin de Hoogh
 
 
Versionierung:
 
07.06.2014, 0.1 alpha
 
- Festlegung der Ports und Pins
- Aufbau des Initialisierungsbilds
- Aufbau der Grundstruktur der Interruptroutine
- Aufbau der Grundstruktur der Hauptschleife
 
15.06.2014, 0.7 alpha
 
- ISR für PCINT0 (bislang ohne Funktion).
- Korrekte Zeitanzeige im Display
- Umsetzung der Ventil- und Pumpensteuerung (ohne Einstellmöglichkeit)
- Statusanzeige der Pumpe und der Ventile auf dem Hauptschirm
- Anzeige der Zeitdauern bis zur nächsten Öffnung für jedes Ventil
- Bitweise Ansteuerung des PORTC (Pumpe & Ventile)
 
27.06.2014, 0.9 alpha
 
- ISR für PCINT0 entfernt (nicht sinvoll nutzbar)
- ISR für Timer der Tasten an Pin 14,15 und 16 des ATMega
- Aufbau der Untermenüs für diverse Einstellungen
- Einstellen der Uhrzeit
- Speichern der eingestellten Uhrzeit im EEprom
 
29.06.2014, 1.0 alpha
 
- EEProm: Schreiben und lesen der Voreinstellungen
- Einstellen der Intervalle der Ventile
- Einstellen der Dauern der Ventilöffnung
 
06.07.14, 1.0 Beta
 
- Abschluß der Umstellung von Arduino auf C
- Korrektur des Timerinterrupts
- Abfrage, ob Laufdauer eines Ventil = 0, dann Ventil stillegen
- Standardwerte vorgeben, wenn Nichts im EEProm
 
 
23.07.14, 1.1 Beta
 
- ClkDiv/8 gesetzt und Programm für Betrieb auf 1MHz umgestellt
- Kontrastanpassung Display (zu hell)
- Behebung "Hyroglyphen" auf dem Display
- Anzeige der Temperatur und Feuchtigkeit reaktiviert
 
*/

 
#define F_CPU           1000000
#ifndef F_CPU
#define F_CPU           1000000                   // processor clock frequency
#warning kein F_CPU definiert
#endif
 
 
// Includes
#include <avr/io.h>
#include <avr/interrupt.h>
 
#include <avr/eeprom.h>
#include <util/delay.h>
 
 
//#include "dht11.c"   // Bibliothek für Temperatur- und Feuchtigkeitssensor
 
 
//True & False
#define TRUE (1 == 1)
#define FALSE (1 != 1)
 
// ===============================================
// Vorgaben für Intervalle & Dauern
// ===============================================
#define STD_INT_VALVE1 120 // Vorgabe für Ventil 1
#define STD_INT_VALVE2 121 // Vorgabe für Ventil 2
#define STD_INT_VALVE3 180 // Vorgabe für Ventil 3
 
#define STD_DUR_VALVE1 60 // Dauer für Ventil 1
#define STD_DUR_VALVE2 30 // Dauer für Ventil 2
#define STD_DUR_VALVE3 20 // Dauer für Ventil 3
 
 
 
// ===============================================
// Interrupteingang für INT0 (Pin 4 des ATMega328)
// ===============================================
#define PIN_INT0 PORTD2
 
 
// ===============================================
// EEProm-Adressen (Voreinstellungen)
// ===============================================
#define EP_HOUR        0x0100
#define EP_MINUTE      0x0101
#define EP_INTVALVE1   0x0102
#define EP_INTVALVE2   0x0104
#define EP_INTVALVE3   0x0106
#define EP_DURVALVE1   0x0108
#define EP_DURVALVE2   0x010A
#define EP_DURVALVE3   0x010C
 
 
// ===============================================
// Variable für die Tastenabfrage + Entprellung
// ===============================================
 
#define KEY_DDR         DDRB
#define KEY_PORT        PORTB
#define KEY_PIN         PINB
#define KEY0            0      // Pin 14
#define KEY1            1      // Pin 15
#define KEY2            2      // Pin 16
#define ALL_KEYS        (1<<KEY0 | 1<<KEY1 | 1<<KEY2)
 
#define REPEAT_MASK     0 // (1<<KEY1 | 1<<KEY2)  // repeat: key1, key2
#define REPEAT_START    50                        // nach 500ms
#define REPEAT_NEXT     20                        // alle 200ms
 
// ===============================================
// Makros für Bit-Operationen
// <a href="http://www.avrfreaks.net/index.php?name=pnphpbb2&file=viewtopic&t=37871" target="_blank" class="mycode_url">http://www.avrfreaks.net/index.php?name=...ic&t=37871</a>
// ===============================================
#define bit_get(p,m) ((p) & (m))
#define bit_set(p,m) ((p) |= (m))
#define bit_clear(p,m) ((p) &= ~(m))
#define bit_flip(p,m) ((p) ^= (m))
#define bit_write(c,p,m) (c ? bit_set(p,m) : bit_clear(p,m))
#define BIT(x) (0x01 << (x))
#define LONGBIT(x) ((unsigned long)0x00000001 << (x))
 
 
// ===============================================
// Datenport für DHT11
// Die Pin-Angaben beziehen sich auf den ATMega328P
// ===============================================
#define DHT11_DATA_PIN  PORTD1  // Port D, Bit 1, = Pin 3
 
// ===============================================
// Datenport für Leistungstransistoren
// Die Pin-Angaben beziehen sich auf den ATMega328P
// ===============================================
// Pumpe    = PORTC5   Pin 28 (Pumpe)
// Ventil 1 = PORTC4   Pin 27 (Ventil 1)
// Ventil 2 = PORTC3   Pin 26 (Ventil 2)
// Ventil 3 = PORTC2   Pin 25 (Ventil 3)
 
// Normale Variable
uint8_t hh,mm,ss; // Uhrzeit
uint8_t err = 0,t = 0,h = 0; // Fehlercode, Temperatur, Feuchtigkeit
uint8_t v = 1;
uint8_t valve[4];
uint8_t high,low;
uint8_t l = 0;
char temperature[4];    // Temperatur
char humidity[4]; // Feuchtigkeit
char tmpstr[12];                // Temporäre Zeichenkette
char time[] = "00:00:00\0";     // Zeit als String
//float temp, humi; // Daten vom Sensor
unsigned char temp, humi; // Daten vom Sensor
uint8_t ss_valve1,ss_valve2,ss_valve3; // Zähler für die Betriebsdauer der einzelnen Ventile
short flag_valve1=0; // Status Ventil 1
short flag_valve2=0; // Status Ventil 2
short flag_valve3=0; // Status Ventil 3
 
 
uint8_t MIN_HUM;    // Luftfeuchtigkeit
uint8_t MAX_TEMP; // Temperatur
uint8_t DUR_VALVE1; // Dauer für Ventil 1
uint8_t DUR_VALVE2; // Dauer für Ventil 2
uint8_t DUR_VALVE3; // Dauer für Ventil 3
uint8_t INT_VALVE1; // Intervall für Ventil 1
uint8_t INT_VALVE2; // Intervall für Ventil 2
uint8_t INT_VALVE3; // Intervall für Ventil 3
 
 
 
//
volatile uint8_t key_state;                       // Tastenstatus entprellt und umgekehrt: bit = 1: key pressed
volatile uint8_t key_press;                       // Tastendruck registriert
volatile uint8_t key_rpt;                         // Taste lange gedrückt und Wiederholung
 
void setWelcomeScr(void);
void setTimeScr(void);
void setIntervalScr(void);
void setDurationScr(void);
void setMenuScr(void);
void setMainScr(void);
void crtClkStr(void);
void setup(void);
 
void setup(void) {
 // Zunächst für alle nicht benötigten Ports die Pulldownwiderstände aktivieren
 // um den Stromverbrauch zu reduzieren und um die Ports in einen definierten
 // Status zu bringen.
 // Das Ganze erfolgt über direkte Ansprache der Pins
 
 // Steuerport für die Leistungsstufe initialisieren
 // Die Pins 28,27,26 und 25 (Port C5-C3) auf Ausgang
 // Die Pins 24 und 23 auf Eingang
 DDRC = 0xB00111100;
 PORTC = 0; // Alle Pins von Port C auf low
 
 // Interrupteingang (INT0) auf Input stellen
 DDRD = 0xB0000000; // Den ganzen Port erstmal auf Eingang
 PORTD = 0; // Alle Pins auf Low
 
 // Die 3 Pins mit den Tastern auf Input, die Pull-Ups einschalten
 KEY_DDR &= ~ALL_KEYS;                // Tastenports auf Input stellen
 KEY_PORT |= ALL_KEYS;                // die Pullups einschalten
 
 // LCD-Display initialisieren und Bildschirm löschen
 LCDInit(); //Init the LCD
 LCDClear();
 
 // Begrüssungsbildchen anzeigen
 setWelcomeScr();
 
 // Hauptschirm anzeigen
 setMainScr();
 
 
 // Interrupt-Serviceroutine einrichten
 // Ereignisse an INT0 (Pin 4 des ATMega328)
 // Bei Unterbrechung an INT0 wird "clock" aufgerufen
 
 EIMSK |= (1<<INT0); // Auf INT0 lauschen
 EICRA |= (1<<ISC01)|(1<<ISC00); // Bei steigender Flanke reagieren
 
 
 // Den Timer für die Tastenabfrage einschalten
 TCCR0B = (1<<CS02)|(1<<CS00);         // divide by 1024
 TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
 TIMSK0 |= 1<<TOIE0;                   // enable timer interrupt
 
 // Intervalle der Ventile lesen
 INT_VALVE1 = eeprom_read_byte (EP_INTVALVE1) + (256 * eeprom_read_byte ((EP_INTVALVE1 + 1))); ss_valve1 = INT_VALVE1; valve[1] = INT_VALVE1;
 INT_VALVE2 = eeprom_read_byte (EP_INTVALVE2) + (256 * eeprom_read_byte ((EP_INTVALVE2 + 1))); ss_valve2 = INT_VALVE2; valve[2] = INT_VALVE2;
 INT_VALVE3 = eeprom_read_byte (EP_INTVALVE3) + (256 * eeprom_read_byte ((EP_INTVALVE3 + 1))); ss_valve3 = INT_VALVE3; valve[3] = INT_VALVE3;
   
 
 if (INT_VALVE1 == 255) { INT_VALVE1 = STD_INT_VALVE1; }
 if (INT_VALVE2 == 255) { INT_VALVE2 = STD_INT_VALVE2; }
 if (INT_VALVE3 == 255) { INT_VALVE3 = STD_INT_VALVE3; }
 
 
 // Zeitdauern der Ventile lesen
 DUR_VALVE1 = eeprom_read_byte (EP_DURVALVE1);
 DUR_VALVE2 = eeprom_read_byte (EP_DURVALVE2);
 DUR_VALVE3 = eeprom_read_byte (EP_DURVALVE3);
 
 if (DUR_VALVE1 == 255) { DUR_VALVE1 = STD_DUR_VALVE1; }
 if (DUR_VALVE2 == 255) { DUR_VALVE2 = STD_DUR_VALVE2; }
 if (DUR_VALVE3 == 255) { DUR_VALVE3 = STD_DUR_VALVE3; }
 
 
 // Letzte Uhrzeit aus dem EEProm lesen
 hh=eeprom_read_byte ( EP_HOUR );    // Stunden aus dem EEprom lesen
 mm=eeprom_read_byte ( EP_MINUTE );  // Minuten aus dem EEprom lesen
 
 if (hh == 255) hh = 12;
 if (mm == 255) mm = 0;
 
 crtClkStr();
     l=251;
 
 // Interrupts zulassen
 sei();
}
 
int main(void)
{
 
   setup();
 
   while(1)
   {
         char valvestr[5];
 
         // Zeit anzeigen
         crtClkStr();
         gotoXY(3*5,0);     LCDString(time);
 
         // Temperatur und Feuchtigkeit auslesen und anzeigen
         getDHT11();
         gotoXY(20,1);    LCDString(temperature);
         gotoXY(65,1);    LCDString(humidity);
 
 
         // in etwa jede Sekunde die Restzeit für ein anderes Ventil anzeigen
         l++;
         if (l>20) {
         if (v == 1) {
         gotoXY(0,2);   LCDString("V1: ");
         gotoXY(28,2);  LCDString("     Min");
         gotoXY(28,2);  itoa(valve[1],valvestr,10); LCDString(valvestr);
     
 gotoXY(0,3);   LCDString("D1: ");
 gotoXY(28,3);  LCDString("     Sek");
 gotoXY(28,3);  itoa(DUR_VALVE1,valvestr,10); LCDString(valvestr);
         }
         if (v == 2) {
         gotoXY(0,2);   LCDString("V2: ");
         gotoXY(28,2);  LCDString("     Min");
         gotoXY(28,2);  itoa(valve[2],valvestr,10); LCDString(valvestr);
 
 gotoXY(0,3);   LCDString("D2: ");
 gotoXY(28,3);  LCDString("     Sek");
 gotoXY(28,3);  itoa(DUR_VALVE2,valvestr,10); LCDString(valvestr);  
         }
         if (v == 3) {
         gotoXY(0,2);   LCDString("V3: ");
         gotoXY(28,2);  LCDString("     Min");
         gotoXY(28,2);  itoa(valve[3],valvestr,10); LCDString(valvestr);
 
     gotoXY(0,3);   LCDString("D3: ");
 gotoXY(28,3);  LCDString("     Sek");
 gotoXY(28,3);  itoa(DUR_VALVE3,valvestr,10); LCDString(valvestr);
         }
         l =0;
         v++;
         if (v > 3) {     v=1;   }
 
         }
 
         // Auf dem Schirm die optischen Flags setzen
         if (flag_valve1 == TRUE || flag_valve2 == TRUE || flag_valve3 == TRUE ) {  gotoXY(20,5); LCDString("#");  }
         else { gotoXY(20,5); LCDString("$");  }
         
         if (flag_valve1 == TRUE) { gotoXY(35,5); LCDString("#"); }
         else { gotoXY(35,5); LCDString("$"); }
         
         if (flag_valve2 == TRUE) { gotoXY(49,5); LCDString("#"); }
         else { gotoXY(49,5); LCDString("$"); }
         
         if (flag_valve3 == TRUE) { gotoXY(63,5); LCDString("#"); }
         else { gotoXY(63,5); LCDString("$"); }
 
         // Hier zeigen wir temporär die aktuelle Rest-Betriebsdauer im Zyklus von Ventil 1 auf dem Display an
         //itoa(bit_get(PORTB0,BIT(0)),valvestr,10);
         //gotoXY(0,3);
         //LCDString(valvestr);
 
 
         // Die rote Taste abfragen und falls gedrückt, zum Menü verzweigen
         if( get_key_press( 1<<KEY0 )) {  setMenuScr(); }
 
   }
}
 
 
 
 
 
// ===============================================
// Willkommensbildchen
// (Ein wenig Speicher verschwenden)
// ===============================================
void setWelcomeScr(void) {
 gotoXY(0,0);
 LCDString("============");
 LCDString("| Waterboy |");
 LCDString("|©2014 by|");
 LCDString("| Martin   |");
 LCDString("============");
 gotoXY(0,0);
 _delay_ms(3000);
 LCDClear();
}
 
 
// ===============================================
// Uhrzeit einstellen
// ===============================================
void setTimeScr(void) {
 short y = 1;
 char h[2],m[2];
 
 LCDClear();
 gotoXY(0,0);
 LCDString("-<UHRZEIT >-");
 gotoXY(0,1); LCDString(" Stunden: ");
 gotoXY(0,2); LCDString(" Minuten: ");
 gotoXY(0,3); LCDString(" Exit       ");  
 
 gotoXY(14*5,1);  itoa(hh,h,10);     LCDString(h);   // Stunden anzeigen
 gotoXY(14*5,2);  itoa(mm,m,10);     LCDString(m);   // Minuten anzeigen
 
 
 PORTB = 0x0;  
 
 // Cursorsteuerung im Menü
 // Der Zähler (y) dient nach Drücken der roten Taste als Entscheidungsvariable
 // Stunden = Menüpunkt 1, Minuten = Menüpunkt 2
 while (!get_key_press( 1<<KEY0 )) {
   // rauf im Menü
   if (get_key_press( 1<<KEY1)) {
     gotoXY(0,y);
     LCDString(" ");
     y--;
     if (y < 1) {
       y=3;
     }
   }
 
   // runter im Menü
   if (get_key_press( 1<<KEY2)) {
     gotoXY(0,y);
     LCDString(" ");
     y++;
     if (y > 3) {
       y=1;
     }
   }
 
   gotoXY(0,y);
   LCDString(">");
 }
 
 // Stunden oder Minuten markieren
 gotoXY(12*5,y); LCDString(">");
 
 // Einstellen der Uhrzeit
 // Bestätigung wieder mit der roten Taste
 if (y != 3) {
   while (!get_key_press( 1<<KEY0 )) {
 
     // rauf zählen
     if (get_key_press( 1<<KEY1)) {
       // Wenn es Stunden sein sollen
       gotoXY(14*5,y); LCDString("   ");
       if (y==1) {
         hh++;
         if (hh>23) { hh = 0;  }
       }
       // Sonst Minuten
       if (y==2) {
         mm++;
         if (mm>59) { mm=0; }
       }
     }
 
     // runter zählen
     if (get_key_press( 1<<KEY2)) {
       // Wenn es Stunden sein sollen
       gotoXY(14*5,y); LCDString("  ");
       if (y==1) {
         hh--;
         if (hh<0) { hh = 23; }
       }
       // Sonst Minuten
       if (y==2) {
         mm--;
         if (mm<0) { mm=59; }
       }
     }
     
 
     gotoXY(14*5,y);
     if (y==1) {
       itoa(hh,h,10);     LCDString(h);   // Stunden anzeigen
     }
 
     if (y==2) {
       itoa(mm,m,10);     LCDString(m);   // Minuten anzeigen
     }
   }
   gotoXY(12*5,y);  LCDString(" ");    
 }  
   // Uhrzeit sichern
eeprom_write_byte (EP_HOUR,  hh); // Stunden ins EEProm
eeprom_write_byte (EP_MINUTE, mm); // Minuten ins EEProm
 
 
   setMenuScr();
 
 
}
 
 
// ===============================================
// Bewässerungsintervalle einstellen
// ===============================================
void setIntervalScr(void) {
 short y = 1;
 char v1[3],v2[3],v3[3];
 
 LCDClear();
 gotoXY(0,0);
 LCDString("-<INTERVAL>-");
 LCDString(" Vnt 1:     ");
 LCDString(" Vnt 2:     ");
 LCDString(" Vnt 3:     ");
 LCDString(" Exit       ");  
 
 gotoXY(11*5,1);  itoa(INT_VALVE1,v1,10);     LCDString(v1);   // Stunden anzeigen
 gotoXY(11*5,2);  itoa(INT_VALVE2,v2,10);     LCDString(v2);   // Minuten anzeigen
 gotoXY(11*5,3);  itoa(INT_VALVE3,v3,10);     LCDString(v3);   // Minuten anzeigen
 
 PORTB = 0x0;  
 
 // Cursorsteuerung im Menü
 // Der Zähler (y) dient nach Drücken der roten Taste als Entscheidungsvariable
 while (!get_key_press( 1<<KEY0 )) {
   // rauf im Menü
   if (get_key_press( 1<<KEY1)) {
     gotoXY(0,y);
     LCDString(" ");
     y--;
     if (y < 1) {
       y=4;
     }
   }
 
   // runter im Menü
   if (get_key_press( 1<<KEY2)) {
     gotoXY(0,y);
     LCDString(" ");
     y++;
     if (y > 4) {
       y=1;
     }
   }
 
   gotoXY(0,y);
   LCDString(">");
 }
 
 
 // Ventil markieren
 gotoXY(9*5,y); LCDString(">");
 
 // Einstellen der Intervalle der Ventile
 // Bestätigung wieder mit der roten Taste
 if (y != 4) {
   while (!get_key_press( 1<<KEY0 )) {
 
     // rauf zählen
     if (get_key_press( 1<<KEY1)) {
       // Intervall für Ventil 1
       gotoXY(11*5,y); LCDString("    ");
       if (y==1) {
         INT_VALVE1++;
         if (INT_VALVE1>1440) { INT_VALVE1 = 0;  }   // Intervalle größer 1440 vermeiden
       }
 
       // Intervall für Ventil 2
       gotoXY(11*5,y); LCDString("    ");
       if (y==2) {
         INT_VALVE2++;
         if (INT_VALVE2>1440) { INT_VALVE2 = 0;  }   // Intervalle größer 1440 vermeiden
       }
 
       // Intervall für Ventil 3
       gotoXY(11*5,y); LCDString("    ");
       if (y==3) {
         INT_VALVE3++;
         if (INT_VALVE3>1440) { INT_VALVE3 = 0;  }   // Intervalle größer 1440 vermeiden
       }
 
     }
 
     // runter zählen
     if (get_key_press( 1<<KEY2)) {
       // Intervall für Ventil 1
       gotoXY(11*5,y); LCDString("    ");
       if (y==1) {
         INT_VALVE1--;
         if (INT_VALVE1<0) { INT_VALVE1 = 1440;  }   // Intervalle größer 1440 vermeiden
       }
 
       // Intervall für Ventil 2
       gotoXY(11*5,y); LCDString("    ");
       if (y==2) {
         INT_VALVE2--;
         if (INT_VALVE2<0) { INT_VALVE2 = 1440;  }   // Intervalle größer 1440 vermeiden
       }
 
       // Intervall für Ventil 3
       gotoXY(11*5,y); LCDString("    ");
       if (y==3) {
         INT_VALVE3--;
         if (INT_VALVE3<0) { INT_VALVE3 = 1440;  }   // Intervalle größer 1440 vermeiden
       }
       
     }
     
 
     gotoXY(11*5,y);
     if (y==1) {
       itoa(INT_VALVE1,v1,10);     LCDString(v1);   // Ventil 1
     }
 
     if (y==2) {
       itoa(INT_VALVE2,v2,10);     LCDString(v2);   // Ventil 2
     }
 
     if (y==3) {
       itoa(INT_VALVE3,v3,10);     LCDString(v3);   // Ventil 3
     }
 
   }
   gotoXY(9*5,y);  LCDString(" ");    
 }  
 
   // Intervalle sichern
   high = INT_VALVE1 / 256; low = INT_VALVE1 - high * 256;
eeprom_write_byte (EP_INTVALVE1,  low); // Dauer Ventil 1 ins EEProm
eeprom_write_byte (EP_INTVALVE1 + 1,  high); // Dauer Ventil 1 ins EEProm
   
   high = INT_VALVE2 / 256; low = INT_VALVE2 - high * 256;
eeprom_write_byte (EP_INTVALVE2,  low); // Dauer Ventil 2 ins EEProm
eeprom_write_byte (EP_INTVALVE2 + 1,  high); // Dauer Ventil 2 ins EEProm
   
   high = INT_VALVE3 / 256; low = INT_VALVE3 - high * 256;
eeprom_write_byte (EP_INTVALVE3,  low); // Dauer Ventil 3 ins EEProm
eeprom_write_byte (EP_INTVALVE3 + 1,  high); // Dauer Ventil 3 ins EEProm
 
   setMenuScr();
}
 
// ===============================================
// Bewässerungsdauern einstellen
// ===============================================
void setDurationScr(void) {
 char d1[3],d2[3],d3[3];
 short y=1;
 
 LCDClear();
 gotoXY(0,0);
 LCDString("-< DAUERN >-");
 LCDString(" Vnt 1:     ");
 LCDString(" Vnt 2:     ");
 LCDString(" Vnt 3:     ");
 LCDString(" Exit       ");  
 
 gotoXY(11*5,1);  itoa(DUR_VALVE1,d1,10);     LCDString(d1);   // Stunden anzeigen
 gotoXY(11*5,2);  itoa(DUR_VALVE2,d2,10);     LCDString(d2);   // Minuten anzeigen
 gotoXY(11*5,3);  itoa(DUR_VALVE3,d3,10);     LCDString(d3);   // Minuten anzeigen
 
 
 PORTB = 0x0;  
 
 // Cursorsteuerung im Menü
 // Der Zähler (y) dient nach Drücken der roten Taste als Entscheidungsvariable
 while (!get_key_press( 1<<KEY0 )) {
   // rauf im Menü
   if (get_key_press( 1<<KEY1)) {
     gotoXY(0,y);
     LCDString(" ");
     y--;
     if (y < 1) {
       y=1;
     }
   }
 
   // runter im Menü
   if (get_key_press( 1<<KEY2)) {
     gotoXY(0,y);
     LCDString(" ");
     y++;
     if (y > 4) {
       y=4;
     }
   }
 
   gotoXY(0,y);
   LCDString(">");
 }
 
 
 // Einstellen der Zeitdauern der Ventile
 // Bestätigung wieder mit der roten Taste
 if (y != 4) {
   while (!get_key_press( 1<<KEY0 )) {
 
     // rauf zählen
     if (get_key_press( 1<<KEY1)) {
       // Intervall für Ventil 1
       gotoXY(11*5,y); LCDString("    ");
       if (y==1) {
         DUR_VALVE1++;
         if (DUR_VALVE1>120) { DUR_VALVE1 = 0;  }   // Intervalle größer 1440 vermeiden
       }
 
       // Intervall für Ventil 2
       gotoXY(11*5,y); LCDString("    ");
       if (y==2) {
         DUR_VALVE2++;
         if (DUR_VALVE2>120) { DUR_VALVE2 = 0;  }   // Intervalle größer 1440 vermeiden
       }
 
       // Intervall für Ventil 3
       gotoXY(11*5,y); LCDString("    ");
       if (y==3) {
         DUR_VALVE3++;
         if (DUR_VALVE3>120) { DUR_VALVE3 = 0;  }   // Intervalle größer 1440 vermeiden
       }
 
     }
 
     // runter zählen
     if (get_key_press( 1<<KEY2)) {
       // Intervall für Ventil 1
       gotoXY(11*5,y); LCDString("    ");
       if (y==1) {
         DUR_VALVE1--;
         if (DUR_VALVE1<0) { DUR_VALVE1 = 120;  }   // Intervalle größer 1440 vermeiden
       }
 
       // Intervall für Ventil 2
       gotoXY(11*5,y); LCDString("    ");
       if (y==2) {
         DUR_VALVE2--;
         if (DUR_VALVE2<0) { DUR_VALVE2 = 120;  }   // Intervalle größer 1440 vermeiden
       }
 
       // Intervall für Ventil 3
       gotoXY(11*5,y); LCDString("    ");
       if (y==3) {
         DUR_VALVE3--;
         if (DUR_VALVE3<0) { DUR_VALVE3 = 120;  }   // Intervalle größer 1440 vermeiden
       }
       
     }
     
 
     gotoXY(11*5,y);
     if (y==1) {
       itoa(DUR_VALVE1,d1,10);     LCDString(d1);   // Ventil 1
     }
 
     if (y==2) {
       itoa(DUR_VALVE2,d2,10);     LCDString(d2);   // Ventil 2
     }
 
     if (y==3) {
       itoa(DUR_VALVE3,d3,10);     LCDString(d3);   // Ventil 3
     }
 
   }
   gotoXY(9*5,y);  LCDString(" ");    
 }  
 
   // Zeitdauern sichern
eeprom_write_byte (EP_DURVALVE1,  DUR_VALVE1); // Dauer Ventil 1 ins EEProm
eeprom_write_byte (EP_DURVALVE2,  DUR_VALVE2); // Dauer Ventil 2 ins EEProm
eeprom_write_byte (EP_DURVALVE3,  DUR_VALVE2); // Dauer Ventil 3 ins EEProm
   setMenuScr();  
}
 
 
// ===============================================
// Anzeige des Hauptmenüs
// ===============================================
void setMenuScr(void) {
 short y = 1;
 
 LCDClear();
 gotoXY(0,0);
 LCDString("-< SETUP  >-");
 LCDString(" Uhrzeit    ");
 LCDString(" Intervalle ");
 LCDString(" Dauern     ");
 LCDString(" Exit       ");
 gotoXY(0,0);
 
 PORTB = 0x0;  
 
 // Cursorsteuerung im Menü
 // Der Zähler (y) dient nach Drücken der roten Taste als Entscheidungsvariable
 while (!get_key_press( 1<<KEY0 )) {
   // rauf im Menü
   if (get_key_press( 1<<KEY1)) {
     gotoXY(0,y); LCDString(" ");
     y--;
     if (y < 1) {
       y=4;
     }
   }
 
   // runter im Menü
   if (get_key_press( 1<<KEY2)) {
     gotoXY(0,y); LCDString(" ");
     y++;
     if (y > 4) {
       y=1;
     }
   }
 
   gotoXY(0,y);  LCDString(">");
 }
 
 // Jetzt wurde die rote Taste gedrückt --> Es geht weiter
 
 switch (y) {
  case 1:   setTimeScr();     break;
  case 2:   setIntervalScr(); break;
  case 3:   setDurationScr(); break;
  case 4:   setMainScr();
 }  
}
 
 
 
 
// ===============================================
// Hauptschirm
// Anzeige Statusdaten
// ===============================================
void setMainScr(void) {
 LCDClear();
 gotoXY(2*5,0);  LCDString("[");
 gotoXY(75,0);   LCDString("]");
 gotoXY(0,1);    LCDString("T:");
 gotoXY(45,1);   LCDString("H:");
 
 gotoXY(0,4);    LCDString("---P-1-2-3--");
 gotoXY(0,5);    LCDString("S:          ");
}
 
 
// ===============================================
// Umwandlung der Zähler für Sekunden, Minuten und
// Stunden in einen String, der so angezeigt werden
// kann
// ===============================================
void crtClkStr(void) {
 char h[]="00"  ,m[]="00" ,s[]="00" ;
 
 itoa(hh,h,10);  // Stunden
 itoa(mm,m,10);  // Minuten
 itoa(ss,s,10);  // Sekunden
 
 
 if (hh<10) { time[0] = '0';  time[1] = h[0];  }
 else { time[0] = h[0];  time[1] = h[1];  }
 if (mm<10) { time[3] = '0';  time[4] = m[0];  }
 else { time[3] = m[0]; time[4] = m[1];   }
 if (ss<10) { time[6] = '0';  time[7] = s[0];  }
 else { time[6] = s[0]; time[7] = s[1];   }
 
}
 
 
// =============================================== =============================================== =============================================== ===============================================
// === Interrupts
// =============================================== =============================================== =============================================== ===============================================
 
 
// ===============================================
// Interrupt-Service Routine für INT0 (Pin 4)
// Hier wird die interne Uhr, die ihren Takt über
// den quarzgesteuerten Taktgeber am Pin 4 des
// ATMega328 bekommt, hochgezählt.
// Die Routine simuliert lediglich eine Uhr und
// zählt die Intervalle für die einzelnen Ventile
// runter
// ===============================================
ISR(INT0_vect) {
//void clock(void) {
 //char h[]="00"  ,m[]="00" ,s[]="00" ;
 
 
 PORTD |= (0 << PIN_INT0); // wieder auf Low
 
 
 // Ventil 1 ist offen, jetzt solange warten, bis maximale Zeit erreicht, dann wieder schließen
 if (flag_valve1 == TRUE) {
   ss_valve1--;
   if (ss_valve1 < 1) {
     flag_valve1 = FALSE;
     ss_valve1 = DUR_VALVE1;        
     bit_clear(PORTC,BIT(5));
     bit_clear(PORTC,BIT(4));  
   }
 }
 
 
 // Ventil 2 ist offen, jetzt solange warten, bis maximale Zeit erreicht, dann wieder schließen
 if (flag_valve2 == TRUE) {
   ss_valve2--;
   if (ss_valve2 < 1) {
     flag_valve2 = FALSE;
     ss_valve2 = DUR_VALVE2;
     bit_clear(PORTC,BIT(5));
     bit_clear(PORTC,BIT(3));
   }
 }
 
 
 // Ventil 3 ist offen, jetzt solange warten, bis maximale Zeit erreicht, dann wieder schließen    
 if (flag_valve3 == 1) {
   ss_valve3--;
   if (ss_valve3 < 1) {
     flag_valve3 = FALSE;
     ss_valve3 = DUR_VALVE3;
     bit_clear(PORTC,BIT(5));
     bit_clear(PORTC,BIT(2));
   }
 }
 
 
 ss++;   // Sekunden rauf
 
 // 60 Sekunden sind um...
 if (ss > 59) {
   ss = 0;
   mm++;  // Minuten rauf
 
   // Die Intervalle für die Ventile herunterzählen
// aber nur, wenn die Laufdauer für ein Ventil nicht 0 ist
   if ( DUR_VALVE1 != 0) { valve[1]--; }
   if ( DUR_VALVE2 != 0) { valve[2]--; }
   if ( DUR_VALVE3 != 0) { valve[3]--; }
 
   // Für Ventil 1 ist die Zeit gekommen, bitte einschalten
   if (valve[1] < 1) {
     valve[1] = INT_VALVE1;
     bit_set(PORTC,BIT(5));
     bit_set(PORTC,BIT(4));      
     flag_valve1 = TRUE;   // Flag für Zähler Ventil 1 + Pumpe
   }
 
 
 
   // Für Ventil 2 ist die Zeit gekommen, bitte einschalten
   if (valve[2] < 1) {
     valve[2] = INT_VALVE2;
     bit_set(PORTC,BIT(5));
     bit_set(PORTC,BIT(3));      
     flag_valve2 = TRUE;   // Flag für Zähler Ventil 2 + Pumpe
   }
 
 
 
   // Für Ventil 3 ist die Zeit gekommen, bitte einschalten    
   if (valve[3] < 1) {
     valve[3] = INT_VALVE3;    
     bit_set(PORTC,BIT(5));
     bit_set(PORTC,BIT(2));              
     flag_valve3 = TRUE;   // Flag für Zähler Ventil 3 + Pumpe
   }    
 }  
 
 
 if (mm > 59) {
   mm = 0;
   hh++;
 }
 if (hh > 23) {
   hh = 0;
 }  
 
 
}
 
 
// ===============================================
// Interrupt-Service Routine für TIMER1
// Es werden die Pins 14,15 und 16 abgefragt
// Atmega328 Port B (0-2)
//
// Die Routine fragt den Status der Pins ab und
// gibt den Status zurück
//
// Die Tasten werden bei der Abfrage entprellt
//
// Die Basis hierzu hat Peter Dannegger entwickelt
// ===============================================
ISR( TIMER0_OVF_vect )                            // alle 10 ms
{
 static uint8_t ct0, ct1, rpt;
 uint8_t i;
 
 TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
 
 i = key_state ^ ~KEY_PIN;                       // Tastenstatus geändert? ?
 ct0 = ~( ct0 & i );                             // reset oder zählen ct0
 ct1 = ct0 ^ (ct1 & i);                          // reset oder zählen ct1
 i &= ct0 & ct1;                                 // Zählen bis zum Überlauf ?
 key_state ^= i;                                 // Dann den Prellstatus ändern
 key_press |= key_state & i;                     // 0->1: Tastendruck registrieren
 
 if( (key_state & REPEAT_MASK) == 0 )            // Wiederholfunktion prüfen
   rpt = REPEAT_START;                          // Pause beginnen
 if( --rpt == 0 ){
   rpt = REPEAT_NEXT;                            // Pause wiederholen
   key_rpt |= key_state & REPEAT_MASK;
 }
}
 
// ===============================================
// Prüfen ob eine Taste gedrückt wurde. Jeder Tastendruck
// wird nur EINMAL gemeldet.
// ===============================================
int get_key_press( int key_mask )
{
 cli();                                          // read and clear atomic !
 key_mask &= key_press;                          // read key(s)
 key_press ^= key_mask;                          // clear key(s)
 sei();
 return key_mask;
}
 
// ===============================================
// Prüfen ob eine Taste solange gedrückt wurde, dass
// die Tastenwiederholfunktion aktiviert wird
// Es wird sozusagen simuliert, dass der Benutzer
// die Taste mehrfach drückt und wieder loslässt.
// ===============================================
uint8_t get_key_rpt( uint8_t key_mask )
{
 cli();                                          // read and clear atomic !
 key_mask &= key_rpt;                            // read key(s)
 key_rpt ^= key_mask;                            // clear key(s)
 sei();
 return key_mask;
}
 
// ===============================================
// Prüfen ob eine Taste gerade JETZT gedrückt wurde.
// Jeder Tastendruck wird nur EINMAL gemeldet.
// ===============================================
uint8_t get_key_state( uint8_t key_mask )
{
 key_mask &= key_state;
 return key_mask;
}
 
// ===============================================
// Prüfen ob eine Taste KURZ gedrückt wurde.
// ===============================================
uint8_t get_key_short( uint8_t key_mask )
{
 cli();   // Interrupt unterdrücken
 return get_key_press( ~key_state & key_mask );
}
 
// ===============================================
// Prüfen ob eine Taste LANG gedrückt wurde.
// ===============================================
uint8_t get_key_long( uint8_t key_mask )
{
 return get_key_press( get_key_rpt( key_mask ));
}
 
// =============================================== =============================================== =============================================== ===============================================
// =============================================== =============================================== =============================================== ===============================================
 
 
 
// ===============================================
// Werte des DHT11-Sensors lesen
// ===============================================
 
void getDHT11() {
 
 //if (
  dht11(&humi, &temp); // == 0)
 {
   t = &temp;
   h = &humi;
 
   itoa(t,temperature,10);
   itoa(h,humidity,10);
 }  
 
}
 
 


Zu der reinen Steuerung der Bewässerung hatte ich damals noch einen Temperatur- und Feuchtigkeitssensor vom Typ DHT111 eingebaut. Außerdem ein LCD-Display, auf dem Zeiten, Intervalle und Bewässerungsdauer angezeigt werden.

Ich würde sagen: Viel Spaß beim lesen. Ich bin für weitere Anregungen offen. Sofern ich die Schaltung noch anpassen sollte, werde ich sie dann aber auch als Platine bestellen und ordentlich aufbauen.

Grüße
Uni
(Dieser Beitrag wurde zuletzt bearbeitet: 13.04.2019, 17:41 von Unilein.)
Zitieren
Unilein
Fachgebiet Rauchentwicklung
*******

Beiträge: 758
Registriert seit: Apr 2014
Bewertung: 5
22.04.2019, 15:41

Hallo zusammen,

inzwischen habe ich meine Magnetventile auf Funktion getestet. Leider ist eines fest und bewegt sich nicht mehr. Da muss ich mal schauen, ob ich das wieder gängi bekomme.

Die Schaltung selbst funktioniert soweit, verbraucht jedoch viel zuviel Strom. Der 9-Volt-Block, mit dem die Schaltung betrieben wird, ist nach 2 Tagen leer. Das ist natürlich nicht der Brüller.
Hintergrund für den hohen Stromverbrauch ist vermutlich der Taktgeber für die interne Uhr. Dieser ist mit einem CMOS-Baustein aufgebaut, der durch Teilung aus 4,19 MHz einen Sekundentakt generiert. Weil der Takt so hoch ist, benötigt der Baustein 9 Volt.

Die aktuelle Schaltung hat folgende Funktionen:
  • Interne Uhr zur Steuerung der Bewässerungsintervalle (extern getaktet)
  • 3 Bewässerungsintervalle (für je einen Bewässerungsstrang)
  • 3 Bewässerungsdauern (je Intervall einen)
  • Temperatur und Luftfeuchtigkeitsmessung
  • Anzeige aktueller Daten auf dem Display
  • Menüsteuerung zur Parametereinstellung
  • Sicherung der Parameter im EEPROM des Atmega

Ich habe beschlossen, meine Schaltung zu überdenken und neu zu entwickeln. Dabei werde ich folgendes umsetzen:
  • Taktfrequenz von 1 MHZ runter auf 32,768 KHz (Uhrenquarz). Aus dem Takt lässt sich per Teiler intern ein Sekundentakt generieren
  • Wegfall der externen Taktquelle
  • 3 Bewässerungsintervalle
  • 3 Bewässerungsdauern
  • Betrieb der Schaltung mit 3,7 Volt
  • Display wird nur eineschaltet, wenn Interaktion statt findet und geht aus, wenn Interaktion beender
  • Betrieb der Ventile und der Pumpe (wie zuvor auch) über eine zweite Spannungsquelle

Optional werde ich prüfen, ob Luftfeuchtigkeitsmessung überhaupt sinnvoll ist. Auch die Temperaturmessung erscheint mir fragwürdig. Ich werde eher auf Bodenfeuchtigkeitsmessung setzen um die Bewässerung zu steuern.
Ob, wie zuvor in der Schaltung vorgesehen, weiter Optokoppler zum Einsatz kommen, muss ich noch überlegen. Vermutlich tut es auch eine einfache Diode. Die Schaltung werde ich dann wieder in China fertigen lassen.
Di fertige Schaltung wird vermutlich auf eine 50 x 50 mm kleine Platine passen. Das Display soll huckepack oben drauf, das spart jede Menge Platz.

Jetzt muss ich das nur noch umsetzen...

Gruß
Uni
Zitieren
AteEris
Junior Member
**

Beiträge: 1
Registriert seit: Jan 2020
Bewertung: 0
28.01.2020, 17:12

Vielleicht kann ma ja den shield auch dafür nutzen:
https://www.ramser-elektro.at/der-gies-o...n-arduino/

Die Sensoren sehen gut aus.
Wurden schon bei wissenschaftlichen Arbeiten benutzt:
https://opus.hs-offenburg.de/frontdoor/d...ringer.pdf

Hier wird auf alle verfügbaren Bodensensoren eingegangen:
https://wwwvs.cs.hs-rm.de/vs-wiki/index...._Kapazitiv
Zitieren


Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 2 Gast/Gäste