Hello all
I'm implementing timout funcion for pressed button. Not sure all code is required but variable "lastFire" contains value of "millis()" the time button was pressed last time. Variable "prevFire" contains value of "millis()" previous button press. In main loop I have implemented this simple condition
which should change variable "SetMode" to zero if the time from last button press is more than 5 seconds. I had to add "Serial.println" statements there to investigate because this code gets randomly executed after some of button presses.
The first "Button timeout" is correct after 5 seconds of "idle" but the second one happens after random presses of the buttons. You can see the "previous" press happened 605ms before the last press of button.
Question to me is how it's possible that it executes the code after the "if" statement if the condition is not met (0 is not greater than 5000)
I had an idea that the "lastFire" variable gets changed after the "if" statement is evaluated but in such case it should be the "prevFire" value to be used for evaluation and still same - condition was not met (
605 is not greater than 5000)
Please any idea?
If necessary I would provide whole code including interrupt driven buttons (touching only "lastFire" variable) + timer driven LED blinking (not touching any of these variables)
I don't know what Arduino you have.
I don't know if you have any large arrays.
I don't know how currTime is declared.
I don't know how lastFire is declared.
The problem is likely to be in the code that you have not shown. Please share it properly by autoformatting it and posting it inline with code tags.
vaj4088:
I don't know what Arduino you have.
I don't know if you have any large arrays.
I don't know how currTime is declared.
I don't know how lastFire is declared.
The problem is likely to be in the code that you have not shown. Please share it properly by autoformatting it and posting it inline with code tags.
Hello,
whole code is attached to the original post.
I'm using Arduino Uno.
One simple array of four interger values.
Variables to hold "millis()" are declared as unsigned long integers.
Thank you for reviewing the code and sharing any idea what to check there. I'm out of ideas now.
// 4 buttons controled by solution taken from https://create.arduino.cc/projecthub/Svizel_pritula/10-buttons-using-1-interrupt-2bd1f8
// defines Common and Buttons pins
const int commonPin = 2;
const int buttonPins[] = {11,10,9,8};
// Common anode RGB LED connected over resitors to pins 3, 4 and 5 (red, green, blue)
// volatile variables defined to be used in Timer interrupt function
volatile uint8_t pinLED = 3; // default first (RED) LED
volatile uint8_t timer_flip = 0;
// global variables to be used in the button interrupt function
unsigned long currTime; // curent time to compare
unsigned long lastFire = 0; // time of last button press
unsigned long prevFire = 0; // time of previous buttin press
byte PButton = 0; // Indicates whether button was pressed (>0) and number of pressed button (1..4)
byte SetMode = 0; // Indicates whether we are in Setting Mode and which "level"
byte PrevMode; // Used for testing whether the Setting Mode level has changed or not
void setup() {
interrupts();
// Prepare TIMER 1 for interrupt frequency 10 Hz (LED blinking)
cli(); // stop interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// set compare match register for 10 Hz increments
OCR1A = 1562; // 200 millisecond cycle (100ms down, 100ms up)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// no clock selected at the moment. It's done during Mode Selection (red, green, blue)
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei(); // allow interrupts
configureCommon(); // Setup pins for interrupt from buttons
attachInterrupt(digitalPinToInterrupt(commonPin), pressInterrupt, FALLING); // enter interrupt function during falling on Common pin
Serial.begin(115200);
pinMode(3, OUTPUT); // sets the digital pin 3 as output
digitalWrite(3, HIGH);
pinMode(4, OUTPUT);
digitalWrite(4, HIGH);
pinMode(5, OUTPUT);
digitalWrite(5, HIGH);
}
ISR(TIMER1_COMPA_vect){
if (timer_flip == 0) {
timer_flip = 1;
digitalWrite(pinLED, LOW);
} else {
timer_flip = 0;
digitalWrite(pinLED, HIGH);
}
}
void pressInterrupt() { // ISR
// Serial.println("interrupt");
if (millis() - lastFire < 150) { // Debounce
// Serial.println("debounce");
return;
}
prevFire = lastFire;
lastFire = millis();
configureDistinct(); // Setup pins for testing individual buttons
for (int i = 0; i < sizeof(buttonPins) / sizeof(int); i++) { // Test each button for press
if (!digitalRead(buttonPins[i])) {
PButton = i + 1; // pressed button is detected in array keys 0..3 ie. translated to button numbers 1..4
}
}
if (PButton != 0) {
PrevMode = SetMode;
if (SetMode > 0) {
switch (PButton) {
case 1: // if we are already in Set Mode and button 1 is pressed then increment Set Mode level (red->green->blue->red...)
SetMode++;
if (SetMode > 3) {
SetMode = 1; // Set Mode 1 will blink Red LED, 2 will blink Green LED and 3 will blink Blue LED
}
break;
case 4:
// if LED is blinking the Timer (bliking) is stopped and LED is lighting
TCCR1B = TCCR1B & B11111000; // stop clock
TCNT1 = 0; // initialize counter value to 0
digitalWrite(pinLED, LOW);
break;
}
} else if (PButton == 1) {
SetMode = 1; // enter Set Mode only if button 1 is pressed
}
// If Setting Mode level has changed do the action
if (PrevMode != SetMode) {
switch (SetMode) {
case 1: // Red LED blinking
// stop blinking of Blue LED
TCCR1B = TCCR1B & 0xf8; // stop Timer1 (clear bits CS10-CS12)
TCNT1 = 0; // initialize counter value to 0
digitalWrite(5, HIGH); // switch off Blue LED
pinLED = 3; // set blinking on pin 3 (Red LED)
TCCR1B |= (1 << CS12) | (0 << CS11) | (1 << CS10); // start Timer1
break;
case 2: // Green LED blinking
TCCR1B = TCCR1B & 0xf8;
TCNT1 = 0;
digitalWrite(3, HIGH); // switch off Red LED
pinLED = 4; // set blinking on pin 4 (Green LED)
TCCR1B |= (1 << CS12) | (0 << CS11) | (1 << CS10);
break;
case 3: // Blue LED blinking
TCCR1B = TCCR1B & 0xf8;
TCNT1 = 0;
digitalWrite(4, HIGH); // switch off Green LED
pinLED = 5; // set blinking on pin 4 (Blue LED)
TCCR1B |= (1 << CS12) | (0 << CS11) | (1 << CS10);
break;
}
}
}
PButton = 0; // Pressed button reset to 0 (nothing pressed)
configureCommon(); // Return to original state ie. waiting for intrrupt from any button
}
// Interrupt waits for Common pin is falling to LOW level from any Button pin
void configureCommon() {
pinMode(commonPin, INPUT_PULLUP);
for (int i = 0; i < sizeof(buttonPins) / sizeof(int); i++) {
pinMode(buttonPins[i], OUTPUT);
digitalWrite(buttonPins[i], LOW);
}
}
// All Button pins are input+pullup and one or more of them are hold on LOW level from the Common pin
void configureDistinct() {
pinMode(commonPin, OUTPUT);
digitalWrite(commonPin, LOW);
for (int i = 0; i < sizeof(buttonPins) / sizeof(int); i++) {
pinMode(buttonPins[i], INPUT_PULLUP);
}
}
void loop() {
if (SetMode != 0) { // if Set Mode level is 1..3
currTime = millis(); // take current time
if ((currTime - lastFire) > 5000) { // if more than 5 seconds since last button press
Serial.println("Button timeout");
Serial.println(currTime);
Serial.println(lastFire);
Serial.println(prevFire);
Serial.println(currTime - lastFire);
TCCR1B = TCCR1B & 0xf8; // stop Timer1
TCNT1 = 0; // initialize counter value to 0
SetMode = 0; // escape from any Set Mode
digitalWrite(3, HIGH); // and switch off all LEDs
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
}
}
}