bewaesserungsautomat:programmversion_0.3
Bewässerungsautomat Programmversion 0.3
Achtung!
Diese Programmversion wird nicht mehr weiter entwickelt. Weiter geht es mit Programmversion 0.4
Gegenüber Programmversion 0.2 alpha wurde verändert:
- Der DHT22 wird ausgelesen und die Werte an die serielle Schnittstelle ausgegeben.
- Auf Basis der gemessenen Temperatur und Luftfeuchte wird der Hitzeindex berechnet und an die serielle Schnittstelle ausgegeben.
- Auf Basis der gemessenen Temperatur und Luftfeuchte wird der Taupunk berechnet und an die serielle Schnittstelle ausgegeben.
- Wenn die Gehäuseinnentemperatur unter den Taupunkt fällt, leuchten am NeoPixel-Ring am Wasserstandssensor zwei LEDs rot statt weiß.
- Der Wasserstandssensor für den Vorratsbehälter wird ausgelesen und in einen prozentualen Füllstand umgerechnet. Damit funktioniert jetzt auch die Ansteuerung des NeoPixel-Rings am Wasserstandssensor.
- Der TSL2591 wird ausgelesen und die Werte an die serielle Schnittstelle ausgegeben.
- Auf Basis der gemessenen Helligkeit wird eine Variable berechnet, mit der die Helligkeit der NeoPixel gesteuert wird.
Hilfreiche Links:
- https://learn.adafruit.com/thermistor (Ich will zwar keinen Thremistor anschließen, aber der Level-Sensor funktioniert genauso.))
- https://forums.adafruit.com/viewtopic.php?f=47&t=41143 (Sehr hilfreich für die automatische Anpassung der Helligkeit der NeoPixels.)
Was noch zu tun ist (in dieser oder einer späteren Programmversion):
- Damit die Neopixel blinken oder pulsieren können, müsste das Programm ohne den delay-Befehl auskommen.
- Wenn das Programm entsprechend umgestellt wurde, sollen die NeiPixel in den Blumenkastensensoren pulsieren.
- Für die NeoPixel-Ringe sind Animationen denkbar.
- Bluetooth
- Der Wasserstandssensor könnte schneller ausgelesen und ein Mittelwert über die letzten X Messwerte gebildet werden, um schnelle Schwankungen, die auf Messfehler zurückgehen, zu vermeiden.
- Es wäre zu überlegen, wie der gemessene Referenzwiederstand in die Berechnung des Wasserstands einbezogen werden kann.
Belegung der Arduino-Pins für diese Programmversion
Im Folgenden ist die Pin-Belegung am Arduino für diese Programmversion dokumentiert. Um Verwechselungen vorzubeugen, ist außerdem die Farbe der Kabel der Signalleitungen dokumentiert.
Strom:
- GND: Masse von Stromverteilerplatine
- Vin: 5 Volt von Stromverteilerplatine
Müssen vom Proto-Board mit Strom versorgt werden:
- NeoPixel-Ring 1
- BeoPixel-Ring 2
- TSL2591
Analoge Eingänge
- A0: Variabler Widerstand Level-Sensor und über 1500 Ohm-Widerstand an 5 Volt
- A1: Konstanter Widerstand Level-Sensor und über 1500 Ohm-Widerstand an 5 Volt
Digitale Eingänge:
- Pin 26: Hall-Schalter 1 (direkt) (blau)
- Pin 28: Hall-Schalter 2 (direkt) (blau)
- Pin 30: Hall-Schalter 3 (direkt) (blau)
- Pin 32: Hall-Schalter 4 (direkt) (blau)
- Pin 46: Masse Blumenkastensensor 1 (direkt) (grün)
- Pin 48: Masse Blumenkastensensor 2 (direkt) (grün)
- Pin 50: Masse Blumenkastensensor 3 (direkt) (grün)
- Pin 52: Masse Blumenkastensensor 4 (direkt) (grün)
- Pin 39: DHT22 (grün)
Digitale Ausgänge:
- Pin 36: Relais 1 (direkt) (gelb)
- Pin 38: Realis 2 (direkt) (grün)
- Pin 40: Relais 3 (direkt) (gelb)
- Pin 42: Relais 4 (direkt) (grün)
NeoPixel:
- Pin 12: Blumenkastensensor 1 über 470 Ohm (gelb)
- Pin 11: Blumenkastensensor 2 über 470 Ohm (gelb)
- Pin 10: Blumenkastensensor 3 über 470 Ohm (gelb)
- Pin 9: Blumenkastensensor 4 über 470 Ohm (gelb)
- Pin 8: Wasserstandssensor über 470 Ohm (gelb)
- Pin 7: Neopixelring 1 über 470 Ohm (gelb)
- Pin 6: Neopixelring 2 über 470 Ohm (gelb)
I2C-Bus:
- SDA (20): TSL2591 (gelb)
- SCL (21): TSL2591 (blau)
Code
// Bibliotheken einbinden
#include <Wire.h>
#include <Adafruit_NeoPixel.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_TSL2591.h"
#include "DHT.h"
// Definiert die Pins für die NeoPixels
int neoPin1 = 12; // Neopixel an Blumenkastenensor 1
int neoPin2 = 11; // Neopixel an Blumenkastenensor 2
int neoPin3 = 10; // Neopixel an Blumenkastenensor 3
int neoPin4 = 9; // Neopixel an Blumenkastenensor 4
int neoPin5 = 8; // Neopixelring am Wasserstandssensor im Vorratsbehälter
int neoPin6 = 7; // Neopixelring im Gehäusedeckel
//int neoPin6 = 6; // Reserviert für Erweiterungen
//int neoPin6 = 5; // Reserviert für Erweiterungen
// Definiert die NeoPixels
Adafruit_NeoPixel neopix1 = Adafruit_NeoPixel(1, neoPin1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel neopix2 = Adafruit_NeoPixel(1, neoPin2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel neopix3 = Adafruit_NeoPixel(1, neoPin3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel neopix4 = Adafruit_NeoPixel(1, neoPin4, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel neopix5 = Adafruit_NeoPixel(12, neoPin5, NEO_RGBW + NEO_KHZ800);
Adafruit_NeoPixel neopix6 = Adafruit_NeoPixel(24, neoPin6, NEO_RGBW + NEO_KHZ800);
// pass in a number for the sensor identifier (for your use later)
Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591);
// Definiert die Pins für die Hall-Sensoren
int hallPin1 = 32; // Hall-Sensor 1
int hallPin2 = 30; // Hall-Sensor 2
int hallPin3 = 28; // Hall-Sensor 3
int hallPin4 = 26; // Hall-Sensor 4
// Definiert die Pins für die Verfügbarkeitskontrolle
int massePin1 = 46; // Masse an Blumenkastenensor 1
int massePin2 = 48; // Masse an Blumenkastenensor 2
int massePin3 = 50; // Masse an Blumenkastenensor 3
int massePin4 = 52; // Masse an Blumenkastenensor 4
// Definiert die Pins des Wasserstandssensor für den Vorratsbehälter
int refPin = A1; // Rref
int levelPin = A2; // Rsense
// Definiert den Pin für den DHT22
int dhtPin = 39;
// Definiert den angeschlossenen Sensor
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321)
// Initialisiert den DHT-Sensor
DHT dht(dhtPin, DHTTYPE);
// Definiert die Pins für die Pumpenrelais
int relPin1 = 36; // Pumpe 1
int relPin2 = 38; // Pumpe 2
int relPin3 = 40; // Pumpe 3
int relPin4 = 42; // Pumpe 4
// Definiert die Variablen
int hall1 = LOW;
int hall2 = LOW;
int hall3 = LOW;
int hall4 = LOW;
int masse1 = LOW;
int masse2 = LOW;
int masse3 = LOW;
int masse4 = LOW;
int rlevel = 0;
int rref = 0;
int brightness = 0;
void setup() {
// Initialisiere die NeoPixel-Pins
pinMode(neoPin1, OUTPUT);
pinMode(neoPin2, OUTPUT);
pinMode(neoPin3, OUTPUT);
pinMode(neoPin4, OUTPUT);
pinMode(neoPin5, OUTPUT);
pinMode(neoPin6, OUTPUT);
// Initialisiere die Hall-Pins als Inputs mit Pullup. Außerdem werden die internen Pullup-Widerstände aktiviert.
// Liegt an dem Hall-Sensor ein Magnetfeld an, ist der Input LOW, ansonsten ist der Input HIGH.
pinMode(hallPin1, INPUT_PULLUP);
pinMode(hallPin2, INPUT_PULLUP);
pinMode(hallPin3, INPUT_PULLUP);
pinMode(hallPin4, INPUT_PULLUP);
pinMode(massePin1, INPUT_PULLUP);
pinMode(massePin2, INPUT_PULLUP);
pinMode(massePin3, INPUT_PULLUP);
pinMode(massePin4, INPUT_PULLUP);
//Initialisiert den Pin für den DHT22 als Input mit Pullup
pinMode(dhtPin, INPUT_PULLUP);
// Initialisiere die Relais-Pins
pinMode(relPin1, OUTPUT);
pinMode(relPin2, OUTPUT);
pinMode(relPin3, OUTPUT);
pinMode(relPin4, OUTPUT);
// Initialisiere den Wasserstandssensor
pinMode(rlevel, INPUT);
pinMode(rref, INPUT);
// Initialisiere alle NeoPixels
neopix1.begin();
neopix1.show(); // Initialize all pixels to 'off'
neopix2.begin();
neopix2.show(); // Initialize all pixels to 'off'
neopix3.begin();
neopix3.show(); // Initialize all pixels to 'off'
neopix4.begin();
neopix4.show(); // Initialize all pixels to 'off'
neopix5.begin();
neopix5.show(); // Initialize all pixels to 'off'
neopix6.begin();
neopix6.show(); // Initialize all pixels to 'off'
// Konfiguration des TSL2591
// You can change the gain on the fly, to adapt to brighter/dimmer light situations
//tsl.setGain(TSL2591_GAIN_LOW); // 1x gain (bright light)
tsl.setGain(TSL2591_GAIN_MED); // 25x gain
// tsl.setGain(TSL2591_GAIN_HIGH); // 428x gain
// Changing the integration time gives you a longer time over which to sense light
// longer timelines are slower, but are good in very low light situtations!
tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS); // shortest integration time (bright light)
// tsl.setTiming(TSL2591_INTEGRATIONTIME_200MS);
// tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
// tsl.setTiming(TSL2591_INTEGRATIONTIME_400MS);
// tsl.setTiming(TSL2591_INTEGRATIONTIME_500MS);
// tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS); // longest integration time (dim light)
// Debugging output
Serial.begin(9600);
dht.begin();
tsl.begin();
delay(2000); // Diese Pause benötigt der DHT22 um erste Messwerte zu lesen.
// Perspektivisch könnte eine Startanimation des NeoPixel-Rings die Wartezeit verkürzen.
}
void loop() {
// Auslesen der digitalen Eingänge
hall1 = digitalRead(hallPin1);
hall2 = digitalRead(hallPin2);
hall3 = digitalRead(hallPin3);
hall4 = digitalRead(hallPin4);
masse1 = digitalRead(massePin1);
masse2 = digitalRead(massePin2);
masse3 = digitalRead(massePin3);
masse4 = digitalRead(massePin4);
// Auslesen der analogen Eingänge
rlevel = analogRead(levelPin);
rref = analogRead(refPin);
// Ausgabe der Eingangssignale an den digitalen Masse-Pins an die serielle Schnittstelle
// Der Ausgabewert "0" bedeutet, dass der entsprechende Blumenkastensensor angeschlossen ist
Serial.print("Sensor Kasten 1: ");
Serial.print(masse1);
Serial.print(" \t");
Serial.print("Sensor Kasten 2: ");
Serial.print(masse2);
Serial.print(" \t");
Serial.print("Sensor Kasten 3: ");
Serial.print(masse3);
Serial.print(" \t");
Serial.print("Sensor Kasten 4: ");
Serial.print(masse4);
Serial.println(" \t");
// Ausgabe der Eingangssignale an den digitalen Hall-Pins an die serielle Schnittstelle
// Der Ausgabewert "1" bedeutet, dass kein Magnetfeld gemessen wird
Serial.print("Hallschalter 1: ");
Serial.print(hall1);
Serial.print(" \t");
Serial.print("Hallschalter 2: ");
Serial.print(hall2);
Serial.print(" \t");
Serial.print("Hallschalter 3: ");
Serial.print(hall3);
Serial.print(" \t");
Serial.print("Hallschalter 4: ");
Serial.print(hall4);
Serial.println(" \t");
// Ausgabe des Eingangssignals an den analogen Wasserstands-Pins an die serielle Schnittstelle
Serial.print("Wert Sensorwiderstand: ");
Serial.print(rlevel);
Serial.print("\t");
Serial.print("Wert Referenzwiederstand: ");
Serial.print(rref);
Serial.println("\t");
// Berechnung des Wasserstands im Vorratsbehälter in Prozent
float rlevelmin = 830; // Messwert bei minimalem Wasserstand
float rlevelmax = 430; // Messwert bei maximalem Wasserstand
float level = 100 - (((rlevelmax - rlevel) / (rlevelmax - rlevelmin)) * 100);
// Ausgabe des Wasserstands im Vorratsbehälter in Prozent an die serielle Schnittstelle
Serial.print("Wasserstand: ");
Serial.print(level);
Serial.println(" %");
// More advanced data read example. Read 32 bits with top 16 bits IR, bottom 16 bits full spectrum
// That way you can do whatever math and comparisons you want!
uint32_t lum = tsl.getFullLuminosity();
uint16_t ir, full;
ir = lum >> 16;
full = lum & 0xFFFF;
Serial.print("[ "); Serial.print(millis()); Serial.print(" ms ] ");
Serial.print("IR: "); Serial.print(ir); Serial.print(" ");
Serial.print("Full: "); Serial.print(full); Serial.print(" ");
Serial.print("Visible: "); Serial.print(full - ir); Serial.print(" ");
Serial.print("Lux: "); Serial.println(tsl.calculateLux(full, ir));
// Berechnung der Helligkeit der NeoPixel
float brightness = log(full) / 10;
Serial.print(brightness);
// Ansteuerung der Pumpen.
// Ist der Wasserstand niedrig, liegt kein Magnetfeld am Hall-Sensor an (hall = 1).
// Die entsprechende Pumpe wird aktiviert, bis der Soll-Wasserstand erreicht ist (hall = 0),
// - sofern keine andere Pumpe läuft und
// - sofern Wasser im Vorratsbehälter ist.
// Pumpe 1
if (masse1 == 0 && hall1 == 1 && level > 5 && digitalRead(relPin2) == HIGH && digitalRead(relPin3) == HIGH && digitalRead(relPin4) == HIGH) {
digitalWrite(relPin1, LOW);
}
else {
digitalWrite(relPin1, HIGH);
}
// Pumpe 2
if (masse2 == 0 && hall2 == 1 && level > 5 && digitalRead(relPin1) == HIGH && digitalRead(relPin3) == HIGH && digitalRead(relPin4) == HIGH) {
digitalWrite(relPin2, LOW);
}
else {
digitalWrite(relPin2, HIGH);
}
// Pumpe 3
if (masse3 == 0 && hall3 == 1 && level > 5 && digitalRead(relPin1) == HIGH && digitalRead(relPin2) == HIGH && digitalRead(relPin4) == HIGH) {
digitalWrite(relPin3, LOW);
}
else {
digitalWrite(relPin3, HIGH);
}
// Pumpe 4
if (masse4 == 0 && hall4 == 1 && level > 5 && digitalRead(relPin1) == HIGH && digitalRead(relPin2) == HIGH && digitalRead(relPin3) == HIGH) {
digitalWrite(relPin4, LOW);
}
else {
digitalWrite(relPin4, HIGH);
}
// Ansteuerung der NeoPixels in den Blumenkastensensoren
if (hall1 == 0) {
neopix1.setPixelColor(0, 0, 255*brightness, 0); //grün-weiß, wenn Wasserstand ok
}
else {
neopix1.setPixelColor(0, 255*brightness, 0, 0); //rot, wenn Wasserstand niedrig
}
neopix1.show();
if (hall2 == 0) {
neopix2.setPixelColor(0, 0, 255*brightness, 0); //grün-weiß, wenn Wasserstand ok
}
else {
neopix2.setPixelColor(0, 255*brightness, 0, 0); //rot, wenn Wasserstand niedrig
}
neopix1.show();
if (hall3 == 0) {
neopix3.setPixelColor(0, 0, 255*brightness, 0); //grün-weiß, wenn Wasserstand ok
}
else {
neopix3.setPixelColor(0, 255*brightness, 0, 0); //rot, wenn Wasserstand niedrig
}
neopix3.show();
if (hall4 == 0) {
neopix4.setPixelColor(0, 0, 255*brightness, 0); //grün-weiß, wenn Wasserstand ok
}
else {
neopix4.setPixelColor(0, 255*brightness, 0, 0); //rot, wenn Wasserstand niedrig
}
neopix4.show();
//Ansteuerung des NeoPixel-Rings im Wasserstandssensor für den Vorratsbehälter
neopix5.setPixelColor(0, 0, 0, 0, 127);
neopix5.setPixelColor(11, 0, 0, 0, 127);
if (level >= 90) {
neopix5.setPixelColor(10, 0, 255*brightness, 0, 0);
} else if (level < 90) {
neopix5.setPixelColor(10, 0, 0, 0, 0);
}
if (level >= 80) {
neopix5.setPixelColor(9, 0, 255*brightness, 0, 0);
} else if (level < 80) {
neopix5.setPixelColor(9, 0, 0, 0, 0);
}
if (level >= 70) {
neopix5.setPixelColor(8, 0, 255*brightness, 0, 0);
} else if (level < 70) {
neopix5.setPixelColor(8, 0, 0, 0, 0);
}
if (level >= 60) {
neopix5.setPixelColor(7, 0, 255*brightness, 0, 0);
} else if (level < 60) {
neopix5.setPixelColor(7, 0, 0, 0, 0);
}
if (level >= 50) {
neopix5.setPixelColor(6, 127*brightness, 127*brightness, 0, 0);
} else if (level < 50) {
neopix5.setPixelColor(6, 0, 0, 0, 0);
}
if (level >= 40) {
neopix5.setPixelColor(5, 127*brightness, 127*brightness, 0, 0);
} else if (level < 40) {
neopix5.setPixelColor(5, 0, 0, 0, 0);
}
if (level >= 30) {
neopix5.setPixelColor(4, 127*brightness, 127*brightness, 0, 0);
} else if (level < 30) {
neopix5.setPixelColor(4, 0, 0, 0, 0);
}
if (level >= 20) {
neopix5.setPixelColor(3, 255*brightness, 0, 0, 0);
} else if (level < 20) {
neopix5.setPixelColor(3, 0, 0, 0, 0);
}
if (level >= 10) {
neopix5.setPixelColor(2, 255*brightness, 0, 0, 0);
} else if (level <10) {
neopix5.setPixelColor(2, 0, 0, 0, 0);
}
neopix5.show();
// Auslesen des DHT22 und Ausgabe der Werte an serielle Schnittstelle
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity(); // Luftfeuchte auslesen
float t = dht.readTemperature(); //Temperatur in Grad Celsius auslesen
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t)) {
Serial.println("DHT22 konnte nicht ausgelesen werden!");
return;
}
// Hitzeindex in Celsius berechnen (isFahreheit = false)
float hic = dht.computeHeatIndex(t, h, false);
// Taupunkt berechnen
float a = 17.271;
float b = 237.7;
float taupunktTmp = (a * t) / (b + t) + log(h/100);
float taupunkt = (b * taupunktTmp) / (a - taupunktTmp);
Serial.print("Luftfeuchte: ");
Serial.print(h);
Serial.print(" %\t");
Serial.print("Temperatur: ");
Serial.print(t);
Serial.print(" *C\t");
Serial.print("Hitzeindex: ");
Serial.print(hic);
Serial.print(" *C\t");
Serial.print("Taupunkt: ");
Serial.print(taupunkt);
Serial.println(" *C");
// Warnung bei Unterschreiten der Gehäuseinnentemperatur unter den Taupunkt
if (t <= taupunkt) {
neopix5.setPixelColor(0, 127, 0, 0, 0);
neopix5.setPixelColor(11, 127, 0, 0, 0);
} else if (t > taupunkt) {
neopix5.setPixelColor(0, 0, 0, 0, 127);
neopix5.setPixelColor(11, 0, 0, 0, 127);
}
delay(1000); // 1 Sek Pause
}
Tags: #Arduino #Bewässerungsautomat #Code
bewaesserungsautomat/programmversion_0.3.txt · Zuletzt geändert: 18.05.2023 12:15 von 127.0.0.1