Virtualwire and Adafruit_NeoPixel not working together?

Hi everybody,
I have a problem with the libraries VirtualWire and Adafruit_NeoPixel.
As soon as both libraries are included and I set a variable within the VirtualWire receive part, the program won’t receive anymore data.

In my code I set the variable “ctest” to the value 1 (line 46) when I receive a message. At this point no more messages will be received but the program is still running. When I uncomment the variable everything will work fine.

Thanks for any help!
Ben

#include <Adafruit_NeoPixel.h>
#include <VirtualWire.h>


// Neopixel
#define Ada_Pin 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, Ada_Pin, NEO_GRB + NEO_KHZ800);
int ctest = 0;

void setup()
{
    // Start Neopixel
    strip.begin();
    strip.show();

    Serial.begin(9600);	// Debugging only
    Serial.println("setup");

    // Initialise the IO and ISR
    vw_set_ptt_inverted(true); // Required for DR3100
    vw_setup(2000);	 // Bits per sec

    vw_rx_start();       // Start the receiver PLL running    
}

void loop()
{
    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t bufleng = VW_MAX_MESSAGE_LEN;

    //Serial.println(vw_get_message(buf, &buflen));


    if (vw_get_message(buf, &bufleng)) // Non-blocking
    {
	int j;

        digitalWrite(13, true); // Flash a light to show received good message
	// Message with a good checksum received, dump it.
	Serial.print("Got: ");
	
	for (j = 0; j < bufleng; j++)
	{
            char letter = char(buf[j]);
            if (buf[j] == 35) {
              ctest = 1;
              Serial.println("Test");
            }
  
	    Serial.print(buf[j]);
	    Serial.print(" ");
	}       
        digitalWrite(13, false);
    }


  // detect ring
//  if (command_pos != 0 && char(buf[command_pos] == 'K') && char(buf[command_pos+1] == 'L') && char(buf[command_pos+2] == '1')) {
  if (ctest != 0) {
    // Klingel 1
//    Serial.println("Klingel 1");
    strip.setPixelColor(1,strip.Color(127, 127, 127));
    strip.show();
  }

delay(10);
}

This problem never got a response and now I'm having an extremely similar issue.

I have two Arduinos, one running with a 433mhz receiver and the other with a 433mhz transmitter. The one with the receiver is hooked up to an Adafruit Neopixel 60 LED strip. If I have it receive messages from the transmitter arduino, it does so without a problem. If I have it just randomly switch between patterns on the neopixel strip, that works fine.

So I know both sides work independent of each other.

When I set the program on the receiving end to change Neopixel patterns when a message comes in, the behavior gets a bit strange. As soon as the Neopixel strip is altered, no future messages are received. I know by way of debugging that the non-blocking function call for receiving a message is still being called, and the main loop is still going, but no message ever gets received. I started checking what code could be removed to find the problem, and I found a rather peculiar issue: Everything works if I don't call strip.show(). Note: "strip" is the variable name for the LED strip, just like in the library example.

If I remove the strip.show() call, the messages keep getting received and everything is fine. The second I call strip.show(), no more messages can get received even though the main loop, and the message retrieval call, is still going through.

Has anyone solved this issue or something similar?

Hi MensInvictaManet

Please post your code. Use code tags (the </> button on the toolbar above the reply window).

Regards

Ray

I'm going to to try manually re-enabling interrupts, resetting the radio calls / virtualwire calls, and using FastLED libraries instead of the NeoPixel ones as well to see if any of those fix the issue.

I'll post the code right here as soon as I get home. I'm away from my desk at the moment.

Okay so first thing is first… I just turned it on and it’s sometimes working fine now. Like, a few times it worked fine and now it’s back to not working again… without even changing the code. I have no fucking clue why though. I didn’t change the code since yesterday when it was broken.

Here is the code for the receiving Arduino, the one giving me the problem.

#include <VirtualWire.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define VW_DATA_RX_PIN 2    //  Digital Pin 12 for receiving data
#define DISPLAY_PIN 13   //  Digital Pin 13 to represent power save mode (until implemented)
#define NEOPIXEL_PIN 12   //  Digital Pin 4 for feeding data to the neopixel string

// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino 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(60, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);

enum MessageID
{
  MI_COLOR_RED             = 0,
  MI_COLOR_GREEN           = 1,
  MI_COLOR_BLUE            = 2
};

uint8_t LastMessage = MI_COLOR_RED;

enum ColorNames 
{
  RED          = 0,
  GREEN        = 1,
  BLUE         = 2,
  COLOR_COUNT
};

const int Colors[COLOR_COUNT][3] = 
{
  { 255, 0, 0 },       // RED
  { 0, 255, 0 },       // GREEN
  { 0, 0, 255 },      // BLUE
};

uint8_t MessageBuffer[VW_MAX_MESSAGE_LEN];
uint8_t MessageBufferLength = VW_MAX_MESSAGE_LEN;

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  Serial.print(strip.numPixels());
  Serial.print(" - ");
  Serial.print(wait);
  Serial.print("\n");
  for (int i = 0; i < 10; ++i) strip.setPixelColor(i, c);
  delay(50);
}

