vw_send only works on pin 2?

I’m new here and I don’t know where to put this topic, it seems like it might be a programming problem or it could be a hardware issue but I think it is probably programming so I put it here.

I have an Arduino Uno and a Nano. I want the Nano to receive some data and the Uno to send it. But for some reason the Nano doesn’t get anything unless I send the data from pin 2 on the Uno. Also: If I do use pin 2 it still doesn’t work unless the Uno is getting USB power. I have a 5V power supply that is running the Nano (and can run the Uno as well) but if I use that the Nano won’t receive anything from the Uno.

Nano running this program:

// Simple Receive
#include <SPI.h>
#include <VirtualWire.h>

int in_a     =  10;
int out_a    =  9;
int out_b    =  7;

void setup()
{
  pinMode(in_a, INPUT);
  pinMode(out_a, OUTPUT);
  pinMode(out_b, OUTPUT);
  
  Serial.begin(9600);
    
  digitalWrite(out_a, HIGH);
  delay(2000);
  digitalWrite(out_a, LOW);
  delay(200);
  digitalWrite(out_a, HIGH);
  delay(200);
  digitalWrite(out_a, LOW);
  
  Serial.println("setup");
  vw_set_rx_pin(in_a);
  vw_setup(2000);
  vw_rx_start();
}
 
void loop()
{
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
  if(vw_get_message(buf, &buflen)) // non-blocking I/O
  {
    int i;
    // Message with a good checksum received, dump HEX
    Serial.print("Got: ");
    for(i = 0; i < buflen; ++i)
    {
      Serial.print(buf[i], HEX);
      Serial.print(" ");
	  //Serial.print(buf[i]);
    }
    Serial.println("");
    digitalWrite(out_a, HIGH);
  }
}

So as you can see the Nano starts up, flashes a blue LED on output A, turns it off, then goes into the loop. During the loop it waits until it hears some serial data and then if it gets some it will turn the blue LED back on.

Here’s the Uno:

#include <VirtualWire.h>

const int led_pin = 11;
const int transmit_pin = 2;
const int receive_pin = 12;
const int transmit_en_pin = 3;

void setup()
{
  pinMode(11, OUTPUT);
  pinMode(12, INPUT);
  pinMode(3, OUTPUT);
  pinMode(2, OUTPUT);
  // Initialise the IO and ISR
  vw_set_tx_pin(transmit_pin);
  vw_set_rx_pin(receive_pin);
  vw_set_ptt_pin(transmit_en_pin);
  vw_set_ptt_inverted(true); // Required for DR3100
  vw_setup(2000);	 // Bits per sec
}

byte count = 1;

void loop()
{
  char msg[7] = {'h','e','l','l','o',' ','#'};

  msg[6] = count;
  digitalWrite(led_pin, HIGH); // Flash a light to show transmitting
  vw_send((uint8_t *)msg, 7);
  vw_wait_tx(); // Wait until the whole message is gone
  delay(200);
  digitalWrite(led_pin, LOW);
  delay(1000);
  count = count + 1;
}

I just got that code off the internet, but changed it a little bit. Anyway, it turns on then starts flashing a yellow LED every time it sends the hello message.

If I try to set transmit_pin to 12 for example and then the receive_pin to 2 and I change the pin modes accordingly it doesn’t work.

The Nano had a serial output on it. If I connect that to the computer and use the Serial Monitor and then use a wire between the Uno’s pin 2 and the Nano’s pin 10 the serial monitor will write the hex values of the letters it got on the Serial Monitor, and it will turn on the blue LED. But it stops working (like the Nano does not see any serial data) if I either change the transmit pin or I use the 5V breadboard supply for the Uno as opposed to USB.

Oh and I tested pin 12 on the Uno (the one I want to use instead of 2) and it isn’t dead, it can light up an LED just fine.

I hope that makes sense.

EDIT
I also discovered that unless the Uno is connected via ground to the Nano’s ground it won’t work either.

Hi, welcome to the forum.

The cheap 433MHz modules don't need an inverted signal. Please remove that line.

Is that a 5V power supply you connect to the barrel jack ? or it is a usb charger that you connect to the usb connector ?

You need to have some kind of wire to the antenna pin. About 17cm is best, but any wire is better than no wire. A ground is not needed. The Arduino board can be battery operated and not connected to anything, as long as there an antenna wire.

You can have two Arduion IDE open, each with a serial monitor open, and each connected to its own board. Did you know that ? Try it, so you can develop the sketch for both boards at the same time. And you see the messages of both boards at the same time.

Wireless Fun! Which modules are you using?

You have several issues to work through, and here is how I would troubleshoot them.

  1. Power Supply. Can you power both Arduinos from USB ports on the same computer? You will not need to connect the grounds in this case, and you will be able to upload sketches to both. Remember to change the target board and USB port if you switch back and forth to program the Arduinos.

  2. Software. I recommend that you begin with the transmitter and receiver example sketches in the Virtual Wire library examples. They will use the default RX pin 11 and TX pin 12. One change you will have to make to the Receiver sketch is to set the Serial baud rate to Serial.begin(115200). You could also increase the delay(200) in the transmitter sketch, but without these changes the receiver will not display on the monitor.

  3. Hardware–Arduinos and radio modules. To begin with, I would not use the radios, but just get the software on the two Arduino’s taking together. You will disconnect the RX and TX pins of the Arduinos from the radio modules and connect them together. You will run a jumper from the TX pin 12 on the UNO to the RX pin 11 on the nano. If the two Arduino’s do not communicate with the default pins, you can switch the UNO TX pin and see if that works. If so, there is a hardware problem on the UNO pin 12. If you are using different power supplies with the direct TX/RX connection you will need to connect the grounds together.

When you get the basic sketches working with the direct connection, you can move on to the radios. Remove the jumper between the Arduinos, and connect the Arduino RX or TX pin to its module. Start with the units close, and if you can run a piece of straight antenna wire like Peter_n suggests it will help, but it may not be necessary if the two units are next to each other on your desk. How you hook up the antenna wire will depend on your modules and how you have them mounted.

Good luck, let us know what you find as you break this problem down into its smaller parts.

Okay, the above is my current setup. The Uno with the keypad shield is transmitting the Nano is receiving. Most of the stuff on the breadboard is ancillary and not wired to the Nano. The breadboard is powered from an old 5V DC cell phone charger I connected to it. Uno is USB’d to the computer, the Nano has a USB link but as you can see here it wasn’t connected. I’m using the 433 XD-RF-5V receiver/transmitter pair.

Pressing Left on the Uno makes the blue LED next to the Nano light up, pressing Right makes the red one light up (currently illuminated), Select turns them off.

Two main issues right now…

1: Range sucks. Best range I got is about 1 foot. The antennas are not ideal, but I don’t know much about antennas. I just used steel picture hanging wire for them, is there an ideal antenna material and gauge? I haven’t really looked at this yet, I have mostly been interested in attaining minor successes.

2: The LCD shield on the Uno has a glitch. Earlier in this thread Peter_n advised I don’t need the vw_set_ptt_inverted(true); line for the transmitter code. But for some reason without it the LCD screen remains dark unless I press one of the buttons, then it lights up. With the code the LCD remains lit up (as in the picture) but flickers when I hold down one of the buttons. Any ideas?

v Updated code below v

Transmitter Code:

// Simple Transmit

#include <LiquidCrystal.h>
#include <SPI.h>
#include <VirtualWire.h>

// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// define some values used by the panel and buttons
int lcd_key     = 0;
int btn_press  = 0;
int current_screen = 0;
int prev_screen = 0;
int screen_ready = 0;
int screen_time  = 0;
int out_a  =  A4;

int ready = 0;

#define RIGHT  0
#define UP     1
#define DOWN   2
#define LEFT   3
#define SELECT 4
#define NONE   5

// read the buttons
int read_LCD_buttons()
{
 btn_press = analogRead(0);
 if (btn_press > 1000) return NONE; // We make this the 1st option for speed reasons
 // For V1.1 us this threshold
 /*
 if (btn_press < 50)   return RIGHT;  
 if (btn_press < 250)  return UP; 
 if (btn_press < 450)  return DOWN; 
 if (btn_press < 650)  return LEFT; 
 if (btn_press < 850)  return SELECT;  
*/
 // For V1.0 comment the other threshold and use the one below:

 if (btn_press < 50)   return RIGHT;  
 if (btn_press < 195)  return UP; 
 if (btn_press < 380)  return DOWN; 
 if (btn_press < 555)  return LEFT; 
 if (btn_press < 790)  return SELECT;   

 return NONE;  // when all others fail, return this...
}

void setup()
{
  pinMode(out_a, OUTPUT);
  vw_set_ptt_inverted(true);
  
  vw_setup(2000);
  vw_set_tx_pin(out_a);
  
  // Set up the display.
  lcd.begin(16, 2);    
}
 
void loop()
{
  if (ready == 0)
  {
    getReady();
    ready = 1;
  }
  lcd.setCursor(0,1);            // move to the begining of the second line
  lcd_key = read_LCD_buttons();  // read the buttons
  
  if (prev_screen != current_screen)
  {
    displayScreen(current_screen);
    prev_screen = current_screen;
    screen_ready = 0;
  }

  if ((current_screen == 0) && (screen_ready == 1))
  {   
    switch (lcd_key)               // depending on which button was pushed, we perform an action
    {
      case RIGHT:
      {
        char *msg = "0";
        vw_send((uint8_t *)msg, strlen(msg));
        vw_wait_tx();
        break;
      }
      case LEFT:
      {
        char *msg = "1";
        vw_send((uint8_t *)msg, strlen(msg));
        vw_wait_tx();
        break;
      }
      case UP:
      {
        break;
      }
      case DOWN:
      {
        break;
      }
      case SELECT:
      {
        char *msg = "2";
        vw_send((uint8_t *)msg, strlen(msg));
        vw_wait_tx();
        break;
      }
      case NONE:
      {
        break;
      }
    }  
  }
}

void displayScreen(int scr)
{
  if (current_screen == 0)
  {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Main Screen");
    delay(400);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Blue L or Red R");
    lcd.setCursor(0,1);
    lcd.print("Select is Off");
    screen_ready = 1;
    screen_time = millis();
  }
  else if (current_screen < 0)
  {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("ERROR:");
    lcd.setCursor(0,1);
    lcd.print("current_screen < 0");
  }
}
  
void printWithSpace(int num, int posx, int posy)
{
  lcd.setCursor(posx, posy);
  lcd.print(num);
  if (num < 1000)
  {
    lcd.setCursor(posx + 3, posy);
    lcd.print(" ");
  }
  if (num < 100)
  {
    lcd.setCursor(posx + 2, posy);
    lcd.print("  ");
  }
  if (num < 10)
  {
    lcd.setCursor(posx + 1, posy);
    lcd.print("   ");
  }
}
void getReady()
{
    // Hello World!!
  lcd.clear();        
  lcd.setCursor(0,0);
  lcd.print("Simple Transmit");
  lcd.setCursor(0,1);
  lcd.print(" Version 0.00 N ");
  
  delay(2000);
  lcd.clear();
  
  current_screen = 0;
  displayScreen(current_screen);
}

Receiver Code:

// Simple Receive

#include <SPI.h>
#include <VirtualWire.h>


int in_a     =  3;
int out_a    =  9;
int out_b    =  10;

void setup()
{
  pinMode(in_a, INPUT);
  pinMode(out_a, OUTPUT);
  pinMode(out_b, OUTPUT);
  
  Serial.begin(9600);
    
  digitalWrite(out_a, HIGH);
  delay(2000);
  digitalWrite(out_a, LOW);
  delay(200);
  digitalWrite(out_a, HIGH);
  delay(200);
  digitalWrite(out_a, LOW);
  
  Serial.println("setup");
  vw_set_rx_pin(in_a);
  vw_setup(2000);
  vw_rx_start();
}
 
void loop()
{
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
  if(vw_get_message(buf, &buflen)) // non-blocking I/O
  {
    int i;
    // Message with a good checksum received, dump HEX
    Serial.print("Got: ");
    for(i = 0; i < buflen; ++i)
    {
      Serial.write(buf[i]);
      Serial.write(" ");
      Serial.print(buf[i]);
      Serial.write(" ");
      Serial.print(buf[i], HEX);
       
      if(buf[i] == 48)
      {
        digitalWrite(out_a, LOW);
        digitalWrite(out_b, HIGH);
      }
      else if(buf[i] == 49)
      {
        digitalWrite(out_a, HIGH);
        digitalWrite(out_b, LOW);
      }
      else if(buf[i] == 50)
      {
        digitalWrite(out_a, LOW);
        digitalWrite(out_b, LOW);
      }
    }
    Serial.println("");
  }
}

I’m glad I got this much working but I’m going to have to make a lot more progress if I want this to be usable. In the end it needs to transmit about 200 feet.

2: The LCD shield on the Uno has a glitch. Earlier in this thread Peter_n advised I don't need the vw_set_ptt_inverted(true); line for the transmitter code. But for some reason without it the LCD screen remains dark unless I press one of the buttons, then it lights up. With the code the LCD remains lit up (as in the picture) but flickers when I hold down one of the buttons. Any ideas?

There is a conflict with pin 10 which is being used as the PTT pin and backlight control on the shield.

If you go to the Displays section of the forum, there is a sticky post on issues with the backlight on this shield.

I would suggest that you handle the back lightpin 10 in setup as follows

digitalWrite(10,LOW);
  pinMode(10,INPUT);//LCD backlight ON
  //pinMode(10,OUTPUT);//LCD backlight OFF

I have been looking in the VW library and there may be a way to turn off the PTT function in VirtualWire_Config, but I'm not currently comfortable with how to do it. If you don't invoke the vw_set_PTT_inverted(true) it may not be activated as well. To be safe for for now, use vw_set_PTT_pin(#) to set it for some unused pin. You won't need to use the inverted(true) setting. See if this doesn't fix the interaction between the backlight and the TX.

Thanks cattledog.

For the transmitter I put vw_set_ptt_pin(12); into the void setup() section and that solved the LCD backlight. I also commented out vw_set_ptt_inverted(true);.

Reading another thread gave me the idea of playing with vw_setup(); so I first tried changing it to 500 but that halved the range, I was only getting like 5"-6" with it at 500. So naturally I tried switching it to 4000 which a little more than doubled the initial range and it started working at a distance of about 1 yard.

In the other thread I was reading it seemed like having a slower data speed would increase reliability but here it is giving me better reliability to have a higher speed? Also, for the end result the receiver Nano needs to be on a battery supply, will a higher speed make the battery die faster? The battery will only need to last about 1 day, and could still be workable if it lasted as little as 2 hours. The load will be one LED at a time and the LEDs will be turned off at least 75% of the time that the Nano is activated. The antenna for the Nano will be elevated about 5 feet off the ground in a mostly open area free of metallic obstructions but people might go between it and the transmitter, the transmitter being about 100 feet away.

You are making good progress, and are up and running to the point where you are dealing with issues of range and battery life, which are more difficult than getting two units to say "hello" on your desktop.

The default transmit speed is 2000, and if you don't get better range going below there, it might be best to stick with that. If range goes up at 4000 for some reason, there may be a trade off with missed data.

One easy experiment is to run the transmitter module from a 9v battery or even 12v source if you have one. TX power rises at higher voltages. With USB and the shield you may not be getting 5v. Be careful if you use an unregulated wall wart for power, as they can be quite a bit higher in output voltage at less than the stated load and the TX module will probably draw less than 50 ma.

Take a look at this thread "Best Cheap and Simple 433 MHZ modules with good range" http://forum.arduino.cc/index.php?topic=216524.30

Many people have struggled with the lowest cost modules, and there are slightly more expensive versions which use superheterodyne receivers instead of superregenerative ones. http://www.ebay.com/itm/281169560721

If you can't get the range as you move through the cheapo radios, there are quite good 433mhz units above the second tier price range.

The one you just linked to, does it still use the vw library or something entirely different?

Yes, the rf modules which use ASK work with VirtualWire.

There is a replacement for VW called RadioHead-- http://www.airspayce.com/mikem/arduino/RadioHead

The RH_ASK driver in that library provides the features of VirtualWire.

RadioHead also includes drivers for a wide range of other families of wireless devices.

Having another problem with this.

Long story short I am trying to put the transmitter code on a second Arduino. I’m using an UNO with a keypad shield once again, but I think the shield was made by a different manufacturer. (Retailer must have changed suppliers.) It says Mango on it but I can’t find it in google.

Anyway, the problem is that the keypad shield is not displaying any text. The backlight is on, and I modified the code to give serial output when the buttons are pressed and they seem to work, but there are no words or letters of any kind displayed on the screen, it just lights up blue.

Current code:

// Simple Transmit

#include <LiquidCrystal.h>
#include <SPI.h>
#include <VirtualWire.h>

// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// define some values used by the panel and buttons
int lcd_key     = 0;
int btn_press  = 0;
int current_screen = 0;
int prev_screen = 0;
int screen_ready = 0;
int screen_time  = 0;
int out_a  =  A4;

int ready = 0;

#define RIGHT  0
#define UP     1
#define DOWN   2
#define LEFT   3
#define SELECT 4
#define NONE   5

// read the buttons
int read_LCD_buttons()
{
 btn_press = analogRead(0);
 if (btn_press > 1000) return NONE; // We make this the 1st option for speed reasons since it will be the most likely result
 // For V1.1 us this threshold
 /*
 if (btn_press < 50)   return RIGHT;  
 if (btn_press < 250)  return UP; 
 if (btn_press < 450)  return DOWN; 
 if (btn_press < 650)  return LEFT; 
 if (btn_press < 850)  return SELECT;  
*/
 // For V1.0 comment the other threshold and use the one below:

 if (btn_press < 50)   return RIGHT;  
 if (btn_press < 195)  return UP; 
 if (btn_press < 380)  return DOWN; 
 if (btn_press < 555)  return LEFT; 
 if (btn_press < 790)  return SELECT;   

 return NONE;  // when all others fail, return this...
}

void setup()
{
  pinMode(out_a, OUTPUT);
//  vw_set_ptt_inverted(true);
  vw_set_ptt_pin(12);
  
  vw_setup(8000);
  vw_set_tx_pin(out_a);
  
  // Set up the display.
  lcd.begin(16, 2);
  Serial.begin(9600);
  Serial.println("setup");
}
 
void loop()
{
  if (ready == 0)
  {
    getReady();
    ready = 1;
  }
  lcd.setCursor(0,1);            // move to the begining of the second line
  lcd_key = read_LCD_buttons();  // read the buttons
  
  if (prev_screen != current_screen)
  {
    displayScreen(current_screen);
    prev_screen = current_screen;
    screen_ready = 0;
  }

  if ((current_screen == 0) && (screen_ready == 1))
  {   
    switch (lcd_key)               // depending on which button was pushed, we perform an action
    {
      case RIGHT:
      {
        char *msg = "0";
        vw_send((uint8_t *)msg, strlen(msg));
        vw_wait_tx();
        Serial.println("R");
        break;
      }
      case LEFT:
      {
        char *msg = "1";
        vw_send((uint8_t *)msg, strlen(msg));
        vw_wait_tx();
        Serial.println("L");
        break;
      }
      case UP:
      {
        Serial.println("U");
        break;
      }
      case DOWN:
      {
        Serial.println("D");
        break;
      }
      case SELECT:
      {
        char *msg = "2";
        vw_send((uint8_t *)msg, strlen(msg));
        vw_wait_tx();
        Serial.println("SELECT");
        break;
      }
      case NONE:
      {
        break;
      }
    }  
  }
}  
void displayScreen(int scr)
{
  if (current_screen == 0)
  {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Main Screen");
    delay(400);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Blue L or Red R");
    lcd.setCursor(0,1);
    lcd.print("Select is Off");
    screen_ready = 1;
    screen_time = millis();
  }
  else if (current_screen < 0)
  {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("ERROR:");
    lcd.setCursor(0,1);
    lcd.print("current_screen < 0");
  }
}
  
void printWithSpace(int num, int posx, int posy)
{
  lcd.setCursor(posx, posy);
  lcd.print(num);
  if (num < 1000)
  {
    lcd.setCursor(posx + 3, posy);
    lcd.print(" ");
  }
  if (num < 100)
  {
    lcd.setCursor(posx + 2, posy);
    lcd.print("  ");
  }
  if (num < 10)
  {
    lcd.setCursor(posx + 1, posy);
    lcd.print("   ");
  }
}
void getReady()
{
    // Hello World!!
  lcd.clear();        
  lcd.setCursor(0,0);
  lcd.print("Simple Transmit");
  lcd.setCursor(0,1);
  lcd.print(" Version 0.00 N ");
  
  delay(2000);
  lcd.clear();
  
  current_screen = 0;
  displayScreen(current_screen);
}