Sending & Receiving multiple variables with VirtualWire

Hello, I am creating a weather station and am having trouble with the programs I use. whenever I upload the code there are no error messages, but I am getting nothing in my serial monitor and my led never flashes for a received message.

Currently, my transmit program is:

 pinMode(13,OUTPUT);          // Testing Indicator setup
   pinMode(12,OUTPUT);          // Default transmitter pin for headsup
   
  vw_set_ptt_inverted(true);
    vw_setup(2000);        
     vw_set_tx_pin(12);         // Radio Setup
    
    if (!bme.begin()) { 
Serial.println("Could not find a valid BME280 sensor, check wiring!"); 
while (1); 
} 



}

void loop() {

  bme.readSensor();

temp = bme.getTemperature_F();
tempc = bme.getTemperature_C();
pressure = bme.getPressure_MB();
humidity = bme.getHumidity();

sprintf(Array, "%d,%d,%d.",temp,tempc,pressure,humidity);
vw_send((uint8_t*)Array, strlen(Array));
vw_wait_tx();

digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
  

  delay(500);


           
  
 
 
}

and my Receive program is:

#include <VirtualWire.h>

uint8_t data[25];



void setup() {
 Serial.begin(9600);
 vw_setup(2000);
 vw_set_rx_pin(12);
 vw_set_ptt_inverted(true);
 vw_rx_start();
 

 pinMode(13,OUTPUT);
 

}

void loop() {
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
 if (vw_get_message(buf, &buflen)){// Non-blocking

digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);

 int temp = atoi(strtok((char*)buf, ","));
 int tempc = atoi(strtok(NULL, ","));
 int pressure = atoi(strtok(NULL, ","));
 int humidity = atoi(strtok(NULL, "."));

 Serial.print(temp);
 Serial.print(", ");
 Serial.print(tempc);
 Serial.print(", ");
 Serial.print(pressure);
 Serial.print(", ");
 Serial.print(humidity);
 Serial.println();
 }
 }

I know that my devices are working because the code here: [u]http://www.instructables.com/id/RF-315433-MHz-Transmitter-receiver-Module-and-Ardu/step4/One-Transmitter-Multi-Receiver[/u]/ works, but the many other codes I have tried including this one give no result.

At this point, I have no clue what is happening, except that I might be getting interference, but wouldn't that just give me false readings instead of nothing at all?

I am in desperate need of help.

First, you do not send and receive variables. You send and receive values. The source and destination of the values may be variables, but it is not variables that you are sending or receiving.

Second, I'm sure that the fine folks at http://snippets-r-us.com will be happy to help you with your snippets.

temp = bme.getTemperature_F();
tempc = bme.getTemperature_C();

What part of the world do you live in where you can't decide whether the temperature is in degrees Celcius or degrees Fahrenheit?

Why is one variable called temp and one called tempc? tempF and tempC would make more sense.

sprintf(Array, "%d,%d,%d.",temp,tempc,pressure,humidity);

Why do you have 3 format specifiers for 4 values?

What IS in Array?

Are the 4 variables all ints?

 int temp = atoi(strtok((char*)buf, ","));
 int tempc = atoi(strtok(NULL, ","));
 int pressure = atoi(strtok(NULL, ","));
 int humidity = atoi(strtok(NULL, "."));

Only idiots assume that strtok() will return a non-NULL pointer. That isn't really you, is it?

At this point, I have no clue what is happening, except that I might be getting interference

The chances that interference is the culprit are not much better than Trump's chances of having a brain.

Okay, here we go...

First, you do not send and receive variables. You send and receive values. The source and destination of the values may be variables, but it is not variables that you are sending or receiving.

I was referring to the source and destination of the values, I was also trying to make the title so that people would understand what I was trying to do at first glance.

Second, I'm sure that the fine folks at http://snippets-r-us.com will be happy to help you with your snippets

I posted my whole program, at least I thought.

What part of the world do you live in where you can't decide whether the temperature is in degrees Celcius or degrees Fahrenheit?

I plan to have a switch that you can use to switch between Celsius and Fahrenheit. If the sensor offers it, I might as well try to use it.

Why is one variable called temp and one called tempc? tempF and tempC would make more sense

I use Fahrenheit, so I didn't add the f because the program made sense to me; I had no intention of ever posting this on the forum, until I had problems.

Why do you have 3 format specifiers for 4 values?

I found this part of my program on this forum, but I guess I missed this part when I was trying to modify it.

What IS in Array?

I would like to believe it was the string I am trying to send.

Are the 4 variables all ints?

ummm... yes?

Only idiots assume that strtok() will return a non-NULL pointer. That isn't really you, is it?

No, it is not me, it is another snippet of code I tried to modify, but it might as well be, because I literally have no clue about how C works at all. I'm not kidding. Can someone help me understand this part so I can fix my program?

The chances that interference is the culprit are not much better than Trump's chances of having a brain.

I actually agree.

Thanks, I will change the things you have pointed out, and I will see if it works. I just need help understanding what you said about the strtok() part.

I would like to believe it was the string I am trying to send.

That was a hint to print Array to the serial port before sending it over the air.

ummm... yes?

Yes! would have been a lot more convincing.

I just need help understanding what you said about the strtok() part.

  char *pToken = strtok((char*)buf, ",");
  if(pToken)
  {
     int tempF = atoi(pToken);
     pToken = strtok(NULL, ",");
     if(pToken)
     {
        int tempC = atoi(pToken);
        pToken = strtok(NULL, ",");
        if(pToken)
        {
           int pressure = atoi(pToken);
           pToken = strtok(NULL, ".");
           if(pToken)
           {
              int humidity = atoi(pToken);

You should not assume that strtok() returns a valid pointer. You should not keep parsing if parsing has failed.

Now, this level of indenture can be unwieldy if you have a lot of values in the string being parsed. Therefore, it is easier to store the values in an array, and simply increment the index each time you get a non-NULL token.

  int values[4];
  byte index = 0;

  char *pToken = strtok((char*)buf, ",.");
  while(pToken)
  {
     values[index++] = atoi(pToken);
     pToken = strtok(NULL, ",.");
  }

After this loop is over, you can tell how many values were found in the string (index contains that number), and, if the right number was found, use them:

  if(index == 4)
  {
     int tempF = values[0];
     int tempC = values[1];
     int pressure = values[2];
     int humidity = values[3];

Of course, this last bit is not really necessary. The compiler doesn't care if you use the name pressure or the name values[2]. You or I might, but the compiler doesn't.

Thanks that should help a lot. Will my receiving program work with the differences, or do i need to change that too?

wburns:
Thanks that should help a lot. Will my receiving program work with the differences, or do i need to change that too?

The strtok() related changes are to be made in the receiver program.

I am still having problems with the code even after attempting to follow what you said. I am probably putting the wrong pieces of code in the wrong places, and it would help if you could clarify where the parts go in the program.

Here is my transmission code:

#include"Arduino.h"
#include <VirtualWire.h>    // Library for radio transmitting
#include "cactus_io_BME280_I2C.h" // Library for BME280 Weather Sensor
#include <Wire.h> 



int bytes = 2;

char Array[20];
int temp,tempc,pressure,humidity;


BME280_I2C bme;

void setup() {
  Serial.begin(9600); 
  
  
   pinMode(13,OUTPUT);          // Testing Indicator setup
   pinMode(12,OUTPUT);          // Default transmitter pin for headsup
   
  vw_set_ptt_inverted(true);
    vw_setup(2000);        
     vw_set_tx_pin(12);         // Radio Setup
    
    if (!bme.begin()) { 
Serial.println("Could not find a valid BME280 sensor, check wiring!"); 
while (1); 
} 
}
void loop() {

  bme.readSensor();

temp = bme.getTemperature_F();
tempc = bme.getTemperature_C();
pressure = bme.getPressure_MB();
humidity = bme.getHumidity();

sprintf(Array, "%d,%d,%d,%d.",temp,tempc,pressure,humidity);
vw_send((uint8_t*)Array, strlen(Array));
vw_wait_tx();

digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
  

  delay(2000);


           
  
 
 
}

And my receiving code:

#include <VirtualWire.h>

uint8_t data[25];

int temp;
int tempc;
int pressure;
int humidity;

void setup() {
 Serial.begin(9600);
 vw_setup(2000);
 vw_set_rx_pin(12);
 vw_set_ptt_inverted(true);
 vw_rx_start();
 

 pinMode(13,OUTPUT);
 

}

void loop() {
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
 if (vw_get_message(buf, &buflen)){// Non-blocking

digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);

  char *pToken = strtok((char*)buf, ",");
  if(pToken)
  {
     int temp = atoi(pToken);
     pToken = strtok(NULL, ",");
     if(pToken)
     {
        int tempc = atoi(pToken);
        pToken = strtok(NULL, ",");
        if(pToken)
        {
           int pressure = atoi(pToken);
           pToken = strtok(NULL, ".");
           if(pToken)
           {
              int humidity = atoi(pToken);
 
 
 
 }
   }
     }
  }
 
 Serial.print(temp);
 Serial.print(", ");
 Serial.print(tempc);
 Serial.print(", ");
 Serial.print(pressure);
 Serial.print(", ");
 Serial.print(humidity);
 Serial.println(); 
 
 }




}

If I seem tired of writing this, it's because my internet keeps cutting out and I keep losing my response, and I may have just posted a topic on the forum named Subject because I lost my subject when typing my response.

sprintf(Array, "%d,%d,%d,%d.",temp,tempc,pressure,humidity);
vw_send((uint8_t*)Array, strlen(Array));

I'll ask again. What IS in Array? If you don't KNOW, how on earth do you think you can parse the data on the other end?

CanIsuggestthatyougetyourspacekeyfixed? AND YOUR SHIFT KEY?

sprintf(Array, "%d,%d,%d,%d.", tempF, tempC, pressure, humidity);

would be a lot easier to read.

  if(pToken)
  {
     int temp = atoi(pToken);
     pToken = strtok(NULL, ",");
     if(pToken)
     {
        int tempc = atoi(pToken);

At this point you have global variables named temp and tempc and local variables named temp and tempc. Why?

           if(pToken)
           {
              int humidity = atoi(pToken);
 
 
 
 }
   }
     }

NEVER POST SHIT LIKE THIS AGAIN!

 Serial.print(temp);
 Serial.print(", ");
 Serial.print(tempc);
 Serial.print(", ");
 Serial.print(pressure);
 Serial.print(", ");
 Serial.print(humidity);
 Serial.println();

Are you printing the local variables or the global variables? I KNOW the answer. Do you?

PaulS:

 Serial.print(temp);

Serial.print(", ");
Serial.print(tempc);
Serial.print(", ");
Serial.print(pressure);
Serial.print(", ");
Serial.print(humidity);
Serial.println();



Are you printing the local variables or the global variables? I KNOW the answer. Do you?

I probably should have specified in my reply, but my problem is not the global or local values but that I am not receiving a message at the other end. My led is not lighting up and nothing is printing in the monitor, not even zeros because the Arduino has not entered into the if (vw_get_message(buf, &buflen)){ section. This is also the reason I haven't been printing array because I don't need to know what it is, at least not yet.

I do see your point, though, If I were to remove the int before the values like this:

 char *pToken = strtok((char*)buf, ",");
  if(pToken)
  {
      temp = atoi(pToken);
     pToken = strtok(NULL, ",");
     if(pToken)
     {
         tempc = atoi(pToken);
        pToken = strtok(NULL, ",");
        if(pToken)
        {
            pressure = atoi(pToken);
           pToken = strtok(NULL, ".");
           if(pToken)
           {

would that remove the conflict between the global and local variables?

This is also the reason I haven't been printing array because I don't need to know what it is, at least not yet.

You don't need to know what you sent, because you aren't receiving anything? That makes no sense. If you are sending 812 characters, that would explain why nothing gets sent.

You debug by printing things one step at a time.

If you won't do that, I'm done.

would that remove the conflict between the global and local variables?

Yes.

It has been a while and I have visited a local maker space to get some hep with the problems. As it turns out I was not sending anything, but it was because we had to change the connection rate to 4000. while I was there we changed the way we were building the array to the way displayed on this website at array - Arduino Reference.

I know I am now receiving data because the program WAS entering the if message is received loop, but was not able to print the array; Nothing shows up in the serial monitor now I am not receiving anything at all. There is also an error on the sending side. when I try to print the array it displays like this: L, , Õ, 4with the 4 changing to 3 and 5. I know that it is not supposed to show up like this. I don't know what happened with the send program, and after that is figured out I need to know how I am going to receive the data on the other end and translate it to separate variables.

Send

#include <VirtualWire.h>    // Library for radio transmitting
#include "cactus_io_BME280_I2C.h" // Library for BME280 Weather Sensor
#include <Wire.h> 



int bytes = 2;

char Array[5];
int temp;
int tempc;
int pressure;
int humidity;


BME280_I2C bme;

void setup() {
 Serial.begin(9600); 
 
 
  pinMode(13,OUTPUT);          // Testing Indicator setup
  pinMode(12,OUTPUT);          // Default transmitter pin for headsup
  
 vw_set_ptt_inverted(true);
   vw_setup(4000);        
    vw_set_tx_pin(12);         // Radio Setup
   
   if (!bme.begin()) { 
Serial.println("Could not find a valid BME280 sensor, check wiring!"); 
while (1); 
} 
}
void loop() {

 bme.readSensor();

temp = bme.getTemperature_F();
tempc = bme.getTemperature_C();
pressure = bme.getPressure_MB();
humidity = bme.getHumidity();

Array[1] = temp;
Array[2] = tempc;
Array[3] = pressure;
Array[4] = humidity;

Serial.print(Array[1]);
Serial.print(", ");
Serial.print(Array[2]);
Serial.print(", ");
Serial.print(Array[3]);
Serial.print(", ");
Serial.println(Array[4]);

vw_send((uint8_t*)Array, strlen(Array));
vw_wait_tx();

digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
 

 delay(2000);


          
 


}

Receive

#include <VirtualWire.h>

uint8_t data[5];

int temp;
int tempc;
int pressure;
int humidity;

void setup() {
 Serial.begin(9600);

 vw_set_rx_pin(12);
  vw_setup(4000);
 vw_set_ptt_inverted(true);
 vw_rx_start();
 

 pinMode(13,OUTPUT);
 

}

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 i;
digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);

Serial.println("Message Received");

Serial.println (buf[i]);


 
 }




}

Please help me with this.

vw_send((uint8_t*)Array, strlen(Array));

Array is NOT a string. You can NOT use strlen() to get the length of something that is NOT a string.

You can NOT store int (2 byte) values in char elements (1 byte).

How would I send an array then? I thought that was what you were telling me to do in the first place. To fix the storing 2 bytes in 1 byte problem should I just change all my ints to chars?

I don't know if you forgot or just skipped over it, but in the intro to this forum entry, I mentioned that I have little coding experience with c++ or Arduino coding. All of this time I have been basically moving through the forums and web pages copying bits and pieces that I think might work with no base knowledge that I can use to stick them together or edit them. I am moving through the dark right now so if you could explain everything to me I might be able to understand it a little better, and I will be able to stop bugging you.

How would I send an array then?

Step 1: Use one that is the right type
Step 2: Learn that array indexes start at 0, not 1
Step 3: Learn that sizeof() tells you how big an array is.

Thank you. The receiving program is now detecting a signal and printing a message received and at least a zero. The problem now is that I am still getting the garbage when I try to print the array in the serial monitor even after I changed the variables to chars. is there something else I should change?

even after I changed the variables to chars

Why would you do that? The variables made sense as ints (or floats). They do not as chars.

   int vals[4];
   vals[0] = temp;
   vals[1] = tempc;
   vals[2] = pressure;
   vals[3] = humidity;
   vw_send((uint8_t*)vals, sizeof(vals));

Show your receiving code, and serial output.

is there something else I should change?

Undoubtedly, but until you post the latest code, no one can say.

Thanks, I will change the variables to ints again PaulS, and sorry jremington I guess you would need that.

Here you go, This is the Transmit:

#include <VirtualWire.h>    // Library for radio transmitting
#include "cactus_io_BME280_I2C.h" // Library for BME280 Weather Sensor
#include <Wire.h> 



int bytes = 2;

int Array[5];

int temp;
int tempc;
int pressure;
int humidity;


BME280_I2C bme;

void setup() {
  Serial.begin(9600); 
  
  
   pinMode(13,OUTPUT);          // Testing Indicator setup
   pinMode(12,OUTPUT);          // Default transmitter pin for headsup
   
  vw_set_ptt_inverted(true);
    vw_setup(4000);        
     vw_set_tx_pin(12);         // Radio Setup
    
    if (!bme.begin()) { 
Serial.println("Could not find a valid BME280 sensor, check wiring!"); 
while (1); 
} 
}
void loop() {

  bme.readSensor();

temp = bme.getTemperature_F();
tempc = bme.getTemperature_C();
pressure = bme.getPressure_MB();
humidity = bme.getHumidity();

Array[1] = temp;
Array[2] = tempc;
Array[3] = pressure;
Array[4] = humidity;

Serial.println(Array);

Serial.print(Array[1]);
Serial.print(", ");
Serial.print(Array[2]);
Serial.print(", ");
Serial.print(Array[3]);
Serial.print(", ");
Serial.println(Array[4]);

vw_send((uint8_t*)Array, sizeof(Array));
vw_wait_tx();

digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
  

  delay(2000);


           
  
 
 
}

This is my receive:

#include <VirtualWire.h>

uint8_t data[5];

int temp;
int tempc;
int pressure;
int humidity;

void setup() {
 Serial.begin(9600);

 vw_set_rx_pin(12);
  vw_setup(4000);
 vw_set_ptt_inverted(true);
 vw_rx_start();
 

 pinMode(13,OUTPUT);
 

}

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 i;
digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);

Serial.println("Message Received");

Serial.println (buf[i]);


 
 }




}
Array[1] = temp;
Array[2] = tempc;
Array[3] = pressure;
Array[4] = humidity;

Array indexes STILL start at 0.

int i;
digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);

Serial.println("Message Received");

Serial.println (buf[i]);

I contains whatever crap was in the memory location it is assigned to. Why do you want to print the someRandomCrap'th element of the array?

It looks like I forgot a part to transfer the received data in the buffer to I. That's what I need to do right? Would

for (i = 0; i < buflen; i++){

Serial.print(buf[i]);
}

work? Or is there a different way I am supposed to do this?

After I am able to print the array in a serial monitor how would I turn it back to an array so I can process the numbers? would a simple Array[5] = buf[i] work, or is it more complicated than that? Something tells me it's more difficult.