void CheckForMessages()
{
  if (vw_get_message(MessageBuffer, &MessageBufferLength)) // Non-blocking
  {
    //if (MessageBufferLength != 1) Serial.print(MessageBufferLength);
    if (LastMessage == MessageBuffer[0]) return;
    LastMessage = MessageBuffer[0];
      
    Serial.print(MessageBuffer[0]);
    Serial.write("\n");
      
    switch (MessageBuffer[0])
    {
      case MI_COLOR_RED:          colorWipe(strip.Color(255, 0, 0), 1);              break;
      //case MI_COLOR_GREEN:      /*DO NOTHING*/           break;
      case MI_COLOR_BLUE:         colorWipe(strip.Color(0, 0, 255), 1);             break;
    }
    
    strip.show();
  }
  //else Serial.print(".\n");
  
  //ContinuePattern();
}

void setupReceiver()
{
  //  Set up the VirtualWire system
  vw_set_rx_pin(VW_DATA_RX_PIN);
  vw_set_ptt_inverted(true); // Required for DR3100
  vw_setup(400); // Bits per sec
  vw_rx_start(); // Start the receiver PLL running
}

void setup()
{
  pinMode(DISPLAY_PIN, OUTPUT);
  
  // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
  #if defined (__AVR_ATtiny85__)
    if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
  #endif
  // End of trinket special code

  strip.begin();
  colorWipe(strip.Color(0, 0, 0), 0);
  strip.show(); // Initialize all pixels to 'off'
  
  Serial.begin(9600);
  randomSeed(analogRead(0));
  
  setupReceiver();
  
  Serial.write("Program started\n");
}

void loop()
{
  CheckForMessages();
}

As you can see, the signal recieved for green (message ID 1) does nothing, except that it shows in the serial output that a message is received. This is how I first discovered that the freezing (of sorts) occurs when I change the color.

If I remove the line “strip.show();” the program works, and I can tell from the Serial output that all messages are being received. Having that line in there breaks the message system completely, though… and obviously I need it to have the LED strip actually light up.

Some notes:

  • I tried putting in “interrupts();” right after strip.show() just in case interrupts were still disabled by NeoPixel, but that did nothing.
  • I tried re-initializing the radio receiver after strip.show() just in case the interrupts being off temporarily caused a problem, but that did nothing.
  • I tried using FastLED as well, but it had the same problem

There's been a break through. I set the lights up to be blue and then removed the power and when I turned it back on with my working code (the one without "FastLED.show()") it didn't work... and I realized that the radio receiver isn't just not working because I'm calling show... it's not working because the lights are on. This just happened to be what FastLED.show() was doing so I thought it must be a software issue... but now I know that it happens even when that call isn't made, only when the lights are on.

So I checked the voltage going to the radio receiver when the lights were completely disconnected. 4.6 volts (I would have expected closer to 5 but it's clearly enough to run the receiver). Then I checked the amount when the lights were connected. 3.4 volts (a drastic lowering that seems to have taken it into the range where it is not operable).

So this isn't really a networking or protocol problem anymore, but I think it might be a devices issue still, as using a NeoPixel lowers the remaining working voltage below what we need to run the receiver.

Does anyone have any suggestion for what I could do about this?

A neopixel on full brightness white draws 60mA. So your strip of 60 needs a maximum of 3.6A. If you limit your effects to lower brightness and not having all three colours on at once, you could get away with less.

But either way you should use a separate power supply for the neopixels, not power them through the Arduino. Adafruit also recommend a 1,000uF capacitor across the neopixel strip power connections and a 470R resistor in series between the Arduino output pin and the neopixel Din connection.

I'll try adding the 1,000uF capacitor and the 470R resistor to see if that helps at all. I'd like to have full brightness but also would like (for the sake of my project... it's supposed to be a simple product) to have all power come from the same source. I'll keep searching for solutions if the capacitor and resistor don't help.

Thank you for your reply.

You could use the external power supply for the Arduinos too.

I’m back. After a couple of days, the parts I needed arrived. I put the 1000uf capacitor between the power and ground lines near where the NeoPixel strip connects to them. I put the 470 Ohm resistor between the Arduino and the data line going to the NeoPixel strip. I might be imagining it, but it almost seems like the problem is slightly lessened (though it could be an improvement in my testing… now I just send out the messages automatically and repeatedly every second so I can test more easily).

I’m not exactly sure what yo mean regarding the external power supply. I would need to be supplying 5volts to the NeoPixel strip, and then at least 5volts to the Arduino as well. I don’t want the device I’m building to have multiple power supplies, so it would have to be just one. So I’m at a bit of a stand-still.

There has to be a way to do this, right? You were in another topic where it looks like this guy was having the same problem a year ago and never got it resolved… I think his issue was probably also the voltage: http://forum.arduino.cc/index.php?topic=241922.0

How are you powering the Arduino and the neopixels in your tests?

I've tried through USB and through a battery pack supplying around 5 volts (4 AA batteries so it should have had plenty of current for what it's doing)

Hi,

I have the same problem - I am using the nonblocking version of Adafruits Neopixel library (Put it all together... | Multi-tasking the Arduino - Part 3 | Adafruit Learning System).
After googling a lot it appears that both Neopixel and VirtualWire are using Timer1 (which also breaks servos).

You can either manually edit the VirtualWire library to use Timer2 or use an alternative like RadioHead (RadioHead: RadioHead Packet Radio library for embedded microprocessors).
For RadioHead you need to edit the RH_ASK.cpp and uncomment "#define RH_ASK_ARDUINO_USE_TIMER2".

Please note that with the Arduino Leonardo you still need to edit some of the files, all other Arduinos should be fine.