Hi all,
I keep having to take time away from my little dryer project, so I haven’t looked at it in a few weeks. I did some refactoring of my code, but I’m messing up my logic somehow…
What I’m making is an IoT clothes dryer, and I’m getting stuck on updating the settings from the menu. What I want to happen is update the settings using the lcd > that updates a variable called temp selected > if current temp selected != previous temp selected, then temp_setpoint is set equal to temp_selected > temp setpoint controls how hot it gets in the dryer.
What is actually happening is that I can change the temp_selected, but it doesn’t affect the temp_setpoint
time=615, currentMode=2, inside_temp=77.00, inside_moisture=42.00, average= 41, time_selected=60, time_remaining=0, temp_selected=130, temp_setpoint=101, heater on?=0, motor on?=1, button pressed?=1, heater timeout?=1, cooldown start=0
Also, the time_remaning != time_selected, which it should. I’m doing something wrong, but I can’t figure out what it is
full code is below.
Thanks!
JR
// This #include statement was automatically added by the Particle IDE.
#include "Adafruit_RGBLCDShield/Adafruit_RGBLCDShield.h"
#include "Adafruit_RGBLCDShield/Adafruit_MCP23017.h"
// This #include statement was automatically added by the Particle IDE.
#include "Adafruit_DHT/Adafruit_DHT.h"
//dryer v3 uses the adafruit dht library since the pietteTech lib seems to have stopped working? -it just reads -5.00 all the time
#include "math.h"
#define DHTTYPE DHT11 // Sensor type DHT11/21/22/AM2301/AM2302
#define DHTPIN 3 // what pin we're connected to
#define ON 0x7
#define OFF 0x0
DHT dht(DHTPIN, DHTTYPE); //adafruit dht init
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
//initialize icons
byte icons[3][7] = {{ 0x0, 0x4, 0x6, 0x1f, 0x6, 0x4, 0x0},
{0x0, 0xe, 0x15, 0x17, 0x11, 0xe, 0x0},
{0x4, 0xe, 0xe, 0x1e, 0x1b, 0xb, 0x6}
};
//! Index into the bitmap array for the icons.
const int ARROW_ICON_IDX = 0;
const int CLOCK_ICON_IDX = 1;
const int FLAME_ICON_IDX = 2;
//constants
const long meas_interval = 3000;
const int motorPin = 7;
const int heaterPin = A5;
const long heater_timeout_interval = 120000; //2 minute lockout
const long time_interval = 3000; //check how much time left every 3 seconds
const long temp_interval = 3000; //check what to set temp to every 3 seconds
//variables
uint8_t clicked_buttons;
int menu = 0;
unsigned long previous_print_millis;
const unsigned long printInterval = 3000;
unsigned long heater_last_used_millis;
int motorState = LOW;
int heaterState = LOW;
boolean heater_timeout = false;
unsigned long previous_meas_millis = 0;
unsigned long previous_time_millis = 0;
unsigned long previous_temp_millis = 0;
float inside_temp;
float inside_moisture;
int time_remaining = 60;
int temp_setpoint = 101;
unsigned long currentMillis;
unsigned long cooldown_start_millis = 0;
unsigned long cooldown_interval = 300000;
//button variables
int buttonPin = 6; // the number of the input pin
int buttonReading; // the current reading from the input pin
int buttonPrevious = LOW;
//variables and constants for moving average of moisture
const int numReadings = 10;
int readings[numReadings]; // the readings from the analog input
int reading_idx = 0; // the index of the current reading
int total = 0; // the running total
int average_moisture = 0; // the average
//variables for time and temp selections
String run_selected;
int temp_selected;
int time_selected;
int prev_temp_selected = 0;
int prev_time_selected = 0;
int run_type = 0;
int prev_time_remaining = 0;
unsigned long previous_run_millis = 0;
unsigned long time_elapsed = 0;
enum OperatingMode{
STANDBY_MODE,
RUN_MODE,
COOL_MODE,
STOP_MODE
};
OperatingMode currentMode = STANDBY_MODE;
OperatingMode lastMode = STANDBY_MODE;
//*********************** setup ********************************//
void setup()
{
Serial.begin(9600);
lcd.begin(16, 2);
lcd.setBacklight(ON);
lcd.createChar(ARROW_ICON_IDX, icons[ARROW_ICON_IDX]);
lcd.createChar(CLOCK_ICON_IDX, icons[CLOCK_ICON_IDX]);
lcd.createChar(FLAME_ICON_IDX, icons[FLAME_ICON_IDX]);
pinMode(motorPin, OUTPUT);
pinMode(heaterPin, OUTPUT);
pinMode(buttonPin, INPUT);
dht.begin(); //adafruit dht start
for (int thisReading = 0; thisReading < numReadings; thisReading++) //initialize counter for moving average of moisture
readings[thisReading] = 0;
lcd.setCursor(0, 0);
lcd.write(FLAME_ICON_IDX);
lcd.write(CLOCK_ICON_IDX);
lcd.print(" Welcome to ");
lcd.write(CLOCK_ICON_IDX);
lcd.write(FLAME_ICON_IDX);
lcd.setCursor(2, 1);
lcd.print("Dryerbot9000");
delay(2000);
lcd.clear();
menu_fun();
}
//
//
//********************************* loop *****************************//
//
//
??
void loop()
{
delay(10);
currentMillis = millis();
read_button_clicks();
menu_fun();
digitalWrite(motorPin, motorState);
digitalWrite(heaterPin, heaterState);
evaluateSensors(); //force a state change on evaluation of your sensor data, you can even do this at an interval
print_fun();
if (lastMode != currentMode)
{
//doSomething ?
lastMode = currentMode;
}
switch(currentMode){
case (STANDBY_MODE):
motorState = LOW;
heaterState = LOW;
menu = 0;
break;
case (RUN_MODE):
menu = 999;
motorState = HIGH;
//do HEAT_MODE stuff
//check time remaining
//check temp setting
check_time_remaining();
check_temp_setting();
heater_timeout_check();
if (inside_temp <= temp_setpoint && heater_timeout == false) {
heaterState = HIGH;
}
else {
heaterState = LOW;
}
break;
case (COOL_MODE):
motorState = HIGH;
// do COOL_MODE stuff
break;
case (STOP_MODE):
motorState = LOW;
heaterState = LOW;
menu = 0;
// do STOP_MODE stuff
break;
}
}
void evaluateSensors(){
buttonReading = digitalRead(buttonPin);
total = total - readings[reading_idx];
if (currentMillis - previous_meas_millis >= meas_interval) {
previous_meas_millis = currentMillis;
readings[reading_idx] = read_inside_moisture();
read_inside_temp();
}
total = total + readings[reading_idx];
reading_idx = reading_idx + 1;
if (reading_idx >= numReadings){
reading_idx = 0;
}
average_moisture = total / numReadings;
if (buttonReading == LOW){
currentMode = STANDBY_MODE;
}
if (buttonReading == HIGH && time_remaining >0){
currentMode = RUN_MODE;
}
if (buttonReading == HIGH && time_remaining <=0 && time_remaining > -5){
currentMode = COOL_MODE;
}
if (buttonReading == HIGH && time_remaining <= -5) {
currentMode = STOP_MODE;
}
}
int check_time_remaining(){
if (prev_time_selected != time_selected){
prev_time_selected = time_selected;
if(prev_time_selected == 'auto'){
auto_time();
}
else{
time_remaining = time_selected;
}
}
else{
time_remaining = prev_time_selected - (currentMillis/60000);
}
}
int check_temp_setting(){
if (prev_temp_selected != temp_selected){
prev_temp_selected = temp_selected;
if(prev_temp_selected =='auto'){
auto_heat();
}
else{
temp_setpoint = temp_selected;
}
}
}
int auto_time(){
time_remaining = map(average_moisture, 35,52,0,60);
return time_remaining;
}
int auto_heat() {
if (average_moisture < 35)
{
temp_setpoint = 0;
}
else
{
temp_setpoint = 10 * (constrain(map(average_moisture, 35, 52, 100, 160), 100, 160) / 10);
}
return temp_setpoint;
}
float read_inside_temp() {
// Read temperature as farenheit
inside_temp = dht.getTempFarenheit();
// Check if any reads failed and exit early (to try again).
if (isnan(inside_temp)) {
//lcd.print("Failed to read from DHT sensor!");
Serial.println("Failed to read from DHT sensor!");
}
return inside_temp;
}
float read_inside_moisture() {
inside_moisture = dht.getHumidity();
if (isnan(inside_moisture)) {
//lcd.print("Failed to read from DHT sensor!");
Serial.println("Failed to read from DHT sensor!");
}
return inside_moisture;
}
boolean heater_timeout_check() {
//heaterState = digitalRead(heaterPin);
if (heaterState == HIGH) {
heater_last_used_millis = currentMillis;
heater_timeout = false;
}
else if (heaterState == LOW && (currentMillis - heater_last_used_millis >= heater_timeout_interval)) {
heater_timeout = false;
}
else {
heater_timeout = true;
}
return heater_timeout;
}
void read_button_clicks() {
lcd.setBacklight(ON);
static uint8_t last_buttons = 0;
uint8_t buttons = lcd.readButtons();
clicked_buttons = (last_buttons ^ buttons) & (~buttons);
last_buttons = buttons;
/*if (clicked_buttons) {
menu_fun();
}*/
}
int prev_menu=-1;
int menu_fun() {
if (clicked_buttons & BUTTON_RIGHT) {
menu++;
}
if (clicked_buttons & BUTTON_LEFT) {
menu--;
}
if (menu > 2 && menu < 100) {
menu = 0;
}
if (menu < 0) {
menu = 2;
}
if (menu > 106 && menu < 200) {
menu = 101;
}
if (menu < 101 && menu > 99) {
menu = 106;
}
if (menu > 205 && menu < 300) {
menu = 201;
}
if (menu < 201 && menu > 199) {
menu = 205;
}
switch (menu) {
case 0: //time
//lcd.clear();
lcd.setCursor(0,0);
lcd.write(ARROW_ICON_IDX);
lcd.print("time ");
lcd.print("heat ");
//if (time_selected && temp_selected){
lcd.setCursor(0,1);
lcd.print("time:");
lcd.print(time_selected);
lcd.print(" temp:");
lcd.print(temp_selected);//}
if (clicked_buttons & (BUTTON_SELECT | BUTTON_DOWN)) {
lcd.clear();
menu=101;
}
break;
case 1: //heat
lcd.setCursor(0,0);
lcd.print(" time");
lcd.write(ARROW_ICON_IDX);
lcd.print("heat ");
//if (time_selected && temp_selected){
lcd.setCursor(0,1);
lcd.print("time:");
lcd.print(time_selected);
lcd.print(" temp:");
lcd.print(temp_selected);//}
if (clicked_buttons & (BUTTON_SELECT | BUTTON_DOWN)) {
lcd.clear();
menu = 201;
}
//prev_menu = 1;
break;
case 101: //time auto
lcd.setCursor(0,0);
lcd.write(CLOCK_ICON_IDX);
lcd.print("time ");
lcd.setCursor(0, 1);
lcd.write(ARROW_ICON_IDX);
lcd.print("Auto 90 60 45 30 15");
if (clicked_buttons & BUTTON_UP) {
lcd.clear();
menu = 0;
}
if (clicked_buttons & BUTTON_SELECT) {
time_selected = -99;
lcd.clear();
lcd.print("Auto Time");
delay(1000);
lcd.clear();
menu =1;
}
break;
case 102: //time 90
lcd.setCursor(0,0);
lcd.write(CLOCK_ICON_IDX);
lcd.print("time ");
lcd.setCursor(0, 1);
lcd.print(" Auto");
lcd.write(ARROW_ICON_IDX);
lcd.print("90 60 45 30 15");
if (clicked_buttons & BUTTON_UP) {
lcd.clear();
menu = 0;
}
if (clicked_buttons & BUTTON_SELECT) {
time_selected = 90;
lcd.clear();
lcd.print("90 Minutes");
delay(1000);
lcd.clear();
menu =1;
}
break;
case 103: //time 60
lcd.setCursor(0,0);
lcd.write(CLOCK_ICON_IDX);
lcd.print("time ");
lcd.setCursor(0, 1);
lcd.print(" Auto 90");
lcd.write(ARROW_ICON_IDX);
lcd.print("60 45 30 15");
if (clicked_buttons & BUTTON_UP) {
lcd.clear();
menu = 0;
}
if (clicked_buttons & BUTTON_SELECT) {
time_selected = 60;
lcd.clear();
lcd.print("60 Minutes");
delay(1000);
lcd.clear();
menu = 1;
}
break;
case 104: //time 45
lcd.setCursor(0,0);
lcd.write(CLOCK_ICON_IDX);
lcd.print("time ");
lcd.setCursor(0, 1);
lcd.print(" Auto 90 60");
lcd.write(ARROW_ICON_IDX);
lcd.print("45 30 15");
if (clicked_buttons & BUTTON_UP) {
lcd.clear();
menu = 0;
}
if (clicked_buttons & BUTTON_SELECT) {
time_selected = 45;
lcd.clear();
lcd.print("45 Minutes");
delay(1000);
lcd.clear();
menu =1;
}
break;
case 105: //time30
lcd.setCursor(0,0);
lcd.write(CLOCK_ICON_IDX);
lcd.print("time ");
lcd.setCursor(0, 1);
lcd.print("90 60 45");
lcd.write(ARROW_ICON_IDX);
lcd.print("30 15 ");
if (clicked_buttons & BUTTON_UP) {
lcd.clear();
menu = 0;
}
if (clicked_buttons & BUTTON_SELECT) {
time_selected = 30;
lcd.clear();
lcd.print("30 Minutes");
delay(1000);
lcd.clear();
menu =1;
}
break;
case 106: //time 15
lcd.setCursor(0,0);
lcd.write(CLOCK_ICON_IDX);
lcd.print("time ");
lcd.setCursor(0, 1);
lcd.print("90 60 45 30");
lcd.write(ARROW_ICON_IDX);
lcd.print("15 ");
if (clicked_buttons & BUTTON_UP) {
lcd.clear();
menu = 0;
}
if (clicked_buttons & BUTTON_SELECT) {
time_selected = 15;
lcd.clear();
lcd.print("15 Minutes");
delay(1000);
lcd.clear();
menu =1;
}
break;
case 201: //heat auto
lcd.setCursor(0,0);
lcd.write(FLAME_ICON_IDX);
lcd.print("heat ");
lcd.setCursor(0, 1);
lcd.write(ARROW_ICON_IDX);
lcd.print("Auto Hi Med Low Off");
if (clicked_buttons & BUTTON_UP) {
lcd.clear();
menu = 0;
}
if (clicked_buttons & BUTTON_SELECT) {
temp_selected = -99;
lcd.clear();
lcd.print("Auto heat");
delay(1000);
lcd.clear();
menu =0;
}
break;
case 202: //heat hi
lcd.setCursor(0,0);
lcd.write(FLAME_ICON_IDX);
lcd.print("heat ");
lcd.setCursor(0, 1);
lcd.print(" Auto");
lcd.write(ARROW_ICON_IDX);
lcd.print("Hi Med Low Off");
if (clicked_buttons & BUTTON_UP) {
lcd.clear();
menu = 0;
}
if (clicked_buttons & BUTTON_SELECT) {
temp_selected = 150;
lcd.clear();
lcd.print("High heat");
delay(1000);
lcd.clear();
menu = 0;
}
break;
case 203: //heat med
lcd.setCursor(0,0);
lcd.write(FLAME_ICON_IDX);
lcd.print("heat ");
lcd.setCursor(0, 1);
lcd.print(" Auto Hi");
lcd.write(ARROW_ICON_IDX);
lcd.print("Med Low Off");
if (clicked_buttons & BUTTON_UP) {
lcd.clear();
menu = 0;
}
if (clicked_buttons & BUTTON_SELECT) {
temp_selected = 130;
lcd.clear();
lcd.print("Medium heat");
delay(1000);
lcd.clear();
menu = 0;
}
break;
case 204: //heat low
lcd.setCursor(0,0);
lcd.write(FLAME_ICON_IDX);
lcd.print("heat ");
lcd.setCursor(0, 1);
lcd.print("Hi Med");
lcd.write(ARROW_ICON_IDX);
lcd.print("Low Off ");
if (clicked_buttons & BUTTON_UP) {
lcd.clear();
menu = 0;
}
if (clicked_buttons & BUTTON_SELECT) {
temp_selected = 110;
lcd.clear();
lcd.print("Low heat");
delay(1000);
lcd.clear();
menu = 0;
}
break;
case 205: //heat off
lcd.setCursor(0,0);
lcd.write(FLAME_ICON_IDX);
lcd.print("heat ");
lcd.setCursor(0, 1);
lcd.print("Hi Med Low");
lcd.write(ARROW_ICON_IDX);
lcd.print("Off ");
if (clicked_buttons & BUTTON_UP) {
lcd.clear();
menu = 0;
}
if (clicked_buttons & BUTTON_SELECT) {
temp_selected = 32;
lcd.clear();
lcd.print("Heat Off");
delay(1000);
lcd.clear();
menu = 0;
}
break;
case 999: //display in run mode
lcd.setCursor(0,0);
lcd.write(CLOCK_ICON_IDX);
lcd.print(":");
lcd.print(time_remaining);
lcd.print(" dry:");
lcd.print(map(average_moisture,35,100,100,0));
lcd.print(" ");
lcd.print(currentMode);
//if (time_selected && temp_selected){
lcd.setCursor(0,1);
lcd.print("time:");
lcd.print(time_selected);
lcd.print(" temp:");
lcd.print(temp_selected);//}
if (clicked_buttons) {
lcd.clear();
menu=0;
}
break;
}
}
void print_fun(){
if (currentMillis - previous_print_millis >= printInterval) {
previous_print_millis = currentMillis;
Serial.print("time=");
Serial.print(currentMillis / 1000);
Serial.print(", ");
Serial.print("currentMode=");
Serial.print(currentMode);
Serial.print(", ");
Serial.print("inside_temp=");
Serial.print(inside_temp);
Serial.print(", ");
Serial.print("inside_moisture=");
Serial.print(inside_moisture);
Serial.print(", average= ");
Serial.print(average_moisture);
Serial.print(", ");
Serial.print("time_selected=");
Serial.print(time_selected);
Serial.print(", ");
Serial.print("time_remaining=");
Serial.print(time_remaining);
Serial.print(", ");
Serial.print("temp_selected=");
Serial.print(temp_selected);
Serial.print(", ");
Serial.print("temp_setpoint=");
Serial.print(temp_setpoint);
Serial.print(", ");
Serial.print("heater on?=");
Serial.print(heaterState);
Serial.print(", ");
Serial.print("motor on?=");
Serial.print(motorState);
Serial.print(", ");
Serial.print("button pressed?=");
Serial.print(buttonReading);
Serial.print(", ");
Serial.print("heater timeout?=");
Serial.print(heater_timeout);
Serial.print(", cooldown start=");
Serial.println(cooldown_start_millis / 1000);
/*
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("tr=");
lcd.print(time_remaining);
lcd.print(" ");
lcd.print("h=");
lcd.print(heaterState);
lcd.print("ts=");
lcd.print(temp_setpoint);
lcd.setCursor(0, 1);
lcd.print("temp=");
lcd.print(inside_temp);
lcd.print(" ");
lcd.print("moist=");
lcd.print(inside_moisture);
*/
}
}