Urgent question regarding neopixels

Ok so I have a sketch that runs some neopixel strips in a chaser fill type of thing. It all works great on the breadboard but in the actual unit it goes in I have an issue where the arduino slows down to probably one update in the time that it usually updates the whole strip of leds. It use's switch cases and it seems to only effect the 'RUNNING' switch case. The Boot and Shutdown all animate normally.

What could be the issue?

#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#include <Adafruit_NeoPixel.h>


//Pin set ups//
#define WandLED_PIN    4           //Wand Neopixel Data OUTPUT
#define PowerCellLED_PIN    2       //Powercell Neopixel Data OUTPUT
#define Cyclotron_PIN  3              //Cyclotron Data Pin OUTPUT
#define WandBar_PIN    9       //Powercell Neopixel Data OUTPUT


// ******************* inputs for switches and buttons ******************* /
const int STARTWAND_SWITCH = 6;           //Wand On Switch INPUT
const int STARTPACK_SWITCH = 5;           //Pack On Switch INPUT
const int MUSIC_SWITCH = 8;               //Music On Switch INPUT
const int FIRE_BUTTON = 7;                //Wand Fire Button INPUT
const int RUMBLE = 13;                    //Output to rumble motor OUTPUT If Required
const int BUSY_PIN = 12;          //Busy Pin Monitor If Required

//**CYCLOTRON**********
#define PixelCount 40  //LED count

int position = 0;
unsigned long precyclotronmillis = 0;
unsigned long cyclotronSpeed = 500L; //set cyclotron spin speed

//**POWERCELL**********
#define PowercellLED_COUNT 16

unsigned long PCPreviousMillis = 0;        // Previous Pixel Millis
unsigned long PCMillis = 0;                 // Current Pixel Millis
int           IdleRamppixelInterval = 66L;       // Idle Pixel Interval (ms)
int           WarnRamppixelInterval = 16L;       // Warning Pixel Interval (ms)
uint16_t      PCpixelCurrent = PowercellLED_COUNT;         // Pattern Current Pixel Number

//**WANDBAR**********
#define WandBarLED_COUNT 6

unsigned long WBPreviousMillis = 0;        // Previous Pixel Millis
unsigned long WBMillis = 0;                 // Current Pixel Millis
int           IdleWBpixelInterval = 200L;       // Idle Pixel Interval (ms)
int           WarnWBpixelInterval = 50L;       // Warning Pixel Interval (ms)
uint16_t      WBpixelCurrent = 0;         // Pattern Current Pixel Number



//***Wand Tip FIRE****
#define Wandfire_COUNT 15
int wandbrightness = 128;
//****Wand Fire Control*****


//********PIXEL STRIPS*************
Adafruit_NeoPixel strip_cyclotron = Adafruit_NeoPixel(PixelCount, Cyclotron_PIN, NEO_GRB + NEO_KHZ800); //CYCLOTRON RING
Adafruit_NeoPixel strip_wandbar = Adafruit_NeoPixel(WandBarLED_COUNT, WandBar_PIN, NEO_GRB + NEO_KHZ800); //Wand Bar Graph
Adafruit_NeoPixel strip_powercell = Adafruit_NeoPixel(PowercellLED_COUNT, PowerCellLED_PIN, NEO_GRB + NEO_KHZ800); //Powercell Bar
Adafruit_NeoPixel strip_wandfire = Adafruit_NeoPixel(Wandfire_COUNT, WandLED_PIN, NEO_GRB + NEO_KHZ800); //wandtip firing

//**DFPlayer**********************************************************************************************************************************************************
SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;

// Audio Tracks - Note DFPlayer is sensitive to file order
unsigned long Pack_startup = 1;
unsigned long Pack_running = 2;
unsigned long Pack_shutdown = 3;
unsigned long Wand_start = 4;
unsigned long Wand_on = 5;
unsigned long Wand_off = 6;
unsigned long Warning = 7;
unsigned long GB_Theme = 8;

//****Pack Status
enum PackState { OFF, BOOTING, RUNNING, FIRE, WARNING, MUSIC, SHUTDOWN};
enum PackState STATUS;

