RGB LED Controller w/ IR input crashes

Hello all,

I’ve been working on a project that requires an LED controller and the ability to make changes to the LED with an IR remote. I decided to try an Arduino out to fill that need. I’ve been teaching myself the basics over the two weeks or so.

The sketch I am working with currently gets input from the remote and then does stuff based on the signal received. Currently I just have it setup to flash random colors when one button is pressed, and stop when another is pressed.

I’ve got the following sketch I’m using for the random LED flashing.

int redPin = 9;   //Sets PWN pin to be used for Red LED
int greenPin = 10;    //Sets PWN pin to be used for Green LED
int bluePin = 11;   //Sets PWN pin to be used for Blue LED
 
int cMin = 0;   //Min value for RGB brightness (0 by default)
int cMax = 255; //Max value for RGB brightness (255 by default)
int cR;   //Brightness value for color Red
int cG;   //Brightness value for color Green
int cB;   //Brightness value for color Blue
long prevMillis = 0;    //Used to store the last time the LED was updated
int interval =0;    //Interval at which to blink the LED in milliseconds. 0 to start by default)
int test =1;
 
void setup()
{  
  pinMode(redPin, OUTPUT);    // Setup output pin for Red LED with value 'redPin' above (9 by default)
  pinMode(greenPin, OUTPUT);    //Setup output pin for Green LED with value 'greenPin' above (10 by default)
  pinMode(bluePin, OUTPUT);   //Setup output pin for Blue LED with value 'bluepin' above (11 by default)
}
 
void loop()
{
  unsigned long currMillis = millis();    //Sets 'currentMillis' to current system time at start of loop
 
  switch(test)
  {
    case 1:
    if(currMillis - prevMillis > interval)
      {
        interval = random(55,300);    //Sets the blink interval to be met for the next loop
        prevMillis = currMillis;   //Sets 'prevMillis' to current time. Thus storing when the LED was last toggled
        cR = random(cMin,cMax);   //Set variable 'cR' to a random number between 'cMin' and 'cMax' as set above
        cG = random(cMin,cMax);   //Set variable 'cG'to a random number between 'cMin' and 'cMax' as set above
        cB = random(cMin,cMax);   //Set variable 'cB' to a random number between 'cMin' and 'cMax' as set above
        setColor(cR, cG, cB);   //Call 'setColor' as shown below and input current values for 'cR', 'cG', and 'cB' to determine the RGB color
      }
      break;
    default: break;  
  }
}   //end of loop
 
void setColor(int red, int green, int blue)
{
  analogWrite(redPin, red);   //Send analog PWM pulse to pin 'redpin'(9 by default) with brightness 'red' as sent in by 'cR' from above
  analogWrite(greenPin, green);   //Send analog PWM pulse to pin 'redpin'(10 by default) with brightness 'green' as sent in by 'cG' from above
  analogWrite(bluePin, blue);   //Send analog PWM pulse to pin 'redpin'(11 by default) with brightness 'blue' as sent in by 'cB' from above  
}

And then I have the larger sketch that includes the above plus takes the IR input from the remote.

//---Libraries---
#include <IRLibAll.h>   //Library included to allow IR input and decoding
 
//---IR Reciver & Decoder---
IRrecv myReceiver(2);   //Create IR Receiver 'myReceiver' on pin 2
IRdecodeNEC myDecoder;   //Create IR Decoder 'myDecoder'
 
//---LED PINS---
int redPin = 9;   //PWN pin used for Red LED
int greenPin = 10;    //PWN pin used for Green LED
int bluePin = 11;   //PWN pin used for Blue LED
 
//---Variables---
int cMin = 0;   //Min value for RGB brightness (0 by default)
int cMax = 255; //Max value for RGB brightness (255 by default)
int cR;   //Brightness value for color Red (Between 0-255 by default)
int cG;   //Brightness value for color Green (Between 0-255 by default)
int cB;   //Brightness value for color Blue (Between 0-255 by default)
long prevMillis = 0;    //Used to store the last time the LED was updated
int interval =0;    //Interval at which to blink the LED in milliseconds. 0 to start by default)
int flash =0;   //Variable used to control if random RGB flash is turned on
 
void setup()
{
  Serial.begin(9600);  //starts serial communication
  myReceiver.enableIRIn(); // Starts the receiver
  pinMode(redPin, OUTPUT);    // Setup output pin for Red LED with value 'redPin' above (9 by default)
  pinMode(greenPin, OUTPUT);    //Setup output pin for Green LED with value 'greenPin' above (10 by default)
  pinMode(bluePin, OUTPUT);   //Setup output pin for Blue LED with value 'bluepin' above (11 by default)
}
 
void loop()
{
  if (myReceiver.getResults())
  {
    myDecoder.decode();
    Serial.println(myDecoder.value);
    Serial.println("Signal Detected");
    switch(myDecoder.value)
    {
      case 16203967:  //Off
        Serial.println("Off");
        flash = 0;
        break;
      case 16240687:  //Flash
        Serial.println("Flash");
        flash = 1;
        break;
      default: break;
    }
    myReceiver.enableIRIn();    //Restart the IR receiver 'myReciever'
    Serial.println("Receiver rebooted");
    Serial.println("---");    
  }//end of decoder IF
 
  unsigned long currMillis = millis();    //Sets 'currentMillis' to current system time at start of loop  
 
  switch(flash)
  {
    case 0:
      setColor(0,0,0);
      break;
    case 1:
      if(currMillis - prevMillis > interval)
      {
        interval = random(55,300);    //Sets the blink interval to be met for the next loop
        prevMillis = currMillis;   //Sets 'prevMillis' to current time. Thus storing when the LED was last toggled
        cR = random(cMin,cMax);   //Set variable 'cR' to a random number between 'cMin' and 'cMax' as set above
        cG = random(cMin,cMax);   //Set variable 'cG'to a random number between 'cMin' and 'cMax' as set above
        cB = random(cMin,cMax);   //Set variable 'cB' to a random number between 'cMin' and 'cMax' as set above
        setColor(cR, cG, cB);   //Call 'setColor' as shown below and input current values for 'cR', 'cG', and 'cB' to determine the RGB color
      }
      break;
    default: break;
  }
}//end of loop
 
void setColor(int red, int green, int blue)   //Light up RGB LED
{
  analogWrite(redPin, red);   //Send analog PWM pulse to pin 'redpin'(9 by default) with brightness 'red' as sent in by 'cR' from above
  analogWrite(greenPin, green);   //Send analog PWM pulse to pin 'redpin'(10 by default) with brightness 'green' as sent in by 'cG' from above
  analogWrite(bluePin, blue);   //Send analog PWM pulse to pin 'redpin'(11 by default) with brightness 'blue' as sent in by 'cB' from above  
}

Here is a link to the library I am using for the IR receiver/decoder: GitHub - cyborg5/IRLib2: Library for receiving, decoding, and sending infrared signals using Arduino

The issue I am currently running in to is that the larger sketch crashes after 7ish random blinks, and I can’t seem to figure out why. From the reading I’ve done I am likely running out of memory, but I’m not sure why or how to debug that.

So far I’ve tried the following to troubleshoot:
-Verified that the sketch I am using to randomly blink a random color is stable and runs fine by itself
-Verified that the sketch I’m using to gather input from the IR remote is stable and runs fine by itself
-Replaced the random cR,cG,cB, and SetColor in the larger sketch with some Serial.Printlns and it is stable.
-Added Switch(test) to the sketch that just blinks the LED to see if my switch in the larger sketch was the problem.

This has gotten me to the point of knowing that something about the way I’ve combined these is causing the problem, but I’m still rather new to this and am not sure what to check next. Any advice would be greatly appreciated! :smiley:

Welcome to the Forum. Please read these two posts:

How to use this forum - please read.
and
Read this before posting a programming question …
You may also find useful information that would answer your question here:
Useful links - check here for reference posts / tutorials

You have posted code on an offsite resource. Many people avoid following such links for security reasons, and also because it’s easier to read online when posted with code tags. The code tags make the code look

like this

when posting source code files. It makes it easier to read, and can be copied with a single mouse click. Also, if you don’t do it, some of the character sequences in the code can be misinterpred by the forum code as italics or funny emoticons.

aarg:
Welcome to the Forum. Please read these two posts:

How to use this forum - please read.
and
Read this before posting a programming question ...
You may also find useful information that would answer your question here:
Useful links - check here for reference posts / tutorials

I looked through the FAQ and nothing stuck out as something that as related or something I hadn't already tried, if I've missed something just let me know and I'll take a closer look. :slight_smile:

aarg:
You have posted code on an offsite resource. Many people avoid following such links for security reasons, and also because it's easier to read online when posted with code tags...

My apologizes on that one. I'd been suggested Pastebin over on Reddit and used that as it seemed easy enough. Didn't see that the built in Code tag was required. I'll make sure not to link off site for code in future posts :slight_smile:

int cMin = 0;   //Min value for RGB brightness (0 by default)
int cMax = 255; //Max value for RGB brightness (255 by default)
int cR;   //Brightness value for color Red (Between 0-255 by default)
int cG;   //Brightness value for color Green (Between 0-255 by default)
int cB;   //Brightness value for color Blue (Between 0-255 by default)

Are you sure that int is the appropriate type to hold a byte? Perhaps you need long long, instead.

long prevMillis = 0;    //Used to store the last time the LED was updated

Keeping your options open in case you develop a time machine that can go back in time?

Posting a link to the non-standard IR library you are using would be useful.
Posting a schematic would be useful.

int redPin = 9;   //PWN pin used for Red LED
int greenPin = 10;    //PWN pin used for Green LED
int bluePin = 11;   //PWN pin used for Blue LED

There are NO PWN pins on any Arduino.

PaulS:

int cMin = 0;   //Min value for RGB brightness (0 by default)

int cMax = 255; //Max value for RGB brightness (255 by default)
int cR;  //Brightness value for color Red (Between 0-255 by default)
int cG;  //Brightness value for color Green (Between 0-255 by default)
int cB;  //Brightness value for color Blue (Between 0-255 by default)



Are you sure that int is the appropriate type to hold a byte? Perhaps you need long long, instead.

Hmmm, it was my understanding that an int would be able to hold a value between 0-255 without any issues (int - Arduino Reference). It's also the same variable type used in all the examples I've looked at for applications like this. Have I misunderstood something? I can try a long, but figured that would just be a waste as I only need these to hold a value between 0-255.

PaulS:

long prevMillis = 0;    //Used to store the last time the LED was updated

Keeping your options open in case you develop a time machine that can go back in time?

Haha no, this is something I took directly from a guide on how to use Millis inplace of delay. prevMillis is stored so that you can compare it against curMillis the next time through the loop to see if it is time to perform an action or not. Using millis() for timing | Multi-tasking the Arduino - Part 1 | Adafruit Learning System

PaulS:
Posting a link to the non-standard IR library you are using would be useful.
Posting a schematic would be useful.

Sorry, didn't think to include that. Below is the library I'm using. If there is something more standard or better supported I'd be happy to give that a try. This was just the first one I ran across in my research and it seemed to work well enough at the time. :slight_smile:

At work at the moment, but I can get something made up and posted later today. Not much to it, just an RGB LED and the IR sensor. I'll follow-up once I've had a chance to create it.

PaulS:

int redPin = 9;   //PWN pin used for Red LED

int greenPin = 10;    //PWN pin used for Green LED
int bluePin = 11;  //PWN pin used for Blue LED



There are NO PWN pins on any Arduino.

Whoops, hadn't noticed that typo. Thanks for pointing that out. I'll get it changed to PWM. :slight_smile:

Hmmm, it was my understanding that an int would be able to hold a value between 0-255 without any issues

It can. But, so can a byte. The byte will use half the memory.

Adafruit makes good hardware. Their software often leaves a lot to be desired. The millis() function returns an unsigned long.

Are you using resistors for the LED?

PaulS:
It can. But, so can a byte. The byte will use half the memory.

Using millis() for timing | Multi-tasking the Arduino - Part 1 | Adafruit Learning System
Adafruit makes good hardware. Their software often leaves a lot to be desired. The millis() function returns an unsigned long.

Ahhhh, ok I'll make sure to read into using byte instead of int. I'll also go find some other resources on millis() to see where I can learn more there! :slight_smile:

INTP:
Are you using resistors for the LED?

I am. I've got a common cathode RGB led connected with a 200 ohm current limiting resistor. I'm curious though, would the value of the resistor be acceptable when running the first sketch, but not the second? Still new to this and assumed if the resistor worked in one application where it is powered on it would work in another the same way.

You should be using a resistor on each anode based on the forward voltage of each color.
Prog 'crashing' sometimes points to dying components. I don't think that's the case with at least the one resistor, but it's still insufficient for effectively 3 LEDs.

INTP:
You should be using a resistor on each anode based on the forward voltage of each color.
Prog ‘crashing’ sometimes points to dying components. I don’t think that’s the case with at least the one resistor, but it’s still insufficient for effectively 3 LEDs.

I did take into consideration the fact I’m running 3 LEDs, maybe I misunderstood something though? My LEDs have a forward voltage of 2V and a peak forward current of 50mA. The supply from the Arduino is 5V. So, that means each LED would require a 68ohm resistor. 68x3=204, but I rounded down since 4ohms shouldn’t made a big difference. Is there a reason that the resistance needs to sit ahead of the LED? Or is there something I’ve missed in my resistance calculation since I’m using a combo LED?

Userdenied:
Is there a reason that the resistance needs to sit ahead of the LED?

I hope you mean, "on the anodes". If you put only one resistor on the cathode, the anode currents are summed, and thus interact. So one will be brighter or dimmer depending on which other ones are on. This is usually considered bad.

aarg:
I hope you mean, "on the anodes". If you put only one resistor on the cathode, the anode currents are summed, and thus interact. So one will be brighter or dimmer depending on which other ones are on. This is usually considered bad.

I did yes, sorry I should have just said on the anodes. :stuck_out_tongue: I didn't realize that was considered poor circuit design. That might explain why I was having issues getting the range of colors I expected... I'm just sitting down at my desk at home now, so I'm going to fix my circuit really fast and see what kind of difference it makes. :slight_smile:

And thank you all for the help on this! This has been a very helpful and welcoming community, one of the nicest I've gotten into really.

aarg:
I hope you mean, "on the anodes". If you put only one resistor on the cathode, the anode currents are summed, and thus interact. So one will be brighter or dimmer depending on which other ones are on. This is usually considered bad.

That made a HUGE difference. I'm getting a much better range of colors and brightness ranges! :slight_smile: I'll make sure to research future components a little better.

PaulS:
It can. But, so can a byte. The byte will use half the memory.

Using millis() for timing | Multi-tasking the Arduino - Part 1 | Adafruit Learning System
Adafruit makes good hardware. Their software often leaves a lot to be desired. The millis() function returns an unsigned long.

I've moved all my ints to bytes since none of them so far needed to store anything larger than a byte can hold. I also moved prevMillis to unsigned long. Sadly it still crashes after 7 blinks. :frowning: I'm going to add some debug lines tonight and see if I can further pin-point where it's crashing now that I understand a little more.

Userdenied:
That made a HUGE difference. I'm getting a much better range of colors and brightness ranges! :slight_smile: I'll make sure to research future components a little better.

How can you do that? They don't exist yet.

aarg:
How can you do that? They don't exist yet.

You got me there... I'm actually a time traveler! :stuck_out_tongue: