[resolved]getting stuck in a switch-case situation

Hi all,

I’m working on a cosplay prop that utilizes neopixels as well as traditional LEDs to create a few different effects. The illumination modes are changed via a button press that controls a switch-case as follows:
(currently using a single LED as an indicator for the case being switched, waiting for parts to come end of the week)
case 0 - LED off
case 1 - LED blinks
case 2 - Full, continuous illumination
case 3 - 50% illumination (allows for bluetooth control of neopixel)

another button press resets the case to 0 and we loop around.

I initially just had the four cases without BLE added, changing the LED’s behavior and it worked fine. Now that I’ve added the neopixel and BLE code I’m 50-50 either not getting a response to the button at all OR when I reach case 3 the case does not change again on button press and I get stuck at case 3. I’m clearly not seeing whatever is going wrong and could use some extra eyes. Code below. Thanks in advance

#include <string.h>
#include <Arduino.h>
#include <SPI.h>
#include <Adafruit_NeoPixel.h>
#include <Adafruit_ATParser.h>
#include <Adafruit_BLE.h>
#include <Adafruit_BluefruitLE_SPI.h>
#include <Adafruit_BluefruitLE_UART.h>
#if SOFTWARE_SERIAL_AVAILABLE
  #include <SoftwareSerial.h>
#endif
#include "BluefruitConfig.h"

//neopixel and BLE definitions
#define FACTORYRESET_ENABLE     0
#define PIN                     9
#define NUMPIXELS               1

//create neopixel and bluefruit objects
Adafruit_NeoPixel pixel = Adafruit_NeoPixel(NUMPIXELS, PIN);
Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST);

//LED status pin variables
const byte ledPin = 5;
int ledState = 0;

//button pin variables
const byte buttonPin = 6;
int buttonState;
int reading;
int lastButtonState = LOW;

//switch mode variables
int mode = 0; //selector state

//debounce check variables
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

//variables for blinking function
const long blinkInterval = 1000; //blink without delay interval for case 1
unsigned long currentMillis=0;
unsigned long blinkingMillis=0;

// A small helper
void error(const __FlashStringHelper*err) {
  Serial.println(err);
  while (1);
}

// function prototypes over in packetparser.cpp
uint8_t readPacket(Adafruit_BLE *ble, uint16_t timeout);
float parsefloat(uint8_t *buffer);
void printHex(const uint8_t * data, const uint32_t numBytes);

// the packet buffer
extern uint8_t packetbuffer[];

void setup() {
  // put your setup code here, to run once:
  pinMode(buttonPin,INPUT);
  pinMode(ledPin,OUTPUT);
  //set initial LED state
  analogWrite(ledPin, ledState);

  //neopixel and BLE initialization
   while (!Serial);  // required for Flora & Micro
  delay(500);

  // turn off neopixel
  pixel.begin(); // This initializes the NeoPixel library.
  for(uint8_t i=0; i<NUMPIXELS; i++) {
    pixel.setPixelColor(i, pixel.Color(0,0,0)); // off
  }
  pixel.show();

  Serial.begin(115200);
  Serial.println(F("Adafruit Bluefruit Neopixel Color Picker Example"));
  Serial.println(F("------------------------------------------------"));

  /* Initialise the module */
  Serial.print(F("Initialising the Bluefruit LE module: "));

  if ( !ble.begin(VERBOSE_MODE) )
  {
    error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?"));
  }
  Serial.println( F("OK!") );

  if ( FACTORYRESET_ENABLE )
  {
    /* Perform a factory reset to make sure everything is in a known state */
    Serial.println(F("Performing a factory reset: "));
    if ( ! ble.factoryReset() ){
      error(F("Couldn't factory reset"));
    }
  }

  /* Disable command echo from Bluefruit */
  ble.echo(false);

  Serial.println("Requesting Bluefruit info:");
  /* Print Bluefruit information */
  ble.info();

  Serial.println(F("Please use Adafruit Bluefruit LE app to connect in Controller mode"));
  Serial.println(F("Then activate/use the sensors, color picker, game controller, etc!"));
  Serial.println();

  ble.verbose(false);  // debug info is a little annoying after this point!

  /* Wait for connection */
  while (! ble.isConnected()) {
      delay(500);
  }

  Serial.println(F("***********************"));

  // Set Bluefruit to DATA mode
  Serial.println( F("Switching to DATA mode!") );
  ble.setMode(BLUEFRUIT_MODE_DATA);

  Serial.println(F("***********************"));
}


void loop() {
  // put your main code here, to run repeatedly:
int reading = digitalRead(buttonPin);

  if (reading != lastButtonState){
    //reset the debouncing timer
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
  //debounce check
    if (reading != buttonState){
      buttonState = reading;//update buttonState
      if (buttonState == HIGH){
        mode++;//cycle the case on button press
      }
    }
  }
      if (mode <= 3){
        switch (mode) {
          case 0:
          //case 0 is everything shut off
          ledState = 0;
          analogWrite(ledPin, ledState);
          break;
          case 1:
          pixelBlinking();
          break;
          case 2:
          // case 2 is led solid
          ledState = 255;
          analogWrite(ledPin, ledState);
          break;
          case 3:
          //case 3 enables neopixel color picking via BLE app
          //it currently sets the led at half brightness to show activity
          ledState = 127;
          analogWrite(ledPin, ledState);
          pixelColorPicker();
          break;
        }
      
      }
      else {
        mode = 0;
      }
   
  lastButtonState = reading;
  
}

void pixelColorPicker(){
   /* Wait for new data to arrive */
  uint8_t len = readPacket(&ble, BLE_READPACKET_TIMEOUT);
  if (len == 0) return;

  /* Got a packet! */
  // printHex(packetbuffer, len);

  // Color
  if (packetbuffer[1] == 'C') {
    uint8_t red = packetbuffer[2];
    uint8_t green = packetbuffer[3];
    uint8_t blue = packetbuffer[4];
    Serial.print ("RGB #");
    if (red < 0x10) Serial.print("0");
    Serial.print(red, HEX);
    if (green < 0x10) Serial.print("0");
    Serial.print(green, HEX);
    if (blue < 0x10) Serial.print("0");
    Serial.println(blue, HEX);

    for(uint8_t i=0; i<NUMPIXELS; i++) {
      pixel.setPixelColor(i, pixel.Color(red,green,blue));
    }
    pixel.show(); // This sends the updated pixel color to the hardware.
  }
}

void pixelBlinking(){
  currentMillis = millis();
  if (currentMillis - blinkingMillis >= blinkInterval) {
            // save the last time you blinked the LED
            blinkingMillis = currentMillis;

            // if the LED is off turn it on and vice-versa:
            if (ledState == 0) {
              ledState = 255;
            } else {
              ledState = 0;
            }
          // set the LED with the ledState of the variable:
          analogWrite(ledPin, ledState);
         }
}

If you comment out "pixelColorPicker();" in case 3, does it work as expected?

If so, your problem is there. And I do expect it to be with readPacket() because you say it's waiting. Waiting for something to happen is never a good thing to do in code. Just don't do anything if something didn't happen. Isn't there a non-blocking alternative like .available()?

  uint8_t len = readPacket(&ble, BLE_READPACKET_TIMEOUT);

Maybe the timeout is set very high? If it's, say, 60 seconds... your button will only get looked at once ever minute. It has to be UP one minute and DOWN another to be detected as a button press.

septillion:
If you comment out "pixelColorPicker();" in case 3, does it work as expected?

If so, your problem is there. And I do expect it to be with readPacket() because you say it's waiting. Waiting for something to happen is never a good thing to do in code. Just don't do anything if something didn't happen. Isn't there a non-blocking alternative like .available()?

commented out the call for pixelColorPicker() and having the same issue.

johnwasser:

  uint8_t len = readPacket(&ble, BLE_READPACKET_TIMEOUT);

Maybe the timeout is set very high? If it's, say, 60 seconds... your button will only get looked at once ever minute. It has to be UP one minute and DOWN another to be detected as a button press.

I adjusted the timeout value (default was 500) to 10, no change.

This is making me think it's something going on in setup(), there is a delay in there that I have shortened to 10 from 500

 /* Wait for connection */
  while (! ble.isConnected()) {
      delay(10);
  }

UPDATE

it's definitely something in the setup code causing a hangup. I moved the ble/neopixel code to a separate function called from case 3 like so

case 3:
          //case 3 enables neopixel color picking via BLE app
          //it currently sets the led at half brightness to show activity
          ledState = 127;
          analogWrite(ledPin, ledState);
          //bleSetup();
          //pixelColorPicker();
          break;

When bleSetup and pixelColorPicker are both commented out, it runs fine and cycles through all cases
When bleSetup is in and pCP is out, it does not work
when both are in, it does not work
when bleS is out and pCP is left in, it cycles as intended, but I'm not sure what problems that will cause in the future as I need the code in BLE to enable communication with the app

If it still don't work with pixelColorPicker() commented out it's noting special to case 3....

Do you have a pull down resistor connected to the button?

delay() in setup() only limits how often to check if BLE is connected. Think you can even leave it out, it's blocking the rest all the same if BLE isn't connected. So when you see your "***********************" printed it's passed that.

Edit, since when is bleSetup() in that case??? And what is in bleSetup() anyway?

septillion:
If it still don’t work with pixelColorPicker() commented out it’s noting special to case 3…

Do you have a pull down resistor connected to the button?

delay() in setup() only limits how often to check if BLE is connected. Think you can even leave it out, it’s blocking the rest all the same if BLE isn’t connected. So when you see your “***********************” printed it’s passed that.

Edit, since when is bleSetup() in that case??? And what is in bleSetup() anyway?

I moved all of the code that was in setup below “analogWrite(ledPin, ledState);” into its own function called bleSetup just to have everything in one place that can easily be taken in-out with comments for the time being. Then, to see if the hangup was in the Setup() function I moved it out of setup and into the case list. This leads me to believe that the problem is somewhere in this block that now exists as bleSetup() instead of a piece of Setup()

also, yes button is on a pulldown resistor

 //neopixel and BLE initialization
   while (!Serial);  // required for Flora & Micro
  delay(10);

  // turn off neopixel
  pixel.begin(); // This initializes the NeoPixel library.
  for(uint8_t i=0; i<NUMPIXELS; i++) {
    pixel.setPixelColor(i, pixel.Color(0,0,0)); // off
  }
  pixel.show();

  Serial.begin(115200);
  Serial.println(F("Adafruit Bluefruit Neopixel Color Picker Example"));
  Serial.println(F("------------------------------------------------"));

  /* Initialise the module */
  Serial.print(F("Initialising the Bluefruit LE module: "));

  if ( !ble.begin(VERBOSE_MODE) )
  {
    error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?"));
  }
  Serial.println( F("OK!") );

  if ( FACTORYRESET_ENABLE )
  {
    /* Perform a factory reset to make sure everything is in a known state */
    Serial.println(F("Performing a factory reset: "));
    if ( ! ble.factoryReset() ){
      error(F("Couldn't factory reset"));
    }
  }

  /* Disable command echo from Bluefruit */
 ble.echo(false);

  Serial.println("Requesting Bluefruit info:");
  /* Print Bluefruit information */
 ble.info();

  Serial.println(F("Please use Adafruit Bluefruit LE app to connect in Controller mode"));
  Serial.println(F("Then activate/use the sensors, color picker, game controller, etc!"));
  Serial.println();

  ble.verbose(false);  // debug info is a little annoying after this point!

  /* Wait for connection */
 while (! ble.isConnected()) {
      delay(10);
  }

  Serial.println(F("***********************"));

  // Set Bluefruit to DATA mode
  Serial.println( F("Switching to DATA mode!") );
  ble.setMode(BLUEFRUIT_MODE_DATA);

  Serial.println(F("***********************"));

Please post all the code if you make changes, I'm not psychic...

But it does sound like a terrible idea. Move something from setup(), aka to set something up once, to be called thousands of times a second when moved to loop...

septillion:
Please post all the code if you make changes, I’m not psychic…

But it does sound like a terrible idea. Move something from setup(), aka to set something up once, to be called thousands of times a second when moved to loop…

Yes, of course. I’ll be more clear next time. I know it’s not best practice, I just wanted to isolate the code somewhere super simple to comment out all at once. I’ve since restored it to only running in setup, which of course has prevented us from even getting to the case setup.

#include <string.h>
#include <Arduino.h>
#include <SPI.h>
#include <Adafruit_NeoPixel.h>
#include <Adafruit_ATParser.h>
#include <Adafruit_BLE.h>
#include <Adafruit_BluefruitLE_SPI.h>
#include <Adafruit_BluefruitLE_UART.h>
#if SOFTWARE_SERIAL_AVAILABLE
  #include <SoftwareSerial.h>
#endif
#include "BluefruitConfig.h"

//neopixel and BLE definitions
#define FACTORYRESET_ENABLE     0
#define PIN                     9
#define NUMPIXELS               1

//create neopixel and bluefruit objects
Adafruit_NeoPixel pixel = Adafruit_NeoPixel(NUMPIXELS, PIN);
Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST);

//LED status pin variables
const byte ledPin = 5;
int ledState = 0;

//button pin variables
const byte buttonPin = 6;
int buttonState;
int reading;
int lastButtonState = LOW;

//switch mode variables
int mode = 0; //selector state

//debounce check variables
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

//variables for blinking function
const long blinkInterval = 1000; //blink without delay interval for case 1
unsigned long currentMillis=0;
unsigned long blinkingMillis=0;

// A small helper
void error(const __FlashStringHelper*err) {
  Serial.println(err);
  while (1);
}

// function prototypes over in packetparser.cpp
uint8_t readPacket(Adafruit_BLE *ble, uint16_t timeout);
float parsefloat(uint8_t *buffer);
void printHex(const uint8_t * data, const uint32_t numBytes);

// the packet buffer
extern uint8_t packetbuffer[];

void setup() {
  // put your setup code here, to run once:
  pinMode(buttonPin,INPUT);
  pinMode(ledPin,OUTPUT);
  //set initial LED state
  analogWrite(ledPin, ledState);

  //neopixel and BLE initialization
   while (!Serial);  // required for Flora & Micro
  delay(10);

  // turn off neopixel
  pixel.begin(); // This initializes the NeoPixel library.
  for(uint8_t i=0; i<NUMPIXELS; i++) {
    pixel.setPixelColor(i, pixel.Color(0,0,0)); // off
  }
  pixel.show();

  Serial.begin(115200);
  Serial.println(F("Adafruit Bluefruit Neopixel Color Picker Example"));
  Serial.println(F("------------------------------------------------"));

  /* Initialise the module */
  Serial.print(F("Initialising the Bluefruit LE module: "));

  if ( !ble.begin(VERBOSE_MODE) )
  {
    error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?"));
  }
  Serial.println( F("OK!") );

  if ( FACTORYRESET_ENABLE )
  {
    /*  Perform a factory reset to make sure everything is in a known state */
    Serial.println(F("Performing a factory reset: "));
    if ( ! ble.factoryReset() ){
      error(F("Couldn't factory reset"));
    }
  }

  /* Disable command echo from Bluefruit */
  ble.echo(false);

  Serial.println("Requesting Bluefruit info:");
  /* Print Bluefruit information */
  ble.info();

  Serial.println(F("Please use Adafruit Bluefruit LE app to connect in Controller mode"));
  Serial.println(F("Then activate/use the sensors, color picker, game controller, etc!"));
  Serial.println();

  ble.verbose(false);  // debug info is a little annoying after this point!

  /* Wait for connection */
  while (! ble.isConnected()) {
      delay(10);
  }

  Serial.println(F("***********************"));

  // Set Bluefruit to DATA mode
  Serial.println( F("Switching to DATA mode!") );
  ble.setMode(BLUEFRUIT_MODE_DATA);

  Serial.println(F("***********************"));
  
}


void loop() {
  // put your main code here, to run repeatedly:
int reading = digitalRead(buttonPin);

  if (reading != lastButtonState){
    //reset the debouncing timer
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
  //debounce check
    if (reading != buttonState){
      buttonState = reading;//update buttonState
      if (buttonState == HIGH){
        mode++;//cycle the case on button press
      }
    }
  }
      if (mode <= 3){
        switch (mode) {
          case 0:
          //case 0 is everything shut off
          ledState = 0;
          analogWrite(ledPin, ledState);
          break;
          case 1:
          pixelBlinking();
          break;
          case 2:
          // case 2 is led solid
          ledState = 255;
          analogWrite(ledPin, ledState);
          break;
          case 3:
          //case 3 enables neopixel color picking via BLE app
          //it currently sets the led at half brightness to show activity
          ledState = 127;
          analogWrite(ledPin, ledState);
          pixelColorPicker();
          break;
        }
      
      }
      else {
        mode = 0;
      }
   
  lastButtonState = reading;
  
}

void pixelColorPicker(){
   /* Wait for new data to arrive */
  uint8_t len = readPacket(&ble, BLE_READPACKET_TIMEOUT);
  if (len == 0) return;

  /* Got a packet! */
  // printHex(packetbuffer, len);

  // Color
  if (packetbuffer[1] == 'C') {
    uint8_t red = packetbuffer[2];
    uint8_t green = packetbuffer[3];
    uint8_t blue = packetbuffer[4];
    Serial.print ("RGB #");
    if (red < 0x10) Serial.print("0");
    Serial.print(red, HEX);
    if (green < 0x10) Serial.print("0");
    Serial.print(green, HEX);
    if (blue < 0x10) Serial.print("0");
    Serial.println(blue, HEX);

    for(uint8_t i=0; i<NUMPIXELS; i++) {
      pixel.setPixelColor(i, pixel.Color(red,green,blue));
    }
    pixel.show(); // This sends the updated pixel color to the hardware.
  }
}

void pixelBlinking(){
  currentMillis = millis();
  if (currentMillis - blinkingMillis >= blinkInterval) {
            // save the last time you blinked the LED
            blinkingMillis = currentMillis;

            // if the LED is off turn it on and vice-versa:
            if (ledState == 0) {
              ledState = 255;
            } else {
              ledState = 0;
            }
          // set the LED with the ledState of the variable:
          analogWrite(ledPin, ledState);
         }
}

Yeah, bt putting the set up in the loop() can give you weird and wonderful other problems.

So I'm still with the poor readPacket(). I don't have packetparser.cpp but the fact it accepts 'timeout' as a parameters screams BLOCKING FUNCTION to me.

septillion:
Yeah, bt putting the set up in the loop() can give you weird and wonderful other problems.

So I’m still with the poor readPacket(). I don’t have packetparser.cpp but the fact it accepts ‘timeout’ as a parameters screams BLOCKING FUNCTION to me.

Problem was actually in not having any way to check the button state once in the case 3 scenario, I fixed that. Then was running into issues where I could only get any of the code to function if the serial monitor was open (part of the example meant for a different board, and I forgot I had left this little beauty in from some which stopped anything else from working if there was no BLE connection:

 while (! ble.isConnected()) {
      delay(10);
  }

This is the final, actually working code!

#include <Adafruit_NeoPixel_ZeroDMA.h>
#include <bittable.h>

#include <string.h>
#include <Arduino.h>
#include <SPI.h>
#include <Adafruit_ATParser.h>
#include <Adafruit_BLE.h>
#include <Adafruit_BluefruitLE_SPI.h>
#include <Adafruit_BluefruitLE_UART.h>
#if SOFTWARE_SERIAL_AVAILABLE
  #include <SoftwareSerial.h>
#endif
#include "BluefruitConfig.h"

//neopixel and BLE definitions
#define FACTORYRESET_ENABLE     0
#define PIN                     5
#define NUMPIXELS               7

//create neopixel and bluefruit objects
Adafruit_NeoPixel_ZeroDMA pixel(NUMPIXELS, PIN, NEO_GRBW);
Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST);

//LED status pin variables
const byte ledPin = 11;
int ledState = 0;

//button pin variables
const byte buttonPin = 6;
int buttonState;
int reading;
int lastButtonState = LOW;

//switch mode variables
int mode = 0; //selector state

//debounce check variables
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

//variables for blinking function
const long blinkInterval = 1000; //blink without delay interval for case 1
unsigned long currentMillis=0;
unsigned long blinkingMillis=0;

// A small helper
void error(const __FlashStringHelper*err) {
  Serial.println(err);
  while (1);
}

// function prototypes over in packetparser.cpp
uint8_t readPacket(Adafruit_BLE *ble, uint16_t timeout);
float parsefloat(uint8_t *buffer);
void printHex(const uint8_t * data, const uint32_t numBytes);

// the packet buffer
extern uint8_t packetbuffer[];

void setup() {
  // put your setup code here, to run once:
  pinMode(buttonPin,INPUT);
  pinMode(ledPin,OUTPUT);
  //set initial LED state
  analogWrite(ledPin, ledState);

  //neopixel and BLE initialization
  delay(10);

  // turn off neopixel
  pixel.begin(); // This initializes the NeoPixel library.
  for(uint8_t i=0; i<NUMPIXELS; i++) {
    pixel.setPixelColor(i, pixel.Color(0,0,0)); // off
  }
  pixel.show();

  Serial.begin(115200);
  Serial.println(F("Adafruit Bluefruit Neopixel Color Picker Example"));
  Serial.println(F("------------------------------------------------"));

  // Initialise the module 
  Serial.print(F("Initialising the Bluefruit LE module: "));

  if ( !ble.begin(VERBOSE_MODE) )
  {
    error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?"));
  }
  
  Serial.println( F("OK!") );

  if ( FACTORYRESET_ENABLE )
  {
    //  Perform a factory reset to make sure everything is in a known state 
    Serial.println(F("Performing a factory reset: "));
    if ( ! ble.factoryReset() ){
      error(F("Couldn't factory reset"));
    }
  }

  // Disable command echo from Bluefruit 
  ble.echo(false);

  Serial.println("Requesting Bluefruit info:");
  // Print Bluefruit information 
  ble.info();

  Serial.println(F("Please use Adafruit Bluefruit LE app to connect in Controller mode"));
  Serial.println(F("Then activate/use the sensors, color picker, game controller, etc!"));
  Serial.println();

  ble.verbose(false);  // debug info is a little annoying after this point!

  // Wait for connection 
  
 /* while (! ble.isConnected()) {
      delay(10);
  }
  */
  Serial.println(F("***********************"));

  // Set Bluefruit to DATA mode
  Serial.println( F("Switching to DATA mode!") );
  ble.setMode(BLUEFRUIT_MODE_DATA);

  Serial.println(F("***********************"));
   // Wait for new data to arrive 
   
}


