RSSI 433 RECEIVER TRANSMITTER

965 views
Skip to first unread message

George Kokkinakis

unread,
Jul 20, 2013, 9:07:05 AM7/20/13
to virtu...@googlegroups.com
i have two arduinos one transmitter and the other is receiver with 434Mhz modules. How can i read the rf signal strength from the receiver arduino using the virtualwire ?. The idea is that the first arduino will be acting as an rf beacon and when the second arduino (the receiver) is near the beacon in a 1 or 2 meters radius the receiver will bling a led.

Mike McCauley

unread,
Jul 20, 2013, 4:48:37 PM7/20/13
to virtu...@googlegroups.com
Hello,
None of the cheap 433 mhz receivers I have seen provide any signal strength
information.

Cheers.

--
Mike McCauley mi...@airspayce.com
Airspayce Pty Ltd 9 Bulbul Place Currumbin Waters QLD 4223 Australia
http://www.airspayce.com
Phone +61 7 5598-7474 Fax +61 7 5598-7070

gary boyce

unread,
Jul 20, 2013, 5:01:20 PM7/20/13
to virtu...@googlegroups.com

Is there any way through code to estimate signal quality by sending a certain amount of bytes of data and showing percentage received? That would be pretty nice.

--
You received this message because you are subscribed to the Google Groups "virtualwire" group.
To unsubscribe from this group and stop receiving emails from it, send an email to virtualwire...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Mike McCauley

unread,
Jul 20, 2013, 6:00:14 PM7/20/13
to virtu...@googlegroups.com
Hello,

On Saturday, July 20, 2013 05:01:20 PM gary boyce wrote:
> Is there any way through code to estimate signal quality by sending a
> certain amount of bytes of data and showing percentage received? That would
> be pretty nice.

Hmm, VirtualWire does keep a 8 bit count of
Number of bad messages received and dropped due to bad lengths
in vw_rx_bad, as well as the
Number of good messages received
in vw_rx_good

Maybe you could experiment with that?

Cheers.

George Kokkinakis

unread,
Jul 20, 2013, 7:29:51 PM7/20/13
to virtu...@googlegroups.com
Do you know if I can low the strength of the rf 434 MHz signal of the transmitter in order to be received only if the receiver is in a 1 or 2 meters radius ?

Mike McCauley

unread,
Jul 20, 2013, 7:34:41 PM7/20/13
to virtu...@googlegroups.com
Hi,

that depends entirely on the transmitter.
The VirtualWire software does not support anything like that: it just sends a
sequence of 0V/5V pulses to the transmitter to encode the data.


Cheers.

James Hamilton

unread,
Jul 20, 2013, 8:00:24 PM7/20/13
to virtu...@googlegroups.com

You might try experimenting with antenna length and input voltage. Higher input voltage will generally result in higher transmit power for these transmitters. Antenna design is more complicated, but I've successfully used my TX/RX pair with 5V in and no antenna at about 20cm distance, more than that becomes unreliable (but I do get some data in that configuration out to about a meter).

73,

~James

On Jul 20, 2013 7:29 PM, "George Kokkinakis" <gred...@gmail.com> wrote:
Do you know if I can low the strength of the rf 434 MHz signal of the transmitter in order to be received only if the receiver is in a 1 or 2 meters radius ?

George Kokkinakis

unread,
Jul 20, 2013, 8:12:32 PM7/20/13
to virtu...@googlegroups.com
I am asking about the strength of the signal because I want to install an arduino with a receiver in my car and tag my keys or my wallet with small rf transmitters that they will act as a beacon. So when I enter the car arduino will inform if all the tagged object are inside the car, that's why I want the transmitters to have a small transmitting radius 1 or 2 meters in order not to be reachable from the receiver if they are out of the car. I have searched for RFID but besides they are expensive they also have a small radius , some cm only.

gary boyce

unread,
Jul 20, 2013, 8:20:45 PM7/20/13
to virtu...@googlegroups.com

If you have the cheap model, decrease the supply voltage. 12 volts gives maximum transmit power. Outside of that you really need to get into some antenna theory. That can get quite complicated. For testing I would suggest using a three inch 50 ohm omni directional antenna over a three inch ground plane. Then only supply the transmitter with three volts. Test the distance and increase or decrease the voltage to achieve the desired operating range.

On Jul 20, 2013 8:12 PM, "George Kokkinakis" <gred...@gmail.com> wrote:
I am asking about the strength of the signal because I want to install an arduino with a receiver in my car and tag my keys or my wallet with small rf transmitters that they will act as a beacon. So when I enter the car arduino will inform if all the tagged object are inside the car, that's why I want the transmitters to have a small transmitting radius 1 or 2 meters in order not to be reachable from the receiver if they are out of the car. I have searched for RFID but besides they are expensive they also have a small radius , some cm only.

gary boyce

unread,
Jul 20, 2013, 10:00:25 PM7/20/13
to virtu...@googlegroups.com
I see // Number of good messages received
static uint8_t vw_rx_good = 0; in the library. How would I print this value to serial?

Mike McCauley

unread,
Jul 20, 2013, 10:05:57 PM7/20/13
to virtu...@googlegroups.com
On Saturday, July 20, 2013 10:00:25 PM gary boyce wrote:
> I see *// Number of good messages received*
> *static uint8_t vw_rx_good = 0;* in the library. How would I print this
> value to serial?

The variable is defined as a static. You will need to edit VirtualWire.cpp and
remove the 'static' keyword.

then you will be able to do thi:

extern uint8_t vw_rx_bad;
Serial.println(vw_rx_bad);

Cheers.

gary boyce

unread,
Jul 20, 2013, 10:19:27 PM7/20/13
to virtu...@googlegroups.com
Thanks!

gary boyce

unread,
Jul 20, 2013, 10:28:39 PM7/20/13
to virtu...@googlegroups.com
I edited VirtualWire.cpp like this
// Number of good messages received
//static uint8_t vw_rx_good = 0;
extern uint8_t vw_rx_good;
And added     Serial.println(vw_rx_good);
When I do that the arduino IDE complains saying... error: 'vw_rx_good' was not declared in this scope
Any idea why?

gary boyce

unread,
Jul 20, 2013, 10:40:24 PM7/20/13
to virtu...@googlegroups.com
Sorry, I got ahead of myself.. OY!

gary boyce

unread,
Jul 20, 2013, 11:07:57 PM7/20/13
to virtu...@googlegroups.com
Okay, I got that part working well. Thanks for that. Now I need suggestions for flooding the link with data for 1 second. With a 100% signal we should be able to send and receive 2000 bytes of data in one second. So thats what I need to do. Any ideas on how to do this with out having to just send 2000 1's?

James Hamilton

unread,
Jul 20, 2013, 11:30:42 PM7/20/13
to virtu...@googlegroups.com
How about this: on the transmitter, keep a counter of how many messages have been sent. Send that counter as the payload. Then the receiver can keep a count of messages received and compare it to how many the transmitter said it sent. 

Much easier than calculating bits sent in a short time period, I think. 

73,

~James


--
~James

gary boyce

unread,
Jul 20, 2013, 11:33:27 PM7/20/13
to virtu...@googlegroups.com
Awesome idea!


gary boyce

unread,
Jul 20, 2013, 11:48:23 PM7/20/13
to virtu...@googlegroups.com
void loop() {
 count++;
delay(1);
if (count == 2000) {
 vw_send(count); //Send all the data in "count"
 vw_wait_tx(); // Wait until the whole message is gone
  
 
Arduino IDE complains saying...  error: too few arguments to function 'uint8_t vw_send(uint8_t*, uint8_t)'

Firstly, Is this what you were saying to do? and secondly, What do I need to do about this error?

gary boyce

unread,
Jul 20, 2013, 11:53:00 PM7/20/13
to virtu...@googlegroups.com
I think I have it with this vw_send((uint8_t *)count, count);
Is this right?

James Hamilton

unread,
Jul 21, 2013, 1:07:23 AM7/21/13
to virtu...@googlegroups.com

I was thinking more along the lines of:

unsigned int count;

void setup() {
count = 0;
// vw setup
// any other setup
}

void loop() {
count++;
mySend(count);
delay(10);
}

void mySend(unsigned int sendValue) {
uint8_t buffer[2];
buffer[0] = highByte(sendValue);
buffer[1] = lowByte(sendValue);
vw_send(buffer, 2);
vw_wait_tx();
}


73,
~James

James Hamilton

unread,
Jul 21, 2013, 1:17:31 AM7/21/13
to virtu...@googlegroups.com

When you call vw_send, you need to give it an array of characters and a length. An int, like count, is not a character array. Although functions like Serial.print() know how to handle things that aren't characters, vw_send() doesn't. You need to convert the int to a sequence of characters (as in my other email). The second argument, the length, is the number of characters to send. For a numeric value, like the count you're sending here, that length is allays the same: the number of characters you used when you converted the number to a character array. To hold numbers from 0 to 65,536 (the range that can be represented by an unsigned int), you need two characters (= 16 bits = 2 bytes = 2*uint8_t).

Does this make more sense?

Cheers,
~James

gary boyce

unread,
Jul 21, 2013, 9:49:40 AM7/21/13
to virtu...@googlegroups.com

Please review my comments and tell me if I understand correctly. 


unsigned int count;

void setup() {
count = 0; // Value to store count


// vw setup
// any other setup
}

void loop() {
count++; // Increment the value of count by 1
mySend(count);
delay(10);
}

void mySend(unsigned int sendValue) {
uint8_t buffer[2]; // States that the buffer is storing 2 bytes?
buffer[0] = highByte(sendValue); //Byte # 1 ?
buffer[1] = lowByte(sendValue); //Byte # 2 ?
vw_send(buffer, 2); //Send the 2 bytes in the buffer?
vw_wait_tx();
}

James Hamilton

unread,
Jul 21, 2013, 12:10:30 PM7/21/13
to virtu...@googlegroups.com
Yep, you got it!

~James


--
~James

gary boyce

unread,
Jul 21, 2013, 12:32:30 PM7/21/13
to virtu...@googlegroups.com
okay.. Good. 
1st Question.. if I want to send 24 bytes of data at one time do I just send 12 high bytes and 12 low bytes?
2nd Question...

I uploaded that sketch to my transmitter and used 

 
int vw_rx_good = 0;
// RF Transmission container
 char vw_rx_goodMsg[4]; 
// Trying to use 5 instead to fit trailing null char 
// go back to 4 if this does not work. 
//char Sensor1CharMsg[5]; 
void setup() {
  Serial.begin(9600);
  Serial.print("RX Start");
 
    // Bits per sec.
    vw_setup(2000);  
   
    // Start the receiver PLL running
    vw_rx_start();       
} // END void setup
void loop(){
    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;
    // Non-blocking
    if (vw_get_message(buf, &buflen)) 
    {
int i;
//        // Message with a good checksum received, dump it. 
        for (i = 0; i < buflen; i++)
{            
//          // Fill vw_rx_goodMsg Char array with corresponding 
//          // chars from buffer.   
         vw_rx_goodMsg[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. 
       vw_rx_goodMsg[buflen] = '\0';
//        
//        // Store value received to vw_rx_good
        vw_rx_good = atoi(vw_rx_goodMsg);
//        
        
        // DEBUG 
        
        Serial.println(vw_rx_good);
}

However, vw_rx_good doesnt print anything. 
If I upload this to my transmitter... 

#include <OneWire.h> //This temperature sensor requires a 4.7k Ohm resistor across its pins 2 and three!!!!
#include <DallasTemperature.h>
#include <Wire.h>
#include <VirtualWire.h>
int ledPin = 13;//Set up the TX indicator pin 13 as LedPin
int vw_rx_good;
int Sensor1Data;//initialize the use of the variable Sensor1Data
//int sensorValue = 0;  // variable to store the value coming from the sensor If using analog sensor
float currentTemp = 0;//to store decimal value coming from the temp sensor
// RF Transmission container
//char Sensor1CharMsg[4]; 
// Trying to use 5 instead to fit trailing null char 
// go back to 4 if this does not work. 
char Sensor1CharMsg[5]; 
//This temperature sensor requires a 4.7k Ohm resistor across its pins 2 and three!!!! Thats the middle pin and the GND pin
// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
DeviceAddress insideThermometer = { 0x28, 0xFA, 0xA5, 0x6B, 0x04, 0x00, 0x00, 0xD8 };
// DeviceAddress outsideThermometer = { 0x28, 0x20, 0x04, 0xA8, 0x02, 0x00, 0x00, 0x4D };

void setup()
{
  pinMode(ledPin, OUTPUT);//Set the ledPin as an output
  Serial.begin(9600);//initialize serial communication
  Serial.print("TX Start");//Print TX Start in the serial terminal
  // VirtualWire 
    // Initialise the IO and ISR
    // Required for DR3100
    //vw_set_ptt_inverted(true); 
    // Bits per sec
    vw_setup(2000); //Set VirtualWire communication speed
// Start up the library
sensors.begin();
// set the resolution to 9 bit (good enough?)
sensors.setResolution(insideThermometer, 9);
// sensors.setResolution(outsideThermometer, 9);
}
void loop(void)
{
  
sensors.requestTemperatures();  //Get temperature from the temp Sensor
float tempC = sensors.getTempC(insideThermometer);
if (tempC == -127.00) {
Serial.write("Error");//Print Error if we read -127
} else {
// lcd.print(tempC);
// lcd.print("/");
Sensor1Data = (DallasTemperature::toFahrenheit(tempC));//Set Sensor1Data as the Celcius to Fahrenheit Conversion
Serial.write(Sensor1Data); //Print the converted temp in the serial terminal
// Integer to ASCII
itoa(Sensor1Data,Sensor1CharMsg,10);
digitalWrite(13, true); // Turn on a light to show transmitting
 vw_send((uint8_t *)Sensor1CharMsg, strlen(Sensor1CharMsg));//Send the data collected

 vw_wait_tx(); // Wait until the whole message is gone
 digitalWrite(13, false); // Turn off a light after transmission
// delay(200);//Wait 200 Milliseconds and then go back to program start
}
}

And this to my receiver....

// include the library code:
#include <avr/sleep.h>
#include "Wire.h"
#include "LiquidCrystal.h"
#include <VirtualWire.h>
int Sensor1Data;
int vw_rx_good;
// RF Transmission container
 char Sensor1CharMsg[4]; 
// Trying to use 5 instead to fit trailing null char 
// go back to 4 if this does not work. 
//char Sensor1CharMsg[5]; 
// Connect via i2c, default address #0 (A0-A2 not jumpered)
LiquidCrystal lcd(0);
void setup() {
  // set up the LCD's number of rows and columns: 
  lcd.begin(16, 2);
  // Print a message to the LCD.
  
       
    // 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();  
}
void loop() {
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  
  lcd.setBacklight(HIGH);
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); 
// lcd.print("Remote Temp: ");
        // 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);
        Sensor1Data = atoi(Sensor1CharMsg);
        
        // DEBUG 
        lcd.setCursor(0, 0);
        lcd.print(vw_rx_good);
        delay(10);
}
}

Then vw_rx_good is readable and is displayed. It is displayed as a number that counts up to 255 then goes back to 0 and starts over. What I really need to do is send 25 bytes of data every 1500ms and on the receiver I need to see how many bytes have been received after 1000ms from the time the last transmission began being received. 

James Hamilton

unread,
Jul 21, 2013, 3:16:04 PM7/21/13
to virtu...@googlegroups.com
1st answer:

If you want to send 24 bytes, you would build a 24-byte buffer:

uint8_t buffer[24];
buffer[0] = 0x1;
buffer[1] = 0x2;
...
buffer[23] = 0x24;

vw_send(buffer, 24);

You could also build a structure and sent it:

struct foo {
  unsigned int a;
  unsigned int b;
// ... other data elements
  unsigned int n;
}

struct foo myFoo;
myFoo.a = 1;
myFoo.b = 2;
myFoo.n = 0xabcd;

vw_send((uint8_t *)&myFoo, sizeof(struct foo));


The highByte() and lowByte() functions are used with the code I sent earlier because an "int" (or "unsigned int") is two bytes.  Using the highByte() and lowByte() functions is an easy way to get the two bytes from the int into an array of type uint8_t, suitable for use with vw_send.  If you wanted to use, for instance, an unsigned long (4 bytes), you may want to be trickier.  This is because the microcontroller that the Arduino is build around is "little endian" (see Endianness on Wikipedia for details).  Alternatively, since you are using an Arduino on both sides, you could ignore endianness altogether (just be aware that it exists if you monitor your TX and RX).

2nd Answer:

Looking at your code, I would choose a different name for vw_rx_good.  Even though it isn't actually conflicting with the vw_rx_good value in the VirtualWire library, it seems like you're trying to manipulate a variable within the library that probably shouldn't be messed with.  For receiving the "sent messages" count I sent previously, I'd use something like this:

unsigned int recvCount;

void setup() {
  recvCount = 0;
 // vw setup, etc
}

void loop() {

  uint8_t buffer[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;

  if (vw_get_message(buf, &buflen)) {
    if (buflen == 2) { // in the example, i always send a 2-byte unsigned int
                            // testing assumptions like this is always good
      recvCount++; // we got another good packet, increment the count
      unsigned int sentCount = word(buffer[0], buffer[1]); // recreate the high and low bytes that were sent
      float recvPercent = (count/sentCount); // percent received = number received / number sent
    }
  }

}

I'm not sure I'm following exactly what you're trying to measure with vw_rx_good on your receiver.  I also don't see where that value is being updated, unless you edited the VirtualWire library to expose its internal vw_rx_good counter.

Cheers,

~James


gary boyce

unread,
Jul 21, 2013, 9:08:11 PM7/21/13
to virtu...@googlegroups.com
Thanks for that James. You have helped me to learn a few things. However, I have realized that in order to measure signal quality, you need two-way communication. So, I believe my little project has come to an end.
Thanks for everyone's help.


Reply all
Reply to author
Forward
0 new messages