Hello all,
I am looking for a little guidance on a project. I am trying to get my code to change a delay time(add 1 sec) when a button is pressed. The code started out simple and I keep adding more onto it, and now I am lost inside of my loops wondering what I am doing wrong. Any help would greatly be appreciated.
#include <OneWire.h> //Include librarys for DS18B20 Temp Sensor see https://www.pjrc.com/teensy/td_libs_OneWire.html for library info
#include <DallasTemperature.h> //see https://github.com/milesburton/Arduino-Temperature-Control-Library for library info
#define ONE_WIRE_BUS 11// Data wire of sensor is connected to the Arduino digital pin 11
int ButtonPin = 13;
int RelayPin = 12;
int HeatOnToggle = 7;
int HeatOffToggle = 6;
int HeaterOn = 1000;
int WaitUntilHeat = 3000;
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature sensor
DallasTemperature sensors(&oneWire);
void setup() {
pinMode(ButtonPin,INPUT);
pinMode(RelayPin,OUTPUT);
pinMode(HeatOnToggle,INPUT);
pinMode(HeatOffToggle,INPUT);
Serial.begin(9600); // Enable Serial Monitoring at 9600 Baud Rate
sensors.begin(); // Start up the library
}
void loop() {
while(digitalRead(ButtonPin == LOW)){
// Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
sensors.requestTemperatures();
if (digitalRead(HeatOnToggle == HIGH))
{
HeaterOn = HeaterOn + 1000; //Add 1 sec to HeatOn time
}
if (digitalRead(HeatOffToggle == HIGH))
{
WaitUntilHeat = WaitUntilHeat + 1000; //Add 1 sec to HeatOff time
}
/* Serial.print(" HeatOnToggle: ");
Serial.println(digitalRead(HeatOnToggle));
Serial.print(" HeatOffToggle: ");
Serial.println(digitalRead(HeatOffToggle));
delay(1000);
*/
Serial.print("Celsius temperature: ");
// Why "byIndex"? You can have more than one IC on the same bus. 0 refers to the first IC on the wire
Serial.print(sensors.getTempCByIndex(0));
Serial.print(" - Fahrenheit temperature: ");
Serial.println(sensors.getTempFByIndex(0));
Serial.println("HeaterOnTime");
Serial.println(HeaterOn);
Serial.println("HeaterOffTime");
Serial.println(WaitUntilHeat);
delay(1000);
if (digitalRead(ButtonPin) == HIGH) {
while(sensors.getTempFByIndex(0)<75){ // SHUTOFF TEMPERATURE ADJUSTMENT
digitalWrite(RelayPin,HIGH); // Turn relay module on
delay(HeaterOn); // Heating on for HeaterOn ms
digitalWrite(RelayPin,LOW); // Turn relay module off
delay(WaitUntilHeat); // Heating off for WaitUtilHeat ms
// Call sensors.requestTemperatures() to issue a global temperature
sensors.requestTemperatures();
Serial.print("Celsius temperature: ");
// Why "byIndex"? You can have more than one IC on the same bus. 0 refers to the first IC on the wire
Serial.print(sensors.getTempCByIndex(0));
Serial.print(" - Fahrenheit temperature: ");
Serial.println(sensors.getTempFByIndex(0));
Serial.println("HeaterOnTime");
Serial.println(HeaterOn);
Serial.println("HeaterOffTime");
Serial.println(WaitUntilHeat);
delay(350);
}
}
else{
digitalWrite(RelayPin, LOW);
}
}
}
What I would like help with:
My goal is to be able to add 1 sec to 'HeaterOn' when a button is pressed on pin 7 and add 1 sec to 'WaitUntilHeat' when pin 6 button is pressed in the folowing section:
digitalWrite(RelayPin,HIGH); // Turn relay module on
delay(HeaterOn); // Heating on for HeaterOn ms
digitalWrite(RelayPin,LOW); // Turn relay module off
delay(WaitUntilHeat); // Heating off for WaitUtilHeat ms
I really just need help with the user input delay.
I have the buttons wired correctly using 10k pullup resistors.
Thank you!
I have been here before for a school project, It has been a long time since I've worked on Arduino. I am not familiar with the millis() function but I will look into it.
Learn to think Loop. The function after “setup” is “loop”. Setup is linear ie do x then y then z then finish and move on to loop. Loop, as it’s name suggests is not linear. Loop does xyzxyzxyz over and over again as fast as it can. This is how code in loop can appear to do multiple things at once. Every time it loops it can check something, increment something and do something depending on if a condition is met.
Your job is to make loop run as fast as possible! A delay is like the handbrake for loop. When you write a delay you are using human timescales and forcing the loop to take a human length of time to go round again. It wants to do it in a millisecond so that it can check all the important stuff you have put in your code and instead you have asked it to stop and take a breather. Nothing else will occur during this delay. Any buttons you push will be ignored, any readings you want to take won’t be taken.
The answer is to use the internal millis clock to act like a stopwatch. If you want to delay an action after a condition is met then ask the microcontroller to check the time and remember it (store millis in a variable eg int startTime = millis). Then each time through the loop the microcontroller can check and compare the current time with the startTime and see if the required delayTime has been exceeded. If it has do x.
For optimal support the best thing would be to give a very detailed description of your entire project.
It might be that your basic approach is bad suited. But this can only be seen if you give this detailed description.
For whatever reason you don't want to do that.
Is asking for help here in the forum illegal for your assigment?
If you are allowed to ask for help ad you might fear to receive comments judging your code as "bad". This will not happen. Everybody here is polite and the moderators take action very quickly if somebody should be ever unpolite.
At least you should be able to describe your wanted functionality in normal words.
example:
If I press the button "INC-Button" a number shown on the display shall increase by one.
If I press the "STORE-Button" the value shall be ....
Once you have learned how non-blocking timing works everything will become pretty easy.
The basic principle of non-blocking coding is to
let do loo() all the looping and if some kind of action shall be taken
do it depending on a condition.
A while-loop is conditional
This means instead of "locking" code-execution inside a while loop
where the while-loop does the repeating
example from your code
while (digitalRead(ButtonPin == LOW)) {
you can let do loop() the looping and code
if (digitalRead(ButtonPin == LOW)) {
// do what is nescessary
}
// the code here wil be executed too because the if does not block
Now you might think OMG how many if-conditions shall I code?
there is another programming-tecnique called state-machine that will reduce the number of if-conditions to a minimum.
Another thing to learn.
So now you have to choose between:
invensting time fiddling around with your current rather limited coding-knowledge having a hard time to test a lot by guessings
or
to invest time in learning new coding-tecniques
and then switch on the afterburner to code high functional code.
As long as you show some own effort in learning you can ask a lot of questions here and you will receive support.
best regards Stefan
To clarify, this is not for a school assignment, it is a personal project. The reason I didn't want to explain the entire project is because I only needed help with a cetain part of it (changing the delays via user input), I didn't want unnecessary answers trying to fix the rest of the code as I already have the rest of the code working properly.
I believe I have enough answers now to start a new approach which is all I needed.
I am familiar with the internal pullups, I had been told they do not provide consistent results as an external resistor. My original code was using LOW to see if they are pressed, I had just been troubleshooting with HIGH in this case. Thanks for catching that.
I will look further into the nested if/while loop, however before I tried adding the user input for delays I had it like that and it was working well.
invensting time fiddling around with your current rather limited coding-knowledge having a hard time to test a lot by guessings
or
to invest time in learning new coding-tecniques
and then switch on the afterburner to code high functional code.
As long as you show some own effort in learning you can ask a lot of questions here and you will receive support.
best regards Stefan
[/quote]
The finding time to learn new coding part is my issue right now, which is why I posted on here in hopes someone could help lead me in the right path. I am looking for general guidance, I am not expecting someone to do it for me.
//********************************************^************************************************
// TemperatureControl.ino
//
//
// Version YY/MM/DD Comments
// ======= ======== ========================================================
// 1.00 22/07/19 Running code
// 1.01 22/07019 Added sensors.setWaitForConversion(false/true)
//
//********************************************^************************************************
//Include librarys for DS18B20 Temp Sensor see https://www.pjrc.com/teensy/td_libs_OneWire.html for library info
#include <OneWire.h>
//see https://github.com/milesburton/Arduino-Temperature-Control-Library for library info
#include <DallasTemperature.h>
//********************************************^************************************************
//Data wire of sensor is connected to the Arduino digital pin 11
#define ONE_WIRE_BUS 11
#define LEDon HIGH
#define LEDoff LOW
#define RELAYon HIGH
#define RELAYoff LOW
#define ENABLED true
#define DISABLED false
#define PUSHED LOW
#define RELEASED HIGH
//********************************************^************************************************
//Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
//Pass our oneWire reference to Dallas Temperature sensor
DallasTemperature sensors(&oneWire);
const byte heartbeatLED = 13;
const byte RelayPin = 12;
//DS18B20 = 11
const byte ButtonPin = 7;
const byte HeatOnToggle = 6;
const byte HeatOffToggle = 5;
unsigned int HeaterOnTime = 1000;
unsigned int WaitUntilTime = 3000;
byte lastButtonPin = RELEASED;
byte lastHeatOnToggle = RELEASED;
byte lastHeatOffToggle = RELEASED;
float temperatureFreading;
float temperatureCreading;
//Timing stuff
unsigned long heartbeatMillis;
unsigned long switchMillis;
unsigned long commonMillis;
unsigned long DS18B20Millis;
const unsigned long heartBeatInterval = 250ul; //1/4 second
const unsigned long sampleInterval = 50ul; //50 milliseconds
const unsigned long DS18B20Interval = 1000ul; //1 second
//States in my FSM
//use names that make sense to you
enum States {WAITING, ONE, TWO, THREE, FOUR};
//start out in the WAITING state
States mState = WAITING;
// s e t u p ( )
//********************************************^************************************************
//
void setup()
{
Serial.begin(115200);
pinMode(RelayPin , OUTPUT);
pinMode(heartbeatLED , OUTPUT);
//+5V --- [InternalPullup] --- Input Pin --- [N.O. Switch] --- GND
//switch closed gives a LOW on the pin
pinMode(ButtonPin , INPUT_PULLUP);
pinMode(HeatOnToggle , INPUT_PULLUP);
pinMode(HeatOffToggle , INPUT_PULLUP);
//read the temperature
sensors.requestTemperatures();
} //END of setup()
// l o o p ( )
//********************************************^************************************************
//
void loop()
{
//*********************************
//is it time to toggle the heartbeatLED ?
if (millis() - heartbeatMillis >= heartBeatInterval)
{
//restart this TIMER
heartbeatMillis = millis();
//toggle the heartbeatLED
digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
}
//*********************************
//is it time to check the switches ?
if (millis() - switchMillis >= sampleInterval)
{
//restart this TIMER
switchMillis = millis();
checkSwitches();
}
//*********************************
//is it time to read the temperature ?
if (millis() - DS18B20Millis >= DS18B20Interval)
{
//restart this TIMER
DS18B20Millis = millis();
temperatureFreading = sensors.getTempFByIndex(0);
temperatureCreading = sensors.getTempCByIndex(0);
Serial.print("Fahrenheit temperature = ");
Serial.println(temperatureFreading);
Serial.print("Celsius temperature = ");
Serial.println(temperatureCreading);
Serial.print("HeaterOnTime = ");
Serial.println(HeaterOnTime);
Serial.print("HeaterOffTime = ");
Serial.println(WaitUntilTime);
Serial.println();
//start a new conversion request
sensors.setWaitForConversion(false);
sensors.requestTemperatures();
sensors.setWaitForConversion(true);
}
//*********************************
//check our FSM
checkMachine();
//*********************************
//other non blocking code
//*********************************
} //END of loop()
// c h e c k S w i t c h e s ( )
//********************************************^************************************************
//
void checkSwitches()
{
byte currentState;
//*********************************
currentState = digitalRead(ButtonPin);
//has this switch changed state ?
if (lastButtonPin != currentState)
{
//update to the new switch state
lastButtonPin = currentState;
//******************
//was the switch pushed ?
if (currentState == PUSHED)
{
//do somthing ?
}
//******************
//switch must have been released
else
{
//do somthing ?
}
} //END of this switch
//*********************************
currentState = digitalRead(HeatOnToggle);
//has this switch changed state ?
if (lastHeatOnToggle != currentState)
{
//update to the new switch state
lastHeatOnToggle = currentState;
//******************
//was the switch pushed ?
if (currentState == PUSHED)
{
//increment
//if ButtonPin is being PUSHED
if (lastButtonPin == PUSHED)
{
//Add 1 sec to HeatOn time
HeaterOnTime = HeaterOnTime + 1000;
}
//decrement
else
{
//Subtract 1 sec to HeatOn time
HeaterOnTime = HeaterOnTime - 1000;
if (HeaterOnTime < 1000)
{
HeaterOnTime = 1000;
}
}
}
} //END of this switch
//*********************************
currentState = digitalRead(HeatOffToggle);
//has this switch changed state ?
if (lastHeatOffToggle != currentState)
{
//update to the new switch state
lastHeatOffToggle = currentState;
//******************
//was the switch pushed ?
if (currentState == PUSHED)
{
//increment
//if ButtonPin is being PUSHED
if (lastButtonPin == PUSHED)
{
//Add 1 sec to HeatOff time
WaitUntilTime = WaitUntilTime + 1000;
}
//decrement
else
{
//Subtract 1 sec to HeatOn time
WaitUntilTime = WaitUntilTime - 1000;
if (WaitUntilTime < 1000)
{
WaitUntilTime = 1000;
}
}
}
} //END of this switch
//*********************************
//future switches go here
//*********************************
} //END of checkSwitches()
// c h e c k M a c h i n e ( )
//********************************************^************************************************
//checking the current state in our FSM to see if something needs to be done
void checkMachine()
{
//proceed to the current state in our machine
switch (mState)
{
//*************************
case WAITING:
{
if (temperatureFreading < 75)
{
digitalWrite(RelayPin, RELAYon);
//restart the common TIMER
commonMillis = millis();
mState = ONE;
}
}
break;
//*************************
case ONE:
{
//has the TIMER expired ?
if (millis() - commonMillis >= HeaterOnTime)
{
//restart the common TIMER
commonMillis = millis();
digitalWrite(RelayPin, RELAYoff);
mState = TWO;
}
}
break;
//*************************
case TWO:
{
//has the TIMER expired ?
if (millis() - commonMillis >= WaitUntilTime)
{
//for now just go to WAITING
mState = WAITING;
}
}
break;
//*************************
case THREE:
{
}
break;
//*************************
case FOUR:
{
}
break;
//*************************
} //END of switch/case
} //END of checkMachine()
//********************************************^************************************************
// E N D o f s k e t c h c o d e
//********************************************^************************************************
As long as you ask specific questions this specific questions will be answered.
The "danger" that you get unnescessary answers is pretty low. Posting the complete sketch is always an advantage because your potential helpers get a much better overview about what you are trying to do. As a beginner your knowledge is pretty limited and there is a chance that more experienced users can show you better suited approaches.