Remote infrared vs1838B problem with LED strip w/ Adafruit_NeoPixel library

Hello

I want to control LED strip by remote vs1838b receiver and pilot.

While, only have routine for remote like

void CheckPilot() {
if (irrecv.decode(&signals)) {
irrecv.decode(&signals);
String strPOM = String(signals.value, HEX);
Serial.println(strPOM);
irrecv.resume(); // get the next signal
}
}

it works good

But also in loop() there's handling of LED strip, when I comment
// strip.show();
there's also OK.

But with
strip.show();
Reading from remote is very hard, with very rare of correct data. Only one solution that works is to handle CheckPilot in loop and handling of LED strip with Metro library

Metro mHandleLED = Metro(100); // Instantiate an instance

:frowning:

So, LEDs goes slow, and remote works not so good. Only when, I'll make
Metro mHandleLED = Metro(500); // Instantiate an instance
is almost OK.

Is there a way to make another task for handling of remote controller, or to make a buffer that holds incoming data from remote?

There is a mistake that many beginners make when writing neopixel code. They use show() too often when it is not necessary. This result is that almost all the Arduino's time taken up sending data to the strip and ir signs are missed. Please post your complete code and we will check for the mistake. Please use code tags, as described in the forum sticky post.

this code is written in Polish language

It must be written in C/C++, or it will not compile.

I cannot open your attachment on my phone. If it is too large, maybe you could create a shorter test sketch that demonstrates your problem. Sometimes, simply creating a short test sketch helps you to figure out the problem. If not, post that, using code tags.

Of course that is written in C language, but names of variables and etc, are written in Polish. Do I have to write it, as small as it could be to demonstrate the problem?

kwestia:
Of course that is written in C language, but names of variables and etc, are written in Polish. Do I have to write it, as small as it could be to demonstrate the problem?

Just post the code in code tags, if you want help. Otherwise take up knitting.

As long as it is short enough to post in code tags in no more than 2 or 3 parts, that's ok.

it seems like follow (important frags)

#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008
#include <Adafruit_NeoPixel.h>
#include <IRremote.h>
#include <Metro.h>

#define PIN 6
const int MAX_LED = 658;
enum EcTabela
{
  CZERWONY,
  ZIELONY,
  NIEBIESKI,
  WIDOCZNY,
};

char cTabela[WIDOCZNY + 1][MAX_LED];

// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(MAX_LED, PIN, NEO_GRB + NEO_KHZ800);

//-------------------pilot
int input_pin = 10; //set D10 as input signal pin
static IRrecv irrecv(input_pin);
static decode_results signals;
//-------------------pilot koniec

//Metro mObsluzPilota = Metro(10);  // Instantiate an instance
Metro mObsluzPrzesuwanie = Metro(100);  // Instantiate an instance

void setup() {
  // put your setup code here, to run once:
  randomSeed(analogRead(5));
  Serial.begin(9600);

  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

  irrecv.enableIRIn(); // enable input from IR receiver
}

void loop() {
  // put your main code here, to run repeatedly:
  if (mObsluzPrzesuwanie.check() == 1) {
    ObsluzPrzesuwanie();
  }
  //if (mObsluzPilota.check() == 1)
  ObsluzPilota();
}

void ObsluzPilota() {
  if (irrecv.decode(&signals)) {
    irrecv.decode(&signals);
    String strPOM = String(signals.value, HEX);
    Serial.println(strPOM);
    //routine to set different LEDs in accordance with incoming data from remote
    irrecv.resume(); // get the next signal
  }
}


void ObsluzPrzesuwanie() {
  int iLicznik, iPOM;

  //....................
  //here's part of routine to set color
  for (iLicznik = 0; iLicznik < MAX_LED; iLicznik++)
  {
    //iPOM is increased in different way than iLicznik
    if (cTabela[WIDOCZNY][iPOM] == TWIDOCZNY)
      strip.setPixelColor(iLicznik , strip.Color(cTabela[CZERWONY][iPOM], cTabela[ZIELONY][iPOM], cTabela[NIEBIESKI][iPOM]));
    //or to set black (NO) color
    else
      strip.setPixelColor(iLicznik , strip.Color(0, 0, 0));
  }
  //...................
  strip.show();
}

As suspected you are sending out the data to the strip on a regular basis. Try to send it out only when there has been a change in the data.

That's it. They're changed with every loop (goes forward or backward), so I have to rearrange each LED.

But this is good idea!, to store before and after complete line of all LEDs, and change only differences :slight_smile:

kwestia:
That's it. They're changed with every loop (goes forward or backward), so I have to rearrange each LED.

No, the strip only gets updated every 100ms, because of this "Metro" object. I don't see the point of this library. It seems to be as many lines of code to use it as doing the same thing but using millis()! But even at 100ms intervals, ir signals can be lost, because strip.show() disables interrupts while the strip is being updated.

kwestia:
But this is good idea!, to store before and after complete line of all LEDs, and change only differences :slight_smile:

You can't do that. The entire strip must be updated to change even one led.

This does not look correct to me:

if (irrecv.decode(&signals)) {
    irrecv.decode(&signals);

Why the second call to irrecv.decode()? Won't that cause signals to be lost? You could try removing that second call.

Hello, thanks for answer.

Obviously second line is unecessary :slight_smile:

Metro is called only for handling of pilot, the rest of time is used for handling of LEDs. If I do both with Metro, it's going unacceptable slow :frowning:

More over for doing with difference from one step to another I have to store sets of colors in two arrays, to distinguish what's changed. So, the memory I will use twice as arrays of 638 (LEds) * 3 (colors) * 2 (before and after) of bytes. There is also one more row in array for indicate if each particular LED is on or off. Frankly, I have to use 638 * 7 bytes, and complier warns me about low of memory. If I will store data as only first 3 bits (3 bits of before, 3 bits of after, 1 bit for visible) I have to shift bits to get correct values. In first alghoritm with 7 rows it goes slow with pilot, the second frees up memory, but it will be much slower....

What is best idea to show LED strip with handling of pilot and display ? I'm really confused because of speed.

Maybe the best one solution is to write code in assembler? does anyone know where's library or source for it?

Kind regards
P.

Maybe the best one solution is to write code in assembler?

No.

does anyone know where’s library or source for it?

The source code is in you libraries folder.

I’m really confused because of speed.

And your inability to pick out the really “important frags” confused me. This is why we ask to see all the code. Think about it if you knew enough about coding that could pick out the “important frags”, you would know enough to not make the mistakes you are making.

There is an easy fix. The IRdecoder does not want its interrrupt closed out while it is decoding a character which takes some 65 milliseconds sort of Morse Speed. The Neopixel absolutely has to cut out interrupts to send the bit stream to the Leds synchronously at about 1 MHz. The way out is not to start a .show while the IR decoder is in the middle of decoding a character from the remote. But the IR lib is friendly enough to tell you that it is busy. So be polite and don´t disturb it. In plain C++ this reads like this

if (irrecv.isIdle()) {
FastLED.show();
} else {
Serial.println("Skipped FastLED.show()");
}

Courtesy goes to Sam Curren who found this efficient work around. his kids loved it so did mine

Good tip thanks @Qualcunodue