Thursday, September 19, 2013

Tutorial: Arduino + Kit rf 433Mhz (Part4: Multiple variables)

In the final part of this tutorial we will see how to send multiple variables using virtual wire. Let's start then.

There are a lot of forms to send multiple variables trough virtual wire. However,if we want to send different types of data or just send some int's, we can do in the same way, with this code.

Transmitter

With Virtual Wire we can only send an string. So if we want to send other types of data, we need to convert this data into a string.

Fortunately, there are a function to do this. Here is the following  line of code that we have to add.

// Function sprintf
 sprintf(Stringtosend, "%d,%d,%d,%d,", Variable1, Variable2, Variable3, Variable4);
The funcion sprintf converts differents types of data into a string. The función works like this:
sprintf(Stringtosend, specifier of the type of data, data);

specifierOutputExample
d or iSigned decimal integer392
uUnsigned decimal integer7235
oUnsigned octal610
xUnsigned hexadecimal integer7fa
XUnsigned hexadecimal integer (uppercase)7FA
fDecimal floating point, lowercase392.65
FDecimal floating point, uppercase392.65
eScientific notation (mantissa/exponent), lowercase3.9265e+2
EScientific notation (mantissa/exponent), uppercase3.9265E+2
gUse the shortest representation: %e or %f392.65
GUse the shortest representation: %E or %F392.65
aHexadecimal floating point, lowercase-0xc.90fep-2
AHexadecimal floating point, uppercase-0XC.90FEP-2
cCharactera
sString of characterssample
pPointer addressb8000000
nNothing printed.
The corresponding argument must be a pointer to a signed int.
The number of characters written so far is stored in the pointed location.
%% followed by another % character will write a single % to the stream.%

In the table we see the different specifiers  for all the types of data. Using this funcion we can also send an integer and a floating point

sprintf(Stringtosend, "%d,%f,", integer, floatingpoint);

For more information you can see the C++ reference http://www.cplusplus.com/reference/cstdio/printf/

Transmitter Example 


/*.............................................................
Sending Multiple Variables Using VirtualWire. Transmitter
Author: Rodrigo Mompo Redoli
For controlrobotics.rodrigomompo.com
..............................................................*/
#include <VirtualWire.h>

int Sensor1Pin = A1;// The pins were sensor are attached
int Sensor2Pin = A2;
int Sensor3Pin = A3;
int Sensor4Pin = A4; 
int ledPin = 13;
int Sensor1Data;// The variable were the data from each sensor
int Sensor2Data;// will be stored 
int Sensor3Data;
int Sensor4Data;
char Sensor1CharMsg[21];// The string that we are going to send trought rf 

void setup() {

 // LED 
 pinMode(ledPin,OUTPUT);
 
 // Sensor(s)
 pinMode(Sensor1Pin,INPUT);
 pinMode(Sensor2Pin,INPUT);
 pinMode(Sensor3Pin,INPUT);
 pinMode(Sensor4Pin,INPUT);
 
 // VirtualWire setup
 vw_setup(2000); // Bits per sec
 vw_set_tx_pin(12);// Set the Tx pin. Default is 12

}

void loop() {
  
  // Read and store Sensor Data
  Sensor1Data = analogRead(Sensor1Pin);
  Sensor2Data = analogRead(Sensor2Pin);
  Sensor3Data = analogRead(Sensor3Pin);
  Sensor4Data = analogRead(Sensor4Pin);
  
  sprintf(Sensor1CharMsg, "%d,%d,%d,%d,", Sensor1Data, Sensor2Data, Sensor3Data, Sensor4Data);
 
 // Turn on a light to show transmitting
 vw_send((uint8_t *)Sensor1CharMsg, strlen(Sensor1CharMsg));
 vw_wait_tx(); // Wait until the whole message is gone
 // Turn off a light after transmission
 delay(40);

}

Receiver

