Hallo,
Ich bin gerade dabei einen Brutschrank zu programmieren.
Angesteuert wird das ganze mit 2 Heizkabeln die mit jeweils einem SSR geschalten werden.
Dabei dachte ich mir, dass ich die ansteuerung mit 2 PID Reglern mache und dann den Output mit einem 0,5Hz PWM Signal auf Pin 9 & 10 ausgebe.
0,5Hz wegen: Periodendauen = 2 Sekunden
Bei einer Ausgabe vom PID Regler von 0-100, ergibt das dann als kleinstes Intervall 20ms was der Typischen ansprechzeit von einem SSR entspricht
Aber leider funktioniert das nicht. Und ich weiß nicht woren es liegt, bzw ob das auch überhaupst so möglich ist?
Hier wäre der Code ausschnitt, ohne den Methoden zusätzlichen Methoden,
Wäre toll wenn mir jemand weiterhelfen könnte, Danke ![]()
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <DHT.h>
#include <QuickPID.h>
#define POTI A0
#define LEDPIN LED_BUILTIN
#define RELAISPIN9 9
#define RELAISPIN10 10
#define TuningTopPIN5 5
#define TuningBottomPIN6 6
//Für Regelung verwendet
int pPotiInput, pAnalogInput;
float pSoll, pIstTop, pIstBottom;
float pOutTop, pOutBottom;
float tKp = 2.0, tKi = 5.0, tKd = 1.0;
QuickPID TopPID(&pIstTop, &pOutTop, &pSoll, tKp, tKi, tKd,
TopPID.pMode::pOnError,
TopPID.dMode::dOnMeas,
TopPID.iAwMode::iAwClamp,
TopPID.Action::direct);
bool pTuningTopActiv, pTuningTopStart;
float bKp = 1.0, bKi = 2.0, bKd = 0.0;
QuickPID BottomPID(&pIstBottom, &pOutBottom, &pSoll, bKp, bKi, bKd,
BottomPID.pMode::pOnError,
BottomPID.dMode::dOnMeas,
BottomPID.iAwMode::iAwClamp,
BottomPID.Action::direct);
//Temperaturen der Sensoren
float pT1, pT2, pT3, pT4, pT5, pH6, pT3T4Average;
int pReferenzCounter = 2; //Anzahl wie viele Sensoren zum Regeln verwendet werden (Im Regelfall T1 & T2 ==> pReferenzCounter = 2)
//Timer
const unsigned long cIntervalAnalogInput = 500; //Poti eingang lesen
const unsigned long cIntervalTempRead = 2000; //Temperaturwerte lesen
unsigned long pCurrentMillisAnalogInput, pLastMillisAnalogInput;
unsigned long pCurrentMillisTempRead, pLastMillisTempRead;
//Display
LiquidCrystal_I2C lcd(0x27,20,4);
char charString[20];
//Definition des OneWire Buses
#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, 0xCB, 0x2D, 0x81, 0xE3, 0xE1, 0x3C, 0xB4 };
uint8_t adT2[8] = { 0x28, 0x92, 0x2A, 0x81, 0xE3, 0xE1, 0x3C, 0x5D };
uint8_t adT3[8] = { 0x28, 0xB0, 0x1E, 0x81, 0xE3, 0xE1, 0x3C, 0x1E };
uint8_t adT4[8] = { 0x28, 0x72, 0x9C, 0x81, 0xE3, 0xE1, 0x3C, 0xA7 };
uint8_t adT5[8] = { 0x28, 0xC2, 0x4B, 0x81, 0xE3, 0xE1, 0x3C, 0xAF };
void setup()
{
lcd.init();
lcd.backlight();
// Start up the Sensors
SensorsDS.begin();
SensorDHT.begin();
//PID Regler
TopPID.SetOutputLimits(0.0, 100.0);
TopPID.SetMode(TopPID.Control::automatic);
BottomPID.SetOutputLimits(0.0, 100.0);
BottomPID.SetMode(BottomPID.Control::automatic);
// Set PWM frequency to ~0.5 Hz on pins 9 and 10 (Timer 1)
TCCR1A = 0b10100000; // Clear OC1A/OC1B on compare match, set at BOTTOM (non-inverting mode)
TCCR1B = 0b00011011; // Set prescaler to 1024 Fast PWM with ICR1 as TOP
ICR1 = 31249; // Set TOP value for ~0.5 Hz frequency
//PWM Frequency =16000000 / {256×(31249+1)} ≈ 1Hz
pinMode(LEDPIN, OUTPUT);
pinMode(RELAISPIN9, OUTPUT);
pinMode(RELAISPIN10, OUTPUT);
}
void loop()
{
//Timer Funktion aufrufen
CallTimers();
//PID Regler aufruf
TopPID.Compute();
BottomPID.Compute();
//Poti Skalieren + auf Display schreiben
if ((pCurrentMillisAnalogInput - pLastMillisAnalogInput) >= cIntervalAnalogInput) {
pLastMillisAnalogInput = pCurrentMillisAnalogInput; //letzte Zeit speichern
pAnalogInput = analogRead(POTI);
pPotiInput = map(pAnalogInput, 0, 1023,200, 300); //300 - 400
pSoll = (float)pPotiInput / 10.0;
//Display Ausgabe
lcd.setCursor(0,0);
lcd.setCursor(0,0);
lcd.print("S:");
lcd.print(pSoll, 1);
lcd.write(0xDF);
sprintf(charString," O:%03d U:%03d",(int)pOutTop,(int)pOutBottom);
lcd.print(charString);
}
if ((pCurrentMillisTempRead - pLastMillisTempRead) >= cIntervalTempRead) {
pLastMillisTempRead = pCurrentMillisTempRead; //letzte Zeit speichern
//Aktuellen Temperaturen und Feuchtigkeit auslesen
ReadTemperatures();
//Ist Temperatur bestimmen je nach gesteckten Fühlern
if (pReferenzCounter > 0) {
//Aktuelle Temperatur bestimmen, nur wenn mindestens 1 Sensor von T1 | T2 gesteckt
pIstTop = (pT1 + pT2) / (float)pReferenzCounter;
}
else {
//Sonst wird Sensor T5 verwendet, egal ob er verwendet wird oder nicht
pIstTop = pT5;
}
pIstBottom = pT4;
//Aktuellen Temperaturen und Feuchtigkeit auf Display schreiben
PrintTemperatures();
}
//Ausgänge schreiben
OCR1A = (uint16_t)(31249.0 * constrain(pOutTop, 0.0, 100.0) / 100.0); //Für Pin 9 Heizkabel Oben
OCR1B = (uint16_t)(31249.0 * constrain(pOutBottom, 0.0, 100.0) / 100.0); //Für Pin 10 Heizkabel Unten
digitalWrite(LEDPIN, HIGH);
}
