Pages: [1]   Go Down
Author Topic: Event-based timer interrupts  (Read 869 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Sr. Member
****
Karma: 1
Posts: 255
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18815
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged


Offline Offline
Sr. Member
****
Karma: 1
Posts: 255
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
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:
void loop() {
  
  //read incoming MIDI data
  MIDI.read();
}

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

Code:
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:
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();
}
« Last Edit: October 25, 2012, 03:23:12 am by kustom » Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18815
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

All of it.
Logged


Offline Offline
Sr. Member
****
Karma: 1
Posts: 255
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

As you wish.

Code:
#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:
//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();
}
« Last Edit: October 25, 2012, 04:47:26 am by kustom » Logged

Offline Offline
Sr. Member
****
Karma: 1
Posts: 255
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

I wrote new function inside OpenDeck.cpp:

Code:
boolean OpenDeckRewrite::getBlinkState() {

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

}

blink function is modified a bit:

Code:
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:
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.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 617
Posts: 49463
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
if (blinkLedOn[0] || blinkLedOn[1]) return true;
This array is not defined anywhere in the code you have posted so far.
Logged

Offline Offline
Sr. Member
****
Karma: 1
Posts: 255
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Okay, I attached it.

* OpenDeckRewrite.ino (7.25 KB - downloaded 3 times.)
* OpenDeckRewrite.cpp (14.4 KB - downloaded 9 times.)
* OpenDeckRewrite.h (3.34 KB - downloaded 6 times.)
* HDDJ.zip (1.79 KB - downloaded 2 times.)
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Sr. Member
****
Karma: 1
Posts: 255
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

How?
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18815
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

This line enables Timer 1 compare interrupts:

Code:
 //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:
 //disable timer compare interrupt:
  TIMSK1 &= ~(1 << OCIE1A);
Logged


Offline Offline
Sr. Member
****
Karma: 1
Posts: 255
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This line enables Timer 1 compare interrupts:

Code:
 //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:
 //disable timer compare interrupt:
  TIMSK1 &= ~(1 << OCIE1A);


THAT is what I've looking for. Thanks.
Logged

Offline Offline
Sr. Member
****
Karma: 1
Posts: 255
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18815
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

How do you mean "see it"? Just assign it to a variable and print it or whatever.
Logged


Pages: [1]   Go Up
Jump to: