VirtualWire and AnalogWrite problems

Dears,

I'm trying to change the color of a RGB led wirelessly but with no success. It seems to be a problem when using both VirtualWire and AnalogWrite together, but I've no idea on how to solve it. When I receive the hex code 00 (led off) or FF (led full on) everything works fine, but when I receive any intermediate value my arduino stops working (i.e., the analogwrite stops working and the serial.println too). The following code is running on an Arduino Nano V3. Thanks for any suggestions.

#include <VirtualWire.h>

int redPin = 3;
int greenPin = 6;
int bluePin = 5;

void setup() {
  Serial.begin(9600);
  Serial.print("Rx ON");
  
  vw_setup(2000); // Bits per sec
  vw_rx_start();    // Start the receiver PLL running
  vw_set_rx_pin(11);

  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
}

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

  if (vw_get_message(buf, &buflen)) {
  
    char redC[3] = {(char)buf[0], (char)buf[1], *"\0"};
    long int red = strtol(redC, NULL, 16);
    analogWrite(redPin, red);
    
    char greenC[3] = {(char)buf[2], (char)buf[3], *"\0"};
    long int green = strtol(greenC, NULL, 16);
    analogWrite(greenPin, green);

    char blueC[3] = {(char)buf[4], (char)buf[5], *"\0"};
    long int blue = strtol(blueC, NULL, 16);
    analogWrite(bluePin, blue);
   
    Serial.print("Red: ");
    Serial.println(red);

    Serial.print("Green: ");
    Serial.println(green);

    Serial.print("Blue: ");
    Serial.println(blue);

  } 
}

Since you don't use pins 9 or 10 for PWM you should be OK.

"Caution: VirtualWire takes over Arduino Timer1, and this will affect the PWM capabil- ities of the digital pins 9 and 10."

Yeap, I've heard that.

Do you have any other idea why this strange behaviour is happening?

Looks like the only thing that would cause the sketch to stop is not receiving any more messages. Have you checked the transmitter to be sure it's still working?

Yes, I've checked the transmitter and it continues to working.

On the receiver side, if I reset the arduino or close and open the serial console, everything comes back until it receives any intermediate value.

Any other suggestions?

carlosraniery:
Any other suggestions?

I don't see any obvious coding errors that might cause a faulure. There is a chance you are triggering some compiler bug. If that's the case then the onlt fix is to make changes to the code style in the hopes of finding a path past the bug.

Two thoughts:

  1. That *"\0" in the array initializer looks fishy to me, somehow. When you print out redC, greenC, and blueC, do you get what you expect? If you change *"\0" to just 0, does it change the behavior?

  2. You don't need strtol() for a one-byte output value; look into atoi(). Probably not what's causing your problem, though.

-br

That *"\0" in the array initializer looks fishy to me, somehow.

It should be '\0'.

You don't need strtol() for a one-byte output value; look into atoi().

The atoi() function does not handle HEX values as input. strtol() does.

Any other suggestions?

Ignore what you get from the VirtualWire class. Hardcode a value for the analogWrite() that is between 0 and 0xFF. What does that do?

I've made some changes on my RX code to find the problem. By now, my code is like that:

#include <VirtualWire.h>

int redPin = 3;

void setup() {
  Serial.begin(9600);
  Serial.print("Rx ON");
  
  vw_setup(1200); // Bits per sec
  vw_rx_start();    // Start the receiver PLL running
  vw_set_rx_pin(11);

  pinMode(redPin, OUTPUT);
}

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

  if (vw_get_message(buf, &buflen)) {
    
    pulse();
    
    //char redC[3] = {(char)buf[0], (char)buf[1], '\0'};
    //long int red = strtol(redC, NULL, 16);
    setRed(255);
    //analogWrite(redPin, (int)red);  
   
  } 
}

void pulse() {
   for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) { 
      setRed(fadeValue);
      delay(30);                            
    } 
  

    for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) { 
      setRed(fadeValue);        
      delay(30);                            
    } 
}

void setRed(int value){
   analogWrite(redPin, value);
}

When I call the method setRed() with 255 or 0 everything goes fine. But when I call it with any intermediate value, the arduino stops working (the pulse method is not executed). This crash is random, sometimes after 1 execution, other times after 10 executions.

Try:

  if (vw_get_message(buf, &buflen)) {
    setRed(255);   
  } 
    pulse();

If the pulses continue it means that your problem is vw_get_message() is not receiving messages with good checksums. Since you assure us that the transmitting code is perfect and refuse to consider that it might have a fault the problem must be in the VirtualWire library. Have you tried updating the library?

How sure are you that the radios are working correctly?

I had the same issue 5 minutes ago and googled for some help to end up in this thread. I found some sort of workaround for this issue. Just surround the analogWrite() calls with a small delay to let the timer return to its normal function or.. I don't know what...

Here is exactly what I did:

        delay(10);
        
        analogWrite(ledR, 255 - r);
        analogWrite(ledG, 255 - g);
        analogWrite(ledB, 255 - b);
        
        delay(100);

the delay(10) and the delay(100) resolved my problem. Haven't tried different set of delays yet, just wanted to share this so that one should not suffer like I did for two days, wondering wtf is going on.

hello,
I've got the same problem on mega and uno.
When i use virtualwire i cannot set PWM on pins 3,5,6 in between 1-254. i can set only 0 or 255.
When i set for ex. 128 arduino hangs (the communication on serial port disappears).

somebody got an idea?
best regards!