Go Down

Topic: Problem with VirtualWire, Sparkfun's BME280, RF Links and Arduino! (Read 1 time) previous topic - next topic

-ctn-

Hello everyone! I think this is the correct place for this thread.

Anyway, I have a small project I've been working on. I wanted to create a small atmospheric sensor that can wirelessly tell me it's readings. I tried using the ESP8266 module for WiFi connection but could not stumble my way around it.

So right now, I have two separate Arduinos talking to eachother. My problem is that I cannot get one to transmit the proper data to the other. I get bits and pieces, or one word, but not the whole thing. I am not sure if this is my misunderstanding of the VirtualWire library, Arduino coding, or just the process in general.

The Arduino Uno is hooked up to an LED on pin13, Sparkfun's BME280 Atmosphere sensor on analogPins A4/A5 (for I2C), and an RF transmitter (434MHz) on pin12. This is the transmitting device.

The Sparkfun Redboard (Uno clone) is hooked up to an LED on pin13 and the RF receiver module (434MHz) on pin12. This is the receiving device, which is also plugged into the computer with USB, so I can use the IDE's Serial Monitor to look at the data being received.

Basically, I can get the transmitting device to send words, set up as a character message. I can get it to send a temperature reading as a message, but I cannot get it to do both.

What I would like it to transmit is basically what the Transmitter device says in the Serial Monitor, for example:

Temperature: 22.0 degrees C
Pressure: 99207.00 Pa
Altitude: 183.81m
Humidity: 28%

But I am unsure on how to send that information (that is, text with the float variables from the sensors) through VirtualWire to the receiving device. I am also unaware of how to get the receiving device to display English instead of HEX codes. As it is, all I see on the receiving device's serial monitor is:

Ready!
Receiving:
54 65 6D 70 65 72 61 74 75 72 65 3A

Which is HEX for "Temperature:", and that is the only message it gets (repeating every few seconds or so.)

Here is the code I have written/compiled:
Transmitter module:
Code: [Select]
#include <VirtualWire.h>
#include <stdint.h>
#include "SparkFunBME280.h"
#include "Wire.h"
#include "SPI.h"

BME280 mySensor;
const int led = 13;

void setup() {
  pinMode(led,OUTPUT);
  digitalWrite(led,HIGH);
  mySensor.settings.commInterface = I2C_MODE;
  mySensor.settings.I2CAddress = 0x77;
  mySensor.settings.runMode = 3;
  mySensor.settings.tStandby = 0;
  mySensor.settings.filter = 0;
  mySensor.settings.tempOverSample = 1;
  mySensor.settings.pressOverSample = 1;
  mySensor.settings.humidOverSample = 1;

  Serial.begin(57600);
  Serial.print("Program Started\n");
  Serial.print("Starting BME280... result of .begin(): 0x");
 
  //Calling .begin() causes the settings to be loaded
  delay(10);  //Make sure sensor had enough time to turn on. BME280 requires 2ms to start up.
  Serial.println(mySensor.begin(), HEX);

  Serial.print("Displaying ID, reset and ctrl regs\n");
 
  Serial.print("ID(0xD0): 0x");
  Serial.println(mySensor.readRegister(BME280_CHIP_ID_REG), HEX);
  Serial.print("Reset register(0xE0): 0x");
  Serial.println(mySensor.readRegister(BME280_RST_REG), HEX);
  Serial.print("ctrl_meas(0xF4): 0x");
  Serial.println(mySensor.readRegister(BME280_CTRL_MEAS_REG), HEX);
  Serial.print("ctrl_hum(0xF2): 0x");
  Serial.println(mySensor.readRegister(BME280_CTRL_HUMIDITY_REG), HEX);

  Serial.print("\n\n");

  Serial.print("Displaying all regs\n");
  uint8_t memCounter = 0x80;
  uint8_t tempReadData;
  for(int rowi = 8; rowi < 16; rowi++ )
  {
    Serial.print("0x");
    Serial.print(rowi, HEX);
    Serial.print("0:");
    for(int coli = 0; coli < 16; coli++ )
    {
      tempReadData = mySensor.readRegister(memCounter);
      Serial.print((tempReadData >> 4) & 0x0F, HEX);//Print first hex nibble
      Serial.print(tempReadData & 0x0F, HEX);//Print second hex nibble
      Serial.print(" ");
      memCounter++;
    }
    Serial.print("\n");
  }
 
 
  Serial.print("\n\n");
 
  Serial.print("Displaying concatenated calibration words\n");
  Serial.print("dig_T1, uint16: ");
  Serial.println(mySensor.calibration.dig_T1);
  Serial.print("dig_T2, int16: ");
  Serial.println(mySensor.calibration.dig_T2);
  Serial.print("dig_T3, int16: ");
  Serial.println(mySensor.calibration.dig_T3);
 
  Serial.print("dig_P1, uint16: ");
  Serial.println(mySensor.calibration.dig_P1);
  Serial.print("dig_P2, int16: ");
  Serial.println(mySensor.calibration.dig_P2);
  Serial.print("dig_P3, int16: ");
  Serial.println(mySensor.calibration.dig_P3);
  Serial.print("dig_P4, int16: ");
  Serial.println(mySensor.calibration.dig_P4);
  Serial.print("dig_P5, int16: ");
  Serial.println(mySensor.calibration.dig_P5);
  Serial.print("dig_P6, int16: ");
  Serial.println(mySensor.calibration.dig_P6);
  Serial.print("dig_P7, int16: ");
  Serial.println(mySensor.calibration.dig_P7);
  Serial.print("dig_P8, int16: ");
  Serial.println(mySensor.calibration.dig_P8);
  Serial.print("dig_P9, int16: ");
  Serial.println(mySensor.calibration.dig_P9);
 
  Serial.print("dig_H1, uint8: ");
  Serial.println(mySensor.calibration.dig_H1);
  Serial.print("dig_H2, int16: ");
  Serial.println(mySensor.calibration.dig_H2);
  Serial.print("dig_H3, uint8: ");
  Serial.println(mySensor.calibration.dig_H3);
  Serial.print("dig_H4, int16: ");
  Serial.println(mySensor.calibration.dig_H4);
  Serial.print("dig_H5, int16: ");
  Serial.println(mySensor.calibration.dig_H5);
  Serial.print("dig_H6, uint8: ");
  Serial.println(mySensor.calibration.dig_H6);
   
  Serial.println();
  pinMode(3,OUTPUT);
  pinMode(2,OUTPUT);
  digitalWrite(3,HIGH);
  digitalWrite(2,LOW);
 
  delay(1000);
  digitalWrite(led,LOW);
  vw_set_tx_pin(12);
  vw_setup(2000);

}

byte count = 1;

void loop() {

  digitalWrite(2,HIGH);
 
  Serial.print("Temperature: ");
  Serial.print(mySensor.readTempC(), 2);
  Serial.println(" degrees C");
  Serial.print("Pressure: ");
  Serial.print(mySensor.readFloatPressure(), 2);
  Serial.println(" Pa");

  Serial.print("Altitude: ");
  Serial.print(mySensor.readFloatAltitudeMeters(), 2);
  Serial.println("m");

  Serial.print("Humidity: ");
  Serial.print(mySensor.readFloatHumidity(), 2);
  Serial.println(" %");
 
  Serial.println();

  digitalWrite(2,LOW);
 
  delay(10000);

    float tempC = mySensor.readTempC();
    int tempC1 = (int)tempC;
    int tempC2 = (int)(tempC - tempC1) * 100;
    char msg[24];
    sprintf(msg, "%i.%i", tempC1,tempC2);
    digitalWrite(led,HIGH);
    vw_send((uint8_t *)msg, strlen(msg));
    vw_wait_tx();
    digitalWrite(led,LOW);
    delay(2000);
    count = count + 1;
}


Here is the code for the Receiver module:
Code: [Select]
#include <VirtualWire.h>
const int led = 13;

void setup() {
  delay(1000);
  Serial.println("Initializing...");
  pinMode(led,OUTPUT);
  digitalWrite(led,HIGH);
  delay(1000);
  digitalWrite(led,LOW);
  Serial.begin(9600);

 
  vw_set_rx_pin(12);
  vw_setup(2000);
  vw_rx_start();
  Serial.println("Ready!");

}

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

  if (vw_get_message(buf, &buflen))
  {
    int i;
    digitalWrite(led, HIGH);
    Serial.println("Recieved: ");

    for (i = 0; i < buflen; i++)
  {
    Serial.print(buf[i], HEX);
    Serial.print(' ');
  }
  vw_wait_rx_max(1000);
  Serial.println();
  digitalWrite(led, LOW);
  }
}


-I know the receiver code says "HEX" right there at Serial.print but if I remove that, I get gibberish. I'm not sure how to try to convert the HEX to regular text from inside the code/arduino instead  of copy-pasting to a hex-text converter.

Anyway, thanks for looking and thanks in advance for any help. This is only my third or fourth project with Arduino. I was pretty excited when I got them to talk wirelessly, but I would like to learn how to make it better.

Any other questions or information I can provide to help, just let me know.

jremington

VirtualWire does not necessarily return a proper zero-terminated character string. If you want to print at text message as text, you have to terminate the string properly and possibly also cast it correctly.

Try this (untested):

Code: [Select]
if (vw_get_message(buf, &buflen))
  {
    buf[buflen] = 0;
    Serial.print("Received: ");  //corrected spelling
    Serial.println((char *)buf);
  }

PaulS

Code: [Select]
   sprintf(msg, "%i.%i", tempC1,tempC2);
%d is the format specifier for ints.

The art of getting good answers lies in asking good questions.

-ctn-

Awesome, now it says "20.0" which is the correct temperature without dealing with hexidecimals. Is there a way to get it to say "Temperature: 20.0" without sending two messages? (One for text "Temperature:" and one for the sensor reading?)

jremington

Send any message you want, or any combination of variables using a struct.

cattledog

Code: [Select]
int tempC2 = (int)(tempC - tempC1) * 100;

This will always show 0 for the decimal value. Remove the declaration of int on the right side

Code: [Select]
int tempC2 = (tempC - tempC1) * 100;

PaulS

Use dtostrf() to convert the float to a string. It deals with the fractional value properly. Your code will not properly handle a value like 27.05 (not that the sensor is that accurate, but, still).

Use sprintf() with a better format string, if you want to continue the route you are going.

Code: [Select]
sprintf(msg, "Temperature: %d.%d", tempC1,tempC);
The art of getting good answers lies in asking good questions.

-ctn-

Use dtostrf() to convert the float to a string. It deals with the fractional value properly. Your code will not properly handle a value like 27.05 (not that the sensor is that accurate, but, still).

Use sprintf() with a better format string, if you want to continue the route you are going.

Code: [Select]
sprintf(msg, "Temperature: %d.%d", tempC1,tempC);
That gave me exactly the result I wanted. I guess I didn't realize I could put text inside the quotations along with the "%d." I think last time I tried that, it didn't transmit it all - but I must have made an error elsewhere.

Thanks for the help, I'm going to try to get it to send all four of the sensors' information now.

-ctn-

Okay, so I have all of the sensors working and transmitting the correct data to the receiver module: except the pressure.

The sensor measures pressure in Pascals, which for me, is around 98,640 Pa.
Integers can only go up to 32,767, correct? When using the same code as above for the pressure sensor, the receiver was getting "Pressure: -32,431.0" which of course is wrong.

I suspect (and tried) to use "long" variables instead of integers for the code but then I receive blank info on the receiver module: "Pressure: ".

Here is the code for the pressure sensor/transmit:
Code: [Select]
  //Pressure Sensor
    float pressure = mySensor.readFloatPressure(); //Take pressure reading.
    long pressure1 = (long)pressure; //Stuff I took from code on the forums - I am not sure what is happening here:
    long pressure2 = (pressure - pressure1) * 100;
    sprintf(msg, "Pressure: %l.%l", pressure1,pressure2); //The actual message transmitted for pressure.
    digitalWrite(led,HIGH); //Turn the TX LED on while transmitting.
    vw_send((uint8_t *)msg, strlen(msg));
    vw_wait_tx();
    delay(1000);
    digitalWrite(led,LOW); //Turn TX LED off after transmitting and delay.
    count = count + 1;
    delay(1000);


I'm not quite sure what is wrong, or if using the long variable is the right way to achieve what I'm looking for. I'll keep searching, but help is always appreciated.

EDIT:
For anyone else having issues, here's what I did and now it's working as it should (displaying "Pressure: 98599" on the receiving module.)

Code: [Select]

  //Pressure Sensor
    float pressure = mySensor.readFloatPressure(); //Take pressure reading.
    long pressure1 = (long)pressure; //Turning the float into long variable
    sprintf(msg, "Pressure: %lu", pressure1); //The actual message transmitted for pressure.
    Serial.println(msg);
    digitalWrite(led,HIGH); //Turn the TX LED on while transmitting.
    vw_send((uint8_t *)msg, strlen(msg));
    vw_wait_tx();
    delay(1000);
    digitalWrite(led,LOW); //Turn TX LED off after transmitting and delay.
    count = count + 1;
    delay(1000);

PaulS

Code: [Select]
    char pressStg[10];
    dtostrf(pressure, 9, 3, pressStg);
    sprintf(msg, "Pressure: %s, pressStg);


will result in msg containing "Pressure: 98.640" if pressure is 98.640.
The art of getting good answers lies in asking good questions.

Go Up