Now we must be able to send an string and receive it. However ,with this string you can't do anything unless you discompose it and storage on differents variables.For this new challenge we are going to use another function.

 sscanf(StringReceived, "%d,%d,%d,%d",&Sensor1Data, &Sensor2Data,&SeensorData3,&SensorData4);

This function is the opposite of sprinft, and let´s you to storage the information on differents variables. Compile the  receiver code and add some cool things that use this data.

At the end of the code you should erase all the previous data from the string where the new string is storage, so you must call this function

 memset( StringReceived, 0, sizeof( StringReceived));// This line is for reset the StringReceived

Receiver Example

/*.............................................................
Sending Multiple Variables Using VirtualWire. Receiver
Author: Rodrigo Mompo Redoli
For controlrobotics.rodrigomompo.com
..............................................................*/
#include <VirtualWire.h>
 
// Sensors 
int Sensor1Data;
int Sensor2Data;
int SensorData3;
int SensorData4;
 
char StringReceived[22]; 
 
 
 
void setup() {
    // VirtualWire 
    // Initialise the IO and ISR
    // Required for DR3100
 
    // Bits per sec
    vw_setup(2000);
    vw_set_rx_pin(11);  
     
    // 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;
     
//Taking the data from the control base
    if (vw_get_message(buf, &buflen)) 
    {
 int i;
        // Message with a good checksum received, dump it. 
        for (i = 0; i < buflen; i++)
 {            
          // Fill Sensor1CharMsg Char array with corresponding 
          // chars from buffer.   
          StringReceived[i] = char(buf[i]);
 }
 
      sscanf(StringReceived, "%d,%d,%d,%d,%d,%d",&Sensor1Data, &Sensor2Data,&SensorData3,&SensorData4); // Converts a string to an array
         
        // Turn off light to and await next message 
        
    }
 
 memset( StringReceived, 0, sizeof( StringReceived));// This line is for reset the StringReceived
}
Please leave some comments, and send your ideas for new posts in this blog. Also, If you have a project you can publish it on my blog. Subscribe and add me to your Google plus circles.

30 comments:

  1. Hi Rodrigo

    your Rx code does not compile , there are declarations missing

    ReplyDelete
    Replies
    1. The code is already changed. Thanks for reporting the problem¡.

      Delete
  2. Hi Rodrigo
    thank you for the change , but im afraid it still does not work, in your Tx code just small bug catch. # include must be VirtualWire and in you tx code you define as vw_rx pin as 11 but there is no mention in the tx code on which pin to Tx? i have added both these things and is still fails to transmit a msg across , any idea? i really wana get this working

    ReplyDelete
    Replies
    1. I changed the trasnmitter code and compiles fine. As I said in the previous part test it using wire. You have to connect both grounds and the TX pin 12 to Rx pin 11.

      Then you have to test if you received the data printing the result's on the serial monitor. The serail monitor code part is not added in the example. Test it and reply

      If you use the deafult pin you don't have to call the function vw_rx_pin();

      Delete
  3. okay, I added the define to which pins im using for tx and rx. and its working now. I can send 4 ints over no problem, have you done any range testing on these units to see what the max range is ? and other question which is my next step, how would i go about sending over Floats, like GPS lat and long floats

    ReplyDelete
    Replies
    1. t deppens on your set up. With my wire antennas an the transmiter working on 9 volts I have a 20 meters of range with my robot. If you put 12 volts an buy some 433 mhz anntenas you will have more range in theory (up to 100 meters).

      To send float you have to change %d to %f and declare the variable as
      float SensorRead1;
      you can see more detail on arduino.cc

      Delete
    2. Okay i have tried to send float over but i get "?" in both place of sensordata1 and sensordata2 on rx . I have done everything you said. any idea?

      Delete
    3. Do you chaged it on the transmitter and on the reciever?. This could be the problem

      Delete
    4. I changed both TX and RX code, I tried float and I tried double . All I receive is "?" . Would it be possible for you to try it and report back ? Maybe it's something else that I'm not seing

      Delete
    5. orry but I didn`t remmeber before. In the code when you declare the string in both codes, you declare like this "char StringReceived[22]" The number 22 expres de maximun size of the string. But this is not the problem.

      I test it and I have the same problem. The problem is on the TX code It seems like it's a problem with the specifier. So, It's a format problem.I'm googling for solve the problem

      Delete
    6. I found this post on arduino.cc http://forum.arduino.cc/index.php/topic,44262.0.html
      The problem it that the arduino board isn't stronge enought to use floats in this function.

      In the forum makes a homemade solution. You can convert the float on an int (if it's to long, you can do in several ints) send the number as ints and then convert the ints on a float in the other arduino. I will try to test this an post a solution on the blog

      Delete
  4. okay thanx for the help Rodrigo , I know these units are limited but is there something in the VirtualWire library to determine Rssi or signal strength of these units ?

    ReplyDelete
    Replies
    1. I read some post on arduino.cc about this. It's posible but it's quite complex. You also need extrahardaware. However, if you search you probably find some proyects that test the signal strength

      Delete
  5. Hey im back again , after i successfully sent a float via the radios we started with a new project with small palm size robots, my problem is my friend is also building one and we are going to use same radios , how can i encryt or ID my message to be sent ? please make tutorial

    ReplyDelete
    Replies
    1. This week I will finish my exams so I will work on it. Thanks for the idea¡ If you want to search, you will need to search for PPL(phase locked loop). This will resolve the problem.

      Here you have two links about it.
      http://forum.arduino.cc/index.php?topic=172425.0
      http://www.diystompboxes.com/smfforum/index.php?topic=102879.0

      I will try to test it and make a easy tutorial. if you want,You can collaborate with the post

      Delete
    2. I notice that some RF kit have PPL. The PPL it's a kind of filter that in a noisy frequency with a lot of people sending data, you receive only your own string of data. I read that PPL also permits you to increase the range because you have less interference.

      In addiction, you can send an ID. you send a variable with a number like 1234. In the receiver, with an if statement, you check if the incoming string have this ID.


      Delete
    3. A tutorial on how to get the best range might be nice? please best antenna/ settings

      Delete
  6. Very nice example ! ! ! Well Done ! ! !

    You Help me a lot to do a project i like ! ! ! :-)

    Thank you very much ! ! ! ! !

    One question please (if you have time :-) ), how can i use the
    irsend.sendRaw(rawbuf, rawlen, frequency); in Rx module and send the rawbuf,rawlen and frequency from Tx module ?

    I want to send the raw codes from the PC and then to the specific address to control the TV or Satellite.

    Thank you in advance from you're time.

    Best Regards,
    Tasos

    ReplyDelete
  7. Hi Tasos
    If you send int rawbuf,int rawlen,int frecuency using the tutorial.Then in the receiver, with this data, call the function irsend.sendRaw(rawbuf, rawlen, frequency);.

    This should work, try it and leave a comment. I don't have a lot of time, I hope this holidays I will be able to upload some new tutorials. I just finish a portable discolights set for parties. I can upload a tutorial

    ReplyDelete
  8. Hello Dear Rodrigo Mompo,

    Thank you very much for the reply :-)

    I think i got the idea :-)

    I have to modify (or better to make a new temp project on vb.net , and on arduino ) only for this ;-)

    The idea is to control different device from PC but with address, working ok on some devices but i must be make the RawCode in case if the protocol it is unknown.

    For now i use the bellow code and i must to modify for get the rawcode :-)

    sscanf(StringReceived, "%d,%lu,%d,%d,%d", &Address, &Command, &BitLength,&Protocol,&RepeatSend);

    I will give a try (maybe on weekend) and i will let you know :-)

    ReplyDelete
  9. Hi, thank you for the code! It was so useful to me to send multiple data variables. Then, i need to control 4 motors with the received data in the receiver arduino (i'am trying to control the motors from the trasmitter arduino with a potenciometer) but i have the next problem, when the data arrives to the receiver, it receives and print the data only one time and then the communication via virtual wire seems blocked. It could be happening because of the sscanf function? If i receive only 1 data variable(without using sscanf), there is no problem, and i can send the speed data to the motor with analogWrite correctly, but i need to control 4 motors, not only 1.

    Bueno, creo que hablás español, Rodrigo, así que acá va lo mismo en español, por las dudas no lo haya puesto claro en inglés.

    Cuando recibo los datos en el arduino receptor, pareciera que la funcion analogWrite provocara el bloqueo de la funcion vw_get_message, ya que solo recibe e imprime los datos 1 sola vez y luego se bloquea. Esto deja de suceder cuando elimino/comento las líneas de analogWrite que son para enviar el dato de velocidad a los motores. Cuando controlaba solo un motor (sin usar sscanf en el receptor) no había problema al enviar el valor de velocidad al motor con analogWrite. Se me ocurre si puede haber algún problema de sscanf que bloquee a vw_get_message cuando uso analogWrite... Muchas gracias!

    ReplyDelete
  10. Hi, I am wanting to control a 4dc motor robot using these rf devices, on the transmitter side I have a joystick an arduino uno and the transmitter on receiver side I have arduino uno adafruit motor controller version2 and receiver can u help me with the code of how to control this, the receiver and transmit code please, thanks. U can email me at Nealat06@gmail.com

    ReplyDelete
  11. thank you...solved my problems

    ReplyDelete
  12. HI, Rodrigo

    i try this to send some floating.. i want to send the ultrasonic measure thru virualwire, have some questions, can i use 2 of this transmitter (433MHz module) and join it into 1 reciber? can u help me with this?

    thanks...

    ReplyDelete
  13. Hi,
    Sir can you help me out on my code, im facing problem with the receiver part, based on the serial monitor, i couldn't get any result, in any mean i can send you my transmitter and receiver for the project of rf i am working on code?
    many thanks.

    ReplyDelete
  14. Awesome code! Love your work!! A BIG thank you!!!

    ReplyDelete
  15. #include
    int input=4;
    int ledPin = 13;
    int Bit=0;
    int count=0;
    float rate=0;
    boolean ledOn = false;
    bool flag = 0;


    void setup()
    {

    Serial.begin(9600);
    pinMode(input,INPUT);
    pinMode(ledPin,OUTPUT);
    Timer1.initialize(500000); // initialize timer1, and set a 1/2 second period
    Timer1.attachInterrupt(callback); // attaches callback() as a timer overflow interrupt

    }
    void callback(){
    count=count+1;
    if(count==16) //after (16/2)=8sec,reset all
    {
    Serial.println("your heart rate is" );
    Serial.println(rate);
    count=0;
    Bit=0;
    interrupts();
    }


    }


    void loop()
    {
    if(digitalRead(input) == 0)
    {
    flag = 1;
    digitalWrite(ledPin,HIGH);
    delay(770);
    Bit=Bit+1;

    }
    else{
    digitalWrite(ledPin,LOW);
    }
    rate=Bit*7.5;



    //Serial.println(rate);

    }
    hellow here is my code. but it doesnt send ,what i will do,i want to send integer data

    ReplyDelete
  16. Hi, thank you for the code! It was so useful to me to send multiple data variables. Then, i need to control 4 motors with the received data in the receiver arduino (i'am trying to control the motors from the trasmitter arduino with a potenciometer) but i have the next problem, when the data arrives to the receiver, it receives and print the data only one time and then the communication via virtual wire seems blocked. It could be happening because of the sscanf function? If i receive only 1 data variable(without using sscanf), there is no problem, and i can send the speed data to the motor with analogWrite correctly, but i need to control 4 motors, not only 1.

    ReplyDelete
  17. i want to print sensors values . HOW CAN I DO THAT?

    ReplyDelete