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);
specifier | Output | Example |
---|---|---|
d or i | Signed decimal integer | 392 |
u | Unsigned decimal integer | 7235 |
o | Unsigned octal | 610 |
x | Unsigned hexadecimal integer | 7fa |
X | Unsigned hexadecimal integer (uppercase) | 7FA |
f | Decimal floating point, lowercase | 392.65 |
F | Decimal floating point, uppercase | 392.65 |
e | Scientific notation (mantissa/exponent), lowercase | 3.9265e+2 |
E | Scientific notation (mantissa/exponent), uppercase | 3.9265E+2 |
g | Use the shortest representation: %e or %f | 392.65 |
G | Use the shortest representation: %E or %F | 392.65 |
a | Hexadecimal floating point, lowercase | -0xc.90fep-2 |
A | Hexadecimal floating point, uppercase | -0XC.90FEP-2 |
c | Character | a |
s | String of characters | sample |
p | Pointer address | b8000000 |
n | Nothing 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. | |
% | A % 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.
Hi Rodrigo
ReplyDeleteyour Rx code does not compile , there are declarations missing
The code is already changed. Thanks for reporting the problem¡.
DeleteHi Rodrigo
ReplyDeletethank 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
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.
DeleteThen 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();
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
ReplyDeletet 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).
DeleteTo send float you have to change %d to %f and declare the variable as
float SensorRead1;
you can see more detail on arduino.cc
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?
DeleteDo you chaged it on the transmitter and on the reciever?. This could be the problem
DeleteI 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
Deleteorry 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.
DeleteI 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
I found this post on arduino.cc http://forum.arduino.cc/index.php/topic,44262.0.html
DeleteThe 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
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 ?
ReplyDeleteI 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
DeleteHey 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
ReplyDeleteThis 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.
DeleteHere 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
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.
DeleteIn 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.
A tutorial on how to get the best range might be nice? please best antenna/ settings
DeleteVery nice example ! ! ! Well Done ! ! !
ReplyDeleteYou 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
Hi Tasos
ReplyDeleteIf 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
Hello Dear Rodrigo Mompo,
ReplyDeleteThank 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 :-)
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.
ReplyDeleteBueno, 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!
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
ReplyDeletethank you...solved my problems
ReplyDeleteHI, Rodrigo
ReplyDeletei 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...
Hi,
ReplyDeleteSir 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.
my email is calvinern@gmail.com
DeleteAwesome code! Love your work!! A BIG thank you!!!
ReplyDelete#include
ReplyDeleteint 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
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.
ReplyDeletei want to print sensors values . HOW CAN I DO THAT?
ReplyDeleteThanks for sharing this wonderful article here about the Arduino + Kit. Your article is very informative and useful for us. If you are looking to Arduino Starter Kit online at the affordable price, Visit quadstore.in
ReplyDeleteHi Rodrigo..
ReplyDeleteThanks for this sketch, i want to send gps data via rf433,, is the data type of gps same with the analogread? Thanks