Possible bad circuit causing Arduino to hang alt. RF transmission to fail.

I'm moving a thread from the Programming Questions part of the forum to here since it's starting to look more and more like a hardware issue. Most likely my not quite able circuit building skills.

The short story:
I want to control an RGB LED via a RF Transmitter/Receiver pair using VirtualWire. The transmitter sends 0-1023 from a potentiometer to the receiver that uses the incoming data to control the LED. Everything in this circuit works perfect as long as I don't try to analogWrite to the LED. Well it works for a couple of seconds but then fails. Seemingly no transmission gets through to the receiver.

For the long story check the thread in the link above.

This is what I've checked:
The transmitter is not the problem. It continues to send data after the "hang".
The LED is not the problem. It works just fine if I run the code "locally" on the receiver unit with a potentiometer hooked up.
If I just yank out the LED from the circuit the problems disappear. But I guess that comes from breaking the circuit this removing the issue that might be causing problems.

EDIT: Fixed broken links.
Circuit diagram
Breadboarded Circuit 1
Breadboarded Circuit 2
Breadboarded Circuit 3

Since it looks a bit messy I might aswell say, NO! There are no crossed leads touching.

Anyone able to spot anything that might cause the RF receiver to stop receiveing data or atleast disturb the transmission.

Code parts below for the curious.

Code for the receiver

/* 
  RGB LED controller
*/

#include <VirtualWire.h>

// LED's
int ledPin = 13;

// Sensors 
int Sensor1Data;
int potVal;

// RF Transmission container
// char Sensor1CharMsg[5]; // commented out not necessary

// set the ledPins
int ledRed = 6; 
int ledGreen = 5; 
int ledBlue = 3; 

// LED Power variables
byte redPwr = 0;
byte greenPwr = 0;
byte bluePwr = 0;

void setup()
{
  
  // sets the digital pin as output
  pinMode(ledPin, OUTPUT);      
    
    // VirtualWire 
    // Initialise the IO and ISR
    // Required for DR3100
    vw_set_ptt_inverted(true); 
    // Bits per sec
    vw_setup(2000);	 
    
    // Start the receiver PLL running
    vw_rx_start();       

  pinMode(ledRed, OUTPUT);
  pinMode(ledGreen, OUTPUT);
  pinMode(ledBlue, OUTPUT);
    
  // serial for debugging purposes only
  Serial.begin(9600);
}

void loop()
{  
  dataRX();
  colorControl();
   
  // DEBUG 
  Serial.print("Sensor 1: ");
  Serial.print(Sensor1Data);
  Serial.print(" potVal: ");
  Serial.print(potVal);
  
  
  Serial.print(" redPwr: ");
  Serial.print(redPwr, DEC);
  Serial.print(" greenPwr: ");
  Serial.print(greenPwr, DEC);
  Serial.print(" bluePwr: ");
  Serial.println(bluePwr, DEC);
  // END DEBUG
 

} // END loop()

void dataRX()
 {
   uint8_t buf[VW_MAX_MESSAGE_LEN];
   uint8_t buflen = VW_MAX_MESSAGE_LEN;
    
    // Non-blocking
    if (vw_get_message(buf, &buflen)) 
    {
	int i;
        // Turn on a light to show received good message 
        digitalWrite(13, true); 
	
        /* Commented out for buffer to integer directly 
        
        // Message with a good checksum received, dump it. 
        for (i = 0; i < buflen; i++)
	{            
          // Fill Sensor1CharMsg Char array with corresponding 
          // chars from buffer.   
          Sensor1CharMsg[i] = char(buf[i]);
	}
        
        // Null terminate the char array
        // This needs to be done otherwise problems will occur
        // when the incoming messages has less digits than the
        // one before. 
        Sensor1CharMsg[buflen] = '\0';
        
        // Convert Sensor1CharMsg Char array to integer
        Sensor1Data = atoi(Sensor1CharMsg);
        
        */
        // Convert buffer directly to Integer String 
        Sensor1Data = atoi((const char*)buf);
        
        // Turn off light to and await next message 
        digitalWrite(13, false);
  }
  // delay(200);
}

// lightMode 1 
void colorControl() {
  
  // read the potentiometer position 
  potVal = Sensor1Data;
  
  // RED > ORANGE > YELLOW
   if (potVal > 0 && potVal < 170) {
     redPwr = 255;
     bluePwr = 0;
     greenPwr = map(potVal, 0, 170, 0, 255);
   }
 
   // YELLOW > LIME?? > GREEN 
   if (potVal > 170 && potVal < 341) {
     greenPwr = 255;
     bluePwr = 0;
     redPwr = map(potVal, 341, 170, 0, 255);
   }

    // GREEN > TURQOUISE
    if (potVal > 341 && potVal < 511) {
      greenPwr = 255;
      redPwr = 0;
      bluePwr = map(potVal, 341, 511, 0, 255);
    }
 
   // TURQOUISE > BLUE  
   if (potVal > 511 && potVal < 682) {
     bluePwr = 255;
     redPwr = 0;
     greenPwr = map(potVal, 682, 511, 0, 255);
   }
 
   // BLUE > PURPLE 
   if (potVal > 682 && potVal < 852) {
     bluePwr = 255;
     greenPwr = 0;
     redPwr = map(potVal, 682, 852, 0, 255);
   }
 
   // PURPLE > RED
   if (potVal > 852 && potVal < 1023) {
     redPwr = 255;
     greenPwr = 0;
     bluePwr = map(potVal, 1023, 852, 0, 255);
   } 
   
  // Display colors 
  colorDisplay();
}        

// Displays the colors when called from other functions
void colorDisplay() {
  analogWrite(ledRed, redPwr);
  analogWrite(ledGreen, greenPwr);
  analogWrite(ledBlue, bluePwr);
}

Code for the transmitter

/* 

Sensor Transmitter 
By Markus Ulfberg 2012-07-06

Takes a sensor reading 0-1023
converts it to a char array and sends 
to RF receiver unit via VirtualWire  

*/

#include <VirtualWire.h>

// LED's
const int ledPin = 13;

// Sensors 
const int Sensor1Pin = A2;
// const int Sensor2Pin = 3; 

int Sensor1Data;
char Sensor1CharMsg[5]; 


void setup() {

 // PinModes 
 // LED 
 pinMode(ledPin,OUTPUT);
 // Sensor(s)
 pinMode(Sensor1Pin,INPUT);
 
 // for debugging
 Serial.begin(9600); 
 
 // VirtualWire setup
 vw_setup(2000);	 // Bits per sec


}

void loop() {
  
  // Read and store Sensor 1 data
  Sensor1Data = analogRead(Sensor1Pin);
  
  // Convert integer data to Char array directly 
  itoa(Sensor1Data,Sensor1CharMsg,10);
  
  /*
  // DEBUG
  Serial.print("Sensor1 Integer: ");
  Serial.print(Sensor1Data);
  Serial.print(" Sensor1 CharMsg: ");
  Serial.print(Sensor1CharMsg);
  Serial.println(" ");

  // END DEBUG
  */
 
 digitalWrite(13, true); // Turn on a light to show transmitting
 vw_send((uint8_t *)Sensor1CharMsg, strlen(Sensor1CharMsg));
 vw_wait_tx(); // Wait until the whole message is gone
 digitalWrite(13, false); // Turn off a light after transmission
 delay(200); 
 
} // END void loop...

Just as a test try replacing those 100R resistors in the LED with 1K and see if it still happens. It could be the PWM causing interference with the receiver and cutting down the current will reduce the amount you generate.

Yup that worked. It's been running for over ten minutes now and seems to work fine, it does however cause some glitches but these are just momentary.

Is there anything I can do to reduce the interference?

