Termostat med hysteres

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
yngve
Inlägg: 84
Blev medlem: 14 november 2005, 11:51:57
Ort: Växjö

Termostat med hysteres

Inlägg av yngve »

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.
Användarvisningsbild
Icecap
Inlägg: 26136
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Termostat med hysteres

Inlägg av Icecap »

Jag skulle göra en variabel (TempLimit) som håller Av/På-gränsen. Den ska starta med 0.

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;
  }
Varför float för temperaturen?
mAVRick
Inlägg: 319
Blev medlem: 19 mars 2013, 12:43:43
Ort: Östersund

Re: Termostat med hysteres

Inlägg av mAVRick »

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å.
Senast redigerad av mAVRick 14 augusti 2016, 18:52:07, redigerad totalt 1 gång.
yngve
Inlägg: 84
Blev medlem: 14 november 2005, 11:51:57
Ort: Växjö

Re: Termostat med hysteres

Inlägg av yngve »

Icecap skrev:Jag skulle göra en variabel (TempLimit) som håller Av/På-gränsen. Den ska starta med 0.

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;
  }
Varför float för temperaturen?
Det blev float för att jag vill ha med decimaler, men det går säkert med int också.
Jag har tittat på din kod, men hänger inte med vad Temp_limit är i sammanhanget.
Användarvisningsbild
Icecap
Inlägg: 26136
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Termostat med hysteres

Inlägg av Icecap »

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.
yngve
Inlägg: 84
Blev medlem: 14 november 2005, 11:51:57
Ort: Växjö

Re: Termostat med hysteres

Inlägg av yngve »

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);
Skriv svar