Hej,
Det var länge sedan jag höll på med programmering, men har nu tagit upp det i form av Arduino.
Jag skulle behöva hjälp att formulera ett uttryck.
Förljande variabler finns;
float tempKyl;
int compressor;
int targetKyl = 24; //för test i rumstemp
int hysteresis = 1;
Hur skapar jag ett uttryck/villkor som tar den uppmätta tempen och avgör tillsammans med hysteresen huruvida kompressorn skall vara 0 eller 1?
Tacksam för förslag.
Termostat med hysteres
Re: Termostat med hysteres
Jag skulle göra en variabel (TempLimit) som håller Av/På-gränsen. Den ska starta med 0.
Varför float för temperaturen?
Kod: Markera allt
if(tempKyl < TempLimit)
{
Kylning = true; // Slå på kylningen
Temp_Limit = targetKyl + hysteresis;
}
else if(tempKyl > TempLimit)
{
Kylning = false; // Slå av kylningen
Temp_Limit = targetKyl - hysteresis;
}
Re: Termostat med hysteres
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:
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å.
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;
}
}
}
}
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å.
Senast redigerad av mAVRick 14 augusti 2016, 18:52:07, redigerad totalt 1 gång.
Re: Termostat med hysteres
Det blev float för att jag vill ha med decimaler, men det går säkert med int också.Icecap skrev:Jag skulle göra en variabel (TempLimit) som håller Av/På-gränsen. Den ska starta med 0.
Varför float för temperaturen?Kod: Markera allt
if(tempKyl < TempLimit) { Kylning = true; // Slå på kylningen Temp_Limit = targetKyl + hysteresis; } else if(tempKyl > TempLimit) { Kylning = false; // Slå av kylningen Temp_Limit = targetKyl - hysteresis; }
Jag har tittat på din kod, men hänger inte med vad Temp_limit är i sammanhanget.
Re: Termostat med hysteres
Temp_Limit är en variabel.
Temperatur med decimal får man vid att ha heltal och använda t.ex. 0,1°C enheter, då är det enklare att räkna med det hela.
Temperatur med decimal får man vid att ha heltal och använda t.ex. 0,1°C enheter, då är det enklare att räkna med det hela.
Re: Termostat med hysteres
Ja, fast du har både TempLimit och Temp_Limit, men det kanske var skrivfel med samma variabel?
Koden fungerade inte rakt av, men efter lite modd funkade det bra.
//Update temperature reading and control compressor
sensors.requestTemperatures();
tempKyl=sensors.getTempCByIndex(0);
if(tempKyl < tempLimit)
{
compressor = false; // Slå av kylningen
tempLimit = targetKyl + hysteresis;
}
else if(tempKyl > tempLimit)
{
compressor = true; // Slå på kylningen
tempLimit = targetKyl - hysteresis;
}
//Update relay status
digitalWrite(13,compressor);
Koden fungerade inte rakt av, men efter lite modd funkade det bra.
//Update temperature reading and control compressor
sensors.requestTemperatures();
tempKyl=sensors.getTempCByIndex(0);
if(tempKyl < tempLimit)
{
compressor = false; // Slå av kylningen
tempLimit = targetKyl + hysteresis;
}
else if(tempKyl > tempLimit)
{
compressor = true; // Slå på kylningen
tempLimit = targetKyl - hysteresis;
}
//Update relay status
digitalWrite(13,compressor);