I also added a small 0.1uF capacitor between the +5V and GND pins closest to the antenna on the RF receiver. Allthough I should add this didn't help anything before, but I just haven't removed it yet. I found it in a similar circuit in Tom Igoe's Making Things Talk so I hoped it might help.

Try putting a small capacitor directly across each LED, to reduce the rise time of the current in the wire, this reduces the interference. Try a 100pF to start with.
Also ferrite beads on the connecting wires of the LED could also help.

Ok, thank you ever so much.

Just to make sure I understand you is this how I should connect them? Circuit Diagram

Next question:
Since I don't have any 100pF Caps lying around I need to order them so I thought I might aswell order a whole bunch of various caps while I'm at it. So what if 100pF won't work then what would you suggest I try next?
The lowest value caps I have at home is 100nF, could I use those?

EDIT: Fixed broken link.

is this how I should connect them?

Yes :slight_smile:

The lowest value caps I have at home is 100nF, could I use those?

They might be a bit big and interfere with the PWM signal but there is nothing stopping you trying.

So what if 100pF won't work then what would you suggest I try next?

Try going up in half decades, 470pF, 1nF, 4n7, 10nF and so on.

Ok thank you.

Regarding the ferrite beads. Is this what I'm looking for?

or is it one of these?
http://www.electrokit.com/en/thru-hole-mounted-rf-chokes.c370

Regarding the ferrite beads. Is this what I'm looking for?
http://www.electrokit.com/en/ferrit-bl01rna62t5-murata-axiell-o3-6x5.43402

Yes that is what I am thinking about. These are effective at very high frequencies.

The other link shows a choke, that can slow down the current rise like the capacitors, you can use them both but the capacitor should do the job just as well as both.

Ok, my order came through pretty quickly but I didn't have the time to try it out until today.

So far I've tried 100pF, 470pF, 1nF, 4n7F and 10nF. None of them really gave me a flawless transmission but I'd say it was a little bit better than before. Not much change from changing caps values.

I've also tried placing three of the ferrites in series with each anode of the LED before the resistor. Also just one ferrite in series with the cathode of the LED to GND. Both of those gave me roughly the same result as the caps.

I've also tried a mix of caps and ferrites.

What else can I try to reduce the interference? Should I continue up in capacitor size until I hit it or are there other approaches?

Well the other thing to try is to get the wiring a lot neater. The wires are where the signals radiate from so short and close, maybe even running together with a ground wire. If you go for a screened cable then make sure the screen is only connected to ground at one end. Make the LED lead shorter as well. Anything to reduce the radiation.
It won't be one thing but a combination of measures. Try and move the receiver antenna further away as well.

These sort of things are not easy to fix, it is more of an art, but now you know where the problem is comming from that is half the battle.

I'd second that - run the wires to the LEDs as twisted pairs to reduce radiation for instance. Keep the receiver far away from the LED side of the circuit. Never share grounds between "input" (receiver) and "output" (LED loads)...

Hi everybody!

I've managed to reduce the noise/interference and increase the range somewhat by fiddling around with all the above tips and tricks.
To recap what I've done (I'll post pictures later Iron Man 2 starts on tv soon and I'm a bit tired)

  1. I've physically increased the distance between the LED and the RF Receiver.
  2. I've decoupled the power rails on the breadboard that holds the RF Receiver, first with a 47 uF Capacitor and then two 1 uF Capacitor close on each GND/VCC pin of the receiver. Also I've added a Ferrite along the VCC power rail of the breadboard (it has a gap in the rails so thats where I put it).
  3. On the LED side of the circuit I've shortened the leads of the LED and resistors and added 1 uF capacitors (as described before).

All this did help albeit very little. What actually helped the most was moving the GND source from one side of the Arduino, I originally had both in the GND sockets next to each other. Also changing the transmission speed from 2000 to 300 helped quite a bit.

Well that's it... I hope to improve this but right now I'm too tired. Pictures will come.

EDIT: Added pictures.