unsigned long currenttrack = 1;
unsigned long starttracklength = 3400;
unsigned long startfiringlength = 2082;
unsigned long stopfiringlength = 2891;

// ******************* Pack states or logic variables ******************* /
bool PowerOn = false; //pack is running
bool PackStarted = false; //pack is booted
bool IsFiring = false; //Is fire button pressed
bool ShutdownRunning = false; //pack closing down
bool WarningOn = false; //Warning sound is playing
bool HumIsPlaying = false; //Pack Hum is playing
bool MusicOn = false; //Theme on
bool Not_Busy = false; //DFPlayer Busy?
bool ShuttingDown = false; //Is pack shutting down?

// ******************* physical switch states ******************* /
bool startpack = false;
bool startwand = false;
bool packidle = false;
bool musicstart = false;
bool fire = false;
bool fireButtonState = false;
bool IsPlaying = false;

//****Call tabs****
void cyclotronspin();
void PowercellRamp();
void PowercellWarn();
void Wandfire();
void WandBarON();
void BootPack();
void starthum();
void WandBarWarn();

//****Millis Variables************
unsigned long currentMillis = 0;
unsigned long bootMillis = 0;
unsigned long fireMillis = 0;
unsigned long stopfireMillis = 0;
unsigned long shutdownMillis = 10800000;
/*****************
  /*************************************************************************
                                 SETUP Function
 *************************************************************************/
void setup()
{
  //*************
  //DFPLAYER Setup
  //*************

  // ***** Start Communication with the DFPlayer ***** //
  mySoftwareSerial.begin(9600);
  Serial.begin(115200);
  myDFPlayer.begin(mySoftwareSerial);
  myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);

  //----Set volume----
  myDFPlayer.volume(29);  //Set volume value (0~30).

  // ***** Assign Proton Pack Switches / Buttons & Outputs***** //
  pinMode(STARTWAND_SWITCH, INPUT_PULLUP);
  pinMode(STARTPACK_SWITCH, INPUT_PULLUP);
  pinMode(MUSIC_SWITCH, INPUT_PULLUP);
  pinMode(FIRE_BUTTON, INPUT_PULLUP);
  pinMode(RUMBLE, OUTPUT);
  pinMode(PowerCellLED_PIN, OUTPUT);
  pinMode(Cyclotron_PIN, OUTPUT);
  pinMode(WandLED_PIN, OUTPUT);
  pinMode(WandBar_PIN, OUTPUT);
  pinMode(BUSY_PIN, INPUT_PULLUP);



  //----Mp3 play----

  // myDFPlayer.play(1);  //Play the first mp3
  //  delay(1000);
  //  myDFPlayer.loop(1);  //Loop the first mp3
  //  delay(1000);
  //  myDFPlayer.enableLoop(); //enable loop.
  //  delay(1000);
  //  myDFPlayer.disableLoop(); //disable loop.
  //  delay(1000);

  //***************
  //Cyclotron setup
  //***************

  strip_cyclotron.begin();
  strip_powercell.begin();
  strip_wandbar.begin();
  strip_wandfire.begin();
  strip_wandfire.setBrightness(wandbrightness);

  //*********
  //Wand Fire setup
  //*********
  strip_wandfire.show();

  //Pack Setup

  delay (200); //sanity wait
}

//LED Colours
uint32_t colour = 0xFF0000; // Default to Red
uint32_t colour1 = 0xCC0000; // Default to fade1
uint32_t colour2 = 0xA30000; // Default to fade2
uint32_t colour3 = 0x820000; // Default to max fade

uint32_t colourPC1 = 0x0000CD; // Powercell Blue
uint32_t colourPC2 = 0x87CEFA; // Powercell Warning
uint32_t colourWB = 0xFFE000; // Wandbar Yellow
uint32_t colourOW = 0xFF3800;//Orange

//reset strips
strip_cyclotron.fill(0);  //fill cyclotron ring with black
strip_powercell.fill(0);  //fill powercell strip with black
strip_wandbar.fill(0);    //fill wandbar with black
strip_cyclotron.show();   //show black
strip_powercell.show();   //show black
strip_wandbar.show();     //show black



void loop()
{
  // put your main code here, to run repeatedly:

  // Check Wand Switch Status
  startwand = digitalRead(STARTWAND_SWITCH);
  startpack = digitalRead(STARTPACK_SWITCH);
  musicstart = digitalRead(MUSIC_SWITCH);
  fire = digitalRead(FIRE_BUTTON);
  Not_Busy = digitalRead(BUSY_PIN);

  //Set Light Speeds and Colours*********************



  if (IsFiring == true) cyclotronSpeed = 75L;
  if (PackStarted == true && IsFiring == false) cyclotronSpeed = 150L;
  if (PackStarted == false) cyclotronSpeed = 300L;

  //All switches are LOW if activated!**************


  //**********

  switch (STATUS) {
    case OFF:   //Pack STARTUP//
      Serial.println("OFF");
      if (startpack == LOW) {
        bootMillis = millis();
        cyclotronspin(); //start cyclotron LED ring at idle speed
        PowercellRamp(); //ramp up powercell LED strip
        BootPack();
      }
      break;


    case BOOTING:
      Serial.println("BOOTING");
      cyclotronspin(); //start cyclotron LED ring at idle speed
      PowercellRamp(); //ramp up powercell LED strip
      if ((millis() - bootMillis) > 2000)
        PackStarted = true;
      //  if (digitalRead(BUSY_PIN) == HIGH)
      if ((millis() - bootMillis) > 2500)
        starthum();
      break;


    case RUNNING:
      Serial.println("RUNNING");
      WandBarON();
      WarningOn = false;
      IsFiring = false;
      cyclotronspin(); //start cyclotron LED ring at idle speed
      PowercellRamp(); //ramp up powercell LED strip
      if (startpack == HIGH) {
        Serial.println("Switch is Off");
        ShuttingDown = true;
        STATUS = SHUTDOWN;
        break;
      }
      if (fire == LOW) {
        STATUS = FIRE;
        IsFiring = true;
        fireMillis = millis();
        break;
      }
      if ((fireMillis - millis()) > 2891) {
        starthum();
        fireMillis = 0;
      }
      if (musicstart == LOW) STATUS = MUSIC;
      break;


    case MUSIC:
      Serial.println("MUSIC");
      WarningOn = false;
      IsFiring = false;
      WandBarON();
      PowercellRamp(); //ramp up powercell LED strip
      cyclotronspin(); //start cyclotron LED ring at idle speed
      myDFPlayer.play(GB_Theme);
      if (musicstart == HIGH) {
        STATUS = RUNNING;
        fireMillis = 10000;
        starthum();
        break;
      }
      break;


    case FIRE:
      Serial.println("FIRE");
      if ((millis() - fireMillis) >= 10000) {
        WarningOn = true;
      }
      cyclotronspin(); //start cyclotron LED ring at fast speed
      WandBarON();
      if (WarningOn == false) {
        PowercellRamp(); //ramp up powercell LED strip
        Wandfire();
        myDFPlayer.play(Wand_start);
      }
      if (WarningOn == true) {
        STATUS = WARNING;
        break;
      }
      if (startpack == HIGH) {
        STATUS = SHUTDOWN;
        ShuttingDown = true;
        break;
      }
      if (fire == HIGH && fireMillis >= 2000) {
        Serial.println("WandOff");
        strip_wandfire.fill(0);
        strip_wandfire.show();
        STATUS = RUNNING;
        myDFPlayer.play(Wand_off);
        fireMillis = millis;
        break;
      }
      break;

    case WARNING:
      Serial.println("WARNING");
      Wandfire();
      WandBarWarn();
      myDFPlayer.play(Warning);
      PowercellWarn(); //ramp up powercell LED strip
      cyclotronspin(); //start cyclotron LED ring at fast speed
      if (startpack == HIGH) {
        STATUS = SHUTDOWN;
        ShuttingDown = true;
        break;
      }
      if (fire == HIGH) {
        strip_wandfire.fill(0);
        strip_wandfire.show();
        STATUS = RUNNING;
        myDFPlayer.play(Wand_off);
        break;
      }
      break;

    case SHUTDOWN:
      Serial.println("SHUTDOWN");
      if (ShuttingDown == true)
      {
        myDFPlayer.play(Pack_shutdown);  //play shutdown sound (approx 3 seconds long)
        shutdownMillis = millis();       //store when sound begins
        ShuttingDown = false;            //set trigger so loop is not triggered next time around
      }
      cyclotronspin(); //keep ring on
      PowercellRamp(); //keep strip on
      if ((millis() - shutdownMillis) > 3000)  //count to 3 seconds
      { Serial.println("SHUTDOWN MILLIS");
        strip_cyclotron.fill(0);  //fill cyclotron ring with black
        strip_powercell.fill(0);  //fill powercell strip with black
        strip_cyclotron.show();   //show black
        strip_powercell.show();   //show black
        strip_wandbar.fill(0);
        strip_wandbar.show();
        PCpixelCurrent = 0;
        STATUS = OFF;     //set pack status off
        shutdownMillis = 0;   //reset for next turn on
        HumIsPlaying = false;
        WarningOn = false;
        IsFiring = false;
        PackStarted = false;
        MusicOn = false;
        PCpixelCurrent = PowercellLED_COUNT;
        break;
      }
  }
}

Which Arduino?
When it's in the enclosure, is USB still connected to your computer?

Your code is unfortunately too big to check on a cell phone. Will try if I can find time later.

Note: a schematic how everything is connected would be useful.

Its an Arduino nano. No the USB isn't connected, it worked fine on the breadboard when externally powered as well as through the USB. The resistor and capacitor across the neopixel strip is a little further away from the strip in the unit than on the breadboard but is still within 30cm of the strip. Would that make a difference?

5V to the Nano must be wired to the 5V pin, which can be either in or output - NOT to Vin, which is intended for >7V sources.

Ah cool, it ran ok on the breadboard going into the VIN but its worth a try for sure.

if you had USB plugged in, that powers the board happily, so it would mask your problem.

I didn't have the USB plugged in. I could power it either way and it was fine on the breadboard.

Let us know when you've changed it.

Ok well I changed it and it made no difference, the boot case worked fine and the shutdown worked fine but the running case didn't.

Don't change it back; now we can debug the rest without wondering...

Too bad, but at least an unknown has been eliminated from the equation.

Usually at this point, it's photos of the hardware that lead to a breakthrough...

Also what 5V power supply are you using?

I can't do any more right now as I am working however I will add in the capacitors and move the resistors closer to the neopixels at this point to eliminate that. It is odd however that it only seems to occur in the 'RUNNING' case but on the breadboard it worked fine.

Also the power supply in the breadboard was a regulated 5V 3A plug in transformer, in the unit it was an 18V powertool battery running into a step down converter with a 5V 3A output. I intend to remove the converter and swap in the original transformer to test that as well.

It's tempting to draw conclusions from odd behaviour, but then all you really have are odd conclusions. :slight_smile:

If you want to mine something from that observation, you need to ask yourself what is different about RUNNING.

It is a really bad idea to switch off the negative rail while still pumping data into the strip. It is probably the series data resistors that is stopping you seeing more problems.

Applying signals to almost any IC that is not correctly powered up can be the cause of latch up and damage to the IC.

Why do you need to turn off the power to the strips in the first place?

I'm not switching off the negative rail at any point in proceedings, in fact the circuit won't allow me to do that physically as its hard wired to maintain the negative?

The stepdown converter is an obvious suspect. Did you measure the output voltage?

1 Like

Now we may be getting somewhere. Please provide a link to the exact stepdown converter used. I have some "3A" converters set to 5V that start to 'droop' at around 2 A, and shutdown well before 3A. Essentially, I wouldn't use them beyond 1.5A.
I'd be testing that one first thing.

I measured 4.98V.

Here is the converter - SY8205

under what conditions?

Just connected to the battery.