Arduino Powered 3-zone termostat (9 / 10 steg)
Steg 9: Göra knapparna göra något.
Varje knapp har tilldelas en funktion eller syfte. I vårt fall, den första och andra knappen är för att öka eller minska knapparna respektive, och den tredje knappen är för växling mellan kör eller håll läge. Jag har bifogat en fjärde knapp, men jag vet inte om det behövs. För nu jag lämnar det i, men vi får se.
Den Final koden:
För att detta Instructable är detta den sista koden
/*
/*
Detta är det program som jag kommer att använda till kontroll den
ugnen. Konceptet är detta: Jag har 3 zoner jag kommer att följa.
Varje zon kommer att ha minst en zon spjäll som kommer att
kontrolleras av arduino ansökan.
Varje zon har en enda termometer som kommer att rapportera
tillbaka till registeransvarige. Beroende på den termometer behandlingen och
termostatinställningen, dämparna kommer att öppna eller stänga och den
centrala ugnen kommer att vara påslagen. En gång en godtagbar temperatur
har uppnåtts i alla zoner, ugnen stängs av.
Utöver de allmänna uppvärmning cykler, kommer systemet att
programmerbar. Vid denna tid, dock kommer programcykeln att hanteras här, inte via termostaten.
VIKTIGT TESTFALL: (som ska läggas till som jag tänker på dem / kommit över dem.
* Måste se till att ugnen är alltid off om alla 3 spjäll är stängda.
* stötdämpare ska vara öppen om de inte uttryckligen behöver stängas.
* om systemet är inställt på "hold", alla zoner är inställda på att öppna och programplaneringen körs inte.
* om systemet är åsidosatta men inte höll, avbryts åsidosättningen när nästa inprogrammerade intervall kommer upp
* kan endast omställning till uttrycklig övre och nedre gränser.
*/
#include < LiquidCrystal.h > //This är ett bibliotek som behövs för LCD-skärmen
#include < OneWire.h > //This är ett bibliotek som behövs för avläsningarna som termometer
#include < DallasTemperature.h > //This är en temperatur bibliotek
#include < Wire.h >
#include "RTClib.h"
Anslutningar:
rs (LCD stift 4) till Arduino stift 12
RW (LCD pin 5) till Arduino stift 11
Aktivera (LCD stift 6) till Arduino stift 10
LCD stift 15 till Arduino stift 13
LCD stift d4, d5, d6 och d7 till Arduino stift 5, 4, 3, 2
LiquidCrystal lcd (12, 11, 10, 5, 4, 3, 2);
byte deg [8] = {
B01000,
B10100,
B01000,
B00111,
B00100,
B00110,
B00100,
B00100
};
CONST int bakgrundsbelysning = 13. kontroller bakgrundsbelysning
#define THERM_BUS 6 / / alla temperaturavläsningar kommer via detta enda stift.
OneWire oneWire(THERM_BUS);
DallasTemperature sensorer (& oneWire);
DeviceAddress zone1Therm = {
0x28, 0x48, 0x39, 0x11, 0x04, 0x00, 0x00, 0x94};
DeviceAddress zone2Therm = {
0x28, 0xF2, 0x1F, 0x11, 0x04, 0x00, 0x00, 0x38};
DeviceAddress zone3Therm = {
0x28, 0xBA, 0xF3, 0x10, 0x04, 0x00, 0x00, 0x98};
RTC_DS1307 RTC;
BÖRJA PROGRAMMERA
Tiderna är 6 AM, 8 AM, 3: 00 och 21: 00
int * PROGRAMMED_VALUES [7].
int SUNDAY_VALUES [4] = {
67 67, 67, 60};
int MONDAY_VALUES [4] = {
67 67, 67, 60};
int TUESDAY_VALUES [4] = {
67 67, 67, 60};
int WEDNESDAY_VALUES [4] = {
67 67, 67, 60};
int THURSDAY_VALUES [4] = {
67 67, 67, 60};
int FRIDAY_VALUES [4] = {
67 67, 90, 75};
int SATURDAY_VALUES [4] = {
67 67, 67, 60};
SLUTET PROGRAMMERING
flyta zone1Temp = 0;
flyta zone2Temp = 0;
flyta zone3Temp = 0;
booleska z1Check = 0;
booleska z2Check = 0;
booleska z3Check = 0;
booleska isOverridden = false;
booleska furnaceState = false; med furnaceState, true false betyder att det är för närvarande avstängd, innebär dess närvarande.
String thermState = "kör";
int overrideValue = 0;
int currentMode = 0;
CONST int furnacePin = 7.
int zoneCounter = 0;
int en = 0;
int loopCounter = 0;
int z1Pin = 8;
int z2Pin = 9;
int z3Pin = 13. rensnings bakgrundsbelysning pin för z3
void setup() {
Serial.BEGIN(57600); Detta ansluter arduino till datorn
TEMPERATUR SENSOR SETUP
sensors.BEGIN();
sensors.setResolution (zone1Therm, 10);
lcd.createChar (0, deg);
RTC SETUP.
Wire.BEGIN();
RTC.begin();
IF (!. RTC.isrunning()) {
log ("Fel", "RTC körs inte!");
RTC.adjust (DateTime (__DATE__, __TIME__)); DETTA MÅSTE BARA VARA OKOMMENTERADE OM DU STÄLLER IN DIN RTC FÖR FÖRSTA GÅNGEN! NÄR DEN ÄR INSTÄLLD, MÅSTE DETTA INAKTIVERAS!
}
SETUP UTGÅNGAR
pinMode (furnacePin, produktionen);
pinMode (z1Pin, produktionen);
pinMode (z2Pin, produktionen);
pinMode (z3Pin, produktionen);
så småningom passar bakgrundsbelysning kontroll tillbaka till arduino. För nu ska vi bara ställa in den till konstant.
digitalWrite (bakgrundsbelysning, hög);
SETUP INGÅNGAR
pinMode (A0, INPUT_PULLUP);
STÄLLA IN VECKOPROGRAMMET
PROGRAMMED_VALUES [0] = SUNDAY_VALUES;
PROGRAMMED_VALUES [1] = MONDAY_VALUES;
PROGRAMMED_VALUES [2] = TUESDAY_VALUES;
PROGRAMMED_VALUES [3] = WEDNESDAY_VALUES;
PROGRAMMED_VALUES [4] = THURSDAY_VALUES;
PROGRAMMED_VALUES [5] = FRIDAY_VALUES;
PROGRAMMED_VALUES [6] = SATURDAY_VALUES;
}
Detta går en kontinuerlig slinga
void loop() {
Delay(100); DRÖJSMÅL INSTÄLLT TILL 1 SEKUNDER. KOMMER ATT JUSTERA EFTER BEHOV
DATUM/TID LOGIK
om (loopCounter % 2 == 0) {
log ("TIME", "Loop initieras på" + getDateAndTime());
// }
TEMPERATUREN LOGIK
logTemperatureData();
om (loopCounter % 30 == 0) {
log ("info", loopCounter (sträng));
förändringar utgång var 3 sekunder
outputToScreen();
}
Följande tillåter oss att bara kontrollera ugnen var 60 sekunder medan du läser knappen förändringarna i effektiv realtime
om (loopCounter % 60 == 0) {
log ("info", loopCounter (sträng));
sensors.requestTemperatures();
zone1Temp = getTemperature(zone1Therm);
zone2Temp = getTemperature(zone2Therm);
zone3Temp = getTemperature(zone3Therm);
z1Check = checkZoneTemp(zone1Temp);
z2Check = checkZoneTemp(zone2Temp);
z3Check = checkZoneTemp(zone3Temp);
loopCounter = 0;
om (z1Check || z2Check || z3Check) {
startFurnace();
} annat {
stopFurnace();
}
om (z1Check & & furnaceState) {
closeDamper(z1Pin);
} annat {
openDamper(z1Pin);
}
om (z2Check & & furnaceState) {
closeDamper(z2Pin);
} annat {
openDamper(z2Pin);
}
om (z3Check & & furnaceState) {
closeDamper(z3Pin);
} annat {
openDamper(z3Pin);
}
}
en = analogRead(0);
DESSA SIFFROR ÄNDRAS BEROENDE PÅ DIN MOTSTÅND.
int targetTemp = getProgrammedTargetTemperature();
IF(a < 20) {
Detta innebär att temperaturen upp.
isOverridden = sant;
om (overrideValue! = targetTemp & & overrideValue! = 0) {
overrideValue ++;
} annat {
overrideValue = targetTemp + 1.
}
om (overrideValue > 80) {
overrideValue = 80.
}
log ("info", "temperatur upp till" + overrideValue (sträng));
loopCounter = -1; DETTA ÅTERSTÄLLER RÄKNAREN LOOP, VILKET BETYDER ATT ALLT KOMMER ATT KÖRAS IGEN
}
om (en < 30 & & a > 20) {
Detta innebär att temperaturen ner.
isOverridden = sant;
om (overrideValue! = targetTemp & & overrideValue > 0) {
overrideValue--;
} annat {
overrideValue = targetTemp - 1;
}
om (overrideValue < 50) {
overrideValue = 50;
}
log ("info", "temperatur ner till" + overrideValue (sträng));
loopCounter = -1; DETTA ÅTERSTÄLLER RÄKNAREN LOOP, VILKET BETYDER ATT ALLT KOMMER ATT KÖRAS IGEN
}
om (en < 45 & & a > 30) {
Detta är ett växlingsobjekt för hold/run
om (thermState == "hold") {
thermState = "kör";
isOverridden = false;
log ("info", "ställa in thermState att köra");
} annat {
thermState = "Håll";
isOverridden = sant;
log ("info", "ställa in thermState att hålla");
}
isOverridden = sant;
loopCounter = -1; DETTA ÅTERSTÄLLER RÄKNAREN LOOP, VILKET BETYDER ATT ALLT KOMMER ATT KÖRAS IGEN
}
om (en < 60 & & a > 45) {
JAG BEHÖVER EN FJÄRDE KNAPPEN?
}
loopCounter ++;
}
booleska checkZoneTemp (int temperatur) {
int temp = getTargetTemperature();
IF(temperature > Temp) {
returnera false;
}
return true;
}
void logTemperatureData() {
log ("Zone1Temp", (String)(int)zone1Temp);
log ("Zone2Temp", (String)(int)zone2Temp);
log ("Zone3Temp", (String)(int)zone3Temp);
}
void outputToScreen() {
zoneCounter ++;
IF(zoneCounter == 1) {
Sträng val = "Zone1:" + (sträng) (int) zone1Temp;
val += "(" + (String)getTargetTemperature();
val += (sträng) ")";
toScreen (val, "läge:" + getModeString());
}
annat if (zoneCounter == 2) {
Sträng val = "zon†2:" + (sträng) (int) zone2Temp;
val += "(" + (String)getTargetTemperature();
val += (sträng) ")";
toScreen (val, "ugnen:" + getFurnaceState());
}
annat {
zoneCounter = 0;
Sträng val = "3:" + (sträng) (int) zone3Temp;
val += "(" + (String)getTargetTemperature();
val += (sträng) ")";
toScreen (val, "Open:" + getActiveZonesForScreen());
}
}
void checkMode() {
int läge = getMode();
om (läge! = currentMode) {
currentMode = läge;
IF(isOverridden) {
om (thermState == "kör") {
Denna logik helt enkelt välter Åsidosätt värdet och återupptas programmet om thermstate inte hålls. Annars används overrideValue.
isOverridden = false;
}
}
}
}
int getTargetTemperature() {
checkMode();
IF(isOverridden) {
återvända overrideValue;
} annat {
återvända getProgrammedTargetTemperature();
}
}
int getProgrammedTargetTemperature() {
int läge = getMode();
DateTime nu = RTC.now();
int datum = now.dayOfWeek();
int-värden = {0};
värden = PROGRAMMED_VALUES [datum];
log ("info", "att få programmerade mål temp:" + (String)values[mode]);
returnera värden [mode];
}
Sträng getActiveZonesForScreen() {
Sträng retVal = "";
om (z1Check & &! furnaceState) {
retVal += "1";
}
om (z2Check & &! furnaceState) {
retVal += "2";
}
om (z3Check & &! furnaceState) {
retVal += "3".
}
IF(retVal.length() == 0) {
retVal += "Ingen";
}
returnera retVal;
}
Sträng getFurnaceState() {
IF(furnaceState) {
returnera "På";
}
annat {
returnera "Off";
}
}
Sträng getModeString() {
IF(isOverridden) {
om (thermState == "kör") {
returnera "Override";
} annat {
returnera "HOLD";
}
}
int läge = getMode();
Växla (läge) {
fall 0:
returnera "Vakna";
fall 1:
returnera "Away";
fall 2:
återvända "Hem";
fall 3:
returnera "Sova";
fall -1:
"fel";
standard:
returnera "N/A";
}
}
int getMode() {
DateTime nu = RTC.now();
int timme = now.hour();
om (timme < 6 || timme > = 21) {
returnera 3.
}
om (timme > = 6 & & timme < 8) {
Return 0;
}
om (timme > = 8 & & timme < 15) {
tillbaka 1.
}
om (timme > = 15 & & timme < 21) {
returnera 2.
}
återvända -1;
}
flyta getTemperature(DeviceAddress deviceAddress) {
flyta tempC = sensors.getTempC(deviceAddress);
Serial.println(tempC);
om (tempC ==-127) {
Serial.println ("fel få temperatur.");
}
återvända DallasTemperature::toFahrenheit(tempC);
}
bekvämlighet funktion. Hanterar alla standardtext för att skriva till LCDScreen
void toScreen (sträng line1Value, sträng line2Value) {
LCD.BEGIN(16,2);
LCD.Clear();
lcd.setCursor(0,0);
LCD.Print(line1Value);
lcd.setCursor(0,1);
LCD.Print(line2Value);
}
Sträng getDateAndTime() {
DateTime nu = RTC.now();
Return String(now.year()) + "/" + String(now.month()) + "/" + String(now.day()) + "" + String(now.hour()) + ":" + String(now.minute()) + ":" + String(now.second());
}
void openDamper (int spjäll) {
om (spjäll == z1Pin || spjäll == z2Pin || spjäll == z3Pin) {
digitalWrite (spjäll, hög);
log ("info", "Öppna spjället" + dämpare);
} annat {
log ("fel", "Problem öppna spjället. Spjället hittades inte. Väntade 1, 2 eller 3. Fick "+ dämpare);
}
}
void closeDamper (int spjäll) {
om (spjäll == z1Pin || spjäll == z2Pin || spjäll == z3Pin) {
digitalWrite (spjäll, låg);
log ("info", "Stänga spjället" + dämpare);
} annat {
log ("fel", "Problem stänger spjället. Spjället hittades inte. Väntade 1, 2 eller 3. Fick "+ dämpare);
}
}
funktion för loggningsmeddelanden till konsolen.
Så småningom tänker skriva till loggfilen på RPi
Tom log (sträng kod, sträng meddelande) {
Serial.println (kod + ":" + meddelande);
}
void recordData (String typ, String objekt, strängvärde) {
TODO - utgång till RPi databas
}
void startFurnace() {
Lämplig signal till ugnen att starta upp
IF(!furnaceState) {
furnaceState =! furnaceState;
log ("INFO", "Starta ugnen");
digitalWrite (furnacePin, hög);
}
}
void stopFurnace() {
Lämplig signal till ugnen att stoppa
IF(furnaceState) {
furnaceState =! furnaceState;
log ("INFO", "Stoppa ugnen");
digitalWrite (furnacePin, låg);
}
}