SparkFun Forums 

Where electronics enthusiasts find answers.

For the discussion of Arduino related topics.
By noobcodertom
#199116
Hi,

I've very recently got into coding and am doing a piece of it for my college project. I have attached an Adafruit Neo_Pixel Shield to an Arduino Uno and want the LEDs to flash the SOS sequence when the button is pushed, and to stop the sequence when the button is pushed a second time.

For some reason unknown to me, the hardware shows absolutely no sign of working when the button is pressed however I know that its the software incorrect as I've loaded other pieces of code onto it that are correct and it works just fine. The code I'm uploading is as follows:

#include <Adafruit_NeoPixel.h> //includes NeoPixel Shield Library

#define PIXELS 6 //sets pin 6 as routing for Neo_Pixels in strip definition of Neopixels

#define NUM_PIX 40

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIX, PIXELS, NEO_RGB + NEO_KHZ800); //defines parameters of neopixel shield

boolean Latch = true; //sets the latch norm as true
const int ButtonPin = 9; //sets pin number 9 as the pushbutton pin
const int PixPin = 6; //sets pin number 6 as the neopixel pin

volatile int ButtonState = 0; //sets button state norm as 0 (LOW)

void setup() {

strip.begin();
strip.show(); //initialise all pins to OFF

strip.setBrightness(100); //sets pixel brightness as 100%

pinMode(ButtonPin,INPUT); //sets button pin as an input
pinMode(PixPin, OUTPUT); //sets pixel pin as an output

attachInterrupt(digitalPinToInterrupt(ButtonPin),pixOFF,RISING); //creates interrupt so that 2nd press of button will turn all pixels off

}


void loop() {

strip.begin();
strip.show();

ButtonState = digitalRead(ButtonPin); //reads the state of button value

if (ButtonState = HIGH) {
if (Latch = true)
Latch = false; //turns latch to OFF if button is pressed and latch is already ON
else
Latch = true; //turns latch to ON if button is pressed and latch is already OFF
}



if (Latch = true)
SOS_Signal(); //plays SOS loop if latch is ON
else
pixOFF(); //keeps pixels OFF if latch is OFF

}


void pixOFF(){
int pix;
for(pix=0; pix<40; pix++){
strip.setPixelColor(pix, 0, 0, 0); //reverts all pixels back to OFF
}
}

void pixON(){
int pix;
for(pix=0; pix<40; pix++){
strip.setPixelColor(pix, 255, 0, 0); //turns on every pixel
}

}

void SOS_Signal() {

int shortdelay=300; //one time unit in morse code
int longdelay=900; //three time units in morse code

pixON();
delay(shortdelay);
pixOFF();
delay(shortdelay);
pixON();
delay(shortdelay);
pixOFF();
delay(shortdelay);
pixON();
delay(shortdelay);
pixOFF();
delay(longdelay); //3 dots (S) and a space

pixON();
delay(longdelay);
pixOFF();
delay(shortdelay);
pixON();
delay(longdelay);
pixOFF();
delay(shortdelay);
pixON();
delay(longdelay);
pixOFF();
delay(longdelay); //3 dashes (O) and a space

pixON();
delay(shortdelay);
pixOFF();
delay(shortdelay);
pixON();
delay(shortdelay);
pixOFF();
delay(shortdelay);
pixON();
delay(shortdelay);
pixOFF();
delay(longdelay); //3 dots (S) and a space

strip.show();

}


It's quite messy but please could anyone help with this as I don't know where I've gone wrong at all!

Thanks a lot,

NoobCoderTom
By n1ist
#199118
A few things
- use code tags when posting code so that indentation is maintained; it makes it easier to read
- = is an assignment, == is a comparison so if (Latch = true) {} will set latch to true and then always do the if since true is true...
- strip.begin() only needs to be executed once, so it should only be in setup(), not loop()
- strip.show() needs to be called whenever you want changes to show up on the strips; the end of pixON() and pixOFF() is the right place.
- Buttons bounce; when pressed or are released, the contacts open and close many times. Do a Google search for 'ganssle debounce' for more info and some code to handle this.
- You are using a mix of interrupts and polling on the button; buttons tied directly to interrupt pins isn't a good idea due to bouncing. Also, latch will misbehave if the button is held down. I would just use digital read and keep track of the previous state; if the current debounced state is different than the previous state, then either do pixOFF or SOS_Signal as appropriate.
This is some pseudocode:
Code: Select all
uint8_t previousValue = 0; // button starts not being pressed
loop()
{
  static uint8_t buttonDebounce = 0;    // Used to debounce button.  Must be stable for 8 times through loop()
  static boolean isSecondPress = false; // Is this an odd or even time the button has been pressed.  Only pay attention to the even
  static boolean isPixelOff = true;     // Used to toggle the state of the LED strip

  buttonDebounce = (buttonDebounce << 1) | digital.read(,,,);
  if (buttonDebounce == 0xFF)
  {
    if (previousValue == 0x00)
    {
      // button is pressed, but it wasn't last time
      previousValue = 0xFF;
      if (isSecondPress == false)
      {
         // Only do things on every other press of the button
         isSecondPress = true;
         // Alternate the LEDs - either off or SOS
         if (isPixelOff)
         {
           isPixelOff = false;
           SOS_Signal();
         }
         else
         {
           isPixelOff = true;
           pixOff();
         }
      }
      else isSecondPress = false;
    }
  }
  else if (buttonDebounce == 0x00)
    previousValue = 0x00; // Button has been released
}
/mike