Go Down

Topic: Sending Weather Data (Multiple Values) between 2 Arduinos (433Mhz) (Read 1 time) previous topic - next topic

AWOL

I'm assuming that for testing, you're using actual wires in place of the radio devices, and that you've already proved that you can copy a simple string like "Hello world" from one board to the other.

man1ac

Nope, even for testing I set up the wireless connection. Submitting one value works flawless (for and int).
Is it really that simple and multiply by 100? I tried something smiliar and hat vales like 2300 (temp) and 4000(hum) but on the receiving end I just got weird numbers >10000...


man1ac

Will do that later on when I am home!

Thats the TX
Code: [Select]

#include <VirtualWire.h>
#include <DHT.h>
int temp = 0;
int hum = 0;
DHT dht;
char string1[21];
char string2[21];

void setup() {
Serial.begin(9600);
vw_set_tx_pin(12);
vw_setup(2000);
dht.setup(13);
}

void loop() {
  delay(dht.getMinimumSamplingPeriod());
  temp = dht.getTemperature();
  hum = dht.getHumidity();
 
  sprintf(string1, "%d,%d", temp, hum);

  vw_send((uint8_t *)string1, strlen(string1));
  vw_wait_tx();
  Serial.println(string1);
}



Thats the RX
Code: [Select]
#include <VirtualWire.h>
#include<Wire.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);
int i;
int temp;
int hum;

void setup() {
Serial.begin(9600);
lcd.begin (16,2);
vw_set_rx_pin(12);
vw_setup(2000);
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) )
{
sscanf ((char*)buf, "%d%*c%d%", &temp, &hum);
Serial.println(temp);
Serial.println(hum);
lcd.setCursor(0, 0);
lcd.print("Temp:");   
lcd.setCursor(7,0);   
lcd.print(temp);
lcd.setCursor(9,0);   
lcd.print((char)223);
lcd.print("C"); 
lcd.setCursor(0, 1);
lcd.print("Humidity:");   
lcd.setCursor(10,1);   
lcd.print(hum);
lcd.print("%"); 

}
}

BulldogLowell

consider TX using markers like this:

Code: [Select]
sprintf(string1, "T%dH%d;", temp, hum);

and in RX check for a 'T' or an 'H' and parse the integer:

Using parseInt() for demonstration only (easy)

Code: [Select]
int temp, humidity;

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

}

void loop()
{
  if(Serial.available())
  {
    if (Serial.peek() =='T')
    {
      Serial.read();
      temp = Serial.parseInt();
    }
    if(Serial.peek() == 'H')
    {
      Serial.read();
      humidity = Serial.parseInt();
    }
    else
    {
      Serial.read();
    }
    Serial.print("Temperature:");
    Serial.println(temp);
    Serial.print("Humidity:");
    Serial.println(humidity);
   
  }
}

man1ac


BulldogLowell

Thanks! Will this fix my float Problem?
Transmit a number multiplied by the precision you want to use (e.g 10 or 100) and divide by that on the RX side.

Or, for fun try parseFloat() instead if ParseInt()

Does that do what you want?

Did you try it?

cattledog

There is no need to send data as character strings. Put the float data into a struct, and cast into bytes to send.
Reassemble the struct at the other end.

Code: [Select]
//TX

#include <VirtualWire.h>
#include <DHT.h>
//int temp = 0;
//int hum = 0;
//DHT dht;
//char string1[21];
//char string2[21];
struct{
  float temp;
  float hum;
}
dataSent;

void setup() {
Serial.begin(9600);
vw_set_tx_pin(12);
vw_setup(2000);
dht.setup(13);
}

void loop() {
  delay(dht.getMinimumSamplingPeriod());
  dataSent.temp = dht.getTemperature();
  dataSent.hum = dht.getHumidity();
  
  //sprintf(string1, "%d,%d", temp, hum);
  //vw_send((uint8_t *)string1, strlen(string1));
  vw_send((uint8_t*)&dataSent, sizeof dataSent);
  vw_wait_tx();
  Serial.println(dataSent.temp,2);
  Serial.println(dataSent.hum,2);
}


Code: [Select]
//RX

#include <VirtualWire.h>
#include<Wire.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);
//int i;
//int temp;
//int hum;
struct{
  float temp;
  float hum;
}
dataReceived;

void setup() {
Serial.begin(9600);
lcd.begin (16,2);
vw_set_rx_pin(12);
vw_setup(2000);
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) )
{
//sscanf ((char*)buf, "%d%*c%d%", &temp, &hum);
memcpy(&dataReceived, buf, buflen);
Serial.println(dataReceived.temp);
Serial.println(dataReceived.hum);
lcd.setCursor(0, 0);
lcd.print("Temp:");    
lcd.setCursor(7,0);  
lcd.print(dataReceived.temp);
lcd.setCursor(9,0);    
lcd.print((char)223);
lcd.print("C");  
lcd.setCursor(0, 1);
lcd.print("Humidity:");    
lcd.setCursor(10,1);  
lcd.print(dataReceived.hum);
lcd.print("%");  

}
}


You do not need to use memcpy and can do a direct read into &dataReceived instead of into buf, but I have left it that way to keep things as close to the standard vw library to make it easy to understand.

man1ac

Thanks guys. Hadnt had the chance to test anything else than switching to an I2C for my LCD.
Today I will try and get the floats right :)

man1ac

THANKS CATTLEDOG! That works like a charm :)

Anyway there is some kind of tutorial on what the struct does? So I can understand why this worked!?

1Thing I did notice:

Sometimes (after 20 TX/RX ) I sometimes get "NaN" - SO not a Number. Is there any way I can check the sended data if it makes sense?

AWOL

You could test using "isnan()".

(It is most likely the received data that doesn't make sense)

man1ac

Thanks! Will try that! Is there a way on how to "fill" the NaN with good values? Or trigger another measurment if the value is NaN and take the correct value?
I'd have to check if the NaN is being sended (so the TX makes the mistake) or the RX. If it's the TX I could change the sending sequece?

I've read that the DHT22 cant handle the speed of the measurements (read something that times less than 10s will cause NaN), can that be true?

Go Up