Issues with VirtualWire and RF Transmitter/Receiver

I'm trying to create a simple link between two arduinos using an RF transmitter/receiver combo I got from SparkFun. It's my first time working with wireless and Arduino, and it's proving to be quite a challenge! Upon wiring everything and uploading sample software, my receiver is not getting anything at all. I researched this problem on this forum and many others, but most posts end in dead ends or solutions which don't work for me or apply to my situation.

In a desperate attempt to troubleshoot the problem, I removed the transmitter/receiver and just ran a wire directly from the transmitting arduino's tx pin to the rx pin on the receiving arduino. Still nothing! This made me wonder if anything is being sent at all. I don't have an oscilloscope, but I used a voltmeter to see if there is any change in voltage when a signal is being transmitted, and there is. It jumps up to about 1.3V when something is sending. So ~something is sending, but the rx pin is not seeing it. What could be wrong?

One thing to note is that when I check the signal with the voltmeter, it's about 1.3V with respect to the sending arduino's ground, but the needle just barely twitches (really tiny voltage) with respect to the receiving arduino's ground. Is this normal?

Also, one of my arduinos (the transmitting one) is a breadboard version as described here:

It runs some test programs just fine (like blink, fade, etc.) so I think it's set up correctly. I don't have a second "real" arduino to test with though, which makes things difficult.

I appreciate any input/hints!

PS: Here is my code:

// TRANSMITTER CODE

#include <VirtualWire.h>

void setup()
{
    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_set_tx_pin(5); 
        
     pinMode(8, INPUT);
     pinMode(9, INPUT);

digitalWrite(8, HIGH);
digitalWrite(9, HIGH);


}

void loop()
{
  char *msg;
  
  if(digitalRead(8) == LOW){
    char *msg = "1";
      digitalWrite(13, true); // Flash a light to show transmitting
    vw_send((uint8_t *)msg, strlen(msg));
    vw_wait_tx(); // Wait until the whole message is gone
    digitalWrite(13, false);}
  if(digitalRead(9) == LOW){
    char *msg = "2";
      digitalWrite(13, true); // Flash a light to show transmitting
    vw_send((uint8_t *)msg, strlen(msg));
    vw_wait_tx(); // Wait until the whole message is gone
    digitalWrite(13, false);}
  }
  
  */
  //END TRANSMITTER CODE
  // RECIEVER CODE
  
  #include <VirtualWire.h>

void setup()
{
    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_set_rx_pin(4);
    vw_rx_start();       // Start the receiver PLL running

pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(13, OUTPUT);
//pinMode(10, OUTPUT);
//pinMode(11, OUTPUT);
}

void loop()
{
  
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);
  digitalWrite(13, LOW);
  
    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;
    if (vw_get_message(buf, &buflen)) // Non-blocking
    {
      Serial.println("Entered Loop");
	int i;

        digitalWrite(13, true); // Flash a light to show received good message
	// Message with a good checksum received, dump it.
	Serial.print("Got: ");
	
	for (i = 0; i < buflen; i++)
	{
	    Serial.print(buf[i]);
        if(buf[i] == '1'){digitalWrite(8, HIGH);}
        if(buf[i] == '2'){digitalWrite(9, HIGH);}
	    Serial.print(" ");
	}
	Serial.println("");
        digitalWrite(13, false);

   }
}

In a desperate attempt to troubleshoot the problem, I removed the transmitter/receiver and just ran a wire directly from the transmitting arduino's tx pin to the rx pin on the receiving arduino. Still nothing!

Did you connect the grounds together, too?

Why are you expecting the Wire library to communicate using the RX and TX pins? It doesn't.

  char *msg;
  
  if(digitalRead(8) == LOW){
    char *msg = "1";
    digitalWrite(13, false);}
  if(digitalRead(9) == LOW){
    char *msg = "2";

Three local variables with the same name is not a good idea.

There are no recognized coding styles that call for the open or close curly braces to be jammed up against other characters. There are none that allow for the close curly brace to be on the same line as any other code. For good reasons.

Thanks for your response!

Did you connect the grounds together, too?

I did not, should I? I'm a novice, so I really have no idea. I was just following a tutorial, and when it didn't work I tried to troubleshoot it like I described.

Why are you expecting the Wire library to communicate using the RX and TX pins? It doesn't.

I was using example code from SparkFun, and they seem to be using RX and TX for the RF transmitter/receiver pair... A line in the code they provide says "vw_set_tx_pin(5);" - doesn't that mean "set the TX pin to pin 5"? Maybe what you mean is that VirtualWire doesn't use the pins marked TX and RX (pins 1 and 2 on my Uno)? When I said I went directly from tx to rx, I mean the pins set as tx and rx in the code I provided (in my case pins 5 and 4).

With regard to how the variables are defined and the styling of the code - I just copy/pasted their sample code, that's how they wrote it. It might not look pretty or be easy to follow, but it should still work, no? I mean, I can change the positioning of the curly braces and add three separate variables, but that should not really make any difference if the code is supposed to be a working example code from SparkFun.

I did not, should I? I'm a novice, so I really have no idea. I was just following a tutorial, and when it didn't work I tried to troubleshoot it like I described.

If you want the electrons to flow, yes.

When using the radios, of course grounds don't need to be connected, because data is moving over radio waves, not wires.

Maybe what you mean is that VirtualWire doesn't use the pins marked TX and RX

I do.

(pins 1 and 2 on my Uno)

They are pins 0 and 1 on everybody elses...

but it should still work, no?

Yes, but it IS hard to read.

Ok, that makes sense - I'll hook up the grounds together when I get home and see if that helps.

And that's my bad about the pin numbers, it is 0 and 1 like you said.

Virtualwire does not use the UART, it bitbangs out other pins, 11 & 12 unless set otherwise.
If you use 0 & 1, it will still not use the UART and you sacrifice the serial port.

I see, thanks for the clarification CrossRoads.

So I bridged the two grounds together, and I got a strange result. I turned on both boards to see if it would work, and still no messages were being received according to the serial monitor. I decided to check if the voltage spikes were present, so I measured the voltage between the outgoing signal and ground, and when I tried to send a message the voltage spike was present, but more importantly, the messages started going through!

So right now the receiving arduino only successfully receives messages if I have the voltmeter between ground and data out.

What does this mean? Is the voltmeter somehow stabilizing the signal or something? I'm not an expert with electronics (if that's not obvious by now :sweat_smile:) so if anyone can explain how/why this is happening and how it could help me fix my circuit, I would greatly appreciate it!

recheck the ground conections. Sound like miswire.

I rechecked all the connections according to the tutorial I mentioned in my first post, and everything looks correct... Why would bridging the data pin with ground with a voltmeter make this work?

Is that with the Tx & Rx cards in place, or not?
Perhaps the voltmeter wiring is acting as the antenna?

No, the Tx and Rx cards are not in use currently. I'm trying to get a direct, wired connection working before I move up to those. Great idea though, if I was using the cards, I would have never thought of that!

Take this line out

vw_set_ptt_inverted(true); // Required for DR3100

You are not using a Push To Talk switch

I removed the line in both the transmitter and receiver codes, but it still doesn't work unless the voltmeter is in place.

So after looking up some stuff I have a theory on how to fix the circuit, but I wanted to share it with people that know what they're doing when it comes to electronics before I go ahead and do it =]

So the way a voltmeter works is that it provides a very large resistance and the current is measured, right? So essentially when I put the voltmeter there it was the same as a adding a resistor between ground and the pin sending the data. Maybe if I add a large resistor (10kOhm? larger?) between ground and data out it will fix the problem. I guess this will be acting like a pull-down resistor? This might not make sense, I'm just throwing the idea out there.

Yes, your description makes sense. Not clear why you'd need it when you have digital output going to digital input.

Thanks for the confirmation. I installed a 1MOhm resistor between ground and signal out, and now sending the information over the wire works. Now that I know the code is correct, time to figure out what's wrong with my hardware setup when it comes to the RF receiver/transmitter.

Thanks for everyone's help!