/* code with timer interrupt that will create an interruption each
* 1s using timer1 and prescalar of 256.
Calculations (for 500ms):
System clock 16 Mhz and Prescalar 256;
Timer 1 speed = 16Mhz/256 = 62.5 Khz
Pulse time = 1/62.5 Khz = 16us
Count up to = 1000ms / 16us = 62500 (so this is the value the OCR register should have)*/
bool LED_STATE = true;
int count = 0;
void setup() {
pinMode(13, OUTPUT); //Set the pin to be OUTPUT
cli(); //stop interrupts for till we make the settings
/*1. First we reset the control register to amke sure we start with everything disabled.*/
TCCR1A = 0; // Reset entire TCCR1A to 0
TCCR1B = 0; // Reset entire TCCR1B to 0
/*2. We set the prescalar to the desired value by changing the CS10 CS12 and CS12 bits. */
TCCR1B |= B00000100; //Set CS12 to 1 so we get prescalar 256
/*3. We enable compare match mode on register A*/
TIMSK1 |= B00000010; //Set OCIE1A to 1 so we enable compare match A
/*4. Set the value of register A to 62500*/
OCR1A = 62500; //Finally we set compare register A to this value
sei(); //Enable back the interrupts
}
void loop() {
// put your main code here, to run repeatedly:
}
//With the settings above, this IRS will trigger each 1s.
ISR(TIMER1_COMPA_vect)
{
count += 1;
TCNT1 = 0; //First, set the timer back to 0 so it resets for next interrupt
if (count >= 6)
{
LED_STATE = !LED_STATE; //Invert LED state
digitalWrite(13,LED_STATE); //Write new state to the LED on pin D5
count = 0;
}
}
I have this code above, I have use timer interrupt to turn ON the LED for 6 seconds, but I want it to turn off for 15 minutes and then on again for 6 secs and off for 15 min., this cycle should last for 2 hours. (But I know that my code for now turns LED ON for 6 secs, off for 6 secs)
It is still not in the code but I want this timer to only start when a button (BUTTON_A) is pushed. Also, another button (BUTTON_B) to stop the operation if BUTTON_B is pushed.
Anyone who can direct me to implement this, would be of great help. Thanks.
is there any reason why you need to play with timer interrupts instead of using millis()? I mean an interval of 6 seconds or 15 minutes is nothing crucial which should need an interrupt at all..
based on what I searched, isn't millis() a blocking timer? I tried to use timer interrupt because there could be a time that when button_b is pressed, the operation of LED should stop. (actually I will be controlling a solenoid valve, but for now I am ofc trying the basic and understandable for me so I use LED as my output)
millis() is nothing else than a timer based counter running in the background.
using the concept of the "Blink Without Delay" example from the IDE you can do all sort of not blocking blinking on your Arduino.
for sure you can use this also with a button to switch on/off the blinking at all.
Thanks for the input about millis, I tried to search about it and implement it on my code. I was able to run this code where if button is push LED lights up for 6 seconds then off for 1 minute. But I can't seem to stop the operation when it's more than 3 minutes.
const int LED = 13; // Define the pin where your solenoid valve is connected
const int buttonAPin = 10; // Define the pin for Push Button A
bool valveOpen = false; // Track if the valve is currently open
bool buttonAPressed = false; // Track if Button A is pressed
unsigned long startTime; // Record the start time of the cycle
unsigned long currentTime; // Record the current time
unsigned long openTime = 6000; // 6 seconds in milliseconds
unsigned long closeTime = 66000; //306000; // 5 minutes // 900000; // 15 minutes in milliseconds
unsigned long cycleDuration = 180000; //7200000; // 2 hours in milliseconds
bool initialCycle = true; // Tracks inital cycle
void setup() {
pinMode(LED, OUTPUT);
pinMode(buttonAPin, INPUT_PULLUP);
Serial.begin(9600);
}
void loop() {
int count = 0;
// Read the state of Push Button A
buttonAPressed = digitalRead(buttonAPin) == LOW;
// Check if Button A is pressed and it's the initial cycle or if the valve is currently closed
if (buttonAPressed && !valveOpen)
{
Serial.println("Button A is pressed");
// Record the start time
startTime = millis();
// Open the valve
digitalWrite(LED, HIGH);
valveOpen = true;
}
// Check if the valve is open and it's time to close it
currentTime = millis();
if (valveOpen && currentTime - startTime >= openTime) // openTime = 6 seconds
{
// Close the valve
digitalWrite(LED, LOW);
valveOpen = false;
}
// Check if the initial 15-minute close period has passed
if (currentTime - startTime >= closeTime) // closeTime = 1 minute
{
// Record the start time for the next cycle
startTime = currentTime;
// Open the valve
digitalWrite(LED, HIGH);
valveOpen = true;
count += 1;
}
// Check if the 2-hour cycle has completed
// for now, it was set to 3 minutes
if (currentTime - startTime >= cycleDuration)
{
// Reset the cycle
valveOpen = false;
digitalWrite(LED, LOW);
}
}
These are my final requirements btw:
Push Button A - 2 hours mode (5 seconds open, 15 minutes close cycle for 2 hours)
Push Button B - 8 hours mode (5 seconds open, 15 minutes close cycle for 8 hours)
Push Button C - stop the operation
But for now with my code above, I am stuck in automating the permanent OFF of LED when it reached the cycleDuration which I set approximately for 3 minutes.
the timer works, thanks for this. But I'll be very honest that I can't seem to follow and fully understand the logic of some functions. I do get their general operation but if I try to understand each line and how is it being processed, it is where I am not confident of.
So I tried to add inside the loop where I poll the status of Button_A and Button_B and set the variable "mode" and execute the mainTimer.start() base on your comment.
Here in the code above (I tied to move the static ProgramMode mode {ProgramMode::modeA} outside the loop ), I was able to light the LED when the Button_A is pressed, but it does not stop at the set time of 1 minute. It continuously turns on and off.
And I'm planning to add a counter at every time the turn OFF time is finished. So if I have it for 2 hours, the count must be a total of 8. It's like I am counting the cycle.
Thank you so much for this, it worked as expected. Will further decode how each line works to align it on how I code as I am not that of an expert in coding efficiently. Just learned the ternary operator when I try to understand the way you code it.
Have you worked with the Arduino Blink Without Delay example?
It does need to make all of the time variables in unsigned long but as is it works longer than necessary and provides a simple do more than one thing at a time lesson. The less wrinkles, the shorter the learning curve to a very fundamental step towards smooth automation.
In real world code, the time dimension is your ally.
Hi there. The final task would be it will open and close a solenoid valve base on the time that I set. But for testing in a simple manner, I just tried to interface with and LED.