Fun With Interrupts – James Kyle

How it works:

I played around with buttons switches and potentiometers to change light blinking patterns and came up with this circuit. The switch has an interrupt which changes whether all lights blink at the same time or different times (a blink mode). The button changes which light blinks in the event that they are not blinking at the same time. The potentiometer changes the speed at which the lights blink.

I had some trouble with getting the switch interrupt to work more than once and I ended up having to place it before the button interrupt which I assume prioritizes it.

 

Code:

int toggle_color = 3;
int GREEN_LED = 7;
int YELLOW_LED = 6;
int RED_LED = 5;
int POT = A0;
int blink_rate = 250;
int toggle_blinkMode = 2;


//LED blinking variables
volatile int LED_pin = 5;
volatile bool individual_blink;


//Debounce variables
volatile unsigned long last_press = 0;
int wait_time = 50;




void setup() {

  Serial.begin(9600);

  //Initializing Pins
  pinMode(GREEN_LED, OUTPUT);
  pinMode(YELLOW_LED, OUTPUT);
  pinMode(RED_LED, OUTPUT);

  pinMode(toggle_color, INPUT_PULLUP);
  pinMode(POT, INPUT);


  //Interrupt initialization
  attachInterrupt(digitalPinToInterrupt(toggle_blinkMode), blinkMode, CHANGE);
  attachInterrupt(digitalPinToInterrupt(toggle_color), switchLED, CHANGE);


}

void switchLED() {

  //Turn off previous light
  digitalWrite(LED_pin, LOW);

  //Debounce
  if ((millis() - last_press) >= wait_time) {
    LED_pin++;
    last_press = millis();
  }

  //Go back to first light
  if (LED_pin > 7) {
    LED_pin = 5;
  }


}

void blinkMode() {

  if (individual_blink) {
    individual_blink = 0;
  } else {
    individual_blink = 1;
  }

}

void loop() {

  blink_rate = map(analogRead(POT), 0, 255, 100, 500);

  if (individual_blink) {
    digitalWrite(LED_pin, HIGH);
    delay(blink_rate);
    digitalWrite(LED_pin, LOW);
    delay(blink_rate);
  } else {
    digitalWrite(RED_LED, HIGH);
    digitalWrite(GREEN_LED, HIGH);
    digitalWrite(YELLOW_LED, HIGH);
    delay(blink_rate);
    digitalWrite(RED_LED, LOW);
    digitalWrite(GREEN_LED, LOW);
    digitalWrite(YELLOW_LED, LOW);
    delay(blink_rate);
  }

  bool value = individual_blink;
  Serial.println(value);


}

 

Messing Around With Interrupts

Messing Around With Interrupts:

Functionality:

There are two different states that the system can be put into. These states are controlled by an interrupt connected to the switch. When the switch is high, the system goes into adjustment mode where the user can use the potentiometer to adjust the brightness of the LED. This adjustment is only possible while in this state. When the switch is low, the system returns to its normal state where there is a blinking mode and solid mode. These modes are controlled by a second interrupt tied to the button. While in the blinking state, the LED’s flash individually for 0.5s each in a sequence of red to yellow to green and back to red. In the solid state, all of the LED’s remain on. The brightness of the LED’s in this mode is also the same as that set in the previous adjustment state.

Code:
/*  Interrupt Assignment 
 *  Judson Kyle 
 *  judsonk 
 *  01/31/2021 
*/
#define POT_PIN     A0
#define SWITCH      3
#define BUTTON      2

#define RED_LED     11
#define YELLOW_LED  10
#define GREEN_LED   9

#define RED     0
#define YELLOW  1
#define GREEN   2

volatile bool ADJUST_STATE = false;
volatile bool BLINK = false;

int potVal = 0;
double ledBrightness;

int currentLED = 0;

int waitTime = 500; //ms
long long startTime;

int buttonDebounceTime = 300;
long long buttonDebounceStart = 0;
volatile bool BUTTON_DEBOUNCE = false;
bool BUTTON_PREV_DEBOUNCE = false;


void setup() {
  
  pinMode(POT_PIN, INPUT);
  pinMode(SWITCH, INPUT);

  //Interrupts
  attachInterrupt(digitalPinToInterrupt(BUTTON), handleButton, RISING);

  //LED's
  pinMode(RED_LED, OUTPUT);
  pinMode(YELLOW_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);

  Serial.begin(9600);

}

void handleButton() {
  if (!BUTTON_DEBOUNCE) {
    BUTTON_DEBOUNCE = true;
    BLINK = !BLINK;
  }
}

void loop() {

  //Read switch state
  ADJUST_STATE = digitalRead(SWITCH);
  Serial.println(ADJUST_STATE);
  
//  Serial.print("DEBOUNCE: \t");
//  Serial.print(DEBOUNCE);
//
//  Serial.print("\tdebounceStart: \t");
//  Serial.print((int)debounceStart);
//
//  Serial.print("\tTime Elapsed: \t");
//  Serial.println(millis() - (int)debounceStart);

  //Process switch logic
  if (ADJUST_STATE) {
    potVal = analogRead(POT_PIN);
    ledBrightness = (256*potVal)/1024;
    analogWrite(RED_LED, (int)ledBrightness);
    analogWrite(YELLOW_LED, (int)ledBrightness);
    analogWrite(GREEN_LED, (int)ledBrightness);
  }

  //Change brightness of LED based off potentiometer switch when not in blink mode
  if (BLINK) {
    if (millis() - startTime > waitTime) {
      startTime = millis();
      currentLED++;
      if (currentLED >= 3) {
        currentLED = 0;
      }
    }
    
    switch(currentLED) {
      case RED:
        analogWrite(RED_LED, (int)ledBrightness);
        analogWrite(YELLOW_LED, LOW);
        analogWrite(GREEN_LED, LOW);
        break;
      case YELLOW:
        analogWrite(RED_LED, LOW);
        analogWrite(YELLOW_LED, (int)ledBrightness);
        analogWrite(GREEN_LED, LOW);
        break;
      case GREEN:
        analogWrite(RED_LED, LOW);
        analogWrite(YELLOW_LED, LOW);
        analogWrite(GREEN_LED, (int)ledBrightness);
        break;
      default:
        break;
    }
  }
  else {  //If not in blinking mode make all LED's light up
    analogWrite(RED_LED, (int)ledBrightness);
    analogWrite(YELLOW_LED, (int)ledBrightness);
    analogWrite(GREEN_LED, (int)ledBrightness);
  }

  //Handle button debounce
  if (BUTTON_DEBOUNCE && !BUTTON_PREV_DEBOUNCE) {
    buttonDebounceStart = millis();
  }
  if (abs(buttonDebounceStart - millis()) > buttonDebounceTime) {
    BUTTON_DEBOUNCE = false;
  }
  BUTTON_PREV_DEBOUNCE = BUTTON_DEBOUNCE;
}

 

Images:

Interrupts

Interrupt, Switch Blinking LED from Red to Yellow

Experimented with some of the values.

Tested the button with pin13 before proceeding- button works.

Did not consistently get it to switch colors every time I pressed the button down.

First interrupt attempt (successful), includes questions:

int rLED=9;
int yLED=10;

int ledOn=5;

volatile int switch_color=2;

//see loop for onoff pattern, did other iterations with more complex onoff patterns, made it more difficult to cue the interrupt
int ledDelay=250;

void setup() {

  pinMode(rLED,OUTPUT);
  pinMode(yLED,OUTPUT);

  pinMode(switch_color,INPUT);
  attachInterrupt(digitalPinToInterrupt(switch_color),switchLed,FALLING);
//does rising or falling matter? maybe only needed with more than 2

  ledOn=rLED;

  Serial.begin(9600);
//does this impact the switch back to red from yellow?

}


void switchLed() {
    ledOn++;
    if (ledOn > yLED) {
        ledOn = rLED;
    }
}


void loop() {
//red LED turns on and off based on delay variable, then on for delay*10, and off for delay*5 before repeating
digitalWrite(ledOn,HIGH);
delay(ledDelay);
digitalWrite(ledOn, LOW);
delay(ledDelay);


}