Strange Happenings with Interrupt

Hi,

I’ve made some progress with my code but it’s exhibiting some strange quirks. Basically I have my board talking to a 74HC595 lighting 8 LEDS. I have some light programs included in my code to animate them back and forth and am experimenting with interrupts to watch my pressing of a button while the lights are running. With each button press go to the next light pattern. I’m trying interrupts because I was unable to figure out how to use millis() to meet my goal. Right now I have 3 programs in the code, all off, a in and out pattern, and a wave pattern. It works to an extent however sometimes when I press my button it will pull the second program first and continue to loop…or even quit after one time through. And sometimes it works just perfectly. This is my first try at interrupt so this is pretty confusing, any help would be appreciated.

#//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;
byte data;
byte dataArray[7];

volatile int lightMode = 0;

void setup() {
pinMode(latchPin, OUTPUT);

attachInterrupt(0, modeSelector, LOW);

dataArray[0] = 0x81; //10000001
dataArray[1] = 0xC3; //11000011
dataArray[2] = 0xE7; //11100111
dataArray[3] = 0xFF; //11111111
dataArray[4] = 0x7E; //01111110
dataArray[5] = 0x3C; //00111100
dataArray[6] = 0x18; //00011000
}

void loop() {

if (lightMode == 0) {
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 0);
digitalWrite(latchPin, 1);
}

if (lightMode == 1) {
for (int j = 0; j < 7; j++) {
//load the light sequence you want from array
data = dataArray[j];
//ground latchPin and hold low for as long as you are transmitting
digitalWrite(latchPin, 0);
//move 'em out
shiftOut(dataPin, clockPin, data);
//return the latch pin high to signal chip that it
//no longer needs to listen for information
digitalWrite(latchPin, 1);
delay(100);
}

for (int j = 6; j >= 0; j–) {
//load the light sequence you want from array
data = dataArray[j];
//ground latchPin and hold low for as long as you are transmitting
digitalWrite(latchPin, 0);
//move 'em out
shiftOut(dataPin, clockPin, data);
//return the latch pin high to signal chip that it
//no longer needs to listen for information
digitalWrite(latchPin, 1);
delay(100);
}
}

if (lightMode == 2) {
for (int j = 0; j < 8; j++) {
lightShiftPinA(j);
delay(150);
}
}
}

void modeSelector() {
if (lightMode == 0) { // if its off
lightMode = 1; // turn lights on!
} else {
if (lightMode == 1) { // if its all-on
lightMode = 2; // make it wave
} else {
if (lightMode == 2) { // if its waving
lightMode = 0; // turn it off
}
}
}
}

//This function uses bitwise math to move the pins up
void lightShiftPinA(int p) {
//defines a local variable
int pin;

//this is line uses a bitwise operator
//shifting a bit left using << is the same
//as multiplying the decimal number by two.
pin = 1<< p;

//ground latchPin and hold low for as long as you are transmitting
digitalWrite(latchPin, 0);
//move 'em out
shiftOut(dataPin, clockPin, pin);
//return the latch pin high to signal chip that it
//no longer needs to listen for information
digitalWrite(latchPin, 1);
}

// the heart of the program
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
// This shifts 8 bits out MSB first,
//on the rising edge of the clock,
//clock idles low

//internal function setup
int i=0;
int pinState;
pinMode(myClockPin, OUTPUT);
pinMode(myDataPin, OUTPUT);

//clear everything out just in case to
//prepare shift register for bit shifting
digitalWrite(myDataPin, 0);
digitalWrite(myClockPin, 0);

//for each bit in the byte myDataOut?
//NOTICE THAT WE ARE COUNTING DOWN in our for loop
//This means that %00000001 or “1” will go through such
//that it will be pin Q0 that lights.
for (i=7; i>=0; i–) {
digitalWrite(myClockPin, 0);

//if the value passed to myDataOut and a bitmask result
// true then… so if we are at i=6 and our value is
// %11010100 it would the code compares it to %01000000
// and proceeds to set pinState to 1.
if ( myDataOut & (1<<i) ) {
pinState= 1;
}
else {
pinState= 0;
}

//Sets the pin to HIGH or LOW depending on pinState
digitalWrite(myDataPin, pinState);
//register shifts bits on upstroke of clock pin
digitalWrite(myClockPin, 1);
//zero the data pin after shift to prevent bleed through
digitalWrite(myDataPin, 0);
}

//stop shifting
digitalWrite(myClockPin, 0);
}#

Unless you have special hardware associated with your button, it will “bounce” and create several actual transitions over a period on the order of 10 milliseconds (and cause multiple interrupts, probably too quickly to notice.) Could that be your problem?

Thanks alot for the dummy check West. I was so engrossed in trying to learn and use the interrupt that I forgot about a simple button bounce. I was playing around with debouncing in the tutorials using delay and have that down fairly well, unfortunately I found out after trying (and then reading) that a delay won't work in the ISR. There's always something isn't there? But I was able to find a good thread using millis() to effectively do the same thing. It works great now with the added code for the bounce in the ISR. A thanks goes out from me to Big Mike and mikalhart.