How to send multiple variables with Virtual Wire

I need help to complete the code. So far I have managed to send the temperature variables from the transmitter and receive it and display it on LCD, so far everything is good. But I also need to send the variables from the pressure sensor, I tried to take the same approach as with the temperature sensor when writing the code, but I don´t know how to make the code on the receiver side. First I need help to check if I have written the code correct on the transmitter(as said the temperature code is working) for the pressure sensor and then I need help to how I can write the receiver code.

I´m using:

  • Arduino Nano
  • RF 315/433 MHz Transmitter-receiver
  • DS18b20 temperature sensor
  • Honeywell pressure sensor
  • LCD

Transmitter_Working_1.ino (2.3 KB)

Receiver_Working.ino (1.74 KB)

I use sprintf() to convert all my variables to a string, and send it out. Then on the receiving side I use strtok() to split the string again. You can also use sscanf() to do the same thing, but it is written differently.

Another method is to use a structure and send it out, but you also need to use a structure to collect the sent data. I find this method to be slower.

sprintf Transmit:

#include <VirtualWire.h>

char Array[20];
int X,Y,Z;

void setup()
{
  Serial.begin(115200);  // Debugging only
  Serial.println("Sending"); // Debugging only

  // Initialise the IO and ISR
  //vw_set_ptt_inverted(true); // Required for DR3100
  vw_setup(2000); // Bits per sec
  vw_set_tx_pin(33); //RF sending pin
 }

void loop()
{ 
  X = constrain(map(analogRead(A14),410,345,0,255),0,255); //415 - 275 415,275
  Y = constrain(map(analogRead(A15),415,275,0,255),0,255);//410 - 340  410,340
  Z = constrain(map(analogRead(A13),310,410,0,255),0,255);//310 - 415  310,420 
  
  sprintf(Array, "%d,%d,%d.",X,Y,Z);
  vw_send((uint8_t*)Array, strlen(Array));
  vw_wait_tx(); 
}

strtok Receive: (fixed)

#include <VirtualWire.h>

uint8_t data[25];

void setup()
{
  Serial.begin(115200); // Debugging only
  Serial.println("Receiving");
  pinMode(13,OUTPUT);
  // Initialise the IO and ISR
  //vw_set_ptt_inverted(true); // Required for DR3100
  vw_setup(2000); // Bits per sec
  vw_set_rx_pin(8);
  vw_rx_start();       // Start the receiver PLL running
}

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 X = atoi(strtok((char*)buf, ","));  // Look for a comma, the return the data before it.
    int Y = atoi(strtok(NULL, ",")); // same as above
    int Z = atoi(strtok(NULL, ".")); // Look for a period, then return data before it.
    Serial.print(X); // X axis
    Serial.print(", ");
    Serial.print(Y); // Y axis
    Serial.print(", ");
    Serial.print(Z); // Z axis
    Serial.println();
  }
}

sscanf Receive:

#include <VirtualWire.h>
int X,Y,Z;

void setup()
{
  Serial.begin(115200); // Debugging only
  Serial.println("setup");
  vw_setup(2000); // Bits per sec
  vw_set_rx_pin(2);     // receiver pin
  vw_rx_start();       // Start the receiver PLL running
}

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

  if (vw_get_message(buf, &buflen)) // Non-blocking
  {
    sscanf ((char*)buf, "%d%*c%d%*c%d%", &X, &Y, &Z);//123,456,7890
  }  
}

Structure Transmit:

//send struct data
#include <VirtualWire.h>

const byte xpin = A15; // x-axis of the accelerometer
const byte ypin = A14; // y-axis
const byte zpin = A13; // z-axis

struct {
  int X;
  int Y;
  int Z;
} DATA;

void setup()
{
  vw_setup(2000); // Bits per sec
  vw_set_tx_pin(33); 
}

