Hello,
I am sending sensor data (temperature and humidity) from one RFM69HCW to another RFM69HCW. I am a new to automation and have cobbled together code that somewhat works, but the temperature data is sometimes being received as humidity data, and I believe this is a programming error on the receiver end on my part.
Hardware: I’m using an AHT20 temp/humidity sensor connected to an Arduino Uno, connected to an RFM69HCW (Adafruit version). This RFM69HCW transmits a signal to an identical RFM69HCW which is connected to an ESP32 which then sends the data to the IOT website ‘Blynk’.
Issue: The temperature data is sometimes (not always) received as the humidity data. I am sending the temperature as a float with 4 bytes, and the humidity as an integer with 2 bytes. This is how I am separating them on the receiving end as temperature or humidity, based on how many bytes they are. I know in Arduino Uno an ‘int’ is 2 bytes, and in the ESP32 it is 4 bytes, but I believe it is still incoming as 2 bytes? - the program seems to label them as 2 and 4 bytes in the Serial Monitor.
This originally seemed the simplest way to send two different variables and separate them -per my novice experience. Any help is appreciated.
Tx Serial Monitor:
GH Temperature and Humidity
⸮
⸮⸮⸮⸮⸮Ʌ⸮⸮ɕ⸮and Humidity found
Feather RFM69 TX Test!
RFM69 radio init OK!
RFM69 radio @915 MHz
Temperature: 75.18 degrees F
Humidity: 50.13% rH
Sending Temp: 75.18 Sending Humidity: 50 Temperature: 75.28 degrees F
Humidity: 50.40% rH
Sending Temp: 75.28 Sending Humidity: 50 Temperature: 75.39 degrees F
Humidity: 50.69% rH
Sending Temp: 75.39 Sending Humidity: 51 Temperature: 75.51 degrees F
Humidity: 50.33% rH
Rx Serial Monitor:
Note: It seems like the temp is getting converted to 2 byte, getting into the past the ‘if (len ==2) statement, and then converted back to a float.
As you can see below, sometimes the real humidity (where it says 32 on Serial Monitor) does make it through. Before I added delays it used to say the correct humidity much more often, but every 4 or so entries it would still post the temp as the humidity.
Feather RFM69 RX Test!
RFM69 radio init OK!
RFM69 radio @915 MHz
.WiFi connected
test1 Receive failed
Test4 test1 Receive failed
Test4 test1 Receive failed
Test4 test1 Receive failed
Test4 test1 Receive failed
Test4 test1 test2 test3 Received Temp [4]: 76.15
RSSI: -31
Test4 test1 test2 test3 Received humidity [2]: 76.00
RSSI: -31
Test4 test1 test2 test3 Received Temp [4]: 76.14
RSSI: -32
Test4 test1 test2 test3 Received humidity [2]: 76.00
RSSI: -31
Test4 test1 Receive failed
Test4 test1 Receive failed
Test4 test1 Receive failed
Test4 test1 Receive failed
Test4 test1 test2 test3 Received humidity [2]: 32.00
RSSI: -31
Test4 test1 test2 test3 Received Temp [4]: 76.13
RSSI: -30
Test4 test1 test2 test3 Received humidity [2]: 76.00
RSSI: -30
Test4 test1 test2 test3 Received Temp [4]: 76.11
RSSI: -30
Rx Serial Monitor w/ line : short transData2 = *((float *)buf);
Line in rx code replaces 'float transData2 = *((float *)buf);', converts transData2 to 2 byte integer.
Feather RFM69 RX Test!
RFM69 radio init OK!
RFM69 radio @915 MHz
.WiFi connected
test1 Receive failed
Test4 test1 Receive failed
Test4 test1 Receive failed
Test4 test1 Receive failed
Test4 test1 Receive failed
Test4 test1 Receive failed
Test4 test1 Receive failed
Test4 test1 test2 test3 Received humidity [2]: 0
RSSI: -44
Test4 test1 test2 test3 Received Temp [4]: 75.04
RSSI: -37
Test4 test1 test2 test3 Received humidity [2]: 75
RSSI: -39
Test4 test1 test2 test3 Received Temp [4]: 75.03
RSSI: -39
Test4 test1 test2 test3 Received humidity [2]: 75
RSSI: -35
Test4 test1 test2 test3 Received humidity [2]: 32
RSSI: -38
Test4 test1 test2 test3 Received Temp [4]: 74.96
RSSI: -38
Test4 test1 test2 test3 Received humidity [2]: 74
RSSI: -38
Test4 test1 test2 test3 Received Temp [4]: 74.94
RSSI: -35
TX Code:
// rf69 demo tx rx.pde
// -*- mode: C++ -*-
// Example sketch showing how to create a simple messageing client
// with the RH_RF69 class. RH_RF69 class does not provide for addressing or
// reliability, so you should only use RH_RF69 if you do not need the higher
// level messaging abilities.
// It is designed to work with the other example rf69_server.
// Demonstrates the use of AES encryption, setting the frequency and modem
// configuration
//Uses RADIOHEAD library and code
#include <SPI.h>
#include <RH_RF69.h>
//Sensor setup
#include <Adafruit_AHTX0.h>
Adafruit_AHTX0 aht;
int i = 0;
/************ Radio Setup ***************/
// Change to 434.0 or other frequency, must match RX's freq!
#define RF69_FREQ 915.0
//#if defined (Arduino Uno) //Arduino Uno input by Calder
#define RFM69_CS 4
#define RFM69_INT 3
#define RFM69_RST 2
#define LED 13
//#endif
// Singleton instance of the radio driver
RH_RF69 rf69(RFM69_CS, RFM69_INT);
int16_t packetnum = 0; // packet counter, we increment per xmission
void setup()
{
//Sensor Setup
// pinMode(9, OUTPUT); //pins for LED and Noise Buzzer
//pinMode(8, OUTPUT);
Serial.begin(9600); // baude rate
Serial.println("GH Temperature and Humidity");
if (! aht.begin()) {
Serial.println("Could not find AHT? Check wiring");
while (1) delay(10);
}
Serial.println("GH Temperature and Humidity found");
//Radio setup
Serial.begin(9600);
//while (!Serial) { delay(1); } // wait until serial console is open, remove if not tethered to computer
pinMode(LED, OUTPUT);
pinMode(RFM69_RST, OUTPUT);
digitalWrite(RFM69_RST, LOW);
Serial.println("Feather RFM69 TX Test!");
Serial.println();
// manual reset
digitalWrite(RFM69_RST, HIGH);
delay(10);
digitalWrite(RFM69_RST, LOW);
delay(10);
if (!rf69.init())
{
Serial.println("RFM69 radio init failed");
while (1);
}
Serial.println("RFM69 radio init OK!");
// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
// No encryption
if (!rf69.setFrequency(RF69_FREQ))
{
Serial.println("setFrequency failed");
}
// If you are using a high power RF69 eg RFM69HW, you *must* set a Tx power with the
// ishighpowermodule flag set like this:
rf69.setTxPower(20, true); // range from 14-20 for power, 2nd arg must be true for 69HCW
//If RSSI on receiver is low, can lower the power to save energy
// The encryption key has to be the same as the one in the server
uint8_t key[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
};
rf69.setEncryptionKey(key);
pinMode(LED, OUTPUT);
Serial.print("RFM69 radio @"); Serial.print((int)RF69_FREQ); Serial.println(" MHz");
}
void loop()
{
//Sensor
sensors_event_t humidity, temp;
aht.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
float t = temp.temperature * (9.0 / 5) + 32; //converting Celsius to Farenheit
float h = humidity.relative_humidity;
//Serial.print("Temperature: "); Serial.print(temp.temperature); Serial.println(" degrees C");
Serial.print("Temperature: "); Serial.print(t); Serial.println(" degrees F");
Serial.print("Humidity: "); Serial.print(humidity.relative_humidity); Serial.println("% rH");
delay(2000);
/*
//Radio
delay(2000); // Wait 1 second between transmits, could also 'sleep' here!
String tempString = String(t); //converting temp float to string for radio transmission
//char radiopacket[20] = "Hoop temp: " + tempString; //radiopacket[20] means there are 20 characters available in the transmission
char radiopacket[30] = "tempString"; //Char is character, has to have quotations
itoa(packetnum++, radiopacket+13, 10);
Serial.print("Sending first ");
Serial.println(radiopacket);
*/
//Temp
float val = t; // a variable
float* pVal = &val; // a pointer to the variable
float anotherVal = *pVal; // dereference the pointer to the first variable, and assign the value to a new variable. "anotherVal" now has the value 't'
//*pVal = 2.718; // "val" now has the value 2.718, but "anotherVal" still has the value 3.1412
//Humidity
float val2 = h; // a variable
float* pVal2 = &val2; // a pointer to the variable
float anotherVal2 = *pVal2; // dereference the pointer to the first variable, and assign the value to a new variable. "anotherVal" now has the value 't'
int int2 = round(anotherVal2);
////Serial.print(int2); //display rounded temperature
////Serial.print(" rounded ");
// Send a message!
//rf69.send((uint8_t *)radiopacket, strlen(radiopacket)); //uint8_t is a byte type
//////////rf69.send((uint8_t *)(&anotherVal, &int2), sizeof(anotherVal + int2));
rf69.send((uint8_t *)(&anotherVal), sizeof(anotherVal)); //sending temp, sizeof is bytes
Serial.print("Sending Temp: ");
Serial.print(anotherVal);
Serial.print(" ");
rf69.waitPacketSent(); //waits for previous transmission to finish -CB
delay (8000);
//When have two sends, becomes 0.00 on other end, maybe b/c of buffering or something?
rf69.send((uint8_t *)(&int2), sizeof(int2)); //sending humidity
Serial.print("Sending Humidity: ");
Serial.print(int2);
Serial.print(" ");
rf69.waitPacketSent(); //waits for previous transmission to finish -CB
delay(2000);
}
RX Code:
/ rf69 demo tx rx.pde
// -*- mode: C++ -*-
// Example sketch showing how to create a simple messageing client
// with the RH_RF69 class. RH_RF69 class does not provide for addressing or
// reliability, so you should only use RH_RF69 if you do not need the higher
// level messaging abilities.
// It is designed to work with the other example rf69_server.
// Demonstrates the use of AES encryption, setting the frequency and modem
// configuration
//Uses RADIOHEAD library and code
#define BLYNK_TEMPLATE_ID "TMPLKcy5ZwCr"
#define BLYNK_DEVICE_NAME "ESP32"
#define BLYNK_AUTH_TOKEN "2CqomTcy2HZE3ML9HgPRn4B_mQqzdDtv"
#define DataDisplay // Disable to display raw data received & errors of data length (added from other code)
#include <SPI.h>
#include <RH_RF69.h>
///////#include "RFM69X.h" //added from https://homeautomation.proboards.com/thread/600/wifi-rfm69-mqtt-network?page=1&scrollTo=4466
////////////SPIClass SPI1(VSPI); //from forum
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_AHTX0.h> //for alarm
int i = 0; //for alarm
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "2CqomTcy2HZE3ML9HgPRn4B_mQqzdDtv";
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "Prince";
char pass[] = "Pr1nc3H0us3!";
/*
//LCD SETUP
// include the library code:
#include <LiquidCrystal.h>
// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 34, en = 35, d4 = 26, d5 = 27, d6 = 14, d7 = 12;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
*/
/************ Radio Setup ***************/
// Change to 434.0 or other frequency, must match RX's freq!
#define RF69_FREQ 915.0
//#define FREQUENCY RF69_915MHZ
//#if defined (Arduino Uno) //Arduino Uno input by Calder
#define RFM69_CS 5
#define RFM69_INT 15 //when switched to 13 got errors
#define RFM69_RST 2
#define LED 33 //when switched to 33 it fixed everything (was 18, earlier 12)
// Singleton instance of the radio driver
RH_RF69 rf69(RFM69_CS, RFM69_INT);
int16_t packetnum = 0; // packet counter, we increment per xmission
void setup()
{
Serial.begin(9600);
//while (!Serial) { delay(1); } // wait until serial console is open, remove if not tethered to computer
// commenting out b/c causing esptool errors
//pinMode(22, OUTPUT); //pin for LED (working) (22 works) (17, 21 does not work)
pinMode(22, OUTPUT); //pin for noise maker pin (can't be 21,17
//LCD Setup
// set up the LCD's number of columns and rows:
////////////////////lcd.begin(16, 2);
//Serial.begin(115200);
//while (!Serial) { delay(1); } // wait until serial console is open, remove if not tethered to computer
pinMode(LED, OUTPUT);
pinMode(RFM69_RST, OUTPUT);
digitalWrite(RFM69_RST, LOW);
Serial.println("Feather RFM69 RX Test!");
// manual reset
digitalWrite(RFM69_RST, HIGH);
delay(10);
digitalWrite(RFM69_RST, LOW);
delay(10);
if (!rf69.init())
{
Serial.println("RFM69 radio init failed");
while (1);
}
Serial.println("RFM69 radio init OK!");
// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
// No encryption
if (!rf69.setFrequency(RF69_FREQ)) {
Serial.println("setFrequency failed");
}
// If you are using a high power RF69 eg RFM69HW, you *must* set a Tx power with the
// ishighpowermodule flag set like this:
rf69.setTxPower(20, true); // range from 14-20 for power, 2nd arg must be true for 69HCW
// The encryption key has to be the same as the one in the server
uint8_t key[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
};
rf69.setEncryptionKey(key);
pinMode(LED, OUTPUT);
Serial.print("RFM69 radio @"); Serial.print((int)RF69_FREQ); Serial.println(" MHz");
//Wifi code copy pasted
WiFi.begin(ssid, pass);
int wifi_ctr = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected");
Blynk.begin(auth, ssid, pass);
}
void loop()
{
//Alarm
Serial.print ("test1 ");
delay(10);
//noTone(32); //no noise for buzzer if temp normal (removed b/c was resetting to void setup(), originally added b/c was not buzzer was not shutting off after loop
if (rf69.available())
{
// Should be a message for us now
Serial.print ("test2 ");
uint8_t buf[RH_RF69_MAX_MESSAGE_LEN]; //Creates array using buf of the amount of units there are in the string
//////////float receivedData[2] = {0}; //added new
//////////uint8_t buflen = sizeof(receivedData); //added new
uint8_t len = sizeof(buf); //len = length of string (or # of bytes of variable)
delay(500);
if (rf69.recv(buf, &len))
{
Serial.print ("test3 ");
//////float hhtemp = *((float *)buf);
//////float hhhumid = *((float *)buf);
///////// float transData = *((float *)buf); //data can be temp(4 length) or humidity(2 length)
if (len == 4) { //if length is 3 or more (for temp) then:
if (!len) return;
{
float transData1 = *((float *)buf);
buf[len] = 0; // zero out remaining string, if don't may get a lot of weird symbols afterward
Serial.print("Received Temp [");
Serial.print(len); //length of message received
Serial.print("]: ");
Serial.println(transData1);
Serial.print("RSSI: "); //RSSI is like the signal strength
Serial.println(rf69.lastRssi(), DEC);
Serial.print(" ");
//Send temp data to Blynk website
Blynk.run();
delay(500);
float val = transData1;
Blynk.virtualWrite(V0, val);
//Buzzer Temp Alarm Siren
if (transData1 > 75) //If temp above 75 F, then buzzer siren goes off
{
for (i = 700; i < 800; i++)
{
tone(22, i); //buzzer pin
//digitalWrite(0, HIGH); //LED pin(change to esp32 pin for buzzer)
delay(15);
}
for (i = 800; i > 700; i--)
{
tone(22, i); //buzzer pin
//digitalWrite(0, LOW); //LED pin (change to esp32 pin for buzzer)
delay(15);
}
}
delay(4000);
}
}
/*
//Print temp to LCD screen
lcd.setCursor(0, 0); //set cursor to top of scrreen
lcd.print("Your HH is ");
lcd.setCursor(0, 1); //set cursor to bottom of screen
lcd.print(hhtemp); //printing temp
lcd.print(" F ");
*/
//if (len == 2){ //just one '=' puts value of 2 into len
else if (len == 2) //just one '=' puts value of 2 into len
{
if (!len) return;
{
float transData2 = *((float *)buf);
buf[len] = 0;
Serial.print("Received humidity [");
Serial.print(len); //length of message received
Serial.print("]: ");
Serial.println(transData2);
Serial.print("RSSI: "); //RSSI is like the signal strength
Serial.println(rf69.lastRssi(), DEC);
Serial.print(" ");
//Send humidity data to Blynk website
Blynk.run();
delay(500);
float val2 = transData2;
Blynk.virtualWrite(V1, val2);
//////////// int hhhumid = *((int *)buf);
///////////// Serial.print(hhhumid);
///////////////lcd.print(hhhumid);
////////////////lcd.print("% RH");
delay(4000);
}
}
delay(1000);
}
} else {
Serial.println("Receive failed");
delay(500);
// set radio to use less power
// it will wake up the next time send() or sendWithRetry() is called
//rf69.sleep(); ///removing to test if doens't work on ESP32 (tried and made it so wouldn't receive anything)
}
Serial.print ("Test4 ");
}
Setup Diagram for the ESP32:
(ignore LED, and buzzer is now connected to gpio pin 22, not 32).
ESP32 Pin Diagram:

