Pages: [1]   Go Down
Author Topic: Sending variable over Virtual Wire  (Read 8433 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 29
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sending text over an RF link using Virtual Wire is easy , but what if
I want to send a int or float or any other variable.

Say I want to send a temp reading from a sensor to another arduino via a RF link.
Unfortunately something simple like this doesn't work.

Code:
tempC = analogRead(tempPin); // read value from sensor
  tempC = (5 * tempC * 100) / 1024; //convert voltage to Celcius
  tempF = (tempC * 9) / 5 + 32;    // convert Celcius to Fahrenheit
  Serial.print(tempF);Serial.println(" F");    // print to serial monitor
void loop()
{
    float *msg = (tempC);       // this is your message to send

   vw_send((uint8_t *)msg, strlen(msg));
   vw_wait_tx();                            // Wait for message to finish
   delay(200);

This gives "can't convert float to float"
So how do you send a variable using Virtual Wire??
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49365
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
This gives "can't convert float to float"
So how do you send a variable using Virtual Wire??
I don't think that that is the correct error message that you got.

The key to how to send a variable using Virtual Wire is in the function call itself:
Code:
vw_send((uint8_t *)msg, strlen(msg));

The strlen function expects a string as an argument. A string is a NULL terminated array of chars.

Code:
char msg[24];
sprintf(msg, "%f", tempC);
vw_send((uint8_t *)msg, strlen(msg));

Unfortunately, sprintf on the Arduino doesn't support the %f format specifier. So, you need to approach the problem slightly differently. Separate the value to be sent into its integral and fractional parts:

Code:
int tempC1 = (int)tempC;
int tempC2 = (int)(tempC - tempC1) * 100; // For two decimal points
char msg[24];
sprintf(msg, "%i.%i", tempC1,tempC2);
vw_send((uint8_t *)msg, strlen(msg));
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 29
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks PaulS, that works.
I never would have figured that out myself.

However one more thing, the resulting tempC on the receiver prints
out as xx.0 it seems to truncate the 2 decimal points to just one and
it's always .0 never the actual tempC, which would be xx.xx,(20.59).
I guess the value of tempC2 will always be 0, due to "
Code:
tempC2 = (int)(tempC - tempC1) * 100

I can live with it, it's not a big deal, but for extra 'wow' factor I would like to have print out the actual temp, xx.xx.
Is this possible?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49365
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You might need an extra set of parentheses in there (or two), and to change 100 to 100.0, but, yes, tempC2 can be made to equal 59 when tempC is 20.59.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 29
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, I'll see if I can work that out.

Next task is to print to an LCD.
Somehow I don't think this will work:
Code:
lcd.print(buf[i])

Can I pass the serial buffer to a variable?
Code:
int x = (buf[i])
lcd.print(x)
Then pass the variable to lcd.print
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49365
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Somehow I don't think this will work:
It will, but it will only print the one value in buf, whatever it is.

You could, if buf is a NULL-terminated array of chars, use:
Code:
lcd.print(buf);
to print the whole string in one step.

Quote
Can I pass the serial buffer to a variable?
Maybe. Maybe not. Depends on whether the variables are the same type. We don't know what type buf is.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 29
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I tried lcd.print(buf), but I got this error:
error "call of overloaded 'print(uint8_t[30])' is ambiguous"

Here is my code;
Code:
#include <VirtualWire.h>  //
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); //set digital pins

#undef int
#undef abs
#undef double
#undef float
#undef round
void setup()
{
     Serial.begin(9600);
     lcd.begin(16, 2); //set colums and rows of LCD  

// Initialise the IO and ISR
    vw_set_ptt_inverted(true);    // Required for RX Link Module
    vw_setup(1200);              // Bits per sec
    vw_set_rx_pin(3);           // We will be receiving on pin 3 () ie the RX pin from the module connects to this pin.
    vw_rx_start();             // Start the receiver
}

void loop()
{
    
    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;

    if (vw_get_message(buf, &buflen)) // check to see if anything has been received
    {
    int i;
     // Message with a good checksum received.
        
    for (i = 0; i < buflen; i++)
    {
        Serial.print(buf[i]);  // the received data is stored in buffer
        }
    Serial.println("");
    
    lcd.clear(); //clear screen
    lcd.setCursor (0, 0); //set cursor to top row
    lcd.print(buf);
    
     }
}
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49365
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Try:
Code:
lcd.print((char)buf);
or
Code:
lcd.print((char *)buf);
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 29
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
lcd.print((char *)buf);

That works fine
Logged

0
Offline Offline
Jr. Member
**
Karma: 1
Posts: 92
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi.
I'm triying send a float value also. I see the next code:
int tempC1 = (int)temperatura;
int tempC2 = (int)((temperatura - tempC1) * 100); // For two decimal points
char msg[24];
sprintf(msg, "%i.%i", tempC1,tempC2);
vw_send((uint8_t *)msg, strlen(msg));
vw_wait_tx(); // Wait until the whole message is gone

Why do you use 24 in the msg declaration?

I'm trying other values and it works fine ...

   2 * int = 8 bytes (8 char)
         "." = 1 byte (1 char)
-------------------------------
                             9 char
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49365
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The maximum value that can be stored in an int is +32767. The minimum is -32768. The minimum value takes 6 characters to represent. 6 * 2 is 12, plus one for the . and one for the NULL makes 14. So, the msg array could be as small as 14 characters and still hold everything that sprintf could possibly write into it. In reality, it could be much smaller, since the Arduino can't function at temperature near -10,000 degrees on any scale.

But, it's better to have an array that is too large than one that is too small.
Logged

Pages: [1]   Go Up
Jump to: