Using TIMER1 for smart timing, gets a weird fault.


I’ve chosen a simple Car interior light project as my first real dive in learning. I get result but not always as expected when running read trial and error read again method. :stuck_out_tongue:

I simply need some help right now to figure this out. I’m using a TIMER1 to control when to check for door and light switches status. I then uses a simple millis timer to hold the light on for 8 seconds after being activated.

Now to the stupid and most annoying part, I’ve tried to get a fade function to work after the timerON has expired but I cant get it right. My wish is that when the fading is running and someone opens a door or turn on the light it should break and turn on the light.

I know I should use interrupts but I’m not sure how to implement that in my code, or if there is another way to deal with it.

Could someone take a look at it and point me in the right direction both in code optimizing and function

// Include external libraries
#include <Bounce2.h>

// Define ports to be used with Bounce class
#define NumButtons 3 
#define OutPin 11
const uint8_t BtnPins[NumButtons] = {2, 3, 4}; 

// Create class objects
Bounce * debo = new Bounce[NumButtons]; 

// Set variables used in the program
unsigned long TimerStartTime = 0;
const int TimerStoppTime = 8000;
bool SwitchState = false;
bool SWstate[3] = {false, false, false};   

// Initialize setup
void setup() {
  pinMode(OutPin, OUTPUT);
  // Initialize all buttonsinstances and set debounce time for each one
  for (byte i = 0; i < NumButtons; i++){
  // Setup TIMER1 as a timer for polling if the Light should be Turned on or not
  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 1hz increments
  OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS12 and CS10 bits for 1024 prescaler
  TCCR1B |= (1 << CS12) | (1 << CS10);  
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  sei(); // Allow interrupts

// Initialize functions
// Function ReadSwitchState, checks the door and interiorlight switches, it stores the result in an array
void ReadSwitchState(){
  for (byte i = 0; i < NumButtons; i++){
    if (debo[i].fell()){
      SWstate[i] = !SWstate[i];
// Function ISR, this uses the built-in Timer1 to read the Switch array once per second and turn on/off the Light
  if (SWstate[0] || SWstate[1] || SWstate[2]){
    TimerStartTime = millis();
    SwitchState = true;
    digitalWrite(OutPin, true);
  } else if (!SWstate[0] && !SWstate[1] && !SWstate[2]){
    if (millis() - TimerStartTime >= TimerStoppTime && SwitchState){
      SwitchState = false;
      digitalWrite(OutPin, false);

// Function FadeOut, this function will fade out the light after the timer has expired
void FadeOut(){
  byte FadeValue = 255;
  while (FadeValue > 0){
    analogWrite(OutPin, FadeValue);
    FadeValue -= 5;

void loop(){

There are two problems (at least).

You should not call the FadeOut() function from inside your ISR. It prevents the ISR from completing quickly. An ISR that takes more than about 50 to 100 microsecs is too long. If you can keep it to 10 microsecs so much the better. Just set a flag in the ISR and have your code in loop() check the flag and then call FadeOut() when it finds the flag has been set.

And your FadeOut() function is a blocking function at two levels - it uses WHILE and it used delay(). Both of those mean that it cannot respond to other inputs.

For the project you describe I don't believe there is any need to use a hardware Timer. The millis() function will achieve all that you need. (Unless, of course, the principal purpose of the project is to learn how to use a hardware timer)

The demo Several Things at a Time illustrates the use of millis() to manage timing without blocking. It may help with understanding the technique.

Have a look at Using millis() for timing. A beginners guide if you need more explanation.