Sending weather data over VirtualWire

Hello.

I think it is important to state that I am a novice Arduino user coming from a Java background. I am trying to build an Arduino based weather station consistent of two parts. The first part is an outdoor sensor, and the second part will be an indoor sensor and display. The stations will be using a cheap XY-FST RF Radio module.

I have read several different guides to view the different approaches people have taken to using the module, and I could not work out the proper format that VirtualWire would like to send the data in. I will be transmitting temp. and humidity information from a DHT11 or DHT22, temp. information from a DS18B20 sensor as well. In addition, there will be a water level sensor (rain sensor) and a air quality sensor.

In this block of code (from VirtualWire’s documentation), each character is being stored in an array of chars. I was thinking that I would convert my numeric float data into separate char messages that would be sent over and over again. I would also include a control character as the first message I send over as a way of informing the indoor unit that the data is on its way, and then a simple check afterwards (based on the temp data) to ensure that the correct information was received.

byte count = 1;

void loop()
{
  char msg[7] = {'h','e','l','l','o',' ','#'};

  msg[6] = count;
  digitalWrite(led_pin, HIGH); // Flash a light to show transmitting
  vw_send((uint8_t *)msg, 7);
  vw_wait_tx(); // Wait until the whole message is gone
  digitalWrite(led_pin, LOW);
  delay(1000);
  count = count + 1;
}

This only works if I could successfully convert the numeric float or double into a char.

In this block of code from Instructables uses “dtostrf”, breaking up a double into chars and placing it into an array. I also don’t understand why it is necessary to put “(uint8_t *)” right beside the msg.

void loop() {

sensors.requestTemperatures();

float temperature = sensors.getTempCByIndex(0);

dtostrf(temperature, 6, 2, msg);

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

vw_wait_tx();

delay(200);

}

Lastly, this and this use what appears to be the same method to transmit the data.

void loop()
{
byte error;
byte rh;
float humival_f;
float tempval_f;
float dew_point_f;
  
char str[15];
 
// Read values from the sensor
  float temp_c;
  float humidity;
  temp_c = dht.readTemperature();
  humidity = dht.readHumidity();

  char buff[30];
  sprintf(buff,"%c",255);
  const char *msg0 = buff;
  vw_send((uint8_t *)msg0, strlen(msg0)); // Send control character 
  vw_wait_tx(); // Wait until the whole message is gone

// Serial.print("Temperature = ");
  serialPrintFloat(temp_c);
  sprintf(buff,"%cC ",223); 
  const char *msg1 = buff;
  vw_send((uint8_t *)msg1, strlen(msg1));
  vw_wait_tx(); // Wait until the whole message is gone
// Serial.print("C");    
 
////////////////////////////////////////////////////////////////////////////////////////     
  sprintf(buff,"%c",254);
  const char *msg5 = buff;
  vw_send((uint8_t *)msg5, strlen(msg5));
  vw_wait_tx(); // Wait until the whole message is gone
 
// Serial.print(" Rel Humidity = ");
  serialPrintFloat(humidity);
// Serial.print("%");
  const char *msg2 = "% ";
  vw_send((uint8_t *)msg2, strlen(msg2));
  vw_wait_tx(); // Wait until the whole message is gone
 
  delay(1000);
}

Once again, I fail to see how this section of code is being implemented rather than what it’s doing. I have googled this and “dtostrf”, but they haven’t assisted in understanding what is being done. From what I see, “%c” is being written to char buff[30], however I do not understand what the 255 does.

char buff[30];
sprintf(buff,"%c",255);
const char *msg0 = buff;

Here is my code for the Sensor Station. Please feel free to give suggestions on how I could make it better or more efficient. Thank you.

#include <Arduino.h>

//Defines the Status led.
int LED = 11;

//Sets up definitions for the DHT11
//DHT11 is on PIN 2
#include <DHT.h>
#define DHTTYPE DHT11 //DHT 11
#define DHTPIN 2 //DHT 11 data on Pin 2
DHT dht(DHTPIN, DHTTYPE);

//Sets up the OneWire communication for the Dallas Temp. Sensor
//Dallas OneWire Temp sensor is on PIN 3
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature TCTempSense(&oneWire);
//TCTempSense = ThemocoupleTempSense
TCTempSense.begin();

//Defines water sensor PIN 8
#define WaterSensor 4     //Attach Water sensor to Arduino Digital Pin 8

//Var to see if the data from the sensors is valid.
boolean SenseSuccess = false;

//Sets up Wireless Transmission
#include <VirtualWire.h>
#undef int
#undef abs
#undef double
#undef float
#undef round

//
float DHT11Temp = 0;
float DHT11Humidity = 0;
float ThermoCoupleT = 0;
boolean RainSensor = false;

//



/*
  Transmits an opening code, then transmits Weather data collected from the sensors.
*/

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

 // initialize the digital pin as an output.
 // Pin 13 has an LED connected on most Arduino boards:
 //pinMode(13, OUTPUT);

    //Initialize the LED pin as a digital output.
    pinMode(LED, OUTPUT);

    //Starts the DHT11 sensor
    dht.begin();

 //Starts the Dallas Temprature Sensor library.
 TCTempSense.begin();

 //Defines the input for the water sensor.
 pinMode(WaterSensor, INPUT);

 //Sets up VirtualWire wireless communications.
 //vw_set_ptt_inverted(true);
    vw_setup(2000); //Bits per second.
    vw_set_tx_pin(13); //Comm. on PIN 13.

}

void loop()
{

    //Poll the sensors for the Environmental Data.
 SenseSuccess = PollSensors();

    //If the sensors correctly pulled in the data,
    //transmit it.
    if(SenseSuccess == true){
        //Transmit the data and fade the LED in and out once.
        TransmitData();
        LEDFade();
    }else{
        //Error, blink the LED 3 times.
        LEDBlink();
        LEDBlink();
        LEDBlink();
    }

}

boolean PollSensors(){

    //Gets the data from the DHT11
    DHT11Temp = dht.readHumidity();
    DHT11Humidity = dht.readTemperature();

    //Get data from the Dallas OneWire temp. sensor
    //Send the command to get temperatures
    TCTempSense.requestTemperatures();
    //Saves the temp. value
    ThermoCoupleT = sensors.getTempCByIndex(0);

    //Checks the Water Sensor
    if(digitalRead(WaterSensor) == HIGH){
        RainSensor = true;
    }else{
        RainSensor = false;
    }

    //Checks to see if any numerical are NAN.
    if( isnan(DHT11Humidity) || isnan(DHT11Temp) || isnan(ThermoCoupleT) ){
    //Reading the Sensors is a failure.
    return false;
    }else{
    //Reading the Sensors is a success.
    return true;
    }


}

void TransmitData(){

    //Serial.println("Wireless!");
    Serial.println("setup");









}

void LEDBlink(){

    //Blinks the LED in question.
    digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);               // wait for a second
    digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);

}


void LEDFade(){

    //Fades the LED in question.
    int brightness = 0;    // how bright the LED is
    int fadeAmount = 5;    // how many points to fade the LED by

    // Sets the brightness of pin 9:
    analogWrite(LED, brightness);

    // Changes the brightness for next time through the loop:
    brightness = brightness + fadeAmount;

    // Reverses the direction of the fading at the ends of the fade:
    if (brightness == 0 || brightness == 255) {
        fadeAmount = -fadeAmount ;
    }
    // Waits for 30 milliseconds to see the dimming effect
    delay(30);

}

Why use floating point numbers, convert to text and transmit as a string? That is a 100X overhead on something very simple. Cheers!

AndyFactor:
I was thinking that I would convert my numeric float data into separate char messages that would be sent over and over again.

The shorter the radio transmission, the higher the chance that the transmission will reach its destination undisturbed.

So you should work to keep the transmission as short as possible,

A suitable way to transmit your data would be two integers:

  • temperature in tenths of degrees
  • humidity in tenths of percent

I’d define a data structure that can take the values:

struct data_t {int temperature; int humidity;}; // user defined data structure
data_t data; // define a variable with that structure

And then use the data structure for sending data like:

  float temp=22.3;
  float hum=66.7;
  data.temperature=lround(temp*10);
  data.humidity=lround(hum*10);
  vw_send((uint8_t *)&data, sizeof(data));

After receiving the data, you simply can divide ‘data.temperatur/10.0’ and ‘data.temperature/10.0’ to get back float values again (if you like ‘float’).

AndyFactor, you have been looking at the wrong examples. Use a struct with binary data as jurs wrote. Using integers instead of float as kowalski write is often better, but you don't have to. I transmit only 6 or 8 bytes, that is on purpose, because our house alarm uses the same frequency and uses a number of repeated messages. When the Arduino transmits a small burst during a transmission of the house alarm, the house alarm thinks that is a short disturbance and still receives the right data. The data from the Arduino might get lost, but that is no problem.

I transmit the temperature in 1/100 degree Celsius or as a float.

struct myData_STRUCT
{
  byte identifier;             // the identifier of the remote Arduino
  int temperature;          // in 1/10 or 1/100 degrees, or use a float
  int humidity;
  int battery;                 // battery voltage
};

myData_STRUCT myData;

You must use the same struct in the receiver and the transmitter of course.

The VirtualWire library uses a 4-to-6 bit encoder to avoid long periods of "zero" (i.e. no transmission). An alternative encoder is to use 4-to-7 or 4-to-8 bit Hamming encoder. This gives error correction and reduces BER to less than 1/10th of the original encoder.

Please see Cosa/VWI and Cosa/Wireless for examples.

There is also a DHT example.

Cheers.

Ok. Thank you for the responses! I have modified my transmission sub-procedure to look like this:

void TransmitData(){

    //Defines a new data structure.
        //a beginning identifer.
        //ints with temp1, humid1, temp2.
        //boolean with rain data
        //int with air quality data.
        //a simple checksum
        //an ending identifier.

    struct wData_STRUCT{

        byte identifierB = byte("SensorStation");
        int t1 = (DHT11Temp*100);
        int h1 = (DHT11Humidity*100);
        int t2 = (ThermoCoupleT*100);
        boolean r = RainSensor;
        int a = airQ;
        int checksum = (t1+t2+h3);
        byte identifierE = byte("END");

    };

    //Defines structure wData as a variable (retaining structure);
    wData_STRUCT wData;

    //Transmitis the data structure with Virtual Wire.
    vw_send((uint8_t *)&wData, sizeof(wData));
    vw_wait_rx();

}

I still have two more questions.

  1. The identifier byte is, well, a byte. What type can I store in that byte? (i.e. an int holds whole numbers, chars hold characters, etc). I tried my best to implement it, but I’m not sure if I did it right. I read the example on the Reference Library, but it didn’t help me understand.

"It holds 8 bit unassigned numbers from 0 to 255

byte b = B10010; // “B” is the binary formatter (B10010 = 18 decimal)"

  1. If I transmit my data by using a data structure, what would the receive end look like? What I mean by this is; how would I re-assemble that data structure into the various ints and booleans that were transmitted.

Thanks!

P.S. I am also working on the receiver code (it will be posted soon, too!)

This is what the entire code looks like:

#include <Arduino.h>

//Defines the Status led.
int LED = 11;

//Sets up definitions for the DHT11
//DHT11 is on PIN 2
#include <DHT.h>
#define DHTTYPE DHT11 //DHT 11
#define DHTPIN 2 //DHT 11 data on Pin 2
DHT dht(DHTPIN, DHTTYPE);

//Sets up the OneWire communication for the Dallas Temp. Sensor
//Dallas OneWire Temp sensor is on PIN 3
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature TCTempSense(&oneWire);
//TCTempSense = ThemocoupleTempSense
TCTempSense.begin();

//Defines water sensor PIN 8
#define WaterSensor 4     //Attach Water sensor to Arduino Digital Pin 8

//Var to see if the data from the sensors is valid.
boolean SenseSuccess = false;

//Sets up Wireless Transmission
#include <VirtualWire.h>
#undef int
#undef abs
#undef double
#undef float
#undef round

//
float DHT11Temp = 0;
float DHT11Humidity = 0;
float ThermoCoupleT = 0;
boolean RainSensor = false;
int airQ = 0;
//


/*
  Transmits an opening code, then transmits Weather data collected from the sensors.
*/


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

	// initialize the digital pin as an output.
	// Pin 13 has an LED connected on most Arduino boards:
	//pinMode(13, OUTPUT);

    //Initialize the LED pin as a digital output.
    pinMode(LED, OUTPUT);

    //Starts the DHT11 sensor
    dht.begin();

	//Starts the Dallas Temprature Sensor library.
	TCTempSense.begin();

	//Defines the input for the water sensor.
	pinMode(WaterSensor, INPUT);

	//Sets up VirtualWire wireless communications.
	//vw_set_ptt_inverted(true);
    vw_setup(2000); //Bits per second.
    vw_set_tx_pin(13); //Comm. on PIN 13.

}

void loop()
{

    //Poll the sensors for the Enviromental Data.
	SenseSuccess = PollSensors();

    //If the sensors correctly pulled in the data,
    //transmit it.
    if(SenseSuccess == true){
        //Transmit the data and fade the LED in and out once.
        TransmitData();
        LEDFade();
    }else{
        //Error, blink the LED 3 times.
        LEDBlink();
        LEDBlink();
        LEDBlink();
    }

}

boolean PollSensors(){

    //Gets the data from the DHT11
    DHT11Temp = dht.readHumidity();
    DHT11Humidity = dht.readTemperature();

    //Get data from the Dallas OneWire temp. sensor
    //Send the command to get temperatures
    TCTempSense.requestTemperatures();
    //Saves the temp. value
    ThermoCoupleT = sensors.getTempCByIndex(0);

    //Checks the Water Sensor
    if(digitalRead(WaterSensor) == HIGH){
        RainSensor = true;
    }else{
        RainSensor = false;
    }

    //Checks to see if any numerical are NAN.
    if( isnan(DHT11Humidity) || isnan(DHT11Temp) || isnan(ThermoCoupleT) ){
    //Reading the Sensors is a failure.
    return false;
    }else{
    //Reading the Sensors is a success.
    return true;
    }

}

void TransmitData(){

    //Defines a new data structure.
        //a beginning identifer.
        //ints with temp1, humid1, temp2.
        //boolean with rain data
        //int with air quality data.
        //a simple checksum
        //an ending identifier.

    struct wData_STRUCT{

        byte identifierB = byte("SensorStation");
        int t1 = (DHT11Temp*100);
        int h1 = (DHT11Humidity*100);
        int t2 = (ThermoCoupleT*100);
        boolean r = RainSensor;
        int a = airQ;
        int checksum = (t1+t2+h3);
        byte identifierE = byte("END");

    };

    //Defines structure wData as a variable (retaining structure);
    wData_STRUCT wData;

    //Transmitis the data structure with Virtual Wire.
    vw_send((uint8_t *)&wData, sizeof(wData));
    vw_wait_rx();

}

void LEDBlink(){

    //Blinks the LED in question.
    digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);               // wait for a second
    digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);

}


void LEDFade(){

    //Fades the LED in question.
    int brightness = 0;    // how bright the LED is
    int fadeAmount = 5;    // how many points to fade the LED by

    // Sets the brightness of pin 9:
    analogWrite(LED, brightness);

    // Changes the brightness for next time through the loop:
    brightness = brightness + fadeAmount;

    // Reverses the direction of the fading at the ends of the fade:
    if (brightness == 0 || brightness == 255) {
        fadeAmount = -fadeAmount ;
    }
    // Waits for 30 milliseconds to see the dimming effect
    delay(30);

}

When there are a number of remote Arduino boards, and they are all transmitting with VirtualWire, it would be nice to know which data is received. So I added an identifier. For example integer value 0 for the first, value 1 for the next and so on. For myself I start at 100, because 0 could be the value when it is not given any value.

Instead of an integer, I used a byte. It can have a value of 0 to 255.

I don’t fill in the values when declaring the struct. I do that in the sketch, before transmitting.
The size of your struct is now 13 bytes, I don’t know what the maximum size is for VirtualWire. I think 13 is okay.
There is no need for an ending identifier.
The VirtualWire has a checksum itself, you dont’ have to add that.

// Create the struct definition above the setup().
struct wData_STRUCT{
  byte identifierB;
  int t1;
  int h1;
  int t2;
  boolean r;
  int a;
  int checksum;
};

...

void setup()
{
  Serial.begin(9600);
  Serial.println(F("\nSensor Station"));

  // Write to the serial monitor the size of the struct
  Serial.print(F("sizeof wData = "));
  Serial.println( sizeof( wData_STRUCT));


  // Defines structure wData as a variable (retaining structure);
  // Declare this global or local.
  wData_STRUCT wData;

  // Fill in the data, before transmitting

  wData.identifierB = 100;           // 100 is the first remote sensor station
  wData.t1 = (DHT11Temp*100);
  wData.h1 = (DHT11Humidity*100);
  wData.t2 = (ThermoCoupleT*100);
  wData.r = RainSensor;
  wData.a = airQ;
  wData.checksum = (t1+t2+h3);

  //Transmit the data structure with Virtual Wire.
  vw_send((uint8_t *)&wData, sizeof(wData));
  vw_wait_rx();

The receiver must have the same struct. When you change the struct, you must change both the transmitter and receiver.
When you have more remote stations, each one can have its own struct. So the receiver has all those structs for every transmitter.

The receiver could copy the incoming data into the struct, or receive it directly into the struct.
Declare the wData_STRUCT above setup(), and create that struct global or local.
I use the ‘buf’ from the examples of VirtualWire and then I copy it into the own struct.

  wData_STRUCT wData;  

  if (vw_get_message(buf, &buflen)) // Non-blocking
  {
    if (buflen == sizeof(wData_STRUCT))
    {
      // The right amount of data was received
      memcpy( &wData, buf, sizeof(wData));       // copy the received data into the struct

      Serial.print(F("identifier = "));
      Serial.println( wData.identifierB);
      ...
    }
    else
    {
      Serial.printl(F("The wrong amount of bytes was received !"));
    }

I did not check the code.
The sizeof(wData_STRUCT) is the same as sizeof(wData), the compiler knows the size of both.

Alright, I hope (with the help of the community) that VirtualWire’s transmission and reception functions have been implemented. Here is the code for the Transmitter side of things:

#include <Arduino.h>

//Defines the Status led.
int LED = 11;

//Sets up definitions for the DHT22
//DHT11 is on PIN 2
#include <DHT.h>
#define DHTTYPE DHT22 //DHT 22
#define DHTPIN 2 //DHT 22 data on Pin 2
DHT dhtOutdoor(DHTPIN, DHTTYPE);

//Sets up the OneWire communication for the Dallas Temp. Sensor
//Dallas OneWire Temp sensor is on PIN 3
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 4
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature TCTempSense(&oneWire);
//TCTempSense = ThemocoupleTempSense
//TCTempSense.begin();

//Defines water sensor PIN 8
#define WaterSensor 4     //Attach Water sensor to Arduino Digital Pin 8

//Defines the air sensor PIN 9
#define AirSensor 7

//Var to see if the data from the sensors is valid.
boolean SenseSuccess = false;

//Sets up Wireless Transmission
#include <VirtualWire.h>
#undef int
#undef abs
#undef double
#undef float
#undef round

//
float DHT22Temp = 0;
float DHT22Humidity = 0;
float ThermoCoupleT = 0;
boolean RainSensor = false;
int airQ = 0;
//


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

	// initialize the digital pin as an output.
	// Pin 13 has an LED connected on most Arduino boards:
	//pinMode(13, OUTPUT);

    //Initialize the LED pin as a digital output.
    pinMode(LED, OUTPUT);

    //Starts the DHT22 sensor
    dhtOutdoor().begin();

	//Starts the Dallas Temprature Sensor library.
	TCTempSense.begin();

	//Defines the input for the water sensor.
	pinMode(WaterSensor, INPUT);

	//Sets up VirtualWire wireless communications.
	//vw_set_ptt_inverted(true);
	vw_set_tx_pin(3); //Comm. on PIN 13.
    vw_setup(2000); //Bits per second.


}

void loop()
{

    //Poll the sensors for the Enviromental Data.
	SenseSuccess = PollSensors();

    //If the sensors correctly pulled in the data,
    //transmit it.
    if(SenseSuccess == true){
        //Transmit the data and fade the LED in and out once.
        TransmitData();
        LEDFade();
    }else{
        //Error, blink the LED 3 times.
        LEDBlink();
        LEDBlink();
        LEDBlink();
    }

}

boolean PollSensors(){

    //Gets the data from the DHT11
    DHT22Temp = dhtOutdoor().readHumidity();
    DHT22Humidity = dhtOutdoor().readTemperature();

    //Get data from the Dallas OneWire temp. sensor
    //Send the command to get temperatures
    TCTempSense.requestTemperatures();
    //Saves the temp. value
    ThermoCoupleT = sensors.getTempCByIndex(0);

    //Checks the Water Sensor
    if(digitalRead(WaterSensor) == HIGH){
        RainSensor = true;
    }else{
        RainSensor = false;
    }

    //Checks to see if any numerical are NAN.
    if( isnan(DHT22Humidity) || isnan(DHT22Temp) || isnan(ThermoCoupleT) ){
    //Reading the Sensors is a failure.
    return false;
    }else{
    //Reading the Sensors is a success.
    return true;
    }

}

void TransmitData(){

    //Defines a new data structure.
        //a beginning identifer.
        //ints with temp1, humid1, temp2.
        //boolean with rain data
        //int with air quality data.
        //a simple checksum

    struct wData_STRUCT{

        byte identifierB;
        int ot1;
        int oh1;
        int ot2;
        boolean r;
        int oa;
        int checksum;

    };

    //Defines structure wData as a variable (retaining structure);
    wData_STRUCT wData;

    //Fill in the data.
    wData.identifierB = 100;
    wData.ot1 = (DHT11Temp*100);
    wData.oh1 = (DHT11Humidity*100);
    wData.ot2 = (ThermoCoupleT*100);
    wData.r = RainSensor;
    wData.oa = airQ;
    wData.checksum = (t1+t2+h3);

    //Transmitis the data structure with Virtual Wire.
    vw_send((uint8_t *)&wData, sizeof(wData));
    vw_wait_rx();

}

void LEDBlink(){

    //Blinks the LED in question.
    digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);               // wait for a second
    digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);

}


void LEDFade(){

    //Fades the LED in question.
    int brightness = 0;    // how bright the LED is
    int fadeAmount = 5;    // how many points to fade the LED by

    // Sets the brightness of pin 9:
    analogWrite(LED, brightness);

    // Changes the brightness for next time through the loop:
    brightness = brightness + fadeAmount;

    // Reverses the direction of the fading at the ends of the fade:
    if (brightness == 0 || brightness == 255) {
        fadeAmount = -fadeAmount ;
    }
    // Waits for 30 milliseconds to see the dimming effect
    delay(30);

}

And here is my Receiver. The reception function should be finished, however the code for the LCD and Date/Time has not been implemented yet.

#include <Arduino.h>

//Defines the Status led.
//int LED = 11;

//Sets up definitions for the DHT22
//DHT22 is on PIN 2
#include <DHT.h>
#define DHTTYPE DHT22 //DHT 22
#define DHTPIN 2 //DHT 22 data on Pin 2
DHT dhtIndoor(DHTPIN, DHTTYPE);

//Defines the air sensor PIN 11
#define AirSensor 11

//Sets up Wireless Transmission
#include <VirtualWire.h>

#undef int
#undef abs
#undef double
#undef float
#undef round

//Definitions for the LCD
#include <LiquidCrystal.h>
LiquidCrystal LCD (8, 13, 9, 4, 5, 6, 7);







//Defines structure wData as a variable (retaining structure);
wData_STRUCT wData;


float it1 = 0;
float ih1 = 0;
float ot1 = 0;
float oh1 = 0;
float ot2 = 0;
int oa = 0;
int ia = 0;
boolean r = false;


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

	//Defines the Struct
    struct wData_STRUCT{

        byte identifierB;
        int ot1;
        int oh1;
        int ot2;
        boolean r;
        int oa;
        int checksum;

    };


    //Sets up the LCD Display.
    LCD.begin(16, 2);
    LCD.clear();
    LCD.noBlink();
    LCD.noCursor();
    //LCD.setCursor (0,0);



	//pinMode(LED, OUTPUT);

    //Starts the DHT22 sensor
    dhtIndoor().begin();



	//Sets up VirtualWire to recieve.
    vw_set_tx_pin(13); //Comm. on PIN 13.
    vw_setup(2000); //Bits per second.
	vw_rx_start();


}

void loop(){



	for(int i = 0; i < 5; i++){


        Screen(i);




	}




}

void Loading(int col, int row, int loop){

    int i = 0

    do{

        LCD.setCursor(col, row);
        LCD.print("|");
        delay(20);
        LCD.setCursor(col, row);
        LCD.print("/");
        delay(20);
        LCD.setCursor(col, row);
        LCD.print("-");
        delay(20);
        LCD.setCursor(col, row);
        LCD.print("\");
        delay(20);

        i = i + 1;

    }while (i <= loop);

}

void Screen(int screen){

    LCD.clear();
    LCD.home();

    switch (screen){

    //Gets Weather data.
    case 0:
        //First bootup screen
        LCD.print("Welcome!");
        LCD.setCursor(0, 1);
        LCD.print("Fetching Data.");
        Loading(15, 1, 5);

        //True if there is an error, false if there is not.
        boolean psError = PollSensor();
        boolean rcError = RecieveData();

            LCD.clear();
            LCD.home();

            if (psError == true){
                LCD.print("Indoor: Good");
            }else{
                LCD.print("Indoor: Bad");
            }

            if (rcError == true){
                LCD.setCursor(0, 1);
                LCD.print("Outdoor: Good");
            }else{
                LCD.setCursor(0, 1);
                LCD.print("Outdoor: Bad");
            }

        break;



    case 1:

        //Date and Time
        //
        break;


    case 2:
        //Basic Temperature overview.
        LCD.clear();
        LCD.home();
        LCD.print("In: " + it1 + (char)223 + "  " + ih1 + "%");
        LCD.setCursor(0, 1);
        LCD.print("Out: " + ot1 + (char)223 + "  " + oh1 + "%");
        break;


    case 3:
        //More detailed outdoor temprature.
        LCD.clear();
        LCD.home();
        LCD.print("Outside: " + oh1 + "%");
        LCD.setCursor(0, 1);
        LCD.print("T1: " + ot1 + (char)223 + " T2: " + ot2 + (char)223);
        break;


    case 4:
        //Rain and Air Quality outdoors.
        LCD.clear();
        LCD.home();
        string rain = "N/A";
        if(r == true){
            rain = "Raining";
        }else{
            rain = "No Rain"
        }
        LCD.print("Outdoors: " + rain);
        LCD.setCursor(0, 1);

        //ADD AIR QUALITY

        break;



    case 5:
        LCD.clear();
        LCD.home();

        LCD.print("Inside: " + ih1 + "%");
        LCD.setCursor(0, 1);
        LCD.print("T1: " + ot1 + (char)223;

        //Indoor Air Quality (CO2) and Temp and Humidity


        //ADD AIR QUALITY

        break;



    }

}

boolean PollSensors (){

    //Polls the local DHT22 sensor, and pulls room temp and humidity.
    it1 = dhtIndoor().readTemperature();
    ih1 = dhtIndoor().readHumidity();
    //Checks CO2 levels indoor.
    ia = 0;

    //Checks to see if any numerical are NAN.
    if( isnan(it1) || isnan(ih1) || isnan(ia) ){
    //Reading the Sensors is a failure.
        return false;
    }else{
        //Reading the Sensors is a success.
    return true;
    }

}

boolean RecieveData (){

    //Waits for the transmission.
    vw_wait_rx();

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

        //Checks to see if the right amout of data was recieved.
        if (buflen == sizeof(wData_STRUCT)){

            //Compies the data into the Struct.
            memcpy( &wData, buf, sizeof(wData));
            Serial.print(F("identifier + "));
            Serial.println( wData.identifierB);

            //Gets the data from the Struct and Saves the data to global variables (each time).
            ot1 = (wData.ot1/100);
            oh1 = (wData.oh1/100);
            ot2 = (wData.ot2/100);
            r = wData.r;
            oa = wData.oa;


            return true;
        }else{
            //Prints error message
            Serial.printl(F("The wrong amount of byts was recieved !"));
            return false;
        }

    }




}

Which Arduino board are you using ? An Arduino Uno ?

Is this really needed ?

#undef int
#undef abs
#undef double
#undef float
#undef round

Could you try to remove it for both the transmitter and receiver and check if the sketch still compiles ?

Which DHT library do you use ? I'm stumbling over this line:

dhtOutdoor().begin();    // very strange ?
dhtOutdoor.begin();     // normal call for object

Did you know that the VirtualWire sets all pins (RX, TX, PTT) to Arduino pins. So I prefer to set them to unused pins myself to avoid a conflict. Please add that to the transmitter and the receiver.

In the transmitter:

vw_set_rx_pin(5);   // set to unused pin
vw_set_tx_pin(3);    // tx pin for RF transmitter
vw_set_ptt_pin(6);   // set to unused pin

In the receiver you forgot to set the RX pin. Could you set every pin as well ?

vw_set_rx_pin(5);   // pin of RF receiver
vw_set_tx_pin(3);    // set to unused pin
vw_set_ptt_pin(10);   // set to unused pin

In your sketch of the transmitter, you use pin3 for TX, but in the comment you say that it is pin 13. Also for other pins the comment is different. You already have a problem with pin 4 (OneWire and Water Sensor). Please fix that. I prefer to define the pins in one section of the sketch. I would keep the "LiquidCrystal LCD (8, 13, 9, 4, 5, 6, 7) ;" as it is, but for the other pins something like this (example for transmitter):

const int pinLed = 11;
const int pinDHT = 2;
const int pinOneWire = 4;
const int pinWaterSensor = 8;
const int pinAirSensor = 7;
const int pin_vw_tx = 3;
const int pin_vw_rx_unused = 5;
const int pin_vw_ptt_unused = 6;

After that you have to change the transmitter and receiver for all those new pin variables of course. For example this section:

vw_set_rx_pin(pin_vw_rx_unused);   // set to unused pin
vw_set_tx_pin(pin_vw_tx);    // tx pin for RF transmitter
vw_set_ptt_pin(pin_vw_ptt);   // set to unused pin

I prefer to put the definition "struct wData_STRUCT{..." above the setup() function in the global section. But if the compiler is okay with, then it is okay. In the receiver, you create the struct with "wData_STRUCT wData ;", but the definition is further down the sketch. I think the compiler doesn't like that. Define the structure first, and after that create the "wData".

In the transmitter, there is no limit to the amount for transmitting data packets. Only the blinking of the led does slow it down. I prefer that you program in your sketch how many times the data is transmitted. For example every minute or every 5 minutes. For 433MHz it is allowed to transmit 1/10 of the time. If your packet takes 70ms, then you may transmit that every 0.7 seconds.

I transmit temperatures every 3 to 10 minutes. I transmit some data (for example battery voltage) only every 30 minutes.

In the receiver I see "vw_wait_rx()". I have never used that function. I like to receive data at any time. I let the loop() run without delay and without blocking and I check in the loop if something is received. If something is received, than I process that data at that moment. That could be very simple, by just copying the data in the structure, and using that data at an other moment.

Sorry,

I would like to apologize for the extended delay. Some of the parts that were purchased were faulty and are being exchanged.

While I wait, I've run the code through the compiler, and have had some java.util type error come up. As for the libraries that I'm using: They are the ones provided by Adafruit (for the DHT and the Dallas Temperature Sensor & One Wire bus).

More to come.

Ok. I have made the suggested modifications to my transmitter, and the Compiler seems to be happy. The code also looks a lot cleaner since you’ve suggested that I define the pins as constant ints. I will add a delay to the transmitter side so it only transmits every 3 minutes or so (as you suggested). I will also remove the vw_wait_rx() from the receiver side.

Edit: I’ll throw up the code for the receiver tomorrow, as it’s proven to take a lot longer to clean

#include <Arduino.h>
#include <DHT.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <VirtualWire.h>

//Defines the Status led.
const int pinLED = 11;
const int pinDHT = 2;
const int pinOneWire = 4;
const int pinAirSensor = 7;
//Analogue Pin A4.
const int analog_pinWaterSensor = 4;
const int pin_vw_tx = 3;
const int pin_vw_rx_unused = 5;
const int pin_vw_ptt_unused = 6;


//Sets up definitions for the DHT22
DHT dhtOutdoor(pinDHT, DHT22);

//Sets up the OneWire communication for the Dallas Temp. Sensor
OneWire oneWire(pinOneWire);
DallasTemperature TCTempSense(&oneWire);
//TCTempSense = ThemocoupleTempSense
//TCTempSense.begin();

//Var to see if the data from the sensors is valid.
boolean SenseSuccess = false;



float DHT22Temp = 0;
float DHT22Humidity = 0;
float ThermoCoupleT = 0;
boolean RainSensor = false;
int airQ = 0;

//#undef int
//#undef abs
//#undef double
//#undef float
//#undef round


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

	// initialize the digital pin as an output.
	// Pin 13 has an LED connected on most Arduino boards:
	//pinMode(13, OUTPUT);

    //Initialize the LED pin as a digital output.
    pinMode(pinLED, OUTPUT);

    //Starts the DHT22 sensor
    dhtOutdoor.begin();

	//Starts the Dallas Temprature Sensor library.
	TCTempSense.begin();

	//Defines the input for the water sensor.
    //N/A (In PollSensors).

	//Sets up VirtualWire wireless (transmission) communications.
	vw_set_ptt_pin(pin_vw_ptt_unused);
	vw_set_rx_pin(pin_vw_rx_unused);
	vw_set_tx_pin(pin_vw_tx); //Comm. on PIN 3.
    vw_setup(2000); //Bits per second.


}

