Go Down

Topic: 433MHz and WS2812b (Read 587 times) previous topic - next topic

Kuuki

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 as receiver/transmitter and the following libraries:

RC-Switch:
https://github.com/sui77/rc-switch
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.

DrAzzy

#1
Jan 22, 2018, 03:23 am Last Edit: Jan 22, 2018, 03:23 am by DrAzzy
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.
ATtiny core for 841+1634+828 and x313/x4/x5/x61/x7/x8 series Board Manager:
http://drazzy.com/package_drazzy.com_index.json
ATtiny breakouts (some assembled), mosfets and awesome prototyping board in my store http://tindie.com/stores/DrAzzy

PORTB

#2
Jan 22, 2018, 04:25 am Last Edit: Jan 22, 2018, 04:30 am by PORTB
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.


Kuuki

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 and 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!

Go Up