void loop() {
  // put your main code here, to run repeatedly:
//confirm we made it to loop()
Serial.println("Well hello there loop()");

int reading = digitalRead(buttonPin);

  if (reading != lastButtonState){
    //reset the debouncing timer
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
  //debounce check
    if (reading != buttonState){
      buttonState = reading;//update buttonState
      if (buttonState == HIGH){
        //print button confirmation
        Serial.println("button toggled");
        mode++;//cycle the case on button press
      }
    }
  }
      if (mode <= 3){
        switch (mode) {
          case 0:
          //confirm we made it to case 0
          Serial.println("Hey look ma I made it to case 0");
          //case 0 is everything shut off
          ledState = 0;
          analogWrite(ledPin, ledState);
          break;
          case 1:
          Serial.println("Now we're in case 1");
          pixelBlinking();
          break;
          case 2:
          Serial.println("and case 2");
          // case 2 is led solid
          ledState = 255;
          analogWrite(ledPin, ledState);
          break;
          case 3:
          Serial.println("case 3, trying to connect to BLE");
          //case 3 enables neopixel color picking via BLE app
          //it currently sets the led at half brightness to show activity
          ledState = 127;
          analogWrite(ledPin, ledState);
          if (ble.isConnected()){
            Serial.println("BLE connected, running neopixel code");
            pixelColorPicker();
            break;
            // god I fucking hope this works, a long hold of the button will break the board out of the neopixel loop
            if (reading != lastButtonState){
              //reset the debouncing timer
              lastDebounceTime = millis();
            }
            if ((millis() - lastDebounceTime) > debounceDelay) {
            //debounce check
              if (reading != buttonState){
                buttonState = reading;//update buttonState
                if (buttonState == HIGH){
                  //print button confirmation
                  Serial.println("button toggled");
                  mode++;//cycle the case on button press
                }
              }
            }
          }
          else{
            Serial.println("No BLE, looping");
            break;
          }
        }
      
      }
      else {
        mode = 0;
      }
   
  lastButtonState = reading;

}

void pixelColorPicker(){
  Serial.println("we in the neopixel world now");
   /* Wait for new data to arrive */
  uint8_t len = readPacket(&ble, BLE_READPACKET_TIMEOUT);
  if (len == 0) return;

  /* Got a packet! */
  // printHex(packetbuffer, len);

  // Color
  if (packetbuffer[1] == 'C') {
    uint8_t red = packetbuffer[2];
    uint8_t green = packetbuffer[3];
    uint8_t blue = packetbuffer[4];
    Serial.print ("RGB #");
    if (red < 0x10) Serial.print("0");
    Serial.print(red, HEX);
    if (green < 0x10) Serial.print("0");
    Serial.print(green, HEX);
    if (blue < 0x10) Serial.print("0");
    Serial.println(blue, HEX);

    for(uint8_t i=0; i<NUMPIXELS; i++) {
      pixel.setPixelColor(i, pixel.Color(red,green,blue));
    }
    pixel.show(); // This sends the updated pixel color to the hardware.
  }
}

void pixelBlinking(){
  currentMillis = millis();
  if (currentMillis - blinkingMillis >= blinkInterval) {
            // save the last time you blinked the LED
            blinkingMillis = currentMillis;

            // if the LED is off turn it on and vice-versa:
            if (ledState == 0) {
              ledState = 255;
            } else {
              ledState = 0;
            }
          // set the LED with the ledState of the variable:
          analogWrite(ledPin, ledState);
         }
}

Uhm, you where still reading the state ::slight_smile: Code isn't stuck in a case, rest of the loop() still does it's bit. So now you simply read the button twice per loop() when you are in mode 3. Aka, not useful :wink: