IR controlling Neopixels

I am very new to this, and I really need some help.

I have recently bought a Neopixel strip, and modified an example sketch so that it lights as I want. But now i want to implement an IR receiver to turn it on and off.

I have run the sketch "IRanalyze" so I know that the on button corresponds to "NEC, Value: 20DF4EB1" and the off button corresponds to "NEC, Value: 20DF8E71".

Now i need help to implement the IR receiver, so that when I start the Arduino, the Neopixel strip is off, and then I can turn it on and off with the remote.

This is the code I want to run when I push the on button:

#include <Adafruit_NeoPixel.h>
#define PIN 6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(126, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
  rainbow(20);
}


void rainbow(uint8_t wait) {
  uint16_t i, j;

  for (j = 0; j < 256; j++) {
    for (i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}


// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

Thanks in advance :smiley:

I have run the sketch "IRanalyze" so I know that the on button corresponds to "NEC, Value: 20DF4EB1" and the off button corresponds to "NEC, Value: 20DF8E71".

Which library does that example come with? Which version of that library?

So, why can't you run the other examples, specifically the one that receives IR data and acts on it?

IRlib, version 1.51.

As said, I am very new to this, so I can not understand much of the examples, and especially not how to add something like that to the simple Neopixel code I use. Sorry for my lack of knowledge :blush: ::slight_smile:

Just knowing the name of a library is not very useful. I can't go download the exact same library, without knowing where you got it.

My version of Ken Shiriff's IRRemote library does not include an example with that name. It does have one called IRrevcDump that produces similar output.

It also includes one called IRrecvDemo, that shows how to print the data received, assuming that one of several protocols was used to generate the data.

Adding an if statement

   if(results.value == 0x20DF4EB1)
   {
   }

to that code is pretty simple. In the body of the if statement, add the call to rainbow().

Add another if statement (an else if, actually) to deal with the off button. In that body, write code to turn all the LEDs in the strip off.

Is this even correct, and what else should I put in to make it work?

#include <Adafruit_NeoPixel.h>
#include <IRremote.h>
#define PIN 6
//ON 20DF4EB1
//OFF 20DF8E71
Adafruit_NeoPixel strip = Adafruit_NeoPixel(126, PIN, NEO_GRB + NEO_KHZ800);
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);

decode_results results;

void setup() {
  Serial.begin(9600);
  irrecv.enableIRIn();
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
  if(results.value == 0x20DF4EB1)
   {
    rainbow(5000);
   }
  else if(results.value == 0x20DF8E71)
  {
    }
}


void rainbow(uint8_t wait) {
  uint16_t i, j;

  for (j = 0; j < 256; j++) {
    for (i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}


// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

Upload the example found in the IDE at File=>Examples=>IRremote=>IRrecvDemo and make certain it works with your setup. The loop() function in that file is:

void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }
}

You can merge it with your code to get:

void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    if (results.value == 0x20DF4EB1)
    {
      Serial.println("On");
      rainbow(5000);
    }
    else if (results.value == 0x20DF8E71)
    {
      Serial.println("Off");
    }
    irrecv.resume(); // Receive the next value
  }


}

I'm not sure what you want to do when you get the off button.

Be aware that pressing the off button while rainbow() is running will accomplish nothing. You will have to know exactly when the press the off button to get the rainbow effect to stop.

A complete restructure of your program is in order, if you expect the remote to turn the strip off.

Okay. Is there any possibility that you would be able to take the time to write me a code that would work? I really need this to work, it is supposed to be a gift to a friend. I can even consider paying you a small fee if you would be able to take the time to write it :blush:

First, can you get the remote to turn the light on? If the remote and NeoPixel strips don't play together, then rewriting the code will be a waste of time.

No, I can´t. But then again, I'm not even sure that my code is correct. If my Arduino and IR receiver can recognize the remote and read the values I wrote, shouldn't it be able to control the Neopixels?

How would a code, that can turn a pin to HIGH and LOW in the same way look? Is that possible? Because in the worst case, I can use one more Arduino with an on/off function to a relay that controls the power to the Neopixel-Arduino?

If my Arduino and IR receiver can recognize the remote and read the values I wrote, shouldn't it be able to control the Neopixels?

Yes. If it doesn't, you need to (help us) figure out why. Add Serial.print() statements, to make sure that the Arduino IS reading the remote, AND getting the value(s) that you expect.

I sort of got it to work! I borrowed a code from @Bajdi, and rewrote it a bit, and also used another remote. But to problems remains. Now when i press the on button, it lights up as I want, but of course only for a couple of seconds. And also, what should I put in the second case to turn it off, because if I only break the data transmit to the Neopixels, it just freezes but continues to light.

This is the code:

#include <IRremote.h> // use the library for IR

#include <Adafruit_NeoPixel.h>
#define PIN 6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(126, PIN, NEO_GRB + NEO_KHZ800);

int receiver = 11; // pin 1 of IR receiver to Arduino digital pin 11
//const int led1 =  3;
IRrecv irrecv(receiver); // create instance of 'irrecv'
decode_results results;

void setup(){

  strip.begin();
  strip.show(); 
  
  irrecv.enableIRIn(); // Start the receiver

}

void translateIR() // takes action based on IR code received


{

  switch(results.value)

  {

    case 0x61D620DF:  rainbow(20);   break;

    case 0x61D6609F:  delay(5000);   break;

   

  }
}

void loop()

{

  if (irrecv.decode(&results)) // have we received an IR signal?

  {

    translateIR();

       irrecv.resume(); // receive the next value

  }

}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for (j = 0; j < 256; j++) {
    for (i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}


// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

Now when i press the on button, it lights up as I want, but of course only for a couple of seconds.

That is because you only cycle through the rainbow cycle once.

And also, what should I put in the second case to turn it off, because if I only break the data transmit to the Neopixels, it just freezes but continues to light.

Look at how rainbow() turns pixels on and off. It calls setPixelColor() for each pixel in the strip, assigning some color value. Now, it should be obvious that the range of red values is not unlimited, that the range of green values is not unlimited, and that the range of blue values is not unlimited. It should also be obvious that some red value means no red light, that some green value means no green light, and that some blue value means no blue light, and, finally, that no red light light, no green light, and no blue light means no light. It is up to you to figure out what that value, for red, green, and blue is to make no light. But, here's a hint. It's not negative and its less than 1.

Haha, thank you so much! :smiley: Now the turning off works. But I still don't understand what to put in the first case. Because now I can turn it off, but only when it has went through the cycle. What exactly do I write to make it repeat the cycle in eternity, and only stop when I press Off?

 case 0x61D620DF: rainbow(20); break;
case 0x61D6609F: strip.setPixelColor(0-125, 0, 0, 0); strip.show(); break;

What exactly do I write to make it repeat the cycle in eternity, and only stop when I press Off?

Some restructure of the code is needed. First, you need a global bool(ean) variable, rainbowOn, initialized to false.

Then, when the on button is pressed, set rainbowOn to true but do not call rainbow(). When the off button is pressed, set rainbowOn to false, and turn all the pixels off.

After the end of the if statement that deals with the remote, add:

  if(rainbowOn)
     rainbow(20);

Now I can turn it on, and it repeats the cycle. But I can't turn it off now, so what do I do wrong?

#include <IRremote.h> // use the library for IR

#include <Adafruit_NeoPixel.h>
#define PIN 6
boolean rainbowOn = false;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(126, PIN, NEO_GRB + NEO_KHZ800);

int receiver = 11; // pin 1 of IR receiver to Arduino digital pin 11

IRrecv irrecv(receiver); // create instance of 'irrecv'
decode_results results;

void setup(){

  strip.begin();
  strip.show(); 
 
  irrecv.enableIRIn(); // Start the receiver

}

void translateIR() // takes action based on IR code received


{

  switch(results.value)

  {

    case 0x61D620DF: rainbowOn = true; break;

    case 0x61D6609F: rainbowOn = false; strip.setPixelColor(0-125, 0, 0, 0); strip.show(); break;

   

  }
}

void loop()

{
  

  if (irrecv.decode(&results)) // have we received an IR signal?

  {

    translateIR();

       irrecv.resume(); // receive the next value

  }

  if(rainbowOn)
     rainbow(20);

}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for (j = 0; j < 256; j++) {
    for (i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}


// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
    case 0x61D6609F: rainbowOn = false; strip.setPixelColor(0-125, 0, 0, 0); strip.show(); break;

Setting the color of the -125th pixel does not seem like a useful thing to do.

so what do I do wrong?

I'm not sure, but I sure get tired scrolling

past all those

blank lines.

And, it's ONE statement per line.

That way, you can easily add Serial.print() or Serial.println() statements, to see what is happening.