The result of subtraction of two unsigned long integers is unsigned.
Cannot be negative.
Results in correct desired behaviour.
Because it is unsigned arithmetic.
a7
The result of subtraction of two unsigned long integers is unsigned.
Cannot be negative.
Results in correct desired behaviour.
Because it is unsigned arithmetic.
a7
And remember, subtraction is done using 2s complement math.
Not in unsigned math. It's modulo arithmetic in that case.
@kellygray: 1-4294967291 is 6 in modulo arithmetic, and that's what you'll get on the Arduino at T+6 milliseconds. Think of modulo arithmetic like a car odometer rolling over. Imagine an odometer with 6 digits. Going from 999999 miles to 1 mile on the odometer is 2 miles. And in a 32-bit unsigned value, going from 4294967291 to 1 is 6.
Edit to add: Showing my work:
000001
- 999999
--------
000002
(You can pretend there's a non-zero digit to the left of "000001" so you can "borrow" from it. The final result is only 6 digits wide so the exact value of that pretend digit doesn't matter.)
const int highLevel = 7; // switch input to indicate high level
const int lowLevel = 6; // switch input to indicate low level
const int pump1 = 13; // led output to emulate active pump 1 - doubles built-in LED for sake of convenience
const int pump2 = 10; // led output to emulate active pump 2
const int alarm = 8; // alarm output
unsigned long pumpTimerStart = 0;
const unsigned long pumpInterval = 5000; // interval before second pump activating
const unsigned long alarmInterval = 5000; // interval before alarm triggers - post second pump activation
void setup() // set pin inputs/outputs - called when the sketch starts and runs only once
{
pinMode(highLevel, INPUT);
pinMode(lowLevel, INPUT);
pinMode(pump1, OUTPUT);
pinMode(pump2, OUTPUT);
pinMode(alarm, OUTPUT);
}
void loop() // main program loop
{
pumpTimerStart = millis(); // stores current time value
{
if (digitalRead(highLevel) == HIGH) // if the water is high, then pump 1 will activate
{
digitalWrite(pump1, HIGH);
}
if (digitalRead(lowLevel) == HIGH) // if the water level reaches low, pump 1 will stop
{
digitalWrite(pump1, LOW);
}
if (millis() - pumpTimerStart >= pumpInterval)
{
digitalWrite(pump2, HIGH);
}
}
}
I'm doing something wrong here that I can't put my finger on.

Use serial print to track your variables and program progression
What does pumpStartTimer do every loop?
Think loop!
Am I wrong in thinking it takes the time value at the start of each cycle?
Yes it stores the time each loop in a variable. But how can you compare this if it is updated each loop? Essentially if you had a stopwatch you are hitting the reset button every few milliseconds so it will never increment to the required delay time
Think about what you are trying to do. Only start your timer when the cookies go in the oven. Donât restart the timer every time you look at the watch!
You need a conditional statement that protects the timer from being updated or a state machine etc. have a look at state change detection or edge detection because you want this to happen only once and if your condition is a pin being HIGH it may (will) be HIGH through multiple cycles of the loop and thus your timer code will reset.
Think loop! Get the concept into your head that code goes abcabcabc⌠not abc!
I'm familiar with edge detection, just not in a coding format.
This seems to be the trend with learning this at the moment, I understand the concept, but being able to work out how to express it in code format is a bit beyond my grasp currently.
Write things in English and look at how they work in a loop. Code can be translated from English using the syntax in the language reference.
Edge detection:
Ie detecting when a pin transitions from one state to another!
Read pin
Remember pin state
If pinstate is different from the last pin state you have detected an edge
Debounce
Note this is a loop so go round and round
Now translate to (pseudo)code
Pinstate=DigitalRead pin; (thatâs reading and remembering the pin state)
If (pinstate != lastPinState)
Edge detected
LastPinState=pinstate
Etc
Note above is all pseudocode and will not work. Use the language reference and understand both syntax and concept. Learn to protect variables behind conditional statements, in different scope or state machines
Read your code in a loop
You might consider making the problem simpler to get the timing concept down. Detect a key press as @pmagowan suggests, turn on the pump, note the time and turn it off after twenty seconds. Forget pump two for now.
Definitely and I donât know why I didnât say that as it is my go-to philosophy!
Always work on the simplest possible block of code and always in a new, well named sketch. Complexity is the end apparent result but is made up of lots of simple steps.
When I code I open a sketch called button and then start coding my button, then âsaveâ and then âsave asâ buttons so you have a second sketch to code for more than 1 button etc etc iterative progress with simple blocks and all bugs contained in the difference between the last working iteration and the current working-on iteration
Gonna have to I think. Got the button press so it will record, but it's getting it to note the time from that point.
Post what you have now.
Need to cycle back round and break it down properly, becoming a mess as I fiddle with it.
const int highLevel = 7; // switch input to indicate high level
const int lowLevel = 6; // switch input to indicate low level
const int pump1 = 13; // led output to emulate active pump 1 - doubles built-in LED for sake of convenience
const int pump2 = 10; // led output to emulate active pump 2
const int alarm = 8; // alarm output
unsigned long pumpTimerStart = 0;
int previousPumpStatus = 0;
int pumpStatus = 0;
int sensorCount = 0;
const unsigned long pumpInterval = 5000; // interval before second pump activating
const unsigned long alarmInterval = 5000; // interval before alarm triggers - post second pump activation
void setup() // set pin inputs/outputs - called when the sketch starts and runs only once
{
pinMode(highLevel, INPUT);
pinMode(lowLevel, INPUT);
pinMode(pump1, OUTPUT);
pinMode(pump2, OUTPUT);
pinMode(alarm, OUTPUT);
pumpTimerStart = millis();
Serial.begin(9600);
}
void loop() // main program loop
{
pumpStatus = digitalRead(highLevel);
if (pumpStatus != previousPumpStatus)
if (pumpStatus == HIGH) {
sensorCount++;
Serial.println("on");
Serial.print("number of button pushes: ");
Serial.println(sensorCount);
} else {
Serial.println("off");
}
previousPumpStatus = pumpStatus;
if (sensorCount % 1 == 0)
if (digitalRead(highLevel) == HIGH) // if the water is high, then pump 1 will activate
{
digitalWrite(pump1, HIGH);
}
if (digitalRead(lowLevel) == HIGH) // if the water level reaches low, pump 1 and pump 2 will stop
{
digitalWrite(pump1, LOW);
digitalWrite(pump2, LOW);
}
if (pumpStatus - pumpTimerStart >= pumpInterval) {
digitalWrite(pump2, HIGH);
}
}
Something has gone badly wrong here:
if (pumpStatus - pumpTimerStart >= pumpInterval)
pumpStatus came from reading the high level sensor, it has nothing to do with time.
Also, millis() should be compared against pumpTimerStart or the passage of time will simply be ignored.
I would start separating the code into functions. Work on one block at a time and then encapsulate it in a function when it is doing what you want. That way you donât end up with a mess of different things competing with each other.
I know it seems like starting again each time but if you learn about it you can just see it as part of the process. Getting bogged down in the total code can be very messy and having a systematic way to code and debug will pay off in the long term
Have a look at this article, I found it explained the millis()
function very well.
The status led.
Why not call high level top pump to use a different word?
Is the high level pin LOW or HIGH can lead to confusion, extra effort.
Top and Bottom Pumps... more clear and easier to think about, even when it's not easy.
Coming up with all the names is a coding skill in itself.
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.