Go Down

Topic: Arduino and RF (Read 84 times) previous topic - next topic

Hi,

I have two Arduino boards linked via RF 315Mhz and the output from one of them is very weird.

Here is the code on the transmitter :
Code: [Select]


#include <VirtualWire.h>
#include "DHT.h"
#define DHTPIN 2        // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)

DHT dht(DHTPIN, DHTTYPE);

const int transmit_pin = 12;

void setup()
{
    // Initialise the IO and ISR
    vw_set_tx_pin(transmit_pin);
    vw_set_ptt_inverted(true); // Required for DR3100
    vw_setup(2000);       // Bits per sec
    dht.begin();
}

void loop()
{

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();           // Reading humidity
  float t = dht.readTemperature();        // Read temperature as Celsius
//  float f = dht.readTemperature(true);    // Read temperature as Fahrenheit
  
  int tempC1 = (int)t;
  int tempC2 = (int)((t*100) - (tempC1*100)); // For two decimal points

  if ((t*100) > (tempC1*100)) // Check to see if the value if higher then the temp
  {
  int tempC2 = (int)((t*100) - ((tempC1*100)-100)); // For two decimal points
  }

  char msg[18];
  sprintf(msg, "Room D Temp: %i.%i", tempC1,tempC2);
  vw_send((uint8_t *)msg, strlen(msg));

  vw_wait_tx(); // Wait until the whole message is gone
  
  int humC1 = (int)h;

  sprintf(msg, "Room D Humidit: %i", humC1);
  vw_send((uint8_t *)msg, strlen(msg));

  vw_wait_tx(); // Wait until the whole message is gone
  
  delay(10000); // Wait 10 Seconds
}


Here is the receiver code:
Code: [Select]

#include <VirtualWire.h>

const int receive_pin = 7;

void setup()
{
    Serial.begin(9600); // Debugging only
    Serial.println("Ready");

    // Initialise the IO and ISR
    vw_set_rx_pin(receive_pin);
    vw_set_ptt_inverted(true); // Required for DR3100
    vw_setup(2000); // Bits per sec
    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
    {
 // Message with a good checksum received, dump it.
 Serial.print((char*)buf);    
 Serial.println();
    }
}


and the output I am getting is :

Code: [Select]

Room D Temp: 17.50Àû
Room D Humidit: 77û
Room D Temp: 17.50ÿ
Room D Humidit: 77
Room D Temp: 17.50ÿ
Room D Humidit: 77ÿ
Room D Temp: 17.50
Room D Humidit: 77@
Room D Temp: 17.40
Room D Humidit: 77þ
Room D Temp: 17.40
Room D Humidit: 77ÿ
Room D Temp: 17.40À×
Room D Humidit: 77
Room D Temp: 17.40À×
Room D Humidit: 77
Room D Temp: 17.40
Room D Humidit: 77
Room D Temp: 17.40ÿ
Room D Humidit: 77Àû
Room D Temp: 17.40ÿ
Room D Humidit: 77


Can anyone tell me what the random output is at the end ?
Thanks

cattledog

#1
Jan 16, 2015, 09:22 pm Last Edit: Jan 16, 2015, 09:22 pm by cattledog
There are two possible sources for how the buffer is getting corrupted. If I am counting your message size correctly, char msg[18] should be char msg[19] to hold the terminating null character added by sprintf.

Also, the declaration of  buf can be explicitly initialized.
 
 
Code: [Select]
uint8_t buf[VW_MAX_MESSAGE_LEN] = {};

By default, an arrays of local scope (like those declared within a function and void loop() is a function) are left uninitialized. This means that none of its elements are set to any particular value  and their contents are undetermined at the point the array is declared.

I didn't know I had to add one to the message length for terminating null character. (I'll Google 'terminating null character' to learn more)

Once I had changed the length from 18 to 19 I still had the same trouble.

So I replaced my 'uint8_t buf[VW_MAX_MESSAGE_LEN]' with your option 'uint8_t buf[VW_MAX_MESSAGE_LEN] = {}' and it jumped into life.

I need to know more about this, as I'm a little confused by it, and would like to know why my code now works, not just to know it works.
Thank for your help.

cattledog

#3
Jan 16, 2015, 11:07 pm Last Edit: Jan 16, 2015, 11:08 pm by cattledog
Code: [Select]
vw_send((uint8_t *)msg, strlen(msg));

strlen(msg) does not count the terminating null character, so it is not sent. If you change that to
Code: [Select]
vw_send((uint8_t *)msg, strlen(msg)+1); The termination appended by sprintf will be sent.
Code: [Select]
Serial.print((char*)buf);  will now know where to stop.

By initializing "buf", you have compenstated for the lack of a null terminator, and made sure it is already there in the unwritten portions of the array.

So yes, size your sprintf buffer to accept the null terminator, and then send it. It doesn't hurt to initialize the receive buffer, but I don't think it was the root cause of problem. Initializing did cover up the flaw.

PaulS

Code: [Select]
  if ((t*100) > (tempC1*100)) // Check to see if the value if higher then the temp
  {
  int tempC2 = (int)((t*100) - ((tempC1*100)-100)); // For two decimal points
  }

What is the scope of tempC2?

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy