RF Link Kit problem / Virtual Wire

This is the RF Link Kit in question:
http://www.seeedstudio.com/depot/2km-long-range-rf-link-kits-w-encoder-and-decoder-p-321.html
(2KM Long Range RF link kits w/ encoder and decoder)


I am building a wireless link to be able to remotely monitor a greenhouse temperature. The temperature will be represented by an analogue voltage derived from a thermistor, say in range 0-3V.

I am using an Arduino Mega to convert the analogue input to a digital output and plan to feed this into a wireless board. I then have a matching wireless receiver which feeds a Arduino Duemilanove which is connected to the PC via USB.

The wireless transmitter and receiver work OK over the required distance - I can transmit a binary signal to flash an LED on the receiver, using the following code

// RECEIVER - DUEMILANOVE
void setup()
{
  pinMode(A1, INPUT);  // Receiver (using analog as digital for convenience)
  pinMode(13, OUTPUT);
}

void loop()
{
  int sig = digitalRead(A1);
  
  if (sig) {
    digitalWrite(13, HIGH);
  }
    else{
    digitalWrite(13, LOW);
  }
}

// TRANSMITTER - MEGA

void setup()
{
  Serial.begin(9600);
  
  pinMode(13, OUTPUT);
  pinMode(50, OUTPUT); // transmitter, digital pin
}

void loop()
{
    digitalWrite(50, HIGH);
    digitalWrite(13,HIGH);
    delay(200);
    digitalWrite(50, LOW);
    digitalWrite(13,LOW);
    delay(200);
}

However I can't figure out how to get it to send a data message representing the analogue signal from the thermistor. My plan was to use virtual wire, but I haven't got the following code to work...

// RECEIVER

#include <VirtualWire.h>

void setup()
{
  pinMode(13, OUTPUT);
  vw_set_ptt_inverted(true);
  Serial.begin(9600);
  vw_set_rx_pin(A1);
  vw_setup(500);
  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))
  {
    Serial.print("Got: ");
    Serial.print(buf[0]);
    digitalWrite(13, HIGH);
    delay(100);
  }
 }

// TRANSMITTER

#include <VirtualWire.h>
void setup()
{
  pinMode(13, OUTPUT);
  vw_set_ptt_inverted(true);
  vw_set_tx_pin(50);
  vw_setup(500);
}

void loop()
{
    char message = 'test';
    vw_send((uint8_t *)&message, strlen(&message));
    vw_wait_tx();
    digitalWrite(13,HIGH);
    delay(400);
    digitalWrite(13,LOW);
    delay(400);
}

I have read something about soldering the pads on the tx and rx boards but I don't see how this would help transmit a message that will vary according to the analogue input to the Arduino....and then pass this on to the PC to decode and translate into a temperature reading.

Can anyone help ? Thanks in advance

The pads on the back are just for setting the 'address' of the Tx & Rx units. If you only have this one set, you can leave them as is.

Take out this line, your part does not need it.
vw_set_ptt_inverted(true);

For your transmitter, you can load up an array and send it like this:

     msg[0]=key;                               // load the array with the key character  --> fill this as needed 

    digitalWrite(ledPin, true);               // Flash a light to show transmitting

    vw_send((uint8_t *)msg, strlen(msg));     // send the character out

//    Serial.println(key);                // for debugging only

    vw_wait_tx();                             // Wait until the whole message is gone

    delay (50);                               // need some delay or seem to miss key presses

    digitalWrite(ledPin, false);              // turn off the flash of LED

The receive side will get the data as a string of character

// **********************************************************************************************
// look for wireless input

uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;

if (vw_get_message(buf, &buflen)) // Non-blocking
{
  int i;
  digitalWrite(ledPin, LOW); // Turn on LED to show working a message

  // Message with a good checksum received, dump it.
  //Serial.println("Got: ");  // Show on PC for debugging

  //    for (i = 0; i < buflen; i++)
  //    {
  //Serial.print(byte(buf[i]));
  //    }
  //Serial.println(""); // spaces it out for the monitor

So I think you're pretty close.

Hi, Thanks for your reply.

I have tried that code but to no avail. Below is the precise code I used.
Does anyone else have any other ideas, perhaps alternative to virtualwire or pointers on how I could implement my own software to achieve my goal?

Thanks

// TRANSMITTER
#include <VirtualWire.h>

const int ledPin = 13;
const int txPin = 50;

void setup()
{
  pinMode(ledPin, OUTPUT);
  vw_set_tx_pin(txPin);
  vw_setup(100);
}

void loop()
{   
    char msg[0];
    msg[0]='a';    
    digitalWrite(ledPin, true);               // Flash a light to show transmitting
    vw_send((uint8_t *)msg, strlen(msg));     // send the character out
    Serial.println(msg[0]);                // for debugging only
    vw_wait_tx();                             // Wait until the whole message is gone
    delay (500);                               // need some delay or seem to miss key presses
    digitalWrite(ledPin, false);              // turn off the flash of LED
    delay(500);
    
}
// RECEIVER
#include <VirtualWire.h>

const int ledPin = 13;

void setup(){
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
  vw_set_rx_pin(A1);
  vw_setup(500);
  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
{
  int i;
  digitalWrite(ledPin, LOW); // Turn on LED to show working a message

  // Message with a good checksum received, dump it.
  Serial.println("Got: ");  // Show on PC for debugging

  for (i = 0; i < buflen; i++){
    Serial.print(byte(buf[i]));
  }
  Serial.println(""); // spaces it out for the monitor
}

}

Post your wiring.

This needs to go before setup()

char msg[0]; << and how can you have an array of size 0? Make this bigger, at least 1. Then msg[0] = 'a' should give vald result

why do you transmit at 100
vw_setup(100);

and receive at 500?
vw_setup(500);

That's not gonna work.

May not make a difference, but use a digital pin here, even if same pin but called by digital name.
vw_set_rx_pin(A1);

Thanks, I'm now using const char msg[] = "a"; and have equalized the tx/rx speeds (tried 1,100,500,2000). Wasn't sure what you meant by "even if same pin but called by digital name".

Here is my wiring. Note that I am not using the variable resistor analog signal in my test code, but will be eventually.
Also note that it looks like I am TXing on a pin that should be RXed at A0. In my testing where I was just sending a high/low pulse (which worked), it was in fact RXed at the A1 pin (not sure why). I've tried both A0 and A1 in the code to no avail

const char msg[] = "a";<<

Try it like this, just to make it simple and more clear what is happening.

char msg[1]; // creates an array of size 1 byte << put this at top of the sketch before void setup()

msg[0] = "a"; // loads the array with data

vw_set_rx_pin(A1); <<
do this as
vw_set_rx_pin(15); // this is definitely a digital pin now. I don't know how virtualwire and/or compiler react with an analog pin called out.

same for A0 - call it out as
vw_set_tx_pin(14); // or pin 50 if that is what you are using.

Hi there,
I write because I want to return to the subject of the message.
I have the kit of 2 km Seeedstudio RF (transmitter and receiver) connected to my Arduino as follows:

http://www.seeedstudio.com/depot/2KM-Long-Range-RF-link-kit-w-encoder-decoder-and-p-321.html

///HARDWARE CONECTION
TX: 
D0 -> pin4; 
D1 -> pin5; 
D2 -> pin6; 
D3 -> pin7; 
GND -> GND; 
VDD -> 5v.

and ...

///HARDWARE CONECTIONS
RX: 
VT -> pin3; 
D0 -> pin4; 
D1 -> pin5; 
D2 -> pin6; 
D3 -> pin7; 
GND -> GND; 
VDD -> 5v.

The Virtual Wire library and these RF devices, ¿I can send and receive one (or more than one, better) data type "char" from sender to receiver?
I managed to send and receive up to 4 bits (one for each pin transmitter / receiver) but WITHOUT Virtual Wire; I use this code (get from Seeeduino forum (!thanks!)):

//RECIVER
int data=0;

void setup()
{
  pinMode(3,INPUT);
  pinMode(4,INPUT);
  pinMode(5,INPUT);
  pinMode(6,INPUT);
  pinMode(7,INPUT);
  attachInterrupt(1,RF_VT,RISING);
  Serial.begin(9600);
}
void loop()
{
}
//=======================================
void RF_VT() // interrupt service function
{
  data=(digitalRead(4)<<3)+(digitalRead(5)<<2)+(digitalRead(6)<<1)+(digitalRead(7)<<0);
  Serial.print("data=");
  Serial.println(data,DEC);
}

and....

//TRANSMITER
void setup()
{
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  Serial.begin(9600);
}
void loop()
{
  unsigned char i=0;
  for(i=0;i<16;i++)
  {
    send_data(i);
    Serial.print("i=");
    Serial.println(i,DEC);
    delay(500);
    send_data(0);
    delay(500);
  }
}
//====================================
void send_data(unsigned char data)
{
  digitalWrite(4,(data&0x01));
  digitalWrite(5,(data&0x02));
  digitalWrite(6,(data&0x04));
  digitalWrite(7,(data&0x08));
}

This works but I not how do you send a "char" (8 bits) or more of 1 "char". Sorry for my english, I use googleTranslator...
Thank you very much for your help!

You have bought the wrong RF link kit.
That kit has a encoder and a decoder on the board with the transmitter and receiver.
Its most likley based on the SC 2262 / SC 2272 4 bit data encoders, which can send a 4 bit value from one to the other.
You dont need Virtual Wire.
To send an 8 bit value , you will have to break it into 2 , 4 bit values , and then send the 4 bit values one after the other.

I just want to add my 2 cents, since I've done something very similar and it's been working.

First, I don't believe you can send 2 4-bit chunks. The interrupt will only trigger when the receiver sees data (actually when it see a transition from 0b0000 to something else. So you can't actually send 0b0000. When I did was to send 3 3-bit chunks, with the 0b1000 bit always high. That way, sending 0b0000 through 0b0111 always triggers the interrupt.

I have an application very similar to what is originally described. I needed to monitor temperature (in case the heater fails), water (in case there is flooding due to a burst pipe), and some PIR motion sensors. I managed to create a sketch that transmits a few bytes of data plus a checksum, with each 5-byte transmission taking about 10 seconds. The sender sketch actually sends about 15 3-bit chunks (as described above) over a 4-second internal, then pauses for 6 seconds. The receiver sketch puts it back together. The pause allows the receiver to know when it only received a partial transmission and resync. This is a "lossy" transmission - on average over a long period, only about 95% of the transmissions get through, but for my application that's good enough. I've been able to transmit over about 300 ft, through windows at both ends and through a wooded area between the buildings.