Eigentlich, aber nur eigentlich bin ich jetzt fertig mit dem Projekt. Alles im Gehäuse eingebaut und funktioniert ... bis auf die Funktion
/ Funktion TuerZu(temp)
void tuerZu(float tempnow) {
...
in Verbindung mit einer Logik, die ermitteln soll, ob die Temperaturänderung signifikant ist, um zu verhindern, dass eine Tür nicht immer bewegt wird, wenn die Temperatur gleich bleibt.
Also, die Schleife wird durchlaufen und eine Aktion soll nur dann ausgeführt werden, wenn sich die Temperaturwerte geändert haben.
Alles schon mal gehabt, nur, dass hier die Temperaturänderungen einen Bereich umfassen und einer zusätzlichen Hysterese unterliegen
Bereich1: tempnow < 18 - 0.8
Bereich2: 18 <= tempnow < 21 - 0.8
Bereich3: 21 <= tempnow < 24 - 0.8
Bereich4: > 24 + 0.8
Dafür habe ich eine globale Variable float letzteTemp = -1; (liegt im Sommer außerhalb jeglichen Bereichs), um den letzten Temperaturwert zu speichern.
Am Ende des Programms prüfe ich, ob sich die Temperatur geändert hat:
if (tempnow >= 21 && tempnow < 24 - hysteresewert) {
tuerZu(tempnow);
letzteTemp = tempnow;
Die Abfrage sollte logisch sein, mittels switch Funktion lasse ich die Schleife hinter mir, wenn der Wert gleich ist und übergebe 0.
Denoch wird der Türstatus städig neu abgefragt und sie bewegt sich laufend hin und her.
Aus C++ weiß ich, dass jede if
- oder else
-Anweisung innerhalb einer Funktion stehen sollte.
Deshalb steht die breakfunktion ab Zeile 71 auch in der Funktion drin. Setze ich sie in einem anderen Programmteil außerhalb der Funktion, dann funktioniert sie. Was ist für Arduino richtig?
Hier der Code: (ohne Fehlermeldung)
#include <MobaTools.h>
#include <LiquidCrystal_I2C.h>
// LCD-Objekt erstellen
LiquidCrystal_I2C lcd(0x26, 20, 4);
LiquidCrystal_I2C lcd1(0x27, 20, 4);
#include <OneWire.h>
#include <DallasTemperature.h>
//#include <Wire.h>
#include <RTClib.h>
RTC_DS3231 rtc;
// PINBELEGUNG Regensensor
const int rainDigitalPin = 13;
const int rainAnalogPin = A0;
const int rainSensorPowerPin = A1;
// PINBELEGUNG Temperatursensor
// OneWire oneWire(TEMP_PIN);
#define ONE_WIRE_BUS 46
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
// PINBELEGUNG Stepper-Motor NEMA 17
const int enablePin = 8; // blau
const int stepPin = 9; // schwarz
const int dirPin = 10; // rot
// PINBELEGUNG für die Endschalter der Linearführung
#define Auf 6 // gelb
#define Zu 7 // rot
// Definiere eine Variable für den Temperatursensor
float tempStatus;
float tempnow;
// Globale Variable, um den letzten Temperaturwert zu speichern
float letzteTemp = -1;
int a;
float hysteresewert = 0.8;
// PINBELEGUNG der Sensoren
#define RAIN_PIN A0 // Regensensor
#define TEMP_PIN A2 // Temperatursensor
// Anzahl der Sensoren und Pumpen
const int n = 6;
int sensorPins[n] = { A3, A4, A5, A6, A7, A8 }; // Sensoren Pins (analog)
int pumpPins[n] = { 30, 31, 32, 33, 34, 35 }; // Pumpen Pins (digital)
// Feuchtigkeitswerte (0 - 1023)
int moistureValues[n];
// Pumpenzustände (0 oder 1)
int pumpStates[n];
int schrittStatus;
int schrittstatusOld;
// Schwellwerte für Pumpensteuerung (in Prozent)
const int lowerThreshold = 55;
const int upperThreshold = 68;
// Start. und Endzeit festlegen
#define START_HOUR 8 // Startstunde des Programms
#define END_HOUR 20 // Endstunde des Programms
MoToStepper myStepper(300, STEPDIR); // 300 Schritte pro Umdrehung
// Funktion tuerZu ohne Parameter
void tuerZu() {
myStepper.doSteps(-20000);
while (digitalRead(Zu) == HIGH)
;
myStepper.doSteps(200);
while (myStepper.moving())
;
myStepper.setZero();
delay(500);
}
// Funktion tuerZu mit Temperaturparameter
void tuerZu(float tempnow) {
const int schritteProVoll = 13624; // Anzahl der Schritte für eine volle Öffnung
int schritte = 0;
if (tempnow < 18 - 0.8) {
tuerZu();
schritte = schritteProVoll;
} else if (tempnow >= 18 && tempnow < 21 - 0.8) {
schritte = schritteProVoll * 3 / 4;
} else if (tempnow >= 21 && tempnow < 24 - 0.8) {
schritte = schritteProVoll / 2;
} else if (tempnow >= 24) {
schritte = schritteProVoll;
}
tuerZu();
// Schritte, wenn nicht NULL
if (schritte != 0) {
myStepper.doSteps(schritte);
while (myStepper.moving()); // Warten bis Bewegungsende
}
// Setzen Sie den Referenzpunkt, wenn die Tür vollständig geöffnet ist
if (schritte == 0) {
myStepper.setZero();
}
}
// Funktion zur Überprüfung der Temperatur und Steuerung der Tür
void pruefeTemperaturUndSteuerTuer(float tempnow) {
if (letzteTemp == tempnow) {
a = 0;
} else {
a = 1;
letzteTemp = tempnow;
}
switch (a) {
case 0:
break;
case 1:
tuerZu(tempnow);
break;
}
}
void setup() {
Serial.begin(9600);
lcd.init(); //Im Setup wird das erste LCD gestartet
lcd1.init(); //Im Setup wird das zweite LCD gestartet
lcd.backlight(); //Hintergrundbeleuchtung vom LCD einschalten
lcd1.backlight();
pinMode(pumpPins[n], OUTPUT);
pinMode(sensorPins[n], INPUT);
//PINMODUS festlegen
pinMode(8, OUTPUT); //Enable BLAU
pinMode(9, OUTPUT); //Puls SCHWARZ
pinMode(10, OUTPUT); //Direction ROT
pinMode(enablePin, OUTPUT);
// PINMODUS für Pullup festlegen
pinMode(4, INPUT_PULLUP); // Tür manuell auf
pinMode(5, INPUT_PULLUP); // Tür manuell zu
pinMode(6, INPUT_PULLUP); // Tür auf GELB
pinMode(7, INPUT_PULLUP); // Tür zu ROT
// Pumpen Pins als Ausgänge definieren
for (int i = 0; i < n; i++) {
pinMode(pumpPins[i], OUTPUT);
digitalWrite(pumpPins[i], HIGH); // Pumpen ausschalten
pumpStates[i] = 0; // Pumpenzustände auf aus setzen
}
// PINMODUS für Regensensor festlegen
//pinMode(rainDigitalPin, INPUT);
pinMode(rainAnalogPin, INPUT);
pinMode(rainSensorPowerPin, OUTPUT);
// Initialisiere den Stepper
myStepper.attach(stepPin, dirPin);
myStepper.setSpeed(4000); // 5000 Schritte pro Sekunde
myStepper.setRampLen(100); // Rampenlänge auf 10 Schritte setzen
digitalWrite(enablePin, LOW);
// Führe die Türschließroutine einmal aus
tuerZu();
Wire.begin();
rtc.begin();
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// Abfrage, ob Zeitmodul gestartet ist
if (!rtc.begin()) {
lcd.print("RTC nicht gefunden!");
while (1)
;
}
// Anzeige am Display zur Orientierung
lcd.setCursor(0, 0);
lcd.print(" Anfahren der");
lcd.setCursor(0, 1);
lcd.print(" Homeposition");
lcd.setCursor(0, 3);
lcd.print(" Bitte warten");
}
void loop() {
// ******* Zu Programmbeginn werden Uhrzeit, Datum und Status auf dem LCD Display angezeigt *******
DateTime now = rtc.now();
lcd.setCursor(0, 0);
if (now.hour() < 10) lcd.print("0");
lcd.print(now.hour(), DEC);
if (now.hour() < 10) lcd.print("0");
lcd.print(':');
if (now.minute() < 10) lcd.print("0");
lcd.print(now.minute(), DEC);
if (now.minute() < 10) lcd.print("0");
lcd.print(" ");
if (now.day() < 10) lcd.print("0");
lcd.print(now.day(), DEC);
lcd.print('.');
if (now.month() < 10) lcd.print("0");
lcd.print(now.month(), DEC);
lcd.print('.');
lcd.print(now.year(), DEC);
if (now.hour() >= START_HOUR && now.hour() < END_HOUR) {
lcd.setCursor(0, 1);
lcd.print(" Programm bereit!");
} else {
lcd.setCursor(0, 1);
lcd.print(" Ausser der Zeit");
}
// ABFRAGE DES REGENSENSORS ANALOG
digitalWrite(rainSensorPowerPin, HIGH);
delay(500);
int rainAnalog = analogRead(rainAnalogPin);
Serial.print(rainAnalog);
if (rainAnalog >= 900) {
lcd.setCursor(0, 3);
lcd.print("Kein Regen");
Serial.println("kein Regen");
delay(500);
}
if (900 > rainAnalog && rainAnalog >= 750) {
lcd.setCursor(0, 3);
lcd.print("leichter Regen");
Serial.println("leichter Regen");
delay(500);
}
if (rainAnalog < 750) {
lcd.setCursor(0, 3);
lcd.print("starker Regen");
Serial.println("starker Regen");
delay(500);
}
digitalWrite(rainSensorPowerPin, LOW);
delay(1000);
// TEMPERATURABFRAGE
tempnow = sensors.getTempCByIndex(0);
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Die Innentemperatur");
sensors.requestTemperatures();
lcd.setCursor(0, 1);
lcd.print("betr\xE1gt: ");
lcd.print(sensors.getTempCByIndex(0));
lcd.print("\337C");
delay(1000);
// Sensorwerte lesen und auf LCD Display anzeigen
lcd1.setCursor(0, 0); // Cursor auf erste Zeile setzen
lcd1.print("Feuchte (%) - Pumpen"); // Überschrift schreiben
for (int i = 0; i < n; i++) {
moistureValues[i] = analogRead(sensorPins[i]); // Sensorwert lesen
int moisturePercent = map(moistureValues[i], 0, 1023, 100, 0); // Sensorwert in Prozent umrechnen
Serial.print("Sensor "); // Sensorname auf serieller Konsole ausgeben
Serial.print(i + 1);
Serial.print(": ");
Serial.println(moisturePercent); // Sensorwert auf serieller Konsole ausgeben
lcd1.setCursor(i * 3 + 2, 1); // Cursor auf zweite Zeile setzen
lcd1.print(i + 1); // Sensornummer auf LCD Display ausgeben
lcd1.setCursor(i * 3 + 1, 2); // Cursor auf dritte Zeile setzen
lcd1.print(moisturePercent); // Sensorwert auf LCD Display ausgeben
delay(500); // Halbe Sekunde warten
}
// Pumpenzustände bestimmen und auf LCD Display anzeigen
lcd1.setCursor(0, 3); // Cursor auf vierte Zeile setzen
delay(1000);
for (int i = 0; i < n; i++) {
int moisturePercent = map(moistureValues[i], 0, 1023, 100, 0); // Sensorwert in Prozent umrechnen
if (moisturePercent < lowerThreshold) { // Wenn Boden zu trocken ist
digitalWrite(pumpPins[i], HIGH); // Pumpe einschalten
pumpStates[i] = 1; // Pumpenzustand auf an setzen
} else if (moisturePercent > upperThreshold) { // Wenn Boden zu nass ist
digitalWrite(pumpPins[i], LOW); // Pumpe ausschalten
pumpStates[i] = 0; // Pumpenzustand auf aus setzen
}
lcd1.setCursor(i * 3 + 1, 3); // Cursor auf vierte Zeile setzen
if (pumpStates[i] == 1) { // Wenn Pumpe an ist
lcd1.print("AN"); // AN auf LCD Display ausgeben
} else { // Wenn Pumpe aus ist
lcd1.print("AU"); // AU auf LCD Display ausgeben
}
}
// TEMPERATURABFRAGE
float tempnow = sensors.getTempCByIndex(0);
// Prüfen, ob sich die Temperatur geändert hat
pruefeTemperaturUndSteuerTuer(tempnow);
if (tempnow < 18 - hysteresewert) {
// Bereich: tempnow < 18 - 0.8
tuerZu(tempnow);
letzteTemp = tempnow;
delay(1000);
letzteTemp = tempnow;
} else if (tempnow >= 18 && tempnow < 21 - hysteresewert) {
// Bereich: 18 <= tempnow < 21 - 0.8
tuerZu(tempnow);
letzteTemp = tempnow;
Serial.print(letzteTemp);
delay(1000);
} else if (tempnow >= 21 && tempnow < 24 - hysteresewert) {
tuerZu(tempnow);
letzteTemp = tempnow;
} else if (tempnow >= 24 + hysteresewert) {
tuerZu(tempnow);
letzteTemp = tempnow;
}
}