I am writing a simple code to monitor analog pin A3 and write digital pin D8 accordingly. Below is a summary of my code in a table form.
Condition
Action
if A3 >1000
Write D8 HIGH
else if A3 < 1000 & D8 = HIGH
Delay for 10 seconds & read A3 again
if A3 >1000
Keep D8 HIGH
else if A3 <1000
Write D8 LOW
else
Write D8 LOW
I read about the millis() concept and tried to implement it for my application. However, I am not able to capture(lock) the millis() value at which CONDITION:A3 < 1000 & D8 = HIGH is true. Below is the code using millis(), if I am able to capture the millis()='triggerTime' each time the above condition is true, that would solve my issue.
Am I missing something in my code? Does anyone have an idea how to achieve this?
Thank you.
int PSON = A3; // 5V PSON to analog pin 3
int SSR = 8; // 5V from digital pin 8
int psState = 0; // PSON status
int ssState = 0; // SSR status
const unsigned long delayTime = 10000; // delay
void setup() {
pinMode(PSON, INPUT); // analog pin 3 as input
pinMode(SSR, OUTPUT); // digital pin 8 as output
}
void loop() {
psState = analogRead(PSON); // read analog input status
ssState = digitalRead(SSR); // read digital output status
if (psState > 1000) {
digitalWrite(SSR, HIGH); // sets digital pin 8 HIGH
}
else if (psState < 1000 && ssState == HIGH) {
unsigned long triggerTime = millis();
if (triggerTime != 0) {
unsigned long currentTime = millis();
if (currentTime - triggerTime >= delayTime) {
psState = analogRead(PSON); // read analog input status
if (psState > 1000) {
digitalWrite(SSR, HIGH); // sets digital output HIGH
}
else if (psState < 1000) {
digitalWrite(SSR, LOW); // sets digital output LOW
}
}
}
}
else {
digitalWrite(SSR, LOW); // sets digital output LOW
}
}
@alto777 what you have said, is the exact behaviour of the code.
The part that you have quoted was just a trial to capture the triggerTime. I thought "if (triggerTime != 0)" would make the code move forward and lock triggerTime to X value. Hence, currentTime would keep running.
This is how I was looking at it, do you have any idea how I could work around this?
I'm not at the big rig, so for now I see that that if condition will never be true. Since currentTime and currentTime will never differ by more than 1.
Typically in this spot, we exploit a variable declared at the beginning of the fuction (so it has scope for the entire body of the function) like
static unsigned long previuosTime;
which we set when we do the thing we want to happen periodically, then next time around compare now (the freshly called millis(), that is to say currentTime) to that previuosTime we stored last time we did the thing. To see if delayTime has yet elapsed.
It's idiomatic and can be seen in virtually all uses of millis() that are intended to eliminate delay() calls.
You are close. I think the "blink without delay" uses that model, and "doing two things at once" also.
Sry I don't have the URLs at my fingertips. But google
Blink without delay Arduino
And/or
Doing two things at once Arduino
And/or they may be in the examples in the IDE.
I'll drop by later. I have no life, but there is eating, Netflix and sleeping...
@alto777 I have read through both "blink without delay" and "doing two things at once", these examples are for repetitive timed events. The moment the board is powered on, it starts ticking.
In my situation it is a timed event nested in an if statement, and the if statement can be true at any given time. One thing I am sure, the board will not be powered long enough for millis() to overflow.
@jremington Thank you for the link, I will read through it and try other avenues.
I will try an explain where the delay() fits, if A3 <1000 and D8 is HIGH it should delay for 10 seconds and then read A3 again for any change.
How I understood the millis() concept, capture the millis() at which 'A3 <1000 and D8 is HIGH' and store it as "triggerTime".
From there have a new variable that keeps track of millis(), naming it as "currentTime".
Then if (currentTime - triggerTime >= delayTime), read A3 and write D8 accordingly.
I hope this gives you an idea of what I am trying to achieve. Please let me know if anything is not clear.
What will the processor do while the interval has not yet expired?
You will be stuck until you come up with some alternative to nested if statements. Either formulate the problem in a completely different way, or just use delay() and get on with your life.
It sounds like what you want is to capture millis() each time the condition becomes true. This is a critical distinction. Read -> IDE/file/examples/digital/statechangedetection
Sry, I did not absorb and have in mind your requirements as you stated in the first place. Although perhaps a waste of your time just now, I can practically guarantee you that soona later anything you discovered or learned will be useful. I hope. Again I apologize for diving into the code so close I didn’t even see what you were trying to do, just how you were doing what I thought incorrect. ly.
Your description is a bit hard to understand, maybe more scrutiny of your attempt will clear it up.
But.
I think you should draw a flowchart of the logic. Where there are not multiple tests. I’ll try later.
Flowcharts are old fashioned but still have their place.
OK I tried to make a flowchart from your multiple line table if/else description and also from examining your code.
And failed.
Could you just describe in plain English what you are trying to accomplish? I have a funny feeling you are making this way too complicated.
Like:
If the value is over 1000, set D8.
If the value is less than 1000, and ten seconds have gone by on a high D8, clear D8.
Try this demo. The pushbutton stands for an analog read over 1000.
I set the time to 2 seconds as life is too short to wait 10 seconds… as long as you keep stabbing the button, the LED stays on. Ans stays on for two additional seconds after the condition clears (you stop stabbing the button).
magicLED is called very very frequently, it uses millis() to only do anything every 100 ms.
This is the way how I understand the behaviour that you want.
It took me 3 minutes to draw this. It is rough, freehand and sketchy but it show all relevant information and the timepoint where D8 changes in time is easy to identify. Even that my drawing has a tolerance of 1 mm = 20%
Please confirm or correct if this is the behaviour that you want to have
I have no issue achieving this with a simple code using delay() function. Please find below the current code I am using.
int PSON = A3; // 5V PSON to analog pin 3
int SSR = 8; // 5V from digital pin 8
int psState = 0; // PSON status
int ssState = 0; // SSR status
void setup() {
pinMode(PSON, INPUT); // analog pin 3 as input
pinMode(SSR, OUTPUT); // digital pin 8 as output
}
void loop() {
psState = analogRead(PSON); // read analog input status
ssState = digitalRead(SSR); // read digital output status
if (psState > 1000) {
digitalWrite(SSR, HIGH); // sets digital pin 8 HIGH
}
else if (psState < 1000 && ssState == HIGH) {
delay(10000); // wait for 10 seconds
psState = analogRead(PSON); // read analog input status
if (psState > 1000) {
digitalWrite(SSR, HIGH); // sets digital output HIGH
}
else if (psState < 1000) {
digitalWrite(SSR, LOW); // sets digital output LOW
}
}
else {
digitalWrite(SSR, LOW); // sets digital output LOW
}
}
Below is the delay() function I am trying to replace with millis() concept.
else if (psState < 1000 && ssState == HIGH) {
delay(10000); // wait for 10 seconds
psState = analogRead(PSON); // read analog input status
I hope this gives you a clearer visual explanation of my code.
Thank you.
Condition 2.2 is not necessary because if A3 goes above 1000 again while the "delayed" time is still active the timer resets as per condition 1 and will produce identical output.