RFM69 RSSI value report

  • Is there any way for a gateway to read the RSSI value of the remote RFM69 based sensors? RSSI reporting is already available in the driver library, however I can only see RSSI reports when using the libraries Struct_send/Struct_receive example sketches. I tried to trick the sketch to report it, yet unsuccessfull. There are some tweaks for the RF24 networks yet they're not actually RSSI reports but rather transport reliability metrics counting failed against sent packets. But since RFM69 natively supports RSSI and the functions are already there, I believe that it's very simple for someone who knows the arhitecture inside out to add some #define MY_RFM69_RSSI option available to the gateway sketch.
    But meanwhile I wouldn't mind any suggestion as to how could I access the RFM69 library RFM69::readRSSI function and get the values in any form. It would help me a great deal to test various antennas, bitrates, range and penetration for the RFM69 modules.
    RSSI reports of the ACK packets sent back from the gateway would be great too in order to have a clear picture of the two-way communication but let's take it one step at a time 😁

  • Mod

  • @mfalkvidd Thank you for pointing me to those resources, I finally got them working.
    @scalz Absolutely awesome work 😄

    Here's a full sketch example using the Si7021 Temp/RH sensor:

    #define MY_NODE_ID 2
    #define MY_DEBUG
    #define MY_RADIO_RFM69
    #define MY_RFM69_FREQUENCY RFM69_433MHZ
    #define MY_IS_RFM69HW 
    #define MY_RFM69_NETWORKID 100
    #include <MySensors.h>  
    #include <SPI.h>
    #include <Wire.h>
    #include "Adafruit_Si7021.h"
    unsigned long SLEEP_TIME = 1000;
    Adafruit_Si7021 sensor = Adafruit_Si7021();
    MyMessage msgTemp(1, V_TEMP);
    MyMessage msgRh(2, V_HUM);
    MyMessage msgRSSI(3,V_VAR5);
    float temp;
    float rh;
    boolean requestACK = false;
    int16_t rssiVal
    char rssiStr[10];
    void setup()  
      sendSketchInfo("Temperature/RH Sensor N2 RFM69", "1.1");
      present(1, S_TEMP);
      present(2, S_HUM);
    void loop() {
      rssiVal = transportGetRSSI();
      rh = sensor.readHumidity();
      temp = sensor.readTemperature();
      snprintf(rssiStr,10,"rssi: %d%",rssiVal);

    However, please note that this only works on:
    Just drop a reply here and I will happily assist you using the above versions until they will be fully commited.

  • Mod

    Awesome @mihai-aldea
    Great work!

  • Hardware Contributor

    and Kudo to @tekka too ! and @marceloaqno who is also working on the linux part 😉

    that said @mihai-aldea cool you have it working. of course we are interested by feedbacks 🙂
    There are some defines which may need some adjustements (timeouts) depending on the clock of the mcu (especially for gw). for the moment the latest rev is still local but it does not differ a lot.

    Important note:

    This new version breaks old packet structure. Because there are new values in the packet header : version, sequence number and Rssi.

    Which means if people want to use these new features, it needs all nodes and GW updated.
    As the next release isn't a major one, there will be a switch define, with these new features default disabled. for compatibility with older nodes.

  • Great work, would like to see this added to RFM95 radio code...

  • Hardware Contributor

    @lafleur said:

    Great work, would like to see this added to RFM95 radio code...

    Like which features?

  • RSSI......

  • Has Rssi been added to mysensors 2.1 ?

  • @rmtucker said:

    Has Rssi been added to mysensors 2.1 ?

    Yes. You can pull it using transportGetRSSI(). From there on, use it just as it is or shape it more nicely with a map() function, it's up to you. But please note that 2.1.0 brings some slight changes so if your sketch throws some errors, just read them and change your sketch accordingly. Eg. #define MY_RF69_FREQUENCY RFM69_433MHZ is replaced by #define MY_RFM69_FREQUENCY RFM69_433MHZ, notice the extra "M".

  • Hardware Contributor

    Well, finally we have decided to wait for releasing the new rfm69 drivers.

    • there was already so much changes/improvements in Mysensors to release.
    • to keep a better history, and the new rfm69 driver has lot of improvements.

    That said, for w5100 users, we have tested the new driver (not the one on my repo) and it works ok with w5100 and rfm69 in hardware spi mode, on same bus, without changing the w5100 lib.

    So Mysensors 2.1 still use the old driver. The new rfm69 driver is planned for 2.2. No eta as far as i know, but with luck, let's see when it will release.

  • I am totally confused now?
    So Rssi data is not available?

  • Hardware Contributor

    @rmtucker no it is not available in 2.1. this will be for 2.2

  • @scalz Just to make it clear. The RFM69 RSSI value is not available in the official MySensors 2.1.0 release but it is available in your GitHub fork here: https://github.com/scalz/Mysensors/tree/rfm69_update2. Is that correct?

  • Admin

    Yes RSSI is a work in progress available in @scalz fork. We didn't have time to test it enough to include it in the 2.1 release.

  • @hek I confirm that the RSSI support works perfect in scalz's fork.

  • Mod

    @mihai.aldea it is not just about verifying RSSI. It is about verifying that the changes don't break anything else for existing users. Unfortunately, the new driver does break things and most users would dislike an upgrade that breaks their existing system.

  • This is perfectly understandable but I merely wanted to give a raw input on the feature status.
    I consider the RSSI values to be paramount when testing MySensors along with new hardware (antennas, wall penetration, registry tweaks etc.) as the simple online/offline node status would not help very much with these scenarios. That's why for the time being I will stick to scalz's rfm69_update2.

  • @rmtucker In my RFM69 sensors using ver2.1 I'm doing as follows to check RSSI and, as well, how to check the background noise level. I have them implemented as two sensor values being reported every 5 minutes in the loop() to the gateway and controller.

    void loop()      
      float humidity = dht.readHumidity();       // get dht22 humidity
      if (isnan(humidity)) {
        Serial.println("Failed reading humidity from DHT");
      } else {
        send(msgHum.set(humidity, 1));           // send dht22 humidity
      float temperature = dht.readTemperature(); // get dht22 temperature
      if (isnan(temperature)) {
        Serial.println("Failed reading temperature from DHT");
      } else {
        send(msgTemp.set(temperature, 1));       // send dht22 temperature
      digitalWrite(DHT22_PWR,LOW);               // save some power. Turn off dht22 module.
      rssi = _radio.readRSSI();                  // read RSSI in RFM69. Measure reception signal level from gw
      send(msgRSSI1.set(rssi));                  // send RSSI, signal level to gateway
      wait(500);                                 // wait to get idle
      rssi = _radio.readRSSI();                  // read RSSI in RFM69. Measure background noise
      send(msgRSSI2.set(rssi));                  // send RSSI, noise level to gateway
      sleep(SLEEP_TIME);                         // sleep a bit
      digitalWrite(DHT22_PWR,HIGH);              // wake up dht22 module
      wait(2000);                                // warm up dht22 module

    To get the RSSI value it's read in the sketch ( int rssi = _radio.readRSSI(); ) immediately after sending something, in this case the dht22 temperature. To check the background noise the RSSI level is read again 500ms after being kept idle (probably a shorter waiting period would work as well, but haven't studied it as it's not a critical issue for me). Normally the background noise-floor should be something around -95dBm and -115dBm. If you have some external interference, it could be easily detected with this method.

  • @jpaulin
    Thank you so much for the info that rssi can be extracted in V2.1.0.
    Would you be able to post your full sketch as it would be easier for me to extract the bits i need.?
    I just can not understand why before your answer i was being told it is not possible in V2.1.0 to do this?
    Or does this need another version of the Rfm69 library?

  • @rmtucker Here's the complete sketch. It's a DHT22 temp/humidity battery powered sensor node with an RFM69 radio.

     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     * Version 1.0 - Henrik EKblad
     * This sketch provides an example how to implement a humidity/temperature
     * sensor using DHT11/DHT-22 
     * http://www.mysensors.org/build/humidity
    // Enable debug prints
    #define MY_DEBUG
    // Enable and select radio type attached
    //#define MY_RADIO_NRF24
    #define MY_RADIO_RFM69
    #define MY_RFM69_FREQUENCY   RF69_433MHZ
    #define MY_NODE_ID 13                        // Identity for temp/hum sensor
    // Set blinking period
    // Flash leds on rx/tx/err
    //#define MY_DEFAULT_ERR_LED_PIN 7           // Error led pin  red
    //#define MY_DEFAULT_RX_LED_PIN  6           // Receive led pin  yellow
    #define MY_DEFAULT_TX_LED_PIN  9             // Transmit led pin  green
    const byte BATT_ADC = 1;                     // ADC Pin to measure battery level
    #include <MySensors.h>
    #include <DHT.h>
    unsigned long SLEEP_TIME = 300000;           // Sleep time between reads (in milliseconds)
    #define CHILD_ID_HUM 0
    #define CHILD_ID_TEMP 1
    #define DHTPIN 18                            // Input pin from DHT22
    #define DHT22_PWR 6                          // Vdc pin DHT22 to get it to sleep
    #define DHTTYPE DHT22
    #define CHILD_ID_RSSI_HIGH  7                // RSSI received signal level
    #define CHILD_ID_RSSI_LOW   8                // RSSI background noise level
    #define CHILD_ID_TEMP2      9                // internal temperature RFM69 chip
    int rssi;                                    // RSSI RFM69 chip
    int temp2;                                   // Internal temperature RFM69 chip
    int batteryLevel;                            // measured battery level
    int batteryPcnt;                             // measured battery level in percentage
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    MyMessage msgRSSI1(CHILD_ID_RSSI_HIGH, V_VAR1);
    MyMessage msgRSSI2(CHILD_ID_RSSI_LOW, V_VAR1);
    MyMessage msgTemp2(CHILD_ID_TEMP2, V_TEMP);
    void setup()  
      digitalWrite(DHT22_PWR,HIGH);              // power-on dht22
      dht.begin();                               // Start-up DHT22 sensor Temperature/Humidity
    void presentation() 
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Temp_Hum", "1.0");
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID_HUM, S_HUM);
      present(CHILD_ID_TEMP, S_TEMP);
      present(CHILD_ID_RSSI_HIGH, S_CUSTOM);
      present(CHILD_ID_RSSI_LOW, S_CUSTOM);
      present(CHILD_ID_TEMP2, S_TEMP);
    void loop()      
      float humidity = dht.readHumidity();       // get dht22 humidity
      if (isnan(humidity)) {
        Serial.println("Failed reading humidity from DHT");
      } else {
        send(msgHum.set(humidity, 1));           // send dht22 humidity
      float temperature = dht.readTemperature(); // get dht22 temperature
      if (isnan(temperature)) {
        Serial.println("Failed reading temperature from DHT");
      } else {
        send(msgTemp.set(temperature, 1));       // send dht22 temperature
      digitalWrite(DHT22_PWR,LOW);               // save some power
      rssi = _radio.readRSSI();                  // read RSSI in RFM69. Measure reception signal from gw
      send(msgRSSI1.set(rssi));                  // send RSSI level
      wait(500);                                 // wait to get idle
      rssi = _radio.readRSSI();                  // read RSSI in RFM69. Wait and measure background noise
      send(msgRSSI2.set(rssi));                  // send RSSI level
      wait(200);                                 // wait for next send
      temp2 = _radio.readTemperature(1);         // read temperature in RFM69
      send(msgTemp2.set(temp2));                 // send temperature
      batteryLevel = analogRead(BATT_ADC);       //  (* 0.0032225806)
      batteryPcnt = batteryLevel / 10;           // battery percentage
      sendBatteryLevel(batteryPcnt);             // send battery level in percentage to controller
      // if (oldBatteryPcnt != batteryPcnt) {    // use if not to send every cycle
      //     sendBatteryLevel(batteryPcnt);
      //     oldBatteryPcnt = batteryPcnt;
      // }
      sleep(SLEEP_TIME);                         // sleep a bit
      digitalWrite(DHT22_PWR,HIGH);              // wake up DHT sensor
      wait(2000);                                // warm up DHT sensor
    void receive(const MyMessage &message) {
      // We only expect one type of message from controller. But we better check anyway.
      Serial.println("something came in");
      if (message.type==V_VAR1) {                // reception to change SLEEP_TIME.
         SLEEP_TIME = message.getULong();        // send topic: eg. my_RFM69_gw1-in/3/1/1/0/24 30000 (payload in ms)
       }                                         // MQTT_publish_topic_prefix/Node_Id/Sensor_Id/Cmd_Type/Ack_flag/type(V_VAR1=24) payload

    readRSSI(); is an internal function in the RFM69.h / RFM69.cpp library that I'm calling in the sketch to get the RSSI and background noise level.

  • @rmtucker Another feature I'm using in the sketch, by calling directly the RFM69 library, is reading the temperature sensor in the RFM69.

    temp2 = _radio.readTemperature(1);         // read temperature in RFM69

    The value (1) sent in the call above to the RFM69 library is a calibration in Centigrades (e.g. 1 = +1 °C). Added here to show the possibility to adjust the measured temperature. The temperature sensor on the chip is not as accurate as for example a dht22 and needs sometimes some manual adjustment.

  • The onboard temperature sensor is not a cool freebie. It's meant to be a way to check the approximate environmental temperature for the outdoor or industrial devices (not only sensor nodes) using RFM69.

  • @jpaulin
    Just wanted to thank you for taking the time to post your example for rssi.
    I have just finished putting my new rfm69 gateway together and about to start assembling a new node to try everything out.
    I will let you know how i get on.

  • In the 2.2 version of MySensors (development branch) the new driver for RFM69 is built. It has new command for reading RSSI value: RFM69_getSendingRSSI() and RFM69_getReceivingRSSI(), so now is very easy to get RSSI value.
    You can get some more information from ATC Signal Report which are useful - look at RFM69_RFM95_ATC_SignalReport example.

  • This post is deleted!

  • Mod


    what kind of variable and type are better for reporting RSSI?

  • @gohan I use V_VAR1 type of variable.

  • Mod

    @gieemek ok, but how about when you present the child? S_CUSTOM is not accepted by Domoticz S_SOUND could be an option

  • Hardware Contributor

    I see in the domoticz code that there are some fields to record Signal Level for other sensors types.
    Making domoticz handle the signal level would then be possible.
    There is 2 enhancements to do so :

    • Handle a standard variable or subtype in MySensors to carry the signal or RSSI level (github issue 581 : https://github.com/mysensors/MySensors/issues/581)
    • Modify the domoticz code to show somewhere the Signal Level for MySensors devices. (no github issue yet)

    That would be interresting, since it would also allow to trigger some custom scripts if a device falls in a poor level...

  • I do not know Domotich - I am working with openHAB through MQTT protocol, which simply reads the sent value of variable and does not wonder what type they are. Yes, I use S_CUSTOM variable to send RSSI value.
    But it really doesn't matter what kind of variable you use. The variable type tells to MySensors that its value is for example: light level, temperature, or voltage, but you can send a temperature value using the S_POWER variable - no problem with that.
    RSSI should be expressed as an integer, so what is realy important that you choose the variable type declared as integer value, such as i.e. S_LIGHT_LEVEL.
    Once you have that value in the controller (openHAB), you can do whatever you want with it.
    So it is in openHAB, and I hope in Domoticz the same.

  • Mod

    I used S_SOUND so it will report it as 'db', so for now I am happy with it.

  • @jpaulin I can see the value of obtaining Gateway RSSI for individual battery powered nodes to inform programmed power settings on them in the absence of ATC implementation at the Node itself, but not sure I understand the purpose of RSSI readings at the node other than to establish noise thresholds on the Gateway signal.

    Although the function of the Gateway is to forward messages to the Controller, is it possible for the Gateway to read and forward RSSI readings for nodes as if locally attached sensors?

  • Mod

    Reading rssi and power on the node it gives you an idea of how much signal that node is getting and if there are interferences around it

  • @gohan Yes, I understood that aspect. I can imagine certain environments where the SNR might inform change of Node location or shielding or directivity of antenna, or increased output from the Gateway, but I would have thought that a one-off task unless the node noise background changes frequently...

  • Mod

    You can always put a counter to send rssi reports after X amount of other data being sent

  • @gohan True, but if no change to the environment is anticipated, why use battery power to convey it at all?
    My own interest in what RSSI the Gateway is receiving should also be a one-time exercise, but is more difficult to implement I suppose.

    Until such time the 2.2 version is released, and what it provides becomes clearer, I might just do the checking with two portable nodes...

  • Mod

    I can show you how background noise rssi and power output changes during the day and I'm not moving things around

  • @gohan Not disputing SNRs vary, what I meant by change to the environment at the node was unforeseen pollution influences, such as somebody working with a welder right beside the node after you had already established the peak diurnal noise and set everything up.

    The Gateway usually can run permanently at high gain, the Node can only do so at the expense of battery life...

  • Mod

    ACS helps a lot, but by recording rssi and tx power I noticed why thenode occasionally was going offline

  • @gohan Fair comment, it was the best tool to resolve the problem.
    I spent 3 days reviewing what I had programmed, inspected wiring, and testing all DS18B20s, two of which are in the loft, only to discover that a faulty telephone socket had partially dislodged it's pins, my tool to resolve? A magnifying glass.... Isn't technology wonderful...🐌

Log in to reply

Suggested Topics