Go Down

Topic: Event-based timer interrupts (Read 940 times) previous topic - next topic

kustom

So, recently I learned about timer interrupts which is really cool feature on Arduino and fits into my project nicely - I've got 2 LEDs which blink every 1 second. However, they should not blink all the time - only when certain button is pressed. Can I activate timer interrupt when that button is pressed? This way the blinkLEDs(); function I wrote constantly checks if the corresonding button was pressed.

Nick Gammon

Post your code?

You can activate or deactivate timer interrupts whenever you want. You might also manage to blink LEDs without interrupts, as the timers are quite capable of doing that on their own.
http://www.gammon.com.au/electronics

kustom

#2
Oct 25, 2012, 10:09 am Last Edit: Oct 25, 2012, 10:23 am by kustom Reason: 1
Code: [Select]
void setup() {

 //initialize Timer1
 //disable global interrupts
 cli();
 //set entire TCCR1A register to 0
 TCCR1A = 0;
 //same for TCCR1B
 TCCR1B = 0;
 //set compare match register to desired timer count
 OCR1A = 15624;
 //turn on CTC mode
 TCCR1B |= (1 << WGM12);
 //set CS10 and CS12 bits for 1024 prescaler:
 TCCR1B |= (1 << CS10);
 TCCR1B |= (1 << CS12);
 //enable timer compare interrupt:
 TIMSK1 |= (1 << OCIE1A);
 //enable global interrupts
 sei();
 
 //initialise all pins
 initPins();
 //turn off all leds
 openDeck.resetLEDs();
 
 //read incoming MIDI messages on channel 6
 MIDI.begin(6);
 //define funnction for handling incoming MIDI data
 MIDI.setHandleNoteOn(callSetLEDstate);
 
 //start serial
 Serial.begin(115200);
 
}


Code: [Select]
void loop() {
 
 //read incoming MIDI data
 MIDI.read();
}


Code: [Select]
ISR(TIMER1_COMPA_vect)
{
   openDeck.blinkLED(BLINK_LED_1, BLINK_LED_2);
}


Code: [Select]
void callSetLEDstate(byte channel, byte pitch, byte velocity) {

switch(pitch) {
 
 case PLAY_LEFT_NOTE:
 //this is where I want to activate interrupt
  openDeck.changeBlinkState(0, velocity);
 break;
 
 case PLAY_RIGHT_NOTE:
 //or here
  openDeck.changeBlinkState(1, velocity);
 break;
 }


Code: [Select]
void OpenDeckRewrite::blinkLED(int blinkLED_1, int blinkLED_2)  {

   int arrayOfBlinkLeds[NUMBER_OF_BLINK_LEDS] = {blinkLED_1, blinkLED_2};

   for (int i=0; i<NUMBER_OF_BLINK_LEDS; i++) {

   if (blinkLedOn[i]) {

   // if the LED is off turn it on and vice-versa:
   if (ledState[arrayOfBlinkLeds[i]] == LOW)   ledState[arrayOfBlinkLeds[i]] = true;
   else    ledState[arrayOfBlinkLeds[i]] = false;
   }

       else ledState[arrayOfBlinkLeds[i]] = false;
 }
   writeLEDs();
}

Nick Gammon

http://www.gammon.com.au/electronics

kustom

#4
Oct 25, 2012, 10:45 am Last Edit: Oct 25, 2012, 11:47 am by kustom Reason: 1
As you wish.

Code: [Select]
#include <OpenDeckRewrite.h>
#include <MIDI.h>
#include <HDDJ.h>

//input shift register pins
#define SR_DATA_PIN 8
#define SR_LATCH_PIN 9
#define SR_CLOCK_PIN 10

//output shift register pins
#define LED_DATA_PIN 19
#define LED_CLOCK_PIN 18
#define LED_LATCH_PIN 17

//multiplexer pins
#define SLAVE_S0 4
#define SLAVE_S1 12
#define SLAVE_S2 11

#define MASTER_S0 7
#define MASTER_S1 6
#define MASTER_S2 5

//rotary encoder 1 pins
#define HDDJ1_PIN1 16
#define HDDJ1_PIN2 2

//rotary encoder 2 pins
#define HDDJ2_PIN1 15
#define HDDJ2_PIN2 3

//define interrupt pins for rotary encoders
#define INTERRUPT_PIN_1 0
#define INTERRUPT_PIN_2 1

#define ANALOGUE_READ_PIN 0

//enable DEBUG in OpenDeck.h and define all buttons with leds
#define PLAY_LEFT_NOTE 7
#define PLAY_RIGHT_NOTE 43
#define BROWSER_NOTE 30
#define FILTER_LEFT_NOTE 5
#define FILTER_RIGHT_NOTE 41
#define HIGH_KILL_LEFT_NOTE 22
#define HIGH_KILL_RIGHT_NOTE 25
#define MID_KILL_LEFT_NOTE 17
#define MID_KILL_RIGHT_NOTE 28
#define LOW_KILL_LEFT_NOTE 21
#define LOW_KILL_RIGHT_NOTE 27
#define LEFT_CUE_NOTE 18
//#define RIGHT_CUE_NOTE 20
#define FX_1_LEFT_NOTE 11
#define FX_2_LEFT_NOTE 2
#define FX_1_RIGHT_NOTE 46
#define FX_2_RIGHT_NOTE 36
#define FX_LEFT_BUTTON_1_NOTE 20
#define FX_LEFT_BUTTON_2_NOTE 16
#define FX_LEFT_BUTTON_3_NOTE 19
#define FX_RIGHT_BUTTON_1_NOTE 31
#define FX_RIGHT_BUTTON_2_NOTE 26
#define FX_RIGHT_BUTTON_3_NOTE 29

//define LED numbers for buttons
#define PLAY_LEFT_LED 8
#define PLAY_RIGHT_LED 3
#define BROWSER_LED 16
#define FILTER_LEFT_LED 0
#define FILTER_RIGHT_LED 24
#define HIGH_KILL_LEFT_LED 22
#define HIGH_KILL_RIGHT_LED 25
#define MID_KILL_LEFT_LED 17
#define MID_KILL_RIGHT_LED 28
#define LOW_KILL_LEFT_LED 21
#define LOW_KILL_RIGHT_LED 27
#define LEFT_CUE_LED 1
#define FX_1_LEFT_LED 4
#define FX_2_LEFT_LED 6
#define FX_1_RIGHT_LED 46
#define FX_2_RIGHT_LED 36
#define FX_LEFT_BUTTON_1_LED 7
#define FX_LEFT_BUTTON_2_LED 9
#define FX_LEFT_BUTTON_3_LED 2
#define FX_RIGHT_BUTTON_1_LED 31
#define FX_RIGHT_BUTTON_2_LED 26
#define FX_RIGHT_BUTTON_3_LED 29

//define LEDs which blink when pressed
#define BLINK_LED_1 PLAY_LEFT_LED
#define BLINK_LED_2 PLAY_RIGHT_LED

OpenDeckRewrite openDeck(SR_LATCH_PIN, SR_CLOCK_PIN, SR_DATA_PIN,
                       LED_DATA_PIN, LED_CLOCK_PIN, LED_LATCH_PIN,
                       SLAVE_S0, SLAVE_S1, SLAVE_S2,
                       MASTER_S0, MASTER_S1, MASTER_S2,
                       ANALOGUE_READ_PIN);
                                         
HDDJ hddj1 = HDDJ(HDDJ1_PIN1, HDDJ1_PIN2);
HDDJ hddj2 = HDDJ(HDDJ2_PIN1, HDDJ2_PIN2);

void setup() {

 //initialize Timer1
 //disable global interrupts
 cli();
 //set entire TCCR1A register to 0
 TCCR1A = 0;
 //same for TCCR1B
 TCCR1B = 0;
 //set compare match register to desired timer count
 OCR1A = 15624;
 //turn on CTC mode
 TCCR1B |= (1 << WGM12);
 //set CS10 and CS12 bits for 1024 prescaler:
 TCCR1B |= (1 << CS10);
 TCCR1B |= (1 << CS12);
 //enable timer compare interrupt:
 TIMSK1 |= (1 << OCIE1A);
 //enable global interrupts
 sei();
 
 //initialise all pins
 initPins();
 //turn off all leds
 openDeck.resetLEDs();
 
 //set interrupt pins for rotary encoders
 attachInterrupt(INTERRUPT_PIN_1, startEncoder0, CHANGE);
 attachInterrupt(INTERRUPT_PIN_2, startEncoder1, CHANGE);
 
 //read incoming MIDI messages on channel 6
 MIDI.begin(6);
 //define funnction for handling incoming MIDI data
 MIDI.setHandleNoteOn(callSetLEDstate);
 
 //assign index to each disk so we could differentiate them
 hddj1.setDiskNumber(0);
 hddj2.setDiskNumber(1);
 
 //start serial
 Serial.begin(115200);
 
}

void loop() {
 
 //read incoming MIDI data
 MIDI.read();
 //get data from shift registers
 openDeck.readButtons();
 //get data from potentiometers
 openDeck.readPotentiometers();
}


void startEncoder0() {
 hddj1.readRotaryEncoder();
}

void startEncoder1() {
 hddj2.readRotaryEncoder();
}

void callSetLEDstate(byte channel, byte pitch, byte velocity) {

switch(pitch) {
 
 case PLAY_LEFT_NOTE:
 openDeck.changeBlinkState(0, velocity);
 break;
 
 case PLAY_RIGHT_NOTE:
 openDeck.changeBlinkState(1, velocity);
 break;
 
 case BROWSER_NOTE:
 openDeck.setLEDstate(BROWSER_LED, velocity);
 break;
 
 case FILTER_LEFT_NOTE:
 openDeck.setLEDstate(FILTER_LEFT_LED, velocity);
 break;
 
 case FILTER_RIGHT_NOTE:
 openDeck.setLEDstate(FILTER_RIGHT_LED, velocity);
 break;
 
 case HIGH_KILL_LEFT_NOTE:
 openDeck.setLEDstate(HIGH_KILL_LEFT_LED, velocity);
 break;
 
 case HIGH_KILL_RIGHT_NOTE:
 openDeck.setLEDstate(HIGH_KILL_RIGHT_LED, velocity);
 break;
 
 case MID_KILL_LEFT_NOTE:
 openDeck.setLEDstate(MID_KILL_LEFT_LED, velocity);
 break;
 
 case MID_KILL_RIGHT_NOTE:
 openDeck.setLEDstate(MID_KILL_RIGHT_LED, velocity);
 break;
 
 case LOW_KILL_LEFT_NOTE:
 openDeck.setLEDstate(LOW_KILL_LEFT_LED, velocity);
 break;
 
 case LOW_KILL_RIGHT_NOTE:
 openDeck.setLEDstate(LOW_KILL_RIGHT_LED, velocity);
 break;
 
 case LEFT_CUE_NOTE:
 openDeck.setLEDstate(LEFT_CUE_LED, velocity);
 break;
 
 case FX_1_LEFT_NOTE:
 openDeck.setLEDstate(FX_1_LEFT_LED, velocity);
 break;
 
 case FX_2_LEFT_NOTE:
 openDeck.setLEDstate(FX_2_LEFT_LED, velocity);
 break;
 
 case FX_1_RIGHT_NOTE:
 openDeck.setLEDstate(FX_1_RIGHT_LED, velocity);
 break;
 
 case FX_2_RIGHT_NOTE:
 openDeck.setLEDstate(FX_2_RIGHT_LED, velocity);
 break;
 
 case FX_LEFT_BUTTON_1_NOTE:
 openDeck.setLEDstate(FX_LEFT_BUTTON_1_LED, velocity);
 break;
 
 case FX_LEFT_BUTTON_2_NOTE:
 openDeck.setLEDstate(FX_LEFT_BUTTON_2_LED, velocity);
 break;
 
 case FX_LEFT_BUTTON_3_NOTE:
 openDeck.setLEDstate(FX_LEFT_BUTTON_3_LED, velocity);
 break;
 
 case FX_RIGHT_BUTTON_1_NOTE:
 openDeck.setLEDstate(FX_RIGHT_BUTTON_1_LED, velocity);
 break;
 
 case FX_RIGHT_BUTTON_2_NOTE:
 openDeck.setLEDstate(FX_RIGHT_BUTTON_2_LED, velocity);
 break;
 
 case FX_RIGHT_BUTTON_3_NOTE:
 openDeck.setLEDstate(FX_RIGHT_BUTTON_3_LED, velocity);
 break;
 
 default:
 break;

}
}

void initPinsDigitalInput() {
 
  pinMode(SR_DATA_PIN, INPUT);
  pinMode(SR_CLOCK_PIN, OUTPUT);
  pinMode(SR_LATCH_PIN, OUTPUT);
}

void initPinsAnalogueInput() {
 
  pinMode(SLAVE_S0, OUTPUT);
  pinMode(SLAVE_S1, OUTPUT);
  pinMode(SLAVE_S2, OUTPUT);
 
  pinMode(MASTER_S0, OUTPUT);
  pinMode(MASTER_S1, OUTPUT);
  pinMode(MASTER_S2, OUTPUT);
 
  pinMode(ANALOGUE_READ_PIN, INPUT);
 
  digitalWrite(SLAVE_S0, HIGH);
  digitalWrite(SLAVE_S1, HIGH);
  digitalWrite(SLAVE_S2, HIGH);
 
  digitalWrite(MASTER_S0, HIGH);
  digitalWrite(MASTER_S1, HIGH);
  digitalWrite(MASTER_S2, HIGH);
 
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
 
  digitalWrite(A1, LOW);
  digitalWrite(A2, LOW);
  digitalWrite(A3, LOW);
 
}

void initPinsDigitalOutput() {
 
 pinMode(LED_DATA_PIN, OUTPUT);
 pinMode(LED_CLOCK_PIN, OUTPUT);
 pinMode(LED_LATCH_PIN, OUTPUT);

}

void initRotaryEncPins() {

 pinMode(HDDJ1_PIN1, INPUT);
 pinMode(HDDJ1_PIN2, INPUT);
 pinMode(HDDJ2_PIN1, INPUT);
 pinMode(HDDJ2_PIN2, INPUT);
 
}

void initPins() {
 
 initPinsDigitalInput();
 initPinsAnalogueInput();
 initPinsDigitalOutput();
 initRotaryEncPins();
 
}

ISR(TIMER1_COMPA_vect)
{
   openDeck.blinkLED(BLINK_LED_1, BLINK_LED_2);
}


Code: [Select]

//LEDs
void OpenDeckRewrite::writeLEDs() {

 int j = NUMBER_OF_595_REGISTERS*8;

  digitalWrite(_led_latchPin, LOW);

 for (i=0; i<NUMBER_OF_595_REGISTERS*8; i++)    {
   digitalWrite(_led_clockPin, LOW);
   digitalWrite(_led_dataPin, ledState[--j]);
   digitalWrite(_led_clockPin, HIGH);
 }

 digitalWrite(_led_latchPin, HIGH);

}

void OpenDeckRewrite::allLEDsOn() {

 //turn on all LEDs
 for (int i=0; i<NUMBER_OF_595_REGISTERS*8; i++)   ledState[i] = true;
 writeLEDs();
}

void OpenDeckRewrite::resetLEDs() {

 //turn off all LEDs
 for (int i=0; i<NUMBER_OF_595_REGISTERS*8; i++)   ledState[i] = false;
 writeLEDs();
}

void OpenDeckRewrite::setLEDstate(int led, boolean state) {

   ledState[led] = state;
   openDeck.writeLEDs();
}

void OpenDeckRewrite::changeBlinkState(int ledIndex, boolean state) {

 switch (ledIndex) {

 case 0:
 if (state) blinkLedOn[0] = true;  else blinkLedOn[0] = false;
 break;

 case 1:
 if (state) blinkLedOn[1] = true;  else blinkLedOn[1] = false;
 break;

 default:
 break;

 }
}

void OpenDeckRewrite::blinkLED(int blinkLED_1, int blinkLED_2)  {

   int arrayOfBlinkLeds[NUMBER_OF_BLINK_LEDS] = {blinkLED_1, blinkLED_2};

   for (int i=0; i<NUMBER_OF_BLINK_LEDS; i++) {

   if (blinkLedOn[i]) {

   // if the LED is off turn it on and vice-versa
   ledState[arrayOfBlinkLeds[i]] = !ledState[arrayOfBlinkLeds[i]];
   }

       else ledState[arrayOfBlinkLeds[i]] = false;
 }
openDeck.writeLEDs();
}

kustom

I kinda fixed it, but it isn't exactly what I wanted.

I wrote new function inside OpenDeck.cpp:

Code: [Select]
boolean OpenDeckRewrite::getBlinkState() {

if (blinkLedOn[0] || blinkLedOn[1]) return true;
else return false;

}


blink function is modified a bit:

Code: [Select]
void OpenDeckRewrite::blinkLED(int blinkLED_1, int blinkLED_2)  {

   int arrayOfBlinkLeds[NUMBER_OF_BLINK_LEDS] = {blinkLED_1, blinkLED_2};
   static boolean intState = false;
   intState = !intState;

   for (int i=0; i<NUMBER_OF_BLINK_LEDS; i++) {

   if (blinkLedOn[i]) {
   //if the LED is off turn it on and vice-versa
   ledState[arrayOfBlinkLeds[i]] = intState;

   }
       else ledState[arrayOfBlinkLeds[i]] = false;
 }
 writeLEDs();
}


And finally, the interrupt function:

Code: [Select]
ISR(TIMER1_COMPA_vect)
{
     if (openDeck.getBlinkState())
       openDeck.blinkLED(BLINK_LED_1, BLINK_LED_2);
}


What I actually wanted was not to call interrupt function at all until one of the blink LEDs is set on.

PaulS

Quote
I kinda fixed it, but it isn't exactly what I wanted.

If you really want help, you'll follow Nick's advice and post ALL of your code. Look at the Additional Options... link below the text entry field. There is an option to attach a zip file, if your code exceeds the 9500 character limit.

Code: [Select]
if (blinkLedOn[0] || blinkLedOn[1]) return true;
This array is not defined anywhere in the code you have posted so far.

kustom


dhenry

Find out where the buttons are processed and turn off the timer or its interrupt.

kustom


Find out where the buttons are processed and turn off the timer or its interrupt.


How?

dhenry

How? Clear CS2..0 bits to stop the timer and clear the corresponding interrupt enable bits to stop the interrupt. All in the datasheet.

Nick Gammon

This line enables Timer 1 compare interrupts:

Code: [Select]

 //enable timer compare interrupt:
 TIMSK1 |= (1 << OCIE1A);


If you don't want them at that point omit it. Put that line where you want the interrupts to go on. To turn them off:

Code: [Select]

 //disable timer compare interrupt:
 TIMSK1 &= ~(1 << OCIE1A);

http://www.gammon.com.au/electronics

kustom


This line enables Timer 1 compare interrupts:

Code: [Select]

 //enable timer compare interrupt:
 TIMSK1 |= (1 << OCIE1A);


If you don't want them at that point omit it. Put that line where you want the interrupts to go on. To turn them off:

Code: [Select]

 //disable timer compare interrupt:
 TIMSK1 &= ~(1 << OCIE1A);




THAT is what I've looking for. Thanks.

kustom

One more question - how can I see the value of timer counter (TCNT1)?

Nick Gammon

How do you mean "see it"? Just assign it to a variable and print it or whatever.
http://www.gammon.com.au/electronics

Go Up