void loop()
{
  DATA.X = constrain(map(analogRead(A14),410,345,0,10),0,10); //415 - 275 415,275
  DATA.Y = constrain(map(analogRead(A15),415,275,0,20),0,20);//410 - 340  410,340
  DATA.Z = constrain(map(analogRead(A13),310,410,0,20),0,20);//310 - 415  310,420

  vw_send((uint8_t*)&DATA, sizeof(DATA));
  vw_wait_tx();
}

Structure Receive:

//struct receive
#include <VirtualWire.h>

struct DATA{
  byte X;
  byte Y;
  byte Z;
};

struct DATA *DataIn;

void setup()
{
  Serial.begin(115200);
  vw_setup(2000); // Bits per sec
  vw_set_rx_pin(8);
  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
  {
    DataIn = (struct DATA*)buf;
    Serial.print(DataIn->X);
    Serial.print(" ");
    Serial.print(DataIn->Y);
    Serial.print(" ");
    Serial.println(DataIn->Z);
  }
}

If you get stuck you might take a look at the EasyTransfer library. It is compatible with VirtualWire; examples in the GitHub page.

I generally just put the data to send in an array, and send the array out.
Put it back in an array on the receive side.
Size is limited to 27 to allow time for Manchester encoding & sending/receiving & decoding:

4.0 Implementation Details
Messages of up to VW_MAX_PAYLOAD (27) bytes can be sent
Each message is transmitted as:
• 36 bit training preamble consisting of 0-1 bit pairs
• 12 bit start symbol 0xb38
• 1 byte of message length byte count (4 to 30), count includes byte count and FCS
bytes
• n message bytes, maximum n is VW_MAX_PAYLOAD (27)
• 2 bytes FCS, sent low byte-hi byte
Everything after the start symbol is encoded 4 to 6 bits, Therefore a byte in the message
is encoded as 2x6 bit symbols, sent hi nybble, low nybble. Each symbol is sent LSBit
first.
The Arduino Diecimila clock rate is 16MHz => 62.5ns/cycle.
For an RF bit rate of 2000 bps, need 500microsec bit period.
The ramp requires 8 samples per bit period, so need 62.5microsec per sample => interrupt
tick is 62.5microsec.
The maximum packet length consists of
(6 + 2 + VW_MAX_MESSAGE_LEN*2) * 6 = 408 bits = 0.204 secs (at 2000 bps).
where VW_MAX_MESSAGE_LEN is VW_MAX_PAYLOAD + 3 (= 30).
The code consists of an ISR interrupt handler. Most of the work is done in the interrupt
handler for both transmit and receive, but some is done from the user level. Expensive
functions like CRC computations are always done in the user level.
Caution: VirtualWire takes over Arduino Timer1, and this will affect the PWM capabilities
of the digital pins 9 and 10.

I believe the airspayce website also indicates Radiohead is being supported now in place of Virtual wire.
http://www.airspayce.com/mikem/arduino/VirtualWire/
I haven't looked into Radiohead yet.

(Why does quote /quote italize things? I don't think I like that)

Thanks for your answers!
Just to say, I´m really new to this.

HazardsMind I got problems when sending float when I used sprintf(), Arduino does not support it, so that's why I wrote the code this way.

Chagrin thanks for the tip.

CrossRoads I will look further into send it as an array. Since I´m new to Arduino, I would like to know if it is possible to make the code as I have done and continue with this, or else I will have to learn more about array and go that way.

How did you write it? %d is for integers and %f is for floats. printf Reference page

Yes, I used the %f, but it did not function.

My problem now is that, if I just send one at the time, may it be(from the transmitter):

" vw_send((uint8_t *)tempconvert, strlen(tempconvert));"

or

" vw_send((uint8_t *)pressconvert, strlen(pressconvert));"

I have the problem that i don´t posses the understanding, to know how to recieve an separate and then send tempconvert to lcd.setCursor(6,0); on my display and then send pressconvert to lcd.setCursor(6,1)

Post your code.

//TRANSMISSOR

#include <VirtualWire.h>
#include <OneWire.h>
const int Press_Pin = A0;//analog pin
const int DS18S20_Pin = 8; //DS18S20 Signal pin on digital 8
OneWire ds(DS18S20_Pin); // on digital pin 8

void setup()
{
Serial.begin(9600);
Serial.println("Starting up");

vw_set_ptt_inverted(true); // Required
vw_set_tx_pin(7); // Pin data
vw_setup(4000); // Connection speed
}

void loop()
{
float temperature = getTemp();
Serial.println(temperature);// Print the values to the serial port
char tempconvert[5];
dtostrf(temperature, 5, 2, tempconvert);//tempsensor

int value = analogRead(Press_Pin);
Serial.print(value); Serial.print(" = ");
float millivolts = (value/1024.0) * 5;
Serial.print(millivolts); Serial.print(" = ");
float pressure = millivolts/0.18;
Serial.println(pressure);
char pressconvert [6];
dtostrf(pressure, 6, 3,pressconvert);//pressuresensor

vw_send((uint8_t *)tempconvert, strlen(tempconvert));// uint8_t is a character array
// with unsigned 8-bit integer
vw_send((uint8_t *)pressconvert, strlen(pressconvert));
vw_wait_tx(); // Wait to finish sending
delay(500); //Wait to send the next txt

}
float getTemp(){
//returns the temperature from one DS18S20 in DEG Celsius

byte data[12];
byte addr[8];

if ( !ds.search(addr)) {
//no more sensors on chain, reset search
ds.reset_search();
return -1000;
}

if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.print("CRC is not valid!\n");
return -1000;
}

if ( addr[0] != 0x10 && addr[0] != 0x28) {
Serial.print("Device is not recognized");
return -1000;
}

ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end

byte present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad

for (int i = 0; i < 9; i++) { // we need 9 bytes
data = ds.read();

  • }*

  • ds.reset_search();*

  • byte MSB = data[1];*

  • byte LSB = data[0];*

  • float tempRead = ((MSB << 8) | LSB); //using two's compliment*

  • float TemperatureSum = tempRead / 16;*

  • return TemperatureSum;*
    }
    // Receiver
    *#include <LiquidCrystal.h> *
    *#include <OneWire.h> *
    *#include <VirtualWire.h> *
    *// select the pins used on the LCD panel *
    *LiquidCrystal lcd(12, 11, 5, 4, 13, 2); *
    *void setup() *
    *{ *

  • int pin=10;*

  • lcd.begin(16, 2); // start the library *

  • lcd.setCursor(0,0); *

  • lcd.print("Temp: "); // print a simple message*

  • lcd.setCursor(0,1);*

  • lcd.print("Press: ");*

  • lcd.setCursor(13,0);*

  • lcd.print((char)223);*

  • lcd.print("C");*

  • lcd.setCursor(13,1);*

  • lcd.print("Psi");*

  • Serial.begin(9600); *

  • //vw_set_ptt_inverted(true); // Required for DR3100 *

  • vw_set_rx_pin(3); *

  • vw_setup(4000); // Bits per sec *

  • vw_rx_start();*

  • pinMode(10,OUTPUT); // for an led on pin 10 (Analogue 3)to blink with rf link*
    *} *
    *void loop() *
    *{ *

  • uint8_t buf[VW_MAX_MESSAGE_LEN]; //a buffer to hold the incoming messages*

  • uint8_t buflen = VW_MAX_MESSAGE_LEN; //the size of the message *

  • if (vw_get_message(buf, &buflen)) // Non-blocking*

  • lcd.setCursor(6,0); *

  • char temp=0;//mod:tim:added a temporary character *

  • for (int i = 0; i < buflen; i++) *

  • {*
    _ temp=(char)buf*;//mod:tim:convert uint to char _
    _ Serial.print(temp); //mod:tim:changed buff to temp here
    lcd.print(temp);

    }}
    }*_