SOLVED: Project only works when Nano is powered via laptop USB

Hello. I have read as many threads as I can find about similar problems, but most were closed without being solved. I have been thrashing around for a couple of weeks on what I thought would be the easy part of a Christmas gift for my science teacher wife, and could use a fresh pair of eyes and some suggestions.

This is the project.

It is wired as shown here:

When I power the entire project via the Nano's USB port, it behaves as expected. When I try powering with an external power supply (5V, 2A), the LEDs chase randomly and the RX and or TX LEDs on the Nano flash. This happens whether or not I power the LEDs separately from the Arduino, and even when I power the Arduino via its USB port with a 5V, 2A USB phone charger. When I use the external power supply, it is connected to the Nano's 5V pin. It will only work when the Arduino is connected to the laptop.

I've swapped in several Nano clones, and even an UNO, and after trying some cheap RTC boards, I am now using one from Adafruit. Always the same result. I know that powering via the Nano's USB port isn't a solution because it can't reliably power the LEDs for the clock (there are always 2 or 3 lit), and the clock wouldn't be much of a gift if it requires a laptop as a dongle, anyway.

So, I'd appreciate any advice I can find here.

Post the code?

#include <FastLED.h>
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;

//replace this value with the number of LEDS on your strip
#define NUM_LEDS 60
#define DATA_PIN 3
#define CLOCK_PIN 13

//Define colors for hours, minutes and seconds.
//you can also define custom RGB colors like this: CRGB( 255, 255, 255);
#define hourColor CRGB::Blue;
#define minuteColor CRGB::Green;
#define secondColor CRGB::Red;

//Define overlapping colors
#define HMoverlap CRGB::Cyan;
#define MSoverlap CRGB::Yellow;
#define SHoverlap CRGB::Purple;

unsigned long actTime = 0;
unsigned long remTime = 0;
const unsigned long period = 500;
bool blinkState = false;
bool menuTriggered = false;
bool toggleSeconds = true;
int BRIGHTNESS = 51;
const int menuButton = 8;
const int upButton = 6;
const int downButton = 4;
boolean buttonPrev = false;
boolean buttonPrev2 = false;
boolean buttonPrev3 = false;

int menuState = 0;
// Define the array of leds
CRGB leds[NUM_LEDS];
int periodic[NUM_LEDS] {0,58,59,57,56,55,54,53,52,51,50,42,43,44,45,46,47,48,49,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,5,4,3,2,1};

void setup() { 
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();
    //uncomment the following line when you first upload the code to set the time
    //RTC.adjust(DateTime(__DATE__, __TIME__));
    //you an also use the following line to set a custom time
    //RTC.adjust(DateTime(2022, 2, 24, 14, 20, 0));
  pinMode(menuButton, INPUT);
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);  // GRB ordering is typical
  FastLED.setBrightness(BRIGHTNESS);
}

void loop() { 

   menuButtonState();

   if(menuState==0){
    if((digitalRead(upButton) && buttonPrev2)){
      if(toggleSeconds){
      toggleSeconds=false;
      }else{toggleSeconds=true;}
      Serial.println(toggleSeconds);
      }
      buttonPrev2 = !digitalRead(upButton);
//increase brightness in increments
    if((digitalRead(downButton) && buttonPrev3)){
      if (BRIGHTNESS <255){
        BRIGHTNESS = BRIGHTNESS + 51;
        }else{
          BRIGHTNESS = 51;
          }
FastLED.setBrightness(BRIGHTNESS);
Serial.print("Brightness set to: ");
Serial.println(BRIGHTNESS);
      }      
    buttonPrev3 = !digitalRead(downButton);
    FastLED.clear();
    
    showTime();
    }else if(menuState==1){
    setMinute();
      }else if(menuState==2){
    setHour();
      }
}

void showTime(){
  unsigned long currentMillis = millis();
      DateTime now = RTC.now();
   if((now.second()==now.minute()) && toggleSeconds){
  leds[periodic[now.second()]] = MSoverlap;
  leds[periodic[now.hour()]] = hourColor;
  }else if((now.second()==now.hour()) && toggleSeconds){
  leds[periodic[now.second()]] = SHoverlap;
  leds[periodic[now.minute()]] = minuteColor;
  }else if(now.minute()==now.hour()){
  if(toggleSeconds){leds[periodic[now.second()]] = secondColor;}
  leds[periodic[now.minute()]] = HMoverlap
  }else{
  if(toggleSeconds){leds[periodic[now.second()]] = secondColor;}
  leds[periodic[now.minute()]] = minuteColor;
  leds[periodic[now.hour()]] = hourColor;
      }
  FastLED.show();
    leds[periodic[now.second()]] = CRGB::Black;
  leds[periodic[now.minute()]] = CRGB::Black;
  leds[periodic[now.hour()]] = CRGB::Black;
  }

void menuButtonState() {
  if(digitalRead(menuButton) && buttonPrev){
    menuTriggered = false;
    if(menuState<2){
    menuState = menuState + 1;
    }else{
    menuState = 0;
      }
       Serial.println(menuState);
    }
    buttonPrev = !digitalRead(menuButton);
    
  }

  void setMinute() {

//    FastLED.clear();
    actTime = millis();
    DateTime now = RTC.now();
    RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute(), 1));

    if(digitalRead(upButton) && buttonPrev2){
      leds[periodic[now.minute()]] = CRGB::Black;
    RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute()+1, now.second()));
    }else if(digitalRead(downButton) && buttonPrev3){
      leds[periodic[now.minute()]] = CRGB::Black;
    RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute()-1, now.second()));
      }
    buttonPrev2 = !digitalRead(upButton);
    buttonPrev3 = !digitalRead(downButton);

if (actTime - remTime >= period){
    remTime = actTime;
    if(!blinkState) {
        blinkState = true;
      Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println(); 
   if(now.second()==now.minute()){
  leds[periodic[now.second()]] = MSoverlap;
  leds[periodic[now.hour()]] = hourColor;
  }else if(now.second()==now.hour()){
  leds[periodic[now.second()]] = SHoverlap;
  leds[periodic[now.minute()]] = minuteColor;
  }else if(now.minute()==now.hour()){
  leds[periodic[now.second()]] = secondColor;
  leds[periodic[now.minute()]] = HMoverlap;
  }else{
  leds[periodic[now.second()]] = secondColor;
  leds[periodic[now.minute()]] = minuteColor;
  leds[periodic[now.hour()]] = hourColor;
      }
      FastLED.show();

    } else {
        blinkState = false;
        
        leds[periodic[now.minute()]] = CRGB::Black;

        FastLED.show();
//        leds[periodic[now.hour()]] = CRGB::Black;
//        leds[periodic[now.second()]] = CRGB::Black;
        

    }
  }


          if(!menuTriggered){
          Serial.println("menu triggered!!");
      FastLED.clear();
      menuTriggered = true;
      }
  }

  void setHour() {

//    FastLED.clear();
    actTime = millis();
    DateTime now = RTC.now();
    RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute(), 1));
        if(!menuTriggered){
          Serial.println("menu triggered!!");
      FastLED.clear();
      menuTriggered = true;
      }
    if(digitalRead(upButton) && buttonPrev2){
      leds[periodic[now.hour()]] = CRGB::Black;
    RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour()+1, now.minute(), now.second()));
    }else if(digitalRead(downButton) && buttonPrev3){
      leds[periodic[now.hour()]] = CRGB::Black;
    RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour()-1, now.minute(), now.second()));
      }
    buttonPrev2 = !digitalRead(upButton);
    buttonPrev3 = !digitalRead(downButton);

if (actTime - remTime >= period){
    remTime = actTime;
    if(!blinkState) {
        blinkState = true;
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println(); 
   if(now.second()==now.minute()){
  leds[periodic[now.second()]] = MSoverlap;
  leds[periodic[now.hour()]] = hourColor;
  }else if(now.second()==now.hour()){
  leds[periodic[now.second()]] = SHoverlap;
  leds[periodic[now.minute()]] = minuteColor;
  }else if(now.minute()==now.hour()){
  leds[periodic[now.second()]] = secondColor;
  leds[periodic[now.minute()]] = HMoverlap;
  }else{
  leds[periodic[now.second()]] = secondColor;
  leds[periodic[now.minute()]] = minuteColor;
  leds[periodic[now.hour()]] = hourColor;
      }
      FastLED.show();

    } else {
        blinkState = false;
        
        leds[periodic[now.hour()]] = CRGB::Black;

        FastLED.show();
//        leds[periodic[now.hour()]] = CRGB::Black;
//        leds[periodic[now.second()]] = CRGB::Black;
        

    }
  }


  
  }

  void increaseBrightness(){
    
    }

What will the serial prints do when no laptop is connected? Have you tried commenting them out?

Do you have some while loop to check serial connection at the beginning of your code?

Thank you. I didn't post the code initially because it works as intended when the Nano is attached to the laptop. Probably not a valid assumption.

If I understand correctly, when you run it from an external 5V supply plugged into the Nano's USB port, it doesn't work. What voltage do you measure on the 5V pin when you power that way?

That says it is not the Nano or the code, and guessing the RTC is good. Your button wiring does not look right. Why not wire the buttons from pin to button to ground and use the internal INPUT_PULLUP so a button press is LOW and not pressed is HIGH.

1 Like

Thanks for your reply. When I power the Arduino via its USB port from a 5V 2A phone charger, the voltage at the 5V pin is 4.8, and the project doesn't work. When I power the USB directly from my laptop, the voltage at the 5V pin is 4.6, and it does work.

Yes, I wondered about that when I wired it up according to the post on Instructables. It seems a bit complicated. I'll give your suggestion a try and look through the code to see what I would have to change. I assume it would be some code where the buttons are defined, and then changing HIGH to LOW in the appropriate spots. Thank you for your help.

Try these steps ...

... wire the button... PIN to BUTTON N.O. | BUTTON N.O. to GND

        +------------------+
pin |---| N.O. button N.C. |--
    |   |                  |
GND |---| N.O. button N.C. |--
        +------------------+

... before setup()...

byte buttonPin = 3; // define pin (byte or int)

... in setup()...

void setup() {
  pinMode(buttonPin, INPUT_PULLUP); // configure pin mode
}

... read the pin...

void loop() {
  bool readButtonPin= digitalRead(buttonPin);  // read pin
  if (readButtonPin == LOW) { // LOW = pressed, HIGH = not pressed
  }
}

Will do! Thanks!

Figured I would update this for those who helped out with suggestions and for anyone else who might search on the same issue. It turns out that the switches, and the way they were wired in the original project were to blame. When I connect each of the input pins on the Nano directly to ground, the project works with an external 5V power supply. I assume that the inputs were floating despite the fact that I wired the switches per the original project description. Now I just need to figure out a way to integrate the switches so I can adjust and set the clock. I'm thinking I will try to follow the advice above and use pull up resistors on the input pins with the switches pulling them to ground when pushed. Thanks to all who weighed in.

2 Likes