Code freezes when independently powered

Hi

I'm running a Arduino Mega 2560 with 3 D (1.5V) batteries in series, which is wired to power 5 Neopixel LED strips and the arduino. They are all in parallel to the power. When the arduino is powered by a USB cable to my computer, the code runs fine.

However, when I detach my computer, hook up the power to the arduino, the code will run for a bit then freeze. It runs for an inconsistent number of the numLoops loop - anywhere from 2-12 before freezing. Once turned off and back on again it'll start running for a bit then freeze. Is this a code or hardware issue?

Help appreciated. I can also draw a circuit diagram if it's helpful/a hardware issue.

#include "FastLED.h"



#define PIN 6
#define PINouter 13
#define PINinner 11
#define PINbottom 7
#define PINtop 2
#define PINcenter 4

#define numOuter 81
#define numInner 64
#define numBottom 46
#define numTop 45
#define numCenter 17
#define numStrips 5
CRGB LED[numStrips][numOuter]; //outer

uint16_t stripSizeArray[] = {numOuter, numInner, numBottom, numCenter, numTop}; 
void setup() {
  FastLED.addLeds<NEOPIXEL, 13>(LED[0], numOuter);
  FastLED.addLeds<NEOPIXEL, 11>(LED[1], numInner);
  FastLED.addLeds<NEOPIXEL, 7>(LED[2], numBottom);
  FastLED.addLeds<NEOPIXEL, 4>(LED[3], numCenter);
  FastLED.addLeds<NEOPIXEL, 2>(LED[4], numTop);
  
}
void loop() {
  walkingPokeBall(10);
}

//Lights up a pokeball, with two pixels bouncing on the outer rim. 
void walkingPokeBall(uint32_t wait){
  // fill the pokeball with base red and white. 
  for(int numLoops = 0; numLoops < 20; numLoops++) {
  fill_solid( (LED[4]), numTop, CHSV(0,255,255));
  fill_solid( (LED[2]), numBottom, CHSV(255,0,100));
  fill_solid( (LED[3]), numCenter, CHSV(255,0,150));
  fill_solid( (LED[1]), numInner, CHSV(255,0,50));
  for(uint8_t i=16; i<49;i++){
    LED[1][i] = CHSV(0,255,50); // use less bright red on the inner outline.
  }

  //the next section sets the bouncing pixels across the outer rims
  
  for(int i = 0; i < 38; i++) {
        // set our current dot to red
    if (i <20){
      
      LED[0][20-i] = CRGB::White; 
      LED[0][20-i-1] = CRGB::White;
      LED[0][20+i] = CRGB::Red;
      LED[0][20+i+1] = CRGB::Red;
    }
    else {
      LED[0][100-i] = CRGB::White;
      LED[0][20+i] = CRGB::Red; 
      LED[0][100-i-1] = CRGB::White;
      LED[0][20+i+1] = CRGB::Red; 
      }
  FastLED.show();
    delay(wait);
    // turn off the pixel.
    if (i <20){
      LED[0][20-i] = CRGB::Black; 
      LED[0][20+i] = CRGB::Black;
       LED[0][20-i-1] = CRGB::Black; 
      LED[0][20+i+1] = CRGB::Black;
    }
    else {
      LED[0][100-i] = CRGB::Black;
      LED[0][20+i] = CRGB::Black; 
      LED[0][100-i-1] = CRGB::Black;
      LED[0][20+i+1] = CRGB::Black;
      }
    
  }
  // make the pixel go back the other way.
  for(uint8_t i = 0; i < 40; i++) {
    if (i <20){
      LED[0][60+i] = CRGB::White; 
      LED[0][59-i] = CRGB::Red;
      LED[0][60+i+1] = CRGB::White; 
      LED[0][59-i-1] = CRGB::Red;
    }
    else {
      LED[0][i-20] = CRGB::White;
      LED[0][59-i] = CRGB::Red; 
       LED[0][i-20-1] = CRGB::White;
      LED[0][59-i-1] = CRGB::Red; 
      }
  FastLED.show();
    delay(wait);
    // turn off the pixel.
    if (i <20){
      LED[0][60+i] = CRGB::Black; 
      LED[0][59-i] = CRGB::Black;
      LED[0][60+i+1] = CRGB::Black; 
      LED[0][59-i-1] = CRGB::Black;
    }
    else {
      LED[0][59-i] = CRGB::Black;
      LED[0][i-20] = CRGB::Black; 
      LED[0][i-20-1] = CRGB::Black;
      LED[0][59-i-1] = CRGB::Black; 
      }
  }
  }
}


Put some code into that loop which flashes the built-in led on the Mega. This will tell you more reliably if the code has frozen or the code is still running but the strips have stopped responding.

I added a blink on/off after each FastLED.show() and it does freeze the board LED. Interestingly, the addition of the blink is causing the LED[0][0] to light up green in sync with the arduino board LED, and the the LED[0][20-i-2] to also light up green. Could this be a grounding thing? Each of the strips is connected to the negative battery terminal and the arduino ground.

#include "FastLED.h"



#define PIN 6
#define PINouter 13
#define PINinner 11
#define PINbottom 7
#define PINtop 2
#define PINcenter 4

#define numOuter 81
#define numInner 64
#define numBottom 46
#define numTop 45
#define numCenter 17
#define numStrips 5
CRGB LED[numStrips][numOuter]; //outer

uint16_t stripSizeArray[] = {numOuter, numInner, numBottom, numCenter, numTop}; 
void setup() {
  FastLED.addLeds<NEOPIXEL, 13>(LED[0], numOuter);
  FastLED.addLeds<NEOPIXEL, 11>(LED[1], numInner);
  FastLED.addLeds<NEOPIXEL, 7>(LED[2], numBottom);
  FastLED.addLeds<NEOPIXEL, 4>(LED[3], numCenter);
  FastLED.addLeds<NEOPIXEL, 2>(LED[4], numTop);
  
}
void loop() {
  walkingPokeBall(10);
}

//Lights up a pokeball, with two pixels bouncing on the outer rim. 
void walkingPokeBall(uint32_t wait){
  // fill the pokeball with base red and white. 
  for(int m = 0; m < 20; m++) {
  fill_solid( (LED[4]), numTop, CHSV(0,255,255));
  fill_solid( (LED[2]), numBottom, CHSV(255,0,100));
  fill_solid( (LED[3]), numCenter, CHSV(255,0,150));
  fill_solid( (LED[1]), numInner, CHSV(255,0,50));
  for(uint8_t i=16; i<49;i++){
    LED[1][i] = CHSV(0,255,50); // use less bright red on the inner outline.
  }

  //the next section sets the bouncing pixels across the outer rims
  
  for(int i = 0; i < 38; i++) {
        // set our current dot to red
    if (i <20){
      
      LED[0][20-i] = CRGB::White; 
      LED[0][20-i-1] = CRGB::White;
      LED[0][20+i] = CRGB::Red;
      LED[0][20+i+1] = CRGB::Red;
    }
    else {
      LED[0][100-i] = CRGB::White;
      LED[0][20+i] = CRGB::Red; 
      LED[0][100-i-1] = CRGB::White;
      LED[0][20+i+1] = CRGB::Red; 
      }
  FastLED.show();
  digitalWrite(LED_BUILTIN, HIGH);
    delay(wait);
    // turn off the pixel.
    if (i <20){
      LED[0][20-i] = CRGB::Black; 
      LED[0][20+i] = CRGB::Black;
       LED[0][20-i-1] = CRGB::Black; 
      LED[0][20+i+1] = CRGB::Black;
    }
    else {
      LED[0][100-i] = CRGB::Black;
      LED[0][20+i] = CRGB::Black; 
      LED[0][100-i-1] = CRGB::Black;
      LED[0][20+i+1] = CRGB::Black;
      }
    
  }
  // make the pixel go back the other way.
  for(uint8_t i = 0; i < 40; i++) {
    if (i <20){
      LED[0][60+i] = CRGB::White; 
      LED[0][59-i] = CRGB::Red;
      LED[0][60+i+1] = CRGB::White; 
      LED[0][59-i-1] = CRGB::Red;
    }
    else {
      LED[0][i-20] = CRGB::White;
      LED[0][59-i] = CRGB::Red; 
       LED[0][i-20-1] = CRGB::White;
      LED[0][59-i-1] = CRGB::Red; 
      }
  FastLED.show();
  digitalWrite(LED_BUILTIN, LOW); 
    delay(wait);
    // turn off the pixel.
    if (i <20){
      LED[0][60+i] = CRGB::Black; 
      LED[0][59-i] = CRGB::Black;
      LED[0][60+i+1] = CRGB::Black; 
      LED[0][59-i-1] = CRGB::Black;
    }
    else {
      LED[0][59-i] = CRGB::Black;
      LED[0][i-20] = CRGB::Black; 
      LED[0][i-20-1] = CRGB::Black;
      LED[0][59-i-1] = CRGB::Black; 
      }
  }
  }
}

Ah, I didn't spot that one of your strips is connected to pin 13. That's also the pin for LED_BUILTIN. So either attach an ordinary led to another pin and blink that instead of LED_BUILTIN, or preferably move the strip to another pin so that you can use LED_BUILTIN.

The digitalWrite(LED_BUILTIN, ...) functions will be interfering with the data going to the strip, causing the effects you mentioned. And the reverse problem, the data going to the strip will make the led blink.

You should have pinMode(LED_BUILTIN, OUTPUT) in setup().

Before you post your code again, please perform Tools->Auto Format

Hi,

I changed the pin number and ran format. It is still freezing, but the green light is gone as you say.

#include "FastLED.h"

#define PINouter 12
#define PINinner 10
#define PINbottom 7
#define PINtop 2
#define PINcenter 4

#define numOuter 81
#define numInner 64
#define numBottom 46
#define numTop 45
#define numCenter 17
#define numStrips 5
CRGB LED[numStrips][numOuter]; //outer

uint16_t stripSizeArray[] = {numOuter, numInner, numBottom, numCenter, numTop};
void setup() {
  FastLED.addLeds<NEOPIXEL, 12>(LED[0], numOuter);
  FastLED.addLeds<NEOPIXEL, 10>(LED[1], numInner);
  FastLED.addLeds<NEOPIXEL, 7>(LED[2], numBottom);
  FastLED.addLeds<NEOPIXEL, 4>(LED[3], numCenter);
  FastLED.addLeds<NEOPIXEL, 2>(LED[4], numTop);
  pinMode(LED_BUILTIN, OUTPUT);

}
void loop() {
  walkingPokeBall(10);
}

//Lights up a pokeball, with two pixels bouncing on the outer rim.
void walkingPokeBall(uint32_t wait) {
  // fill the pokeball with base red and white.
  for (int m = 0; m < 20; m++) {
    fill_solid( (LED[4]), numTop, CHSV(0, 255, 255));
    fill_solid( (LED[2]), numBottom, CHSV(255, 0, 100));
    fill_solid( (LED[3]), numCenter, CHSV(255, 0, 150));
    fill_solid( (LED[1]), numInner, CHSV(255, 0, 50));
    for (uint8_t i = 16; i < 49; i++) {
      LED[1][i] = CHSV(0, 255, 50); // use less bright red on the inner outline.
    }

    //the next section sets the bouncing pixels across the outer rims

    for (int i = 0; i < 38; i++) {
      // set our current dot to red
      if (i < 20) {

        LED[0][20 - i] = CRGB::White;
        LED[0][20 - i - 1] = CRGB::White;
        LED[0][20 + i] = CRGB::Red;
        LED[0][20 + i + 1] = CRGB::Red;
      }
      else {
        LED[0][100 - i] = CRGB::White;
        LED[0][20 + i] = CRGB::Red;
        LED[0][100 - i - 1] = CRGB::White;
        LED[0][20 + i + 1] = CRGB::Red;
      }
      FastLED.show();
      digitalWrite(LED_BUILTIN, HIGH);
      delay(wait);
      // turn off the pixel.
      if (i < 20) {
        LED[0][20 - i] = CRGB::Black;
        LED[0][20 + i] = CRGB::Black;
        LED[0][20 - i - 1] = CRGB::Black;
        LED[0][20 + i + 1] = CRGB::Black;
      }
      else {
        LED[0][100 - i] = CRGB::Black;
        LED[0][20 + i] = CRGB::Black;
        LED[0][100 - i - 1] = CRGB::Black;
        LED[0][20 + i + 1] = CRGB::Black;
      }

    }
    // make the pixel go back the other way.
    for (uint8_t i = 0; i < 40; i++) {
      if (i < 20) {
        LED[0][60 + i] = CRGB::White;
        LED[0][59 - i] = CRGB::Red;
        LED[0][60 + i + 1] = CRGB::White;
        LED[0][59 - i - 1] = CRGB::Red;
      }
      else {
        LED[0][i - 20] = CRGB::White;
        LED[0][59 - i] = CRGB::Red;
        LED[0][i - 20 - 1] = CRGB::White;
        LED[0][59 - i - 1] = CRGB::Red;
      }
      FastLED.show();
      digitalWrite(LED_BUILTIN, LOW);
      delay(wait);
      // turn off the pixel.
      if (i < 20) {
        LED[0][60 + i] = CRGB::Black;
        LED[0][59 - i] = CRGB::Black;
        LED[0][60 + i + 1] = CRGB::Black;
        LED[0][59 - i - 1] = CRGB::Black;
      }
      else {
        LED[0][59 - i] = CRGB::Black;
        LED[0][i - 20] = CRGB::Black;
        LED[0][i - 20 - 1] = CRGB::Black;
        LED[0][59 - i - 1] = CRGB::Black;
      }
    }
  }
}

Disconnect all the strips and run the Arduino on the batteries. Does it still freeze after a few flashes of the built in led? (I expect it will.)

I disconnected the strips and let the code run for an hour and it was fine blinking the arduino LED. (the strips freeze the code in <30 seconds). If its helpful the power to the arduino is wired into the 5V and the ground, even though the total voltage is only going to be 4.5V (3 1.5V in series).

I've also written a quick LEDChase that goes through all the strips and lights up a single pixel, which is fine when running. My animations that involve all of the LEDs e.g. a rainbow animation on all the strips at once don't run at all - they just freeze instantly when not connected to the computer (I used the pokeball just as example code for this post). Storage wise, memory doesn't seem to be a problem. Any thoughts? The storage numbers for my actual sketch including all my code is shown, not for just the pokeball - the pokeball sketch has lower numbers.

Sketch uses 17450 bytes (6%) of program storage space. Maximum is 253952 bytes.
Global variables use 1484 bytes (18%) of dynamic memory, leaving 6708 bytes for local variables. Maximum is 8192 bytes.

void loop() {
  //walkingPokeBall(10);
  LEDChase();
}

void LEDChase() {
  for (int k = 0; k < numStrips; k++) {
    for (int i = 0; i < 81; i++) {
      LED[k][i] = CRGB::Red;    // set our current dot to red
      FastLED.show();
      LED[k][i] = CRGB::Black;  // set our current dot to black before we continue
    }
  }
}

Sounds to me like it's a power problem.

pert:
Sounds to me like it's a power problem.

Absolutely agree.

~250 leds could draw up to 18A. No way can your D cells provide that. Most pattern/colour combinations will use far less, but the rainbow demo sketches will probably be around 1/3 of that, so 6A. Still considerably more than the D cells can manage, so not surprised the Arduino freezes. The voltage will drop to the point where the atmega chip will not run.

Try setting the overall brightness to a low value, like 16 or 32 (there is a FastLED function for this). Will it run with the D cells then? If so, increase the overall brightness until you find the point where the freezing starts happening again. Even then, as the batteries fade, it will freeze earlier and earlier.

Thanks! This solved the problem - I put new batteries in and I ran it at ~120 brightness and it's going fine. I'm going to do battery testing and then color calibration to see how long it works. Appreciate your help!

Great.

There's a basic electronics lesson here. Batteries have an internal resistance. It's always there, even in new, fully charged cells. The more current you draw from them, the more voltage is lost to the internal resistance, which lowers the output voltage. Big, low voltage cells like "D" size have a lower internal resistance than small or higher voltage cells like AAA or PP3, but it is still there and affects the output voltage.

Another lesson is the "surprisingly" (to a beginner) high currents that NeoPixel strips draw! Up to 60mA per led, so one NeoPixel can draw as much as the Arduino.

One more lesson: buy a multimeter, if you don't already have one. For a beginner, a £10 meter is fine and will measure all kinds of useful things like voltage, current, resistance...

Trying to power the things with a high current (up to 4A available) powerbank. More stable and eco friendly. Plus: you can charge your phone :wink:

Thanks. One thing we're going to try is powering the arduino separately from the pixels with its own battery, and observing the color distortion of the LEDs over time to see how much longer we can get out of the batteries if the Arduino itself doesn't freeze/reset. So far, at half brightness and the arduino connected it lasts for 2 hr. Our ideal case is 4 hr to replace the batteries, as we want it to last a total of 8-9 hr. I'm also going to add more filler animations with less LEDs on, and also eventually intend to add sound reactiveness so those should also reduce energy consumption.

I do have a multimeter, although its one that seems to act funky. My friend (who is providing the materials) is having me help him since I've some past experience with microelectronics and am a software engineer. So far I've mainly used it just to check connections.

To charge with a powerbank do you just strip a USB cable? For this specific use case though, we're sticking with batteries (music festival) as replaceable things/disposable are preferable just incase bad things happen, and the amount of time we need it on is pretty long.