Hallo,
Ich habe mittels einen Arduino Uno versucht einen Brutapparat zu bauen.
Im Prinzip sind es 5 DS18B20 Sensoren und ein DHT11 zur Feuchtemessung,
Und 2 Heizkabel die mit einem Optokoppler gesteuerten Relais geschaltet werden.
Es funktioniert alles einwandfrei nur, nach einer gewissen Zeit (~6 Stunden) friert der Arduino ein und die Regelung funktioniert nicht mehr.
Das heißt es werden keine neuen Werte mehr gemessen, die beiden Relais schalten nicht mehr aus. Und beim Bildschrim schaltet auch die Feuchte anzeige nicht mehr hin und her, wie im Code vorgesehen.
Es werden aber die letzten Temperaturwerte normal angezeigt, aber ohne das sie sich ändern.
Ich habe den Code schon mehrmals durchgesehen, und ich finde keine Stelle die dies Problem verursachen könnte.
Der Brutapparat ist auch schon mehr als 30 Tage am Stück gelaufen, ohne Probleme und jetzt weiß ich nicht woher die Probleme kommen könnten.
Könnte es durch eine neuere Version sein?
Könnte mir vielleicht hier wer weiterhelfen, ich hätte einmal den Code angefügt.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <DHT.h>
#define POTI A0
#define LEDPIN LED_BUILTIN
#define RELAISPIN7 7
#define RELAISPIN8 8
int pPotiInput, pAnalogInput;
float pSoll, pIst, pDelta;
const float pTempFenster = 0.8;
bool pHeat, pHysterese, pHeatRelaisOn, pHeatRelaisBottomOn, pHystereseMode, pHystereseOn;
int pHystereseLoopTimer;
float pT1, pT2, pT3, pT4, pT5, pH6, pT3T4Average;
int pReferenzCounter;
const unsigned long cInterval = 100;
const unsigned long cInterval1 = 4000;
unsigned long pCurrentMillis, pLastMillis;
unsigned long pCurrentMillis1, pLastMillis1;
float pSollT5 = 40.0;
const float pSollT5High = 43.0, pSollT5Low = 39.5, pDeltaT5High = 1.6, pDeltaT5Low = 0.2;
bool HumidityDisplay;
//Hysteresensteuerung für Relaistakt
unsigned long pCurrentMillisBlink, pLastMillisBlink;
const unsigned long cIntervalBlinkIntervall = 1000;
LiquidCrystal_I2C lcd(0x27,20,4);
// Data wire is plugged into the Arduino
#define OWB_DS18B20 2
#define OWB_DHT11 3
// Initiat DHT11 Sensor
DHT SensorDHT(OWB_DHT11, DHT11);
// Initiate DS18B20
OneWire oneWire(OWB_DS18B20);
DallasTemperature SensorsDS(&oneWire);
// Addresses of 5 DS18B20s
uint8_t adT1[8] = { 0x28, 0xFF, 0x64, 0x1F, 0x40, 0x5F, 0x16, 0xFA };
uint8_t adT2[8] = { 0x28, 0xFF, 0x64, 0x1F, 0x40, 0x48, 0x83, 0x56 };
uint8_t adT3[8] = { 0x28, 0xFF, 0x64, 0x1F, 0x40, 0x58, 0x91, 0x9B };
uint8_t adT4[8] = { 0x28, 0xFF, 0x64, 0x1F, 0x40, 0x61, 0x1C, 0x75 };
uint8_t adT5[8] = { 0x28, 0xFF, 0x64, 0x1F, 0x40, 0x6D, 0x43, 0xA2 };
void setup()
{
lcd.init();
lcd.backlight();
// Start up the Sensors
SensorsDS.begin();
SensorDHT.begin();
pinMode(LEDPIN, OUTPUT);
pinMode(RELAISPIN7, OUTPUT);
pinMode(RELAISPIN8, OUTPUT);
//Ausgänge initial schreiben
digitalWrite(RELAISPIN7, true); //TRUE bedeutet auf FALSE setzen
digitalWrite(RELAISPIN8, true);
pReferenzCounter = 2;
}
void loop()
{
//Aktuellen Millisekunden auslesen + Überlaufschutz
pCurrentMillis = millis();
if (pCurrentMillis < pLastMillis) {
pLastMillis = 0;
}
pCurrentMillis1 = millis();
if (pCurrentMillis1 < pLastMillis1) {
pLastMillis1 = 0;
}
pCurrentMillisBlink = millis();
if (pCurrentMillisBlink < pLastMillisBlink) {
pLastMillisBlink = 0;
}
if ((pCurrentMillis - pLastMillis) >= cInterval) {
// save the last time
pLastMillis = pCurrentMillis;
pAnalogInput = analogRead(POTI);
pPotiInput = map(pAnalogInput, 0, 1023, 300, 400);
pSoll = (float)pPotiInput / 10.0;
//Display Ausgabe
lcd.setCursor(0,0);
lcd.print("S: ");
lcd.print(pSoll, 1);
lcd.write(0xDF);
}
if ((pCurrentMillis1 - pLastMillis1) >= cInterval1) {
// save the last time
pLastMillis1 = pCurrentMillis1;
//Aktuellen Temperaturen auslesen
SensorsDS.requestTemperatures();
pT1 = SensorsDS.getTempC(adT1);
pT2 = SensorsDS.getTempC(adT2);
pT3 = SensorsDS.getTempC(adT3);
pT4 = SensorsDS.getTempC(adT4);
pT5 = SensorsDS.getTempC(adT5);
//Feuchte Auslesen
pH6 = SensorDHT.readHumidity();
//Anzeige Eliminieren wenn kein Sensor gesteckt
pReferenzCounter = 2;
if (pT1 < 0.0) {
pT1 = 0.0;
pReferenzCounter = pReferenzCounter - 1;
} else {
pT1 = pT1 + 0.5;
}
if (pT2 < 0.0) {
pT2 = 0.0;
pReferenzCounter = pReferenzCounter - 1;
} else {
pT2 = pT2 + 0.6;
}
if (pT3 < 0.0) {
pT3 = 0.0;
} else {
pT3 = pT3 + 0.8;
}
if (pT4 < 0.0) {
pT4 = 0.0;
} else {
pT4 = pT4 + 0.8;
}
if (pT5 < 0.0) {
pT5 = 0.0;
} else {
pT5 = pT5 + 0.0;
}
//Aktuelle Temperatur bestimmen, nur wenn mindestens 1 Sensor von T1 | T2 gesteckt
if (pReferenzCounter > 0) {
pIst = (pT1 + pT2) / pReferenzCounter;
}
//Wenn keine Temperaturen zum einlesen sind dann wird Sensor T3 verwendet (Auch nur wenn ein Wert eingelsen wird)
else if (pT3 > 1.0) {
pIst = pT3;
}
//Sonst wird Sensor T5 verwendet, egal ob er verwendet wird oder nicht
else {
pIst = pT5;
}
//Delta bestimmen
pDelta = pSoll - pIst;
//Linear Regler für T5
pSollT5 = (pDelta - pDeltaT5Low) * (pSollT5High - pSollT5Low) / (pDeltaT5High - pDeltaT5Low) + pSollT5Low;
if (pSollT5 <= pSollT5Low) {
pSollT5 = pSollT5Low;
}
else if (pSollT5 >= pSollT5High) {
pSollT5 = pSollT5High;
}
else {
pSollT5; //Wert nach linearer Rechnung übernehmen
}
//2PunktRegler mit Hysterese
if ((pDelta <= -0.01) || (pT5 >= pSollT5))
{
pHeat = false; //Kühlen (Temperatur ist zu hoch)
pHysterese = false;
}
else if (pDelta >= pTempFenster)
{
pHeat = true; //Heizen (Temperatur ist zu gering)
pHysterese = false;
}
else
{
pHeat = true ; //Hysterese Fenster anfangen zu takten
pHysterese = true;
}
//Ist Anzeige
lcd.setCursor(10,0);
lcd.print("In: ");
lcd.print(pIst, 1);
lcd.write(0xDF);
lcd.setCursor(0,1);
lcd.print("T1: ");
lcd.print(pT1, 1);
lcd.write(0xDF);
lcd.print(" T2: ");
lcd.print(pT2, 1);
lcd.write(0xDF);
lcd.setCursor(0,2);
lcd.print("T3: ");
lcd.print(pT3, 1);
lcd.write(0xDF);
lcd.print(" T4: ");
lcd.print(pT4, 1);
lcd.write(0xDF);
lcd.setCursor(0,3);
lcd.print("T5: ");
lcd.print(pT5, 1);
lcd.write(0xDF);
if (HumidityDisplay) {
lcd.print(" H6: ");
lcd.print(pH6, 0);
lcd.print("% ");
} else {
lcd.print(" S5: ");
lcd.print(pSollT5, 1);
lcd.write(0xDF);
}
HumidityDisplay = !HumidityDisplay;
}
//Code zur Intervallsteuerung
if ((pCurrentMillisBlink - pLastMillisBlink) >= cIntervalBlinkIntervall) {
// save the last time
pLastMillisBlink = pCurrentMillisBlink;
if (pHystereseMode == true) {
// Modus 1 (Benötigt noch mehr Leistung) T, T, T, T, T, T, T, T, T, T, F, F, F, F, F, F
if (pHystereseLoopTimer < 10) {
pHystereseOn = true;
pHystereseLoopTimer = pHystereseLoopTimer + 1;
}
else {
pHystereseOn = false;
if (pHystereseLoopTimer >= 15) {
pHystereseLoopTimer = 0; //LoopTimer auf 0 damit der Zyklus wieder von vorne beginnt
}
else {
pHystereseLoopTimer = pHystereseLoopTimer + 1;
}
}
}
else {
// Modus 0 (Benötigt weniger Leistung) T, T, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F
if (pHystereseLoopTimer < 2) {
pHystereseOn = true;
pHystereseLoopTimer = pHystereseLoopTimer + 1;
}
else {
pHystereseOn = false;
if (pHystereseLoopTimer >= 15) {
pHystereseLoopTimer = 0; //LoopTimer auf 0 damit der Zyklus wieder von vorne beginnt
}
else {
pHystereseLoopTimer = pHystereseLoopTimer + 1;
}
}
}
}
//Ausgänge analysieren und beschalten
if (pHeat == false) {
pHeatRelaisOn = false;
}
else if (pHeat && pHysterese) {
//Fenstererkennung (Modus auswählen)
if (pDelta >= (pTempFenster / 2.0)) {
// Modus 1 (Benötigt noch mehr Leistung)
pHystereseMode = true;
}
else {
// Modus 0 (Benötigt weniger Leistung)
pHystereseMode = false;
}
pHeatRelaisOn = pHystereseOn;
}
else {
//Dauerhaft einschalten
pHeatRelaisOn = true;
}
//Mittelwert bilden
pT3T4Average = (pT3 + pT4) / 2.0;
//Heizkabel am Boden
if (pT3T4Average < (pSoll - 0.1)) {
//Heizkabel am Boden soll Heizen
pHeatRelaisBottomOn = true;
}
else if (pT3T4Average > pSoll) {
//Heizkabel ausschalten
pHeatRelaisBottomOn = false;
}
//Ausgänge schreiben
digitalWrite(RELAISPIN7, !pHeatRelaisOn);
digitalWrite(RELAISPIN8, !pHeatRelaisBottomOn);
digitalWrite(LEDPIN, pHeatRelaisOn);
}