Sketch runs fine on usb @ 3.6V but not from 18650 @ 3.8V+

Hi,

I have a ws2812b 120 led strip driven by an arduino nano for my led staff project.
it has 2 hardware interrupt buttons that either turn all leds white for 5 seconds, multiple presses will increment time by a further 5 seconds til it reverts back to the led patterns. the other changes the brightness of the led strip between 4 different intensity settings.

when powered by laptop usb the voltage measured at Vin = 3.6 ~ 3.9v
when powered by usb from usb wall charger Vin = 2.9 ~ 3.4
when powered by 2500mAh 18650 Vin = 3.8 ~ 3.9v (batt 3.95v when isolated from circuit)

the voltage variance depends on which pattern is currently running.

When powered by battery the code will hang up when either of the buttons are pressed.
the arduino boots up to the dimmest of the 4 intensity setings,

The code is the fastled example named demoreel, with only additions to faciltate function chnges when buttons are pressed.

Any ideas why the code doesnt run properly when its powered by batteries that maintain a higher voltage than pc usb or usb wall charger?

// works with miniscule flash
#include <FastLED.h>

FASTLED_USING_NAMESPACE

// FastLED "100-lines-of-code" demo reel, showing just a few 
// of the kinds of animation patterns you can quickly and easily 
// compose using FastLED.  
//
// This example also shows one easy way to define multiple 
// animations patterns and have them automatically rotate.
//
// -Mark Kriegsman, December 2014

#if defined(FASTLED_VERSION) && (FASTLED_VERSION < 3001000)
#warning "Requires FastLED 3.1 or later; check github for latest code."
#endif
volatile int Torch = 1;
#define DATA_PIN    A0
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS    10
CRGB leds[NUM_LEDS];

#define BRIGHTNESS          20
#define FRAMES_PER_SECOND  120
const byte interruptPin = 3;
const byte interruptPin2 = 2;
volatile int lumins = 1;

void setup() {
 
  delay(3000); // 3 second delay for recovery
   Serial.begin(9600);

  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, FALLING);
  pinMode(interruptPin2, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin2), blinky, FALLING);
  
  // tell FastLED about the LED strip configuration
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  //FastLED.addLeds<LED_TYPE,DATA_PIN,CLK_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);

  // set master brightness control
  FastLED.setBrightness(BRIGHTNESS);
}

// List of patterns to cycle through.  Each is defined as a separate function below.
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = { rainbow, bpm, rainbowWithGlitter, confetti, sinelon, juggle, };

uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current
uint8_t gHue = 0; // rotating "base color" used by many of the patterns
  
void loop(){
  Serial.print("Torch ");
  Serial.print(Torch);
  Serial.print("   lumins " );
  Serial.println(lumins);
  if (lumins == 1){    FastLED.setBrightness(20);    }
  if (lumins == 2){    FastLED.setBrightness(60);    } 
  if (lumins == 3){    FastLED.setBrightness(90);    }
  if (lumins == 4){    FastLED.setBrightness(150);   }
  if (lumins > 4){lumins = 1;}
  // Call the current pattern function once, updating the 'leds' array
  if (Torch > 1){
     fill_solid( leds, 120, CRGB::White);
     FastLED.delay(1000);
     Torch = Torch - 1;}
  else {
     gPatterns[gCurrentPatternNumber]();
     // send the 'leds' array out to the actual LED strip
      FastLED.show();  
     // insert a delay to keep the framerate modest
     FastLED.delay(1000/FRAMES_PER_SECOND); 
  }
  // do some periodic updates
  EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
  EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically
}

#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))

void nextPattern()
{
  // add one to the current pattern number, and wrap around at the end
  gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}
void blink() {
  static unsigned long last_interrupt_time2 = 0;
  unsigned long interrupt_time2 = millis();
  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time2 - last_interrupt_time2 > 500) {
        fill_solid( leds, 120, CRGB::White);
        if (Torch < 100){    Torch = Torch + 5;    }
  last_interrupt_time2 = interrupt_time2;
    }
}
void blinky() {
  static unsigned long last_interrupt_time1 = 0;
  unsigned long interrupt_time1 = millis();
  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time1 - last_interrupt_time1 > 500) {lumins = (lumins + 1);
  }
  last_interrupt_time1 = interrupt_time1;
}

}

Vin, as its name suggests is intended to provide voltage to the Arduino which would normally be between 7V and 12V, but that depends on the exact board being used. The voltage is then regulated down to the voltage required by the board.

As such, the voltage on the pin when the board is powered by USB is irrelevant

Which Arduino board do you have ?

The voltage on the 5V pin is what matters. Vin is designed for 7V or more only.

The board is an Arduino nano.

I've had a wee discovery, when i set the number of leds to only 30, rather than 120 the program runs.
this suggest to me that the voltage is dipping belong the working voltage for an instant hanging up the sketch.

Do you think adding a capcitor across the supply might give it the drop out protection it needs?
...I assumed the 18650 batteries would be able to keep up with the instantaneous current demand..(as said earlier the lower current/voltage pc usb supply keeps up.)

should i change the input power from Vin to the 5v pin?

Are you sure the battery pack can handle that load? At all white, that LED strip would draw 7.2 amps, which is a pretty big load on a single 18650 cell. It's very possible that the voltage briefly collapses (it's also quite possible that you are damaging the cell).

Changed voltage input from Vin to 5v pin. problem solved. thanks!!

Generally the led brightness is set to about 20 of 255, hopefully that doesnt exceed draw excessive current.
I've just hot glued the pcb back into the stick just before reading this now, so I cant measure draw on the battery (at different brightness levels).

It would be better to power the Nano from the 18650 via a boost converter so that the Arduino had a consistent 5V input, and to power the LEDs directly from the 18650 so that the current drawn does not affect the voltage available to the Nano

UKHeliBob:
It would be better to power the Nano from the 18650 via a boost converter so that the Arduino had a consistent 5V input, and to power the LEDs directly from the 18650 so that the current drawn does not affect the voltage available to the Nano

When doing that, I recommend using a logic shifter on the data line. The WS2812 datasheet says absolute maximum for Logical Input Voltage is VDD+0.7 V, so if you're powering the WS2812 at 3.9 V and running the Nano at 5 V you're well beyond the absolute maximum.

in the previous design i had a 0.9 - 5v to 5v boost converter, running off of a single 1.5v AA batttery, it would last about 4 hours with half as many leds on an a premium range battery. I have not been able to find a replacement module capable of passing enough current while still being very small. the elecronics is mounted in the handle of the stick and there is very little room for extra components.

since both the arduino and ws2812 are powered by the same source vin = vdd, im not using a boost converter in the new stick.