Benutzer-Werkzeuge

Webseiten-Werkzeuge


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:

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