Arduino Powered 3-zone termostat (8 / 10 steg)
Steg 8: Lägga till i analoga knappar
Ok. Eftersom jag är ganska magert på min tillgängliga stiften på arduino (jag har 7,8 och 9 digital stift finns, för närvarande, och jag fortfarande behöver ansluta ugnen och dämparna), jag ska leta efter ett sätt att använda de tillgängliga analoga ingångar (jag har A0 genom A3 tillgängliga, eftersom A4 och A5 är anslutna till RTC) att acceptera knappen input. Vackra quckly jag hitta något som är mycket lovande - en handledning om hur att ta emot input från flera knappar via en enda analog ingång. Betala smuts. Detta är perfekt, och allt som krävs är några extra motstånd. Inga problem oavsett. Låt oss komma till ledningar.
(Se denna tutorial för en från hästar mun handledning om hur det fungerar)
Ledningarna för detta är superenkel. Köra en tråd i den analoga pin av ditt val (mitt program läser från stift A0) och Anslut som på ena sidan av knappen matrisen. Andra sidan av knappen matrisen är ansluten till marken. Därifrån, är knapparna helt enkelt sammankopplade via ett motstånd nätverk. En extra tråd läggs från varje knapp till det analoga ingångsstiftet, så varje knapp har en direkt väg till analogt stift (se schema).
Med relevanta delar av koden från handledningen och ändra den för våra egna behov, får vi följande:
/*
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
*/
#include //This är ett bibliotek som behövs för LCD-skärmen
#include //This är ett bibliotek som behövs för avläsningarna som termometer
#include //This är en temperatur bibliotek
#include
#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 isOverrideHeld = false;
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;
CONST int furnacePin = 1;
int zoneCounter = 0;
int en = 0;
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 (bakgrundsbelysning, OUTPUT);
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(3000); FÖRDRÖJNING FÖR NÄRVARANDE INSTÄLLT PÅ 10 SEKUNDER. KOMMER ATT JUSTERA EFTER BEHOV
DATUM/TID LOGIK
log ("TIME", "Loop initieras på" + getDateAndTime());
TEMPERATUREN LOGIK
sensors.requestTemperatures();
zone1Temp = getTemperature(zone1Therm);
zone2Temp = getTemperature(zone2Therm);
zone3Temp = getTemperature(zone3Therm);
logTemperatureData();
getScreenOutput();
z1Check = checkZoneTemp(zone1Temp);
z2Check = checkZoneTemp(zone2Temp);
z3Check = checkZoneTemp(zone3Temp);
om (z1Check || z2Check || z3Check) {
startFurnace();
} annat {
stopFurnace();
}
om (z1Check & & furnaceState) {
closeDamper(1);
} annat {
openDamper(1);
}
om (z2Check & & furnaceState) {
closeDamper(2);
} annat {
openDamper(2);
}
om (z3Check & & furnaceState) {
closeDamper(3);
} annat {
openDamper(3);
}
en = analogRead(0);
DESSA SIFFROR ÄNDRAS BEROENDE PÅ DIN MOTSTÅND.
IF(a < 20) {
Detta innebär att temperaturen upp.
isOverridden = sant;
}
om (en < 30 & & a > 20) {
Detta innebär att temperaturen ner.
isOverridden = sant;
}
om (en < 45 & & a > 30) {
Detta är ett växlingsobjekt för hold/run
om (thermState == "hold") {
thermState = "kör";
isOverridden = false;
} annat {
thermState = "Håll";
isOverridden = sant;
}
isOverridden = sant;
}
om (en < 60 & & a > 45) {
JAG BEHÖVER EN FJÄRDE KNAPPEN?
}
}
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 getScreenOutput() {
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());
}
}
int getTargetTemperature() {
int läge = getMode();
DateTime nu = RTC.now();
int datum = now.dayOfWeek();
int-värden = {
0}.
log ("info", (sträng) datum);
värden = PROGRAMMED_VALUES [datum];
log ("info", "att få målet 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() {
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";
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.
}
}
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 == damper1Pin || spjäll == damper2Pin || spjäll == damper3Pin) {
digitalWrite (spjäll, hög);
} annat {
log ("Problem med att öppna spjället. Spjället hittades inte. Väntade 1, 2 eller 3. Fick "+ dämpare);
// }
}
void closeDamper (int spjäll) {
om (spjäll == damper1Pin || spjäll == damper2Pin || spjäll == damper3Pin) {
digitalWrite (spjäll, låg);
} annat {
log ("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);
}
}