Arduino Forum

Using Arduino => LEDs and Multiplexing => Topic started by: Kuuki on Jan 22, 2018, 01:06 am

Title: 433MHz and WS2812b
Post by: Kuuki on Jan 22, 2018, 01:06 am
Hey!

I am currently building myself some lighting for my appartment using Arduinos and strips of WS2812b LEDs. My plan was to control them with an app from my smartphone and a Raspberry Pi. The phone sends data (like color, mode etc.) to the Pi and the Pi transmits that via a 433MHz transmitter to three Arduino Nanos I wanted to place across the room.
Sending data from my phone through the Pi to the Arduinos works without a problem, the data is received correctly and the LEDs light up, but as soon as I do this once no more data can be received. There is no issue when I just receive and don't do anything else. Here's my code:

Code: [Select]
#include <RCSwitch.h>
#include <Adafruit_NeoPixel.h>

#define LEDPIN         9
#define NUMPIXELS      75

#define STARTBIT       4194305
#define STOPBIT        8388609
#define SETBIT         2097153

RCSwitch rc = RCSwitch();
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, LEDPIN, NEO_GRB + NEO_KHZ800);

uint32_t data[] = {0,0,0};
bool written[] = {false, false, false};
bool led_set = false;

uint32_t wait = 0;

uint16_t j = 0;

int index = 0;
bool recording = false;

int led = 0;
unsigned long time;

static unsigned long received = 0;

void setup() {
  Serial.begin(9600);
  time = millis();
  pinMode(LEDPIN, INPUT);
  rc.enableReceive(0);  // Receiver on interrupt 0 => that is pin #2
  strip.begin();

    for (int i = 0; i < 75; i++) {
        strip.setPixelColor(i, strip.Color(255,255,255));
      }
      strip.show();     
}

void loop() {

  if (millis()-time >= 1000) {
    Serial.println(*((unsigned int*)rc.nReceivedValue));
    Serial.println(rc.nReceivedValue);
    Serial.println(millis());
    time = millis();
  }

  if (rc.available()) {
    received = rc.getReceivedValue();
    rc.resetAvailable();
    Serial.print("received: ");
    Serial.print(received);
    Serial.println();
  }
 
    if ((received == STOPBIT) && recording) {
      Serial.println("stopped");
      recording = false;
    }
    else if ((received == STARTBIT) && not recording) {
      recording = true;
      led_set = false;
      Serial.println("started");
    }
    if (recording) {
      if(received == SETBIT && written[index] && index < 3) {
        index++;
        Serial.println("setbit");
      }
      else if(received != STARTBIT && received != STOPBIT && received != SETBIT && received != 0 && not written[index] && index < 3) {
        data[index] = received & 0xFFFFFFFF;
        written[index] = true;
        //Serial.println(received);
        Serial.println(data[index]);
        Serial.println("written");
      }
    }
   
    else if (data[0] != 0 && data[1] != 0 && data[2] != 0 && not recording && not led_set) {

      Serial.println("setting LED");
     
      for (int i = 0; i < NUMPIXELS; i++) {
        strip.setPixelColor(i, data[2]);
      }
      strip.show();
     
      rc.resetAvailable();
    }
   
   if (not recording) { 
      for (int k = 0; k < 3; k++) {
        written[k] = false;
      }
      index = 0;
   }
   
}


(I pretty much ripped this code to pieces and this is whats left, so there might be some things missing or unclear)

I use these (https://www.amazon.de/gp/product/B00R2U8OEU/ref=oh_aui_detailpage_o01_s00?ie=UTF8&psc=1) as receiver/transmitter and the following libraries:

RC-Switch:
https://github.com/sui77/rc-switch (https://github.com/sui77/rc-switch)
Adafruit NeoPixel:
https://github.com/adafruit/Adafruit_NeoPixel (https://github.com/adafruit/Adafruit_NeoPixel)

What I found out so far is that it works with less than 5 LEDs and sometimes with more if I set the colors to low values. Then it's more or less chance if I get another receive or not. If I do not set the LEDs here
Code: [Select]
    else if (data[0] != 0 && data[1] != 0 && data[2] != 0 && not recording && not led_set) {

      Serial.println("setting LED");
     
      for (int i = 0; i < NUMPIXELS; i++) {
        strip.setPixelColor(i, data[2]);
      }
      strip.show();
     
      rc.resetAvailable();
    }
I can receive more data, if I hardcode the values for the colors it works only for bright white (so every color to 255) or for color values below 14.
If I comment out the last four lines in setup() the problem can't even be solved by the restart button (unplugging helps though). Switching the receiver does not work either.
All three of the Arduinos I use have the same issue.
I use a 6A power supply (at least for the strip with 75 LEDs, the other two have 30 LEDs each with a 2.4A supply) so power should be no issue.
When I hooked up my Arduino Uno to the second data pin of the receiver it couldn't receive anything either, using the Uno with another receiver next to it was fine. Using the Uno as oscilloscope and displaying the voltage on the data pin I noticed a lot of noise after first transmitting. It looked like it increased with the color values. The noise was gone after I restarted the arduino with the LED-setting in setup() and it doesn't occur if I don't do anything with the LEDs at all. There is a 5 MOhm pull-down resistor between data and gnd on the receiver module. I don't actually know if this noise has anything to do with this, because receiving was sometimes fine even with noise.
I really would like to know if there's anything I could try to solve this, besides switching to WiFi-modules or actual wire.
Title: Re: 433MHz and WS2812b
Post by: DrAzzy on Jan 22, 2018, 03:23 am
A 433mhz receiver outputs random noise when there's no signal (the automatic gain control adjusts the gain to get a ~50% duty cycle on the output, so if there's no signal, it cranks it up until the noise gives it 50% duty cycle). So that's not surprising.

I suspect a bug in your code - but I didn't have time to dig through it.
Title: Re: 433MHz and WS2812b
Post by: PORTB on Jan 22, 2018, 04:25 am
It looks like RCSwitch uses interrupts to receive data. The WS2812b leds need precise timing, and therefore the neopixel library disables interrupts, so anything using interrupts probably won't work.

Title: Re: 433MHz and WS2812b
Post by: Kuuki on Jan 22, 2018, 10:54 am
It looks like RCSwitch uses interrupts to receive data. The WS2812b leds need precise timing, and therefore the neopixel library disables interrupts, so anything using interrupts probably won't work.

I tried disabling the receive pin before setting the LEDs and enabling it afterwards but that didn't help. Enabling interrupts manually doesn't do anything either. I changed the rc-switch interrupt handling so it prints something everytime an interrupt occurs. That worked even after receiving the first data. The Arduino somehow just doesn't recognize what's been sent.
Using different LED libraries (FastLED (https://github.com/FastLED/FastLED/wiki/Overview) and light_ws2812 (https://github.com/cpldcpu/light_ws2812)) has the same result.

I suspect a bug in your code

I hope it's in in the code, then I can fix it.

Thanks for the replies so far!