Hi guys,
This is my first arduino project, so Im hoping someone can just have a look over it for me and tell me if I can make any improvements etc. Im still learning the code so I want to pick off any mistakes early before I develop bad habits. Functionally the code is working.
Its a simple pump timer. You have a momentary push button and a rotary switch. You dial the rotary switch to a set time (each position of the rotary switch is connected to a digital input of pin 3 to pin 11) and push the push button. The pump then starts and runs for that corresponding time. You can also turn the pump off during use by pushing the push button again. It runs off solar power, which can provide more than enough power, but I dont like wasting the power unnecessarily and so I have popped a sleep command in there. I have also used software debounce to debounce the push button. I did this just to cut down on the number of external components required.
Everything seems to work - can you have a look over it and just tell me if there is anything that I should/shouldnt be doing.
I have three questions about it, only minor, nothing that Im too worried about but still interested to know about.
1 - The debounce circuit. This is done in an interrupt, I had some problems and so this code I got from the web. It works well, but it is not reliable for long button presses. Probably not a problem but it would be great if I could sort that one out.
2 - The millis and roll-over. I got the impression reading around that there is a potential problem when the millis counter rolls over. If the pump was to run when the millis counter rolled over, Im concerned it may cause the pump to get stuck running (after something like 55 days from memory). I used subtraction as one person suggested, but am not 100% sure.
3 - Sleep mode. When you turn the pump on, it runs through its set time and the pump is then turned off. I then put it to sleep - that works fine. If, however, I turn the pump off while it is running, by pushing the pushbutton again, the interrupt stops the pump but I cant put it to sleep. Trying to put the sleep code into the interrupt caused the arduino to go to sleep and get stuck with the output either stuck on or stuck off.
So here it is, appreciate any feedback at all:
#include <avr/sleep.h> // include the sleep library so we can put the audrino to sleep when its not in use
int pumpPin = 13; // output pin for the pump and solenoid (goes to the relay)
int buttonPin = 2; // input pin (for a pushbutton switch)
int rotaryPin [] = {3,4,5,6,7,8,9,10,11}; // input pins that the rotary switch is connected to
unsigned long delayTime [] = {3,4,5,6,7,8,9,10,11}; // Setup for delay times
unsigned long startMillis = 0; // Used as a starting point for the timer
volatile int flag = HIGH; // Setup to allow the pump to be turned off during a cycle. When triggered and interrupt will set a flag that will stop the timer.
void setup()
{
pinMode(pumpPin, OUTPUT); // declare pump output pin as an output
pinMode(buttonPin, INPUT); // declare switch as input
for (int counter=0; counter<9; counter++)
{
pinMode(rotaryPin[counter], INPUT); // initialize the rotary pins as inputs
digitalWrite(rotaryPin[counter],HIGH); // Set the rotary input pins as logic high using the microprocessors inbuilt 20k pullup resistors.
} // Otherwise we would need a 10k to ground pulldown resistor for each pin.
delayTime[0] = 2; // used to set rotary switch position 1 run time in minutes
delayTime[1] = 5; // used to set rotary switch position 2 run time in minutes
delayTime[2] = 10; // used to set rotary switch position 3 run time in minutes
delayTime[3] = 15; // used to set rotary switch position 4 run time in minutes
delayTime[4] = 20; // used to set rotary switch position 5 run time in minutes
delayTime[5] = 30; // used to set rotary switch position 6 run time in minutes
delayTime[6] = 45; // used to set rotary switch position 7 run time in minutes
delayTime[7] = 60; // used to set rotary switch position 8 run time in minutes
delayTime[8] = 120; // used to set rotary switch position 9 run time in minutes
attachInterrupt (0, setFlag, RISING); // Interrupt to turn the pump off if the push button is pressed when the pump is turned on.
// 0 is the interrupt pin used (digital pin 2).
// setFlag is the function called.
// Rising is the signal to detect from the pushbutton.
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Chooses which power saving mode we would like to use. In this case we are powering down the circuit.
}
void setFlag() // This is the function called by the interrupt to stop the pump
{
static unsigned long last_interrupt_time = 0; // Setup for switch debounce
unsigned long interrupt_time = millis(); // Setup for switch debounce
if (interrupt_time - last_interrupt_time > 250) // Timer for the switch debounce - can be fine tuned if required
{
flag = !flag; // The flag is set which will stop the timer.
last_interrupt_time = interrupt_time; // Update for the switch debounce code
}
}
void loop()
{
for (int count=0; count<9; count++) // Starts a counter which is used to scan the rotary pin inputs
{
if (digitalRead(buttonPin) == HIGH && digitalRead(rotaryPin[count]) == LOW) // If the button is pressed the corresponding rotary switch is checked
{
startMillis = millis(); // Checks the current time so that we can later work out when to stop the pump
while (flag == LOW && (millis() - startMillis) < (delayTime[count] * 60000)) // Checks if the stop flag has been set and if the timer has finished.
// Multiplied by 60000 to convert the delay time to minutes
{
digitalWrite(pumpPin, HIGH); // If the timer hasnt finished and the flag isnt set, the pump is turned on
}
digitalWrite(pumpPin, LOW); // Once we are finished, either because the timer is finished or the flag is set, the pump is turned off. Also sets the pump off when the microprocessor is powered up.
if (flag == LOW) // If the timer completes, the flag needs to be reset
{ // If the flag isnt reset, the next time the button is pressed the flag is set and the pump wont turn on.
flag = HIGH; // This would mean pressing the pushbutton twice if the cycle finished without being stopped.
sleep_enable(); // If the pump finishes we enable sleep mode (enabled but not actually turned on)
sleep_mode(); // Controller is put to sleep. Reduces the standby power from 21mA to 14mA.
}
}
}
}