Hi @Costas can you explain? have I cocked up here some where? should it be and int rather than a float ?
reason I use a float is I add .3 of a degree to the value for hysteresis control in the code. Could this be the issue
here is the full code for you to look at - this may be one version behind as I code it in 2 different buildings but should be 99% the same as it is work in progress and not fully finished yet
#include<BlynkSimpleEthernet.h>
#include<SimpleTimer.h>
#include <TimeLib.h> // Used by WidgetRTC.h
#include <WidgetRTC.h> // Blynk's RTC
#include "DHT.h"
#define DHTPIN 5 // DHT signal in pin
#define DHTTYPE DHT22
SimpleTimer timer;
WidgetRTC rtc;
DHT dht(DHTPIN, DHTTYPE);
float t; //Temp variable
float h; //Humidity variable
bool resetFlag = true; // TRUE when the hardware has been reset.
// Heating control pins and variables
int Heat1_pin = 9; // Pin for Heating rad 1 relay.
int PIR_pin = 4; // choose the input pin (for PIR occupancy sensor)
int Heat1_Status; // Status of relay1 at reset/startup etc also stored on V30
float SetPoint1; // Temp setting for room monitored by DHT22
float Away_Temp1; // Temp to set heating to if on but no occupance ie Away
float Hysteresis1_Val = 0.3; // Allows for 0.3c above and below the setpoint1 to stop 'twitching' around the setpoint
int Activity = 0; // PIR occupancy counter
bool startFlag = false; // TRUE when the heating is on
bool stopFlag = false; // TRUE when the heating is off.
bool daySet = false;
int Occupied_Temp; // Copy of setpoint used in AWAY mode
long todaysAccumRuntimeSec; // Today's accumulated runtime in seconds - displayed in app as minutes.
int currentCycleSec, currentCycleMin; // If Heating is running, the duration of the current cycle (non-accumulating).
int yesterdayRuntime; // Sum of yesterday's runtime in minutes - displays in app.
int yesterdayCount; // Sum of yesterday's cycle count to display in app.
int todaysDate; // Sets today's date related to things that reset at EOD.
int heatingTodaysStartCount; // Today's number of heating cycles
String currentTimeDate; // Time formatted as "0:00AM on 0/0"
String startTimeDate, stopTimeDate, resetTimeDate;
String currentStatus; // What displays in app. Used solely for sync and recover purposes.
// Lighting control pins and AC feedback
int RELAY1_PIN = 2; // Relay 1 pin
int AC_Sens1_pin = 3; // Relay 1 ac sens pin
int feedback1; // AC feedback1 variable
char auth[] = "xxxxxxx";
void setup()
{
Serial.begin(9600);
Blynk.begin(auth);
rtc.begin();
// Setup all of the pins and default ALL relays to OFF before reinstating stored states
pinMode(RELAY1_PIN, OUTPUT);
pinMode(Heat1_pin, OUTPUT);
pinMode(AC_Sens1_pin, INPUT);
pinMode(PIR_pin, INPUT);
digitalWrite(Heat1_pin, 0);
digitalWrite(RELAY1_PIN, 0);
//Lets sync up all the store states for the V pins and load the appropriate variables listed below
Blynk.syncVirtual(V3); // Light 1 Relay state
Blynk.syncVirtual(V28); // Away_Temp1
Blynk.syncVirtual(V29); // SetPoint1
Blynk.syncVirtual(V30); // Heat1_pin state
Blynk.syncVirtual(V31); // CurrentStatus
Blynk.syncVirtual(V110); // heatingTodaysStartCount
Blynk.syncVirtual(V111); // todaysAccumRuntimeSec
Blynk.syncVirtual(V112); // yesterdayRuntime
Blynk.syncVirtual(V113); // yesterdayCount
timer.setInterval(200, AC_detect); // Check AC_detect for AC presence every 50 milliseconds
timer.setInterval(1000, setClockTime); // Creates a current time with leading zeros.
timer.setInterval(1000, countRuntime); // Counts heating runtime for daily accumulation displays.
timer.setInterval(1000, totalRuntime); // Counts heating runtime.
timer.setInterval(1500, sendStatus); // update the app with all the data
timer.setInterval(2000, TempControl); // Check temp control and action
timer.setInterval(5000, Occupancy); // Check if the room is occupied via PIR sensor
timer.setInterval(600000, Check_Away); // Check if we need to go into AWAY mode every 10 mins
}
void loop()
{
Blynk.run();
timer.run();
}
void AC_detect()
{
feedback1 = digitalRead(AC_Sens1_pin);
Blynk.virtualWrite(V2, feedback1); // update SWITCH widget state from AC input only if it has changed
}
void TempControl()
{
//Read temp and humidity from DHT22
h = dht.readHumidity();
t = dht.readTemperature();
// write values to V5 and V6
Blynk.virtualWrite(V5, h); // Update widgets with temp & humidity data
Blynk.virtualWrite(V6, t);
//OK lets action if heating needs to be turned ON or OFF
// ON first
if (t < (SetPoint1 - Hysteresis1_Val)) // Only turn ON when below setpoint1 minus Hysteresis1_Val
{
digitalWrite(Heat1_pin, 0); // Turn rad 1 ON
Blynk.virtualWrite(V30, 0); // update V30 with Heat1_pin current status
}
// Turn OFF then
else if (t > (SetPoint1 + Hysteresis1_Val)) // Only turn OFF when above setpoint1 plus Hysteresis1_Val
{
digitalWrite(Heat1_pin, 1); // Turn rad 1 OFF
Blynk.virtualWrite(V30, 1); // update V30 with current status
}
}
void Occupancy () // Is there anybody in there!!
{
if (digitalRead(PIR_pin) == 1) {
// Count movement activity every 5 seconds via PIR and maintain Setpoint1
Activity = Activity + 1;
SetPoint1 = Occupied_Temp; // set setpoint1 back to what it was before away temp was instigated
Blynk.virtualWrite(V29, SetPoint1);
}
}
void Check_Away ()
{
if (Activity == 0) { // No one present so drop setpoint temp to Away_temp1
Occupied_Temp = SetPoint1; // store current setpoint1
SetPoint1 = Away_Temp1; // Set to Away_temp1
Blynk.virtualWrite(V29, SetPoint1);
}
else {
Activity = 0; // presence has been detected so reset activity counter and and start again
}
}
void setClockTime()
{
//if (year() != 1970) // Doesn't start until RTC is set correctly.
// Below gives me leading zeros on minutes and AM/PM.
if (minute() > 9 && hour() > 11) {
currentTimeDate = String(hourFormat12()) + ":" + minute() + "PM on " + day() + "/" + month();
}
else if (minute() < 10 && hour() > 11) {
currentTimeDate = String(hourFormat12()) + ":0" + minute() + "PM on " + day() + "/" + month();
}
else if (minute() > 9 && hour() < 12) {
currentTimeDate = String(hourFormat12()) + ":" + minute() + "AM on " + day() + "/" + month();
}
else if (minute() < 10 && hour() < 12) {
currentTimeDate = String(hourFormat12()) + ":0" + minute() + "AM on " + day() + "/" + month();
}
}
void sendStatus()
{
// has Arduino been reset or just started.
if (resetFlag == true && year() != 1970)
{
resetTimeDate = currentTimeDate;
Blynk.virtualWrite(V31, currentStatus);
Blynk.setProperty(V31, "label", String("Current Status: SYSTEM RESET at ") + resetTimeDate);
}
if (Heat1_Status == 1 && resetFlag == true) // Runs once following reset/start if Heat is ON.
{
startFlag = true;
resetFlag = false;
}
else if (Heat1_Status == 0 && resetFlag == true) // Runs once following Arduino reset/start if heat is OFF.
{
stopFlag = true;
resetFlag = false;
}
// Display all the data on the app
// Have we passed threshold of heat limit? if so turn it off
if (digitalRead(Heat1_pin) == 1 && startFlag == true) // now OFF, but was on
{
// Purpose: To swap between ON and OFF display once heating state change.
stopTimeDate = currentTimeDate; // Set off time.
Blynk.setProperty(V31, "color", "#23C48E"); // Green
Blynk.virtualWrite(V31, String("Heat OFF since ") + stopTimeDate); // Write to app.
currentStatus = String("Heat OFF since ") + stopTimeDate;
stopFlag = true; // Ready flag when heat turns on.
startFlag = false;// Keep everything locked out until the next cycle.
}
else if (digitalRead(Heat1_pin) == 0 && stopFlag == true) // ON, but was off
{
startTimeDate = currentTimeDate;
Blynk.setProperty(V31, "color", "#D3435C"); // Red
Blynk.virtualWrite(V31, String("Heat ON since ") + startTimeDate);
currentStatus = String("Heat ON since ") + startTimeDate;
startFlag = true;
stopFlag = false;
}
Blynk.virtualWrite(V25, Activity);
}
void countRuntime()
{
if (year() != 1970) // Doesn't start until RTC is set correctly.
{
if (daySet == false) { // Sets the date (once per hardware restart) now that RTC is correct.
todaysDate = day();
daySet = true;
}
if (digitalRead(Heat1_pin) == 0 && todaysDate == day()) // Accumulates seconds unit is running today.
{
++todaysAccumRuntimeSec; // Counts today's Heat1 on time in seconds.
Blynk.virtualWrite(111, todaysAccumRuntimeSec);
}
else if (todaysDate != day()) // day changed so do the business
{
yesterdayRuntime = (todaysAccumRuntimeSec / 60); // Moves today's runtime to yesterday for the app display.
Blynk.virtualWrite(112, yesterdayRuntime); // Record yesterday's runtime to V112
todaysAccumRuntimeSec = 0; // Reset today's sec timer.
Blynk.virtualWrite(111, todaysAccumRuntimeSec);
yesterdayCount = heatingTodaysStartCount; // set yesterdays runtime cycles variable for display
Blynk.virtualWrite(113, yesterdayCount); // Record yesterday's no of cycles to V113
heatingTodaysStartCount = 0; // Reset how many times heating cycle has started today.
todaysDate = day();
}
if (yesterdayRuntime < 1) // Displays yesterday's runtime in app, or 'None' is there's none.
{
Blynk.virtualWrite(14, "None");
}
else
{
Blynk.virtualWrite(14, String(yesterdayRuntime) + " mins (" + (yesterdayCount) + " runs)");
}
if (todaysAccumRuntimeSec == 0) // Displays today's runtime in app, or 'None' if there's none.
{
Blynk.virtualWrite(15, "None");
}
else if (todaysAccumRuntimeSec > 0 && heatingTodaysStartCount == 0)
{
Blynk.virtualWrite(15, String(todaysAccumRuntimeSec / 60) + " minutes");
}
else if (todaysAccumRuntimeSec > 0 && heatingTodaysStartCount > 0)
{
Blynk.virtualWrite(15, String(todaysAccumRuntimeSec / 60) + " mins (" + (heatingTodaysStartCount) + " runs)");
}
}
}
void totalRuntime()
{
if (digitalRead(Heat1_pin) == 0) // If Heating 1 is on running...
{
++currentCycleSec; // accumulate the running time, however...
currentCycleMin = (currentCycleSec / 60);
}
else if (digitalRead(Heat1_pin) == 1 && currentCycleSec > 0) // if Heating 1 is off but recorded some runtime...
{
Blynk.virtualWrite(110, ++heatingTodaysStartCount); // Stores how many times the unit has started today... adds one start.
currentCycleSec = 0; // Reset the current cycle clocks
currentCycleMin = 0;
}
}
// Sync up all of the virtual pin data
BLYNK_WRITE(V2) // Runs every-time switch widget is toggled - For Light 1
{
digitalWrite(RELAY1_PIN, !digitalRead(RELAY1_PIN)); // Toggle relay1
Blynk.virtualWrite(V3, digitalRead(RELAY1_PIN)); // Store Light 1 relay state in V3
}
BLYNK_WRITE(V3)
{
int pinData = param.asInt();
digitalWrite(RELAY1_PIN, pinData); // and reinstate relay state
}
BLYNK_WRITE(V28) // Input from slider in app to set Away_Temp1
{
Away_Temp1 = param.asInt();
}
BLYNK_WRITE(V29) // Input from slider in app to set SetPoint1
{
SetPoint1 = param.asInt();
Occupied_Temp = SetPoint1; // store this in a vrbl as used by Away_Temp1 setting
}
BLYNK_WRITE(V30)
{
Heat1_Status = param.asInt();
digitalWrite(Heat1_pin, Heat1_Status); // and reinstate heat 1 condition
}
BLYNK_WRITE(V31)
{
currentStatus = param.asStr();
}
BLYNK_WRITE(V110)
{
heatingTodaysStartCount = param.asInt();
}
BLYNK_WRITE(V111)
{
todaysAccumRuntimeSec = param.asLong();
}
BLYNK_WRITE(V112)
{
yesterdayRuntime = param.asInt();
}
BLYNK_WRITE(V113)
{
yesterdayCount = param.asInt();
}