void loop()
{

    //Poll the sensors for the Enviromental Data.
	SenseSuccess = PollSensors();

    //If the sensors correctly pulled in the data,
    //transmit it.
    if(SenseSuccess == true){
        //Transmit the data and fade the LED in and out once.
        TransmitData();
        LEDFade();
    }else{
        //Error, blink the LED 3 times.
        LEDBlink();
        LEDBlink();
        LEDBlink();
    }

}

boolean PollSensors(){

    //Gets the data from the DHT11
    DHT22Temp = dhtOutdoor.readHumidity();
    DHT22Humidity = dhtOutdoor.readTemperature();

    //Get data from the Dallas OneWire temp. sensor
    //Send the command to get temperatures
    TCTempSense.requestTemperatures();
    //Saves the temp. value
    ThermoCoupleT = TCTempSense.getTempCByIndex(0);

    //Checks the Water Sensor
    if(analogRead(analog_pinWaterSensor) >= 100){
        RainSensor = true;
    }else{
        RainSensor = false;
    }

    //Checks to see if any numerical are NAN.
    if( isnan(DHT22Humidity) || isnan(DHT22Temp) || isnan(ThermoCoupleT) ){
    //Reading the Sensors is a failure.
    return false;
    }else{
    //Reading the Sensors is a success.
    return true;
    }

}

void TransmitData(){

    //Defines a new data structure.
        //a beginning identifer.
        //ints with temp1, humid1, temp2.
        //boolean with rain data
        //int with air quality data.
        //a simple checksum

    struct wData_STRUCT{

        byte identifierB;
        int ot1;
        int oh1;
        int ot2;
        boolean r;
        int oa;
        int checksum;

    };

    //Defines structure wData as a variable (retaining structure);
    wData_STRUCT wData;

    //Fill in the data.
    wData.identifierB = 100;
    wData.ot1 = (DHT22Temp*100);
    wData.oh1 = (DHT22Humidity*100);
    wData.ot2 = (ThermoCoupleT*100);
    wData.r = RainSensor;
    wData.oa = airQ;
    wData.checksum = ((DHT22Temp*100)+(DHT22Humidity*100)+(ThermoCoupleT*100));

    //Transmitis the data structure with Virtual Wire.
    vw_send((uint8_t *)&wData, sizeof(wData));
    vw_wait_rx();

}

void LEDBlink(){

    //Blinks the LED in question.
    digitalWrite(pinLED, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);               // wait for a second
    digitalWrite(pinLED, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);

}


void LEDFade(){

    //Fades the LED in question.
    int brightness = 0;    // how bright the LED is
    int fadeAmount = 5;    // how many points to fade the LED by

    // Sets the brightness of pin 9:
    analogWrite(pinLED, brightness);

    // Changes the brightness for next time through the loop:
    brightness = brightness + fadeAmount;

    // Reverses the direction of the fading at the ends of the fade:
    if (brightness == 0 || brightness == 255) {
        fadeAmount = -fadeAmount ;
    }
    // Waits for 30 milliseconds to see the dimming effect
    delay(30);

}

I think you can remove the “#include <Arduino.h>”.
Please use A4 for analog pin 4. You may use both, but A4 is preferred since it shows clearly that it is an analog pin.

const int analog_pinWaterSensor = A4;

If you want to be perfect, you can show in the code that a number is a floating point number.
Use 1,2,3 for integers, and use 0.0, 100.0, 200.0 for float.
The next example initializes the integer fadeAmount with an integer and the float DTH22Temp with a float. The compiler doesn’t care about it in this case, but I use mainly to remind myself that we are dealing with float numbers.

int fadeAmount = 5;
float DHT22Temp = 0.0;

Alright, I’ve made those changes to the Transmitter as well (and the compiler is still happy).
I did not think you could define an integer as “A4”, but it gave me no problems. :slight_smile:

//#include <Arduino.h>
#include <DHT.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <VirtualWire.h>

//Defines the Status led.
const int pinLED = 11;
const int pinDHT = 2;
const int pinOneWire = 4;
const int pinAirSensor = 7;
//Analogue Pin A4.
const int analog_pinWaterSensor = A4;
const int pin_vw_tx = 3;
const int pin_vw_rx_unused = 5;
const int pin_vw_ptt_unused = 6;


//Sets up definitions for the DHT22
DHT dhtOutdoor(pinDHT, DHT22);

//Sets up the OneWire communication for the Dallas Temp. Sensor
OneWire oneWire(pinOneWire);
DallasTemperature TCTempSense(&oneWire);

//Var to see if the data from the sensors is valid.
boolean SenseSuccess = false;



float DHT22Temp = 0.0;
float DHT22Humidity = 0.0;
float ThermoCoupleT = 0.0;
boolean RainSensor = false;
int airQ = 0;

//#undef int
//#undef abs
//#undef double
//#undef float
//#undef round


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

	// initialize the digital pin as an output.
	// Pin 13 has an LED connected on most Arduino boards:
	//pinMode(13, OUTPUT);

    //Initialize the LED pin as a digital output.
    pinMode(pinLED, OUTPUT);

    //Starts the DHT22 sensor
    dhtOutdoor.begin();

	//Starts the Dallas Temprature Sensor library.
	TCTempSense.begin();

	//Defines the input for the water sensor.
    //N/A (In PollSensors).

	//Sets up VirtualWire wireless (transmission) communications.
	vw_set_ptt_pin(pin_vw_ptt_unused);
	vw_set_rx_pin(pin_vw_rx_unused);
	vw_set_tx_pin(pin_vw_tx); //Comm. on PIN 3.
        vw_setup(2000); //Bits per second.


}

void loop()
{

    //Poll the sensors for the Enviromental Data.
	  SenseSuccess = PollSensors();

    //If the sensors correctly pulled in the data,
    //transmit it.
    if(SenseSuccess == true){
        //Transmit the data and fade the LED in and out once.
        TransmitData();
        LEDFade();
    }else{
        //Error, blink the LED 3 times.
        LEDBlink();
        LEDBlink();
        LEDBlink();
    }

    delay(180000);
    //Delay for 3 min. (3*60*1000)

}

boolean PollSensors(){

    //Gets the data from the DHT22
    DHT22Temp = dhtOutdoor.readHumidity();
    DHT22Humidity = dhtOutdoor.readTemperature();

    //Get data from the Dallas OneWire temp. sensor
    //Send the command to get temperatures
    TCTempSense.requestTemperatures();
    //Saves the temp. value
    ThermoCoupleT = TCTempSense.getTempCByIndex(0);

    //Checks the Water Sensor
    if(analogRead(analog_pinWaterSensor) >= 100){
        RainSensor = true;
    }else{
        RainSensor = false;
    }

    //Checks to see if any numerical are NAN.
    if( isnan(DHT22Humidity) || isnan(DHT22Temp) || isnan(ThermoCoupleT) ){
    //Reading the Sensors is a failure.
    return false;
    }else{
    //Reading the Sensors is a success.
    return true;
    }

}

void TransmitData(){

    //Defines a new data structure.
        //a beginning identifer.
        //ints with temp1, humid1, temp2.
        //boolean with rain data
        //int with air quality data.
        //a simple checksum

    struct wData_STRUCT{

        byte identifierB;
        int ot1;
        int oh1;
        int ot2;
        boolean r;
        int oa;
        int checksum;

    };

    //Defines structure wData as a variable (retaining structure);
    wData_STRUCT wData;

    //Fill in the data.
    wData.identifierB = 100;
    wData.ot1 = (DHT22Temp*100);
    wData.oh1 = (DHT22Humidity*100);
    wData.ot2 = (ThermoCoupleT*100);
    wData.r = RainSensor;
    wData.oa = airQ;
    wData.checksum = ((DHT22Temp*100)+(DHT22Humidity*100)+(ThermoCoupleT*100));

    //Transmitis the data structure with Virtual Wire.
    vw_send((uint8_t *)&wData, sizeof(wData));
    vw_wait_rx();

}

void LEDBlink(){

    //Blinks the LED in question.
    digitalWrite(pinLED, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);               // wait for a second
    digitalWrite(pinLED, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);

}


void LEDFade(){

    //Fades the LED in question.
    int brightness = 0;    // how bright the LED is
    int fadeAmount = 5;    // how many points to fade the LED by

    // Sets the brightness of pin 9:
    analogWrite(pinLED, brightness);

    // Changes the brightness for next time through the loop:
    brightness = brightness + fadeAmount;

    // Reverses the direction of the fading at the ends of the fade:
    if (brightness == 0 || brightness == 255) {
        fadeAmount = -fadeAmount ;
    }
    // Waits for 30 milliseconds to see the dimming effect
    delay(30);

}

Here is the code for the Receiver end. The last phase of the Receiver is to implement the RTC and the Keypad. The hard part will be programming the Keypad such that I can adjust the RTC’s time and manually scroll through the screens (in addition to have it scroll automatically). The difficult bit is finding a way to interrupt the automatic scroll when the button is pressed (check the analog pin of a voltage divider keypad that’s on an LCD shield).

//TO DO: Implement keypad buttons.
//TO DO: Implement RTC.

#include <Arduino.h>
#include <DHT.h>
#include <LiquidCrystal.h>
#include <VirtualWire.h>

const int pinLCDBL = 10;
const int pinDHT = 2;
const int pinAirSensor = 11;
const int analog_pinKeypad = A0;

const int pin_vw_rx = 13;
const int pin_vw_tx_unused = 3;
const int pin_vw_ptt_unused = 6;

//DHT22 is on PIN 2
DHT dhtIndoor(pinDHT, DHT22);

//Definitions for the LCD
LiquidCrystal LCD (8, 13, 9, 4, 5, 6, 7);

//#undef int
//#undef abs
//#undef double
//#undef float
//#undef round


float it1 = 0.0;
float ih1 = 0.0;
float ot1 = 0.0;
float oh1 = 0.0;
float ot2 = 0.0;
int oa = 0;
int ia = 0;
boolean r = false;


	//Defines the Struct
    struct wData_STRUCT{

        byte identifierB;
        int ot1;
        int oh1;
        int ot2;
        boolean r;
        int oa;
        int checksum;

    };

//Defines structure wData as a variable (retaining structure);
wData_STRUCT wData;


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

    //Sets up the LCD Display.
    pinMode(pinLCDBL, OUTPUT);
    digitalWrite(pinLCDBL, HIGH);
    LCD.begin(16, 2);
    LCD.clear();
    LCD.noBlink();
    LCD.noCursor();
    //LCD.setCursor (0,0);

    //Starts the DHT22 sensor
    dhtIndoor.begin();

	//Sets up VirtualWire to recieve.
	vw_set_ptt_pin(pin_vw_ptt_unused);
	vw_set_tx_pin(pin_vw_tx_unused);
  vw_set_rx_pin(pin_vw_rx); //Comm. on PIN 13.
  vw_setup(2000); //Bits per second.
	vw_rx_start();


}

void loop(){



	for(int i = 0; i < 5; i++){
        Screen(i);
        delay(2000);
        if(i>5){
            i=0;
        }
	}






}

void Loading(int col, int row, int loop){

    //Does a quick little countdown from 5 to 1 as an indicaiton of loading.
    int i = 0;
    int d = 200;

    do{

        LCD.setCursor(col, row);
        LCD.print("5");
        delay(d);
        LCD.setCursor(col, row);
        LCD.print("4");
        delay(d);
        LCD.setCursor(col, row);
        LCD.print("3");
        delay(d);
        LCD.setCursor(col, row);
        LCD.print("2");
        delay(d);
        LCD.setCursor(col, row);
        LCD.print("1");
        delay(d);


        i = i + 1;

    }while (i < loop);

    LCD.setCursor(col, row);
    LCD.print(" ");


}

void BlinkLCD(int onoff){

    //Blinks the LCD display on/off when requested.
    for(int i = onoff; i>=0; i--){
        digitalWrite(pinLCDBL, LOW);
        digitalWrite(pinLCDBL, HIGH);
    }


}

void Screen(int screen){

    //Prints all of the information to the screen.

    LCD.clear();
    LCD.home();

    switch (screen){

    //Gets Weather data.
    case 0:{
        //First bootup screen
        LCD.print("Welcome!");
        LCD.setCursor(0, 1);
        LCD.print("Fetching Data.");
        Loading(15, 0, 1);

        //True if there is an error, false if there is not.
        boolean psError = PollSensors();
        boolean rcError = RecieveData();

            LCD.clear();
            LCD.home();

            if (psError == true){
                LCD.print("Indoor: Good");
            }else{
                LCD.print("Indoor: Bad");
            }

            if (rcError == true){
                LCD.setCursor(0, 1);
                LCD.print("Outdoor: Good");
            }else{
                LCD.setCursor(0, 1);
                LCD.print("Outdoor: Bad");
            }

        }break;



    case 1:{

        //Date and Time
        //
        }break;


    case 2:{
        //Basic Temperature overview.
        LCD.clear();
        LCD.home();

        LCD.print("In: ");
        LCD.print(it1);
        LCD.print((char)223);
        LCD.print(" ");
        LCD.print(ih1);
        LCD.print("%");

        LCD.setCursor(0, 1);

        LCD.print("Out: ");
        LCD.print(ot1);
        LCD.print((char)223);
        LCD.print(" ");
        LCD.print(oh1);
        LCD.print("%");

        }break;


    case 3:{
        //More detailed outdoor temprature.
        LCD.clear();
        LCD.home();

        LCD.print("Outside: ");
        LCD.print(oh1);
        LCD.print("%");

        LCD.setCursor(0, 1);

        LCD.print("T1: ");
        LCD.print(ot1);
        LCD.print((char)223);
        LCD.print(" T2: ");
        LCD.print(ot2);
        LCD.print((char)223);

        }break;


    case 4:{
        //Rain and Air Quality outdoors.
        LCD.clear();
        LCD.home();
        String rain = "N/A";
        if(r == true){
            rain = "Raining";
        }else{
            rain = "No Rain";
        }
        LCD.print("Outdoors: ");
        LCD.print(rain);
        LCD.setCursor(0, 1);
        }break;



    case 5:{
        LCD.clear();
        LCD.home();

        LCD.print("Inside: ");
        LCD.print(ih1);
        LCD.print("%");

        LCD.setCursor(0, 1);

        LCD.print("T1: ");
        LCD.print(it1);
        LCD.print((char)223);

        //Indoor Air Quality (CO2) and Temp and Humidity


        //ADD AIR QUALITY

        }break;



    }

}

boolean PollSensors (){

    //Polls the local DHT22 sensor, and pulls room temp and humidity.
    it1 = dhtIndoor.readTemperature();
    ih1 = dhtIndoor.readHumidity();
    //Checks CO2 levels indoor.
    ia = 0;

    //Checks to see if any numerical are NAN.
    if( isnan(it1) || isnan(ih1) || isnan(ia) ){
    //Reading the Sensors is a failure.
        return false;
    }else{
        //Reading the Sensors is a success.
    return true;
    }

}

boolean RecieveData (){

    //Waits for the transmission.
    //vw_wait_rx();

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

        //Checks to see if the right amout of data was recieved.
        if (buflen == sizeof(wData_STRUCT)){

            //Compies the data into the Struct.
            memcpy( &wData, buf, sizeof(wData));
            Serial.print(F("identifier + "));
            Serial.println( wData.identifierB);

            //Gets the data from the Struct and Saves the data to global variables (each time).
            ot1 = (wData.ot1/100);
            oh1 = (wData.oh1/100);
            ot2 = (wData.ot2/100);
            r = wData.r;
            oa = wData.oa;


            return true;
        }else{
            //Prints error message
            Serial.print(F("The wrong amount of byts was recieved !"));
            BlinkLCD(5);
            return false;
        }

    }




}

After I cleaned up the code, the Java errors disappeared, and the rest had to do with missing ; or a broken case statement. I also have something like “LCD.print(“Test” + “Message”);” and it didn’t seem to like me concatenating statements like that. I had to break them up into separate lines. Is there any way to string them along in the same .print statement?

Below is the error that the compiler is throwing back. It seems to be the virtual wire buffers for some reason.

Arduino: 1.6.5 (Windows 7), Board: "Arduino Uno"

WeatherStation.ino: In function 'boolean RecieveData()':
WeatherStation:311: error: 'buf' was not declared in this scope
WeatherStation:311: error: 'buflen' was not declared in this scope
'buf' was not declared in this scope

  This report would have more information with
  "Show verbose output during compilation"
  enabled in File > Preferences.

Your receiver needs some work.

The correct English word is “receive” by the way (not “recieve”) :wink:

Did you enable the line numbers ? You can turn them on in the settings.
Line 311 is in the function “RecieveData()”. The compiler is missing the variable “buf”.
See the example of VirtualWire and add it like this within the function:

  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;

I still strongly prefer to have the loop() running without delay and check for incoming VirtualWire messages all the time.

When the compiler says: “not declared in this scope”, it is saying: “I have been looking for that variable in the local variables and in the global variables or any other place that has variables that can be used for this specific part of the code, but I just can’t find it. You probably forgot to create that variable. The only thing that I can do now is to stop compiling and tell you about this error”.

The ‘A0’ and ‘A1’ and so on are numbers, because they are simple defines or integer values or so. For the Arduino Uno, I think ‘A0’ is 14, ‘A1’ is 15 and so on. The function analogRead() accepts for the first channel a number ‘0’, a number ‘14’ and also ‘A0’.

Alright. I’ve made those changes to the Receiver end. You mentioned that you prefer not to put a delay in the main loop. Does this prevent VirtualWire from receiving messages? Or do I have to prompt it to wait for the message. Also, I remember that we included an Identifier in the Transmitter. Would I just do an if statement to check if it’s the right message?

//TO DO: Impliment keypad buttons.
//TO DO: Impliment RTC.

//#include <Arduino.h>
#include <DHT.h>
#include <LiquidCrystal.h>
#include <VirtualWire.h>

const int pinLCDBL = 10;
const int pinDHT = 2;
const int pinAirSensor = 11;
const int analog_pinKeypad = A0;

const int pin_vw_rx = 13;
const int pin_vw_tx_unused = 3;
const int pin_vw_ptt_unused = 6;

//DHT22 is on PIN 2
DHT dhtIndoor(pinDHT, DHT22);

//Definitions for the LCD
LiquidCrystal LCD (8, 13, 9, 4, 5, 6, 7);

//#undef int
//#undef abs
//#undef double
//#undef float
//#undef round


float it1 = 0.0;
float ih1 = 0.0;
float ot1 = 0.0;
float oh1 = 0.0;
float ot2 = 0.0;
int oa = 0;
int ia = 0;
int r = 0;


	//Defines the Struct
    struct wData_STRUCT{

        byte identifierB;
        int ot1;
        int oh1;
        int ot2;
        int r;
        int oa;
        //int checksum;

    };

//Defines structure wData as a variable (retaining structure);
wData_STRUCT wData;


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

    //Sets up the LCD Display.
    pinMode(pinLCDBL, OUTPUT);
    digitalWrite(pinLCDBL, HIGH);
    LCD.begin(16, 2);
    LCD.clear();
    LCD.noBlink();
    LCD.noCursor();
    //LCD.setCursor (0,0);

    //Starts the DHT22 sensor
    dhtIndoor.begin();

	//Sets up VirtualWire to recieve.
	vw_set_ptt_pin(pin_vw_ptt_unused);
	vw_set_tx_pin(pin_vw_tx_unused);
  vw_set_rx_pin(pin_vw_rx); //Comm. on PIN 13.
  vw_setup(2000); //Bits per second.
	vw_rx_start();


}

void loop(){



	for(int i = -1; i <= 6; i++){

        //Prints the next screen.
        Screen(i, 4000);
        //Delay is 8 sec.
        int screenDelay = 4000;

            //Checks for a button push every 40ms.
            do{
                screenDelay = screenDelay - 1000;
                //If the button is push, to to next screen or prev.
                if(ButtonCheck() == "btnUp"){
                    i = i - 1;
                }else if(ButtonCheck() == "btnDown"){
                    i = i + 1;
                }else if(ButtonCheck() == "btnSelect"){
                    //If Select is push, open up the menu.
                    ButtonMenu();
                }

            }while(screenDelay >= 0);

        //If the last screen is reached, start off at screen 1.
        if(i>=5){
            i=0;
        }


	}



}

void Loading(int col, int row, int loop){

    //Does a quick little countdown from 5 to 1 as an indicaiton of loading.
    int i = 0;
    int d = 200;

    do{

        LCD.setCursor(col, row);
        LCD.print("5");
        delay(d);
        LCD.setCursor(col, row);
        LCD.print("4");
        delay(d);
        LCD.setCursor(col, row);
        LCD.print("3");
        delay(d);
        LCD.setCursor(col, row);
        LCD.print("2");
        delay(d);
        LCD.setCursor(col, row);
        LCD.print("1");
        delay(d);


        i = i + 1;

    }while (i < loop);

    LCD.setCursor(col, row);
    LCD.print(" ");


}

void BlinkLCD(int onoff){

    //Blinks the LCD display on/off when requested.
    for(int i = onoff; i>=0; i--){
        digitalWrite(pinLCDBL, LOW);
        delay(200);
        digitalWrite(pinLCDBL, HIGH);
        delay(200);
    }


}

void Screen(int screen, int avgDelay){

    //Prints all of the information to the screen.

    LCD.clear();
    LCD.home();

    switch (screen){


    case -1:{

        //First bootup/welcome screen
        LCD.print("Welcome!");
        LCD.setCursor(0, 1);
        LCD.print("Fetching Data.");
        Loading(15, 0, 1);

        }break;



    case 0:{

        //Gets Weather data.
        //True if there is an error, false if there is not.
        boolean psError = PollSensors();
        boolean rcError = ReceiveData();

        LCD.clear();
        LCD.home();

        if (psError == true){
            LCD.print("Indoor: OK");
        }else{
            LCD.print("Indoor: N/A");
        }

        if (rcError == true){
            LCD.setCursor(0, 1);
            LCD.print("Outdoor: OK");
        }else{
            LCD.setCursor(0, 1);
            LCD.print("Outdoor: N/A");
        }
        BlinkLCD(5);
        delay(avgDelay);




        }break;



    case 1:{

        //Date and Time
        //
        }break;


    case 2:{
        //Basic Temperature overview.
        LCD.clear();
        LCD.home();

        LCD.print("In:");
        LCD.print(it1);
        LCD.print((char)223);
        LCD.print(" ");
        LCD.print(ih1);
        LCD.print("%");

        LCD.setCursor(0, 1);

        LCD.print("Ot:");
        LCD.print(ot1);
        LCD.print((char)223);
        LCD.print(" ");
        LCD.print(oh1);
        LCD.print("%");

        delay(avgDelay);

        }break;


    case 3:{
        //More detailed outdoor temprature.
        LCD.clear();
        LCD.home();

        LCD.print("Out: ");
        LCD.print("H1: ");
        LCD.print(oh1);
        LCD.print("%");

        LCD.setCursor(0, 1);

        LCD.print("T1:");
        LCD.print(ot1);
        LCD.print((char)223);
        LCD.print(" ");
        LCD.print(ot2);
        LCD.print((char)223);

        delay(avgDelay);

        }break;


    case 4:{
        //Rain and Air Quality outdoors.
        LCD.clear();
        LCD.home();
        String rain = "N/A";
        if(r == true){
            rain = "Raining";
        }else{
            rain = " No Rain";
        }
        LCD.print("    Outdoors:");
        LCD.setCursor(0, 1);
        LCD.print("    ");
        LCD.print(rain);


        delay(avgDelay);

        }break;



    case 5:{
        LCD.clear();
        LCD.home();

        LCD.print("In: ");
        LCD.print("H1: ");
        LCD.print(ih1);
        LCD.print("%");

        LCD.setCursor(0, 1);

        LCD.print("    T1: ");
        LCD.print(it1);
        LCD.print((char)223);

        //Indoor Air Quality (CO2) and Temp and Humidity


        //ADD AIR QUALITY

        delay(avgDelay);

        }break;



    }

}

String ButtonCheck(){

    int keyIn = analogRead(A0);

    Serial.print("Keypress:");
    Serial.println(keyIn);

    if(keyIn > 1000){
        return "btnNONE";
    }else if (keyIn < 3){
        return "bntRight";
    }else if (keyIn < 135){
        return "btnUp";
    }else if (keyIn < 305){
        return "btnDown";
    }else if (keyIn < 480){
        return "btnLeft";
    }else if (keyIn < 720){
        return "btnSelect";
    }


}

void ButtonMenu(){

    //String btn = ButtonCheck();

    //if(btn == keySelect){



    //}








}


boolean PollSensors(){

    //Polls the local DHT22 sensor, and pulls room temp and humidity.
    it1 = dhtIndoor.readTemperature();
    ih1 = dhtIndoor.readHumidity();
    //Checks CO2 levels indoor.
    ia = 0;

    //Checks to see if any numerical are NAN.
    //|| isnan(ia)
    if( isnan(it1) || isnan(ih1) ){
    //Reading the Sensors is a failure.
      return false;
    }else{
        //Reading the Sensors is a success.
      return true;
    }

}

boolean ReceiveData(){

    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;

    //Waits for the transmission.
    //vw_wait_rx();

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

        //Checks to see if the right amout of data was recieved.
        if (buflen == sizeof(wData_STRUCT)){

            //Compies the data into the Struct.
            memcpy( &wData, buf, sizeof(wData));
            Serial.print(F("identifier + "));
            Serial.println( wData.identifierB);

            //Gets the data from the Struct and Saves the data to global variables (each time).
            ot1 = (wData.ot1/100);
            oh1 = (wData.oh1/100);
            ot2 = (wData.ot2/100);
            r = wData.r;
            oa = wData.oa;

            return true;
        }else{
            //Prints error message
            Serial.print(F("The wrong amount of byts was recieved !"));
            BlinkLCD(5);
            return false;
        }

    }




}

You can check for the identifier, but if you have only one transmitter, then you don't have to. I assumed that you were going to add more transmitters someday anyway ;) The VirtualWire uses a checksum. Every message that is received is valid. You already check for the right size, which is also an extra check.

I started with packets of 6 bytes, but then I improved it and now I use 8 bytes (for the same data). My receiver checks the size and uses the old way when it is 6 or the new way when it is 8 bytes. Many things are possible.

Did you receive a message with VirtualWire ?

It is okay to check for a received message with "vw_get_message()" all the time or only now and then. Both is okay. However, it is very strange for me that you check for an incoming message only when the 'screen' is 0. It has to do with the way my brain sees the program flow :o

void loop() {
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
  
  // Check for a received message
  if (vw_get_message(buf, &buflen)){  //Non-blocking
    Serial.print(F("VirtualWire message received, size="));
    Serial.println(buflen);
    ...
  }

  // do other things, perhaps using millis() for a software timer.
  ...
}

Minor Setback: The ATmega328 chips that I bought don’t seem to have any firmware on them and thus cannot be programmed :frowning: . I’ll have this rectified tomorrow.

P.S. I was going to have the Arduino check for new messages in the Main loop. I hadn’t implemented that as I was trying to figure out a way to check for a keypress on the keypad.

void loop(){



	for(int i = -1; i <= 6; i++){

        //Prints the next screen.
        Screen(i, 4000);
        //Delay is 8 sec.



/*
        int screenDelay = 4000;

            //Checks for a button push every 40ms.
            do{
                screenDelay = screenDelay - 1000;
                //If the button is push, to to next screen or prev.
                if(ButtonCheck() == "btnUp"){
                    i = i - 1;
                }else if(ButtonCheck() == "btnDown"){
                    i = i + 1;
                }else if(ButtonCheck() == "btnSelect"){
                    //If Select is push, open up the menu.
                    ButtonMenu();
                }

            }while(screenDelay >= 0);

*/

        //If the last screen is reached, start off at screen 1.
        if(i>=5){
            i=-1;
        }


	}



}

P.P.S: How long would you recommend I make the antennas on both the transmitter and receiver (from your experience)? I’ve read in some documentation that something like 17cm is good, but the receiver’s antenna has to be coiled.

No coil, just 17 cm on both.
However, I have 120 cm on a receiver. The 17 cm didn’t work very well and 120 cm works twice as good. Perhaps the antenna impedance is lower.
I also have a transmitter with 40 cm of wire. It worked well, and I just kept it as it was.
One transmitter is in a small box. Since that is powered with 230V I wanted to keep the box closed and the antenna inside the box. I tried everything: coil windings in the antenna, antenna in loops at the inside of the box and so on. I have now (opening the box, what a mess :o ) very little stretched windings and the wire to the inside of the box about 70% around.