Jag har ett projekt (STC-1000+) som innefattar ett antal olika firmwares till den populära STC-1000 (digitala) termostaten.
Tanken är att styra både kyla (kompressor) och värme (liten värmekälla inuti kylskåpet) för att kunna kontrollera temperaturen för jäsning.
Så här ser koden ut som styr termostatlogiken:
Kod: Markera allt
unsigned int cooling_delay = 60; // Initial cooling delay
unsigned int heating_delay = 60; // Initial heating delay
static void temperature_control(){
if(cooling_delay){
cooling_delay--;
}
if(heating_delay){
heating_delay--;
}
// Set LED outputs
led_e.e_cool = !LATA4;
led_e.e_heat = !LATA5;
// This is the thermostat logic
if((LATA4 && (temperature <= setpoint )) || (LATA5 && (temperature >= setpoint))){
cooling_delay = eeprom_read_config(EEADR_MENU_ITEM(cd)) << 6;
cooling_delay = cooling_delay - (cooling_delay >> 4);
heating_delay = eeprom_read_config(EEADR_MENU_ITEM(hd)) << 6;
heating_delay = heating_delay - (heating_delay >> 4);
LATA4 = 0;
LATA5 = 0;
}
else if(LATA4 == 0 && LATA5 == 0) {
int hysteresis = eeprom_read_config(EEADR_MENU_ITEM(hy));
if (temperature > setpoint + hysteresis) {
if (cooling_delay) {
led_e.e_cool = led_e.e_cool ^ (cooling_delay & 0x1); // Flash to indicate cooling delay
} else {
LATA4 = 1;
}
} else if (temperature < setpoint - hysteresis) {
if (heating_delay) {
led_e.e_heat = led_e.e_heat ^ (heating_delay & 0x1); // Flash to indicate heating delay
} else {
LATA5 = 1;
}
}
}
}
Koden ovan är rätt vältestad vid det här laget.
temperature_control() kallas en gång per sekund. LATA4 är utgången som styr kyla och LATA5 styr värme. Den har konfigurerbar delay efter en värmecykel samt köldcykel (hd/cd) och detta sparas i EEPROM (i minuter). Även hysteres är konfigurerbar (i EEPROM, hy). Den styr även två LED:ar, som visar status på utgångarna. Som parentes kan sägas att temperaturen representeras av int16 och multiplicerad med 10 (så, 12,7 grader lagras internt som 127), även om det för koden ovan inte spelar någon roll.
Först kontrolleras om om värme/köldcykel pågår (LATA4/5 hög) och gränsvärdet är uppnått. Då avslutas cykeln och köld/värmedelay initieras.
Annars kontrolleras om den är inaktiv (ingen pågående cykel) och om gränsvärde över/underskridits och om motsvarande delay har timat ut. Då aktiveras utgången.
Om inget av ovanstående villkor är uppfyllda, är utgångarna oförändrade.
Just det ja. Jag tillåter 0 delay för hd/cd om så önskas, MEN heating/cooling_delay initieras med ett fast värde (60 sek), så det dröjer alltid 60 sek innan första värme/köldcykel vid kallstart (power on). Det av två anledningar. Om man har 0 delay, så ska inte kompresson stressas i onödan vid eventuellt strömavbrott med fluktuerande nätspänning. MEn framförallt, så filtreras mätvärdet (temperaturen) rätt hårt för att få ett pålitligt och stabilt mätvärde och då tar det ett tag för temperaturen att stabiliseras vid uppstart.
Att jag inte använder lokala static variabler för heating/cooling_delay, beror på att SDCC som används för kompilering i projektet, inte initierar static varibaler korrekt (bug i kompilatorn). Använder man en bättre kompilator, är det rekommenderat att ändra detta. Man kan naturligtvis skicka in temperature och setpoint som parametrar till funktionen också.