Author Topic: Real time RSSI measurement broken RFM69CW?  (Read 25967 times)

perky

  • Hero Member
  • *****
  • Posts: 873
  • Country: gb
Re: Real time RSSI measurement broken RFM69CW?
« Reply #15 on: January 18, 2016, 06:43:55 PM »
Can I ask what modes the receiver and transmitters are in during these tests? E.g. FSK, packet mode, fixed or variable length? Also are you sending legitimate packets that normally would have been received (in other words would it normally trigger a sync address match and payload ready), or are they designed to not produce a payload ready by using a different bit rate or sync word?

I'm confused as to how the receiver might be re-triggering a new RSSI sample event if the receiver is not explicitly being taken out of RX mode or being re-started. I thought the RSSI interrupt was the indication that a new RSSI value is available in the RSSI register, but that interrupt is not cleared down until it is taken out of RX mode or re-started.

Possibly some other condition is causing a restart (maybe a FIFO clear event), for example if you were using fixed packet length and didn't clear the FIFO by reading it out this might cause a reset condition which could possibly cause an RSSI re-trigger.

Mark.

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #16 on: January 19, 2016, 03:15:18 PM »
Can I ask what modes the receiver and transmitters are in during these tests? E.g. FSK, packet mode, fixed or variable length? Also are you sending legitimate packets that normally would have been received (in other words would it normally trigger a sync address match and payload ready), or are they designed to not produce a payload ready by using a different bit rate or sync word?


You're asking the right questions.  I only tried it with the transmitter and receiver parameters set the same.  A better test would be to set the bitrate of the transmitter to something else, so that the receiver would only see the Tx power but not be able to decode the packet.  I haven't run that test yet.

Here is the gateway code that I ran most recently, which tracks the maximum RSSI it measures:
Code: [Select]
// Sample RFM69 receiver/gateway sketch, with ACK and optional encryption
// Passes through any wireless received messages to the serial port & responds to ACKs
// It also looks for an onboard FLASH chip, if present
// Library and code by Felix Rusu - felix@lowpowerlab.com
// Get the RFM69 and SPIFlash library at: https://github.com/LowPowerLab/

#include <RFM69.h>    //get it here: https://www.github.com/lowpowerlab/rfm69
#include <SPI.h>
#include <SPIFlash.h> //get it here: https://www.github.com/lowpowerlab/spiflash
#include <RFM69registers.h>

#define NODEID        1    //unique for each node on same network
#define NETWORKID     100  //the same on all nodes that talk to each other
//Match frequency to the hardware version of the radio on your Moteino (uncomment one):
//#define FREQUENCY     RF69_433MHZ
//#define FREQUENCY     RF69_868MHZ
#define FREQUENCY     RF69_915MHZ
#define ENCRYPTKEY    "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
#define IS_RFM69HW    //uncomment only for RFM69HW! Leave out if you have RFM69W!
#define SERIAL_BAUD   250000

#ifdef __AVR_ATmega1284P__
  #define LED           15 // Moteino MEGAs have LEDs on D15
  #define FLASH_SS      23 // and FLASH SS on D23
#else
  #define LED           9 // Moteinos have LEDs on D9
  #define FLASH_SS      8 // and FLASH SS on D8
#endif

RFM69 radio;
SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for 4mbit  Windbond chip (W25X40CL)
bool promiscuousMode = false; //set to 'true' to sniff all packets on the same network

void setup() {
  Serial.begin(SERIAL_BAUD);
  delay(10);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW
  radio.setHighPower(); //only for RFM69HW!
#endif
  radio.encrypt(ENCRYPTKEY);
  radio.promiscuous(promiscuousMode);
  //radio.setFrequency(919000000);
  radio.writeReg(REG_OPMODE, (radio.readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_STANDBY);  //set standby-mode
  radio.writeReg(REG_RSSITHRESH, 0xFF);  //set RSSI threshhold as low as possible
  radio.writeReg(REG_OPMODE, (radio.readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_RECEIVER);  //set standby-mode

 
  char buff[50];
  sprintf(buff, "\nListening at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(buff);
  if (flash.initialize())
  {
    Serial.print("SPI Flash Init OK. Unique MAC = [");
    flash.readUniqueId();
    for (byte i=0;i<8;i++)
    {
      Serial.print(flash.UNIQUEID[i], HEX);
      if (i!=8) Serial.print(':');
    }
    Serial.println(']');
   
    //alternative way to read it:
    //byte* MAC = flash.readUniqueId();
    //for (byte i=0;i<8;i++)
    //{
    //  Serial.print(MAC[i], HEX);
    //  Serial.print(' ');
    //}
   
  }
  else
    Serial.println("SPI Flash Init FAIL! (is chip present?)");
}

byte ackCount=0;
uint32_t packetCount = 0;
long loopCount=0;
int rssi;
int maxRSSI= (-125);
void loop() {
  radio.writeReg(REG_OPMODE, (radio.readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_STANDBY);  //set standby-mode
  radio.writeReg(REG_RSSITHRESH, 0xFF);  //set RSSI threshhold as low as possible
  radio.writeReg(REG_OPMODE, (radio.readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_RECEIVER);  //set standby-mode

  loopCount++;
  rssi = radio.readRSSI();
  if (rssi > maxRSSI) {
    maxRSSI = rssi;
  }
 
  if ((loopCount%1)==0) {
    Serial.print(loopCount);
    Serial.print(". ");Serial.print(radio.readRSSI());Serial.print(" ");
    Serial.println(maxRSSI);
    //Serial.flush(); 
  }
}

void Blink(byte PIN, int DELAY_MS)
{
  pinMode(PIN, OUTPUT);
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN,LOW);
}

« Last Edit: January 19, 2016, 03:22:45 PM by WhiteHare »

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #17 on: January 19, 2016, 03:15:45 PM »
Here is the transmitter code (run on a separate moteino):
Code: [Select]
// Sample RFM69 sender/node sketch, with ACK and optional encryption
// Sends periodic messages of increasing length to gateway (id=1)
// It also looks for an onboard FLASH chip, if present
// Library and code by Felix Rusu - felix@lowpowerlab.com
// Get the RFM69 and SPIFlash library at: https://github.com/LowPowerLab/

#include <RFM69.h>    //get it here: https://www.github.com/lowpowerlab/rfm69
#include <SPI.h>
#include <SPIFlash.h> //get it here: https://www.github.com/lowpowerlab/spiflash

#define NODEID        2    //unique for each node on same network
#define NETWORKID     100  //the same on all nodes that talk to each other
#define GATEWAYID     1
//Match frequency to the hardware version of the radio on your Moteino (uncomment one):
//#define FREQUENCY   RF69_433MHZ
//#define FREQUENCY   RF69_868MHZ
#define FREQUENCY     RF69_915MHZ
#define ENCRYPTKEY    "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
#define IS_RFM69HW    //uncomment only for RFM69HW! Leave out if you have RFM69W!
#ifdef __AVR_ATmega1284P__
  #define LED           15 // Moteino MEGAs have LEDs on D15
  #define FLASH_SS      23 // and FLASH SS on D23
#else
  #define LED           9 // Moteinos have LEDs on D9
  #define FLASH_SS      8 // and FLASH SS on D8
#endif

#define SERIAL_BAUD   115200

int TRANSMITPERIOD = 150; //transmit a packet to gateway so often (in ms)
char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buff[20];
byte sendSize=0;
boolean requestACK = false;
SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for 4mbit  Windbond chip (W25X40CL)
RFM69 radio;

void setup() {
  Serial.begin(SERIAL_BAUD);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW
  radio.setHighPower(); //uncomment only for RFM69HW!
#endif
  radio.encrypt(ENCRYPTKEY);
  //radio.setFrequency(919000000); //set frequency to some custom frequency
  char buff[50];
  sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(buff);
 
  if (flash.initialize())
  {
    Serial.print("SPI Flash Init OK ... UniqueID (MAC): ");
    flash.readUniqueId();
    for (byte i=0;i<8;i++)
    {
      Serial.print(flash.UNIQUEID[i], HEX);
      Serial.print(' ');
    }
    Serial.println();
  }
  else
    Serial.println("SPI Flash Init FAIL! (is chip present?)");
}

long lastPeriod = 0;
void loop() {
  //process any serial input
  if (Serial.available() > 0)
  {
    char input = Serial.read();
    if (input >= 48 && input <= 57) //[0,9]
    {
      TRANSMITPERIOD = 100 * (input-48);
      if (TRANSMITPERIOD == 0) TRANSMITPERIOD = 1000;
      Serial.print("\nChanging delay to ");
      Serial.print(TRANSMITPERIOD);
      Serial.println("ms\n");
    }

    if (input == 'r') //d=dump register values
      radio.readAllRegs();
    //if (input == 'E') //E=enable encryption
    //  radio.encrypt(KEY);
    //if (input == 'e') //e=disable encryption
    //  radio.encrypt(null);

    if (input == 'd') //d=dump flash area
    {
      Serial.println("Flash content:");
      uint16_t counter = 0;

      Serial.print("0-256: ");
      while(counter<=256){
        Serial.print(flash.readByte(counter++), HEX);
        Serial.print('.');
      }
      while(flash.busy());
      Serial.println();
    }
    if (input == 'e')
    {
      Serial.print("Erasing Flash chip ... ");
      flash.chipErase();
      while(flash.busy());
      Serial.println("DONE");
    }
    if (input == 'i')
    {
      Serial.print("DeviceID: ");
      word jedecid = flash.readDeviceId();
      Serial.println(jedecid, HEX);
    }
  }

  //check for any received packets
  if (radio.receiveDone())
  {
    Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] ");
    for (byte i = 0; i < radio.DATALEN; i++)
      Serial.print((char)radio.DATA[i]);
    Serial.print("   [RX_RSSI:");Serial.print(radio.RSSI);Serial.print("]");

    if (radio.ACKRequested())
    {
      radio.sendACK();
      Serial.print(" - ACK sent");
    }
    Blink(LED,3);
    Serial.println();
  }

  int currPeriod = millis()/TRANSMITPERIOD;
  if (currPeriod != lastPeriod)
  {
    lastPeriod=currPeriod;
   
    //send FLASH id
    if(sendSize==0)
    {
      sprintf(buff, "FLASH_MEM_ID:0x%X", flash.readDeviceId());
      byte buffLen=strlen(buff);
      if (radio.sendWithRetry(GATEWAYID, buff, buffLen))
        Serial.print(" ok!");
      else Serial.print(" nothing...");
      //sendSize = (sendSize + 1) % 31;
    }
    else
    {
      Serial.print("Sending[");
      Serial.print(sendSize);
      Serial.print("]: ");
      for(byte i = 0; i < sendSize; i++)
        Serial.print((char)payload[i]);
 
      if (radio.sendWithRetry(GATEWAYID, payload, sendSize))
       Serial.print(" ok!");
      else Serial.print(" nothing...");
    }
    sendSize = (sendSize + 1) % 31;
    Serial.println();
    Blink(LED,3);
  }
}

void Blink(byte PIN, int DELAY_MS)
{
  pinMode(PIN, OUTPUT);
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN,LOW);
}

One odd thing I did notice is that when I set the modulus of how many receives to do before printing a result to a higher number, I expected it would more quickly pick up the transmitter and record its maximum, since it wouldn't be slowed down by doing all the serial printouts, but it actually seemed to be the opposite of that.  So, maybe there needs to be some settle time explicitly added in between adjustments to the radio.
« Last Edit: January 19, 2016, 03:18:44 PM by WhiteHare »

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #18 on: January 19, 2016, 11:49:16 PM »
I cleaned up the code a little, and it runs even better now.   :)

Also, I ran the test with the transmitter (node Moteino) running at 1200bps, and the receiver (gateway Moteino) has its bitrate set at 300kbps.  It functions the same, so it is further evidence that it is reading the RSSI and not just the RSSI on packets that it decodes.  In fact, with the bitrates set so differently, it shouldn't be decoding any valid packets at all.

Here's Version2 of the transmitter (node Moteino) code:
Code: [Select]
// Sample RFM69 sender/node sketch, with ACK and optional encryption
// Sends periodic messages of increasing length to gateway (id=1)
// It also looks for an onboard FLASH chip, if present
// Library and code by Felix Rusu - felix@lowpowerlab.com
// Get the RFM69 and SPIFlash library at: https://github.com/LowPowerLab/

#include <RFM69.h>    //get it here: https://www.github.com/lowpowerlab/rfm69
#include <SPI.h>
#include <SPIFlash.h> //get it here: https://www.github.com/lowpowerlab/spiflash
#include <RFM69registers.h>

#define NODEID        2    //unique for each node on same network
#define NETWORKID     100  //the same on all nodes that talk to each other
#define GATEWAYID     1
//Match frequency to the hardware version of the radio on your Moteino (uncomment one):
//#define FREQUENCY   RF69_433MHZ
//#define FREQUENCY   RF69_868MHZ
#define FREQUENCY     RF69_915MHZ
#define ENCRYPTKEY    "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
#define IS_RFM69HW    //uncomment only for RFM69HW! Leave out if you have RFM69W!
#ifdef __AVR_ATmega1284P__
  #define LED           15 // Moteino MEGAs have LEDs on D15
  #define FLASH_SS      23 // and FLASH SS on D23
#else
  #define LED           9 // Moteinos have LEDs on D9
  #define FLASH_SS      8 // and FLASH SS on D8
#endif

#define SERIAL_BAUD   115200

int TRANSMITPERIOD = 150; //transmit a packet to gateway so often (in ms)
char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buff[20];
byte sendSize=0;
boolean requestACK = false;
SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for 4mbit  Windbond chip (W25X40CL)
RFM69 radio;

void setup() {
  Serial.begin(SERIAL_BAUD);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW
  radio.setHighPower(); //uncomment only for RFM69HW!
#endif
  radio.encrypt(ENCRYPTKEY);
  //radio.setFrequency(919000000); //set frequency to some custom frequency
  radio.writeReg(REG_BITRATEMSB, RF_BITRATEMSB_1200);  //set MSB bitrate to 1200
  radio.writeReg(REG_BITRATELSB, RF_BITRATELSB_1200);  //set LSB bitrate to 1200
  Serial.println(F("Bitrate set to 1200"));
 
  char buff[50];
  sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(buff);
 
  if (flash.initialize())
  {
    Serial.print("SPI Flash Init OK ... UniqueID (MAC): ");
    flash.readUniqueId();
    for (byte i=0;i<8;i++)
    {
      Serial.print(flash.UNIQUEID[i], HEX);
      Serial.print(' ');
    }
    Serial.println();
  }
  else
    Serial.println("SPI Flash Init FAIL! (is chip present?)");
}

long lastPeriod = 0;
void loop() {
  //process any serial input
  if (Serial.available() > 0)
  {
    char input = Serial.read();
    if (input >= 48 && input <= 57) //[0,9]
    {
      TRANSMITPERIOD = 100 * (input-48);
      if (TRANSMITPERIOD == 0) TRANSMITPERIOD = 1000;
      Serial.print("\nChanging delay to ");
      Serial.print(TRANSMITPERIOD);
      Serial.println("ms\n");
    }

    if (input == 'r') //d=dump register values
      radio.readAllRegs();
    //if (input == 'E') //E=enable encryption
    //  radio.encrypt(KEY);
    //if (input == 'e') //e=disable encryption
    //  radio.encrypt(null);

    if (input == 'd') //d=dump flash area
    {
      Serial.println("Flash content:");
      uint16_t counter = 0;

      Serial.print("0-256: ");
      while(counter<=256){
        Serial.print(flash.readByte(counter++), HEX);
        Serial.print('.');
      }
      while(flash.busy());
      Serial.println();
    }
    if (input == 'e')
    {
      Serial.print("Erasing Flash chip ... ");
      flash.chipErase();
      while(flash.busy());
      Serial.println("DONE");
    }
    if (input == 'i')
    {
      Serial.print("DeviceID: ");
      word jedecid = flash.readDeviceId();
      Serial.println(jedecid, HEX);
    }
  }

  //check for any received packets
  if (radio.receiveDone())
  {
    Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] ");
    for (byte i = 0; i < radio.DATALEN; i++)
      Serial.print((char)radio.DATA[i]);
    Serial.print("   [RX_RSSI:");Serial.print(radio.RSSI);Serial.print("]");

    if (radio.ACKRequested())
    {
      radio.sendACK();
      Serial.print(" - ACK sent");
    }
    Blink(LED,3);
    Serial.println();
  }

  int currPeriod = millis()/TRANSMITPERIOD;
  if (currPeriod != lastPeriod)
  {
    lastPeriod=currPeriod;
   
    //send FLASH id
    if(sendSize==0)
    {
      sprintf(buff, "FLASH_MEM_ID:0x%X", flash.readDeviceId());
      byte buffLen=strlen(buff);
      if (radio.sendWithRetry(GATEWAYID, buff, buffLen))
        Serial.print(" ok!");
      else Serial.print(" nothing...");
      //sendSize = (sendSize + 1) % 31;
    }
    else
    {
      Serial.print("Sending[");
      Serial.print(sendSize);
      Serial.print("]: ");
      for(byte i = 0; i < sendSize; i++)
        Serial.print((char)payload[i]);
 
      if (radio.sendWithRetry(GATEWAYID, payload, sendSize))
       Serial.print(" ok!");
      else Serial.print(" nothing...");
    }
    sendSize = (sendSize + 1) % 31;
    Serial.println();
    Blink(LED,3);
  }
}

void Blink(byte PIN, int DELAY_MS)
{
  pinMode(PIN, OUTPUT);
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN,LOW);
}
« Last Edit: January 20, 2016, 12:10:41 AM by WhiteHare »

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #19 on: January 19, 2016, 11:51:21 PM »
Here's version2 of the receive (Moteino gateway) code:
Code: [Select]
// Sample RFM69 receiver/gateway sketch, with ACK and optional encryption
// Passes through any wireless received messages to the serial port & responds to ACKs
// It also looks for an onboard FLASH chip, if present
// Library and code by Felix Rusu - felix@lowpowerlab.com
// Get the RFM69 and SPIFlash library at: https://github.com/LowPowerLab/

#include <RFM69.h>    //get it here: https://www.github.com/lowpowerlab/rfm69
#include <SPI.h>
#include <SPIFlash.h> //get it here: https://www.github.com/lowpowerlab/spiflash
#include <RFM69registers.h>

#define NODEID        1    //unique for each node on same network
#define NETWORKID     100  //the same on all nodes that talk to each other
//Match frequency to the hardware version of the radio on your Moteino (uncomment one):
//#define FREQUENCY     RF69_433MHZ
//#define FREQUENCY     RF69_868MHZ
#define FREQUENCY     RF69_915MHZ
#define ENCRYPTKEY    "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
#define IS_RFM69HW    //uncomment only for RFM69HW! Leave out if you have RFM69W!
#define SERIAL_BAUD   250000

#ifdef __AVR_ATmega1284P__
  #define LED           15 // Moteino MEGAs have LEDs on D15
  #define FLASH_SS      23 // and FLASH SS on D23
#else
  #define LED           9 // Moteinos have LEDs on D9
  #define FLASH_SS      8 // and FLASH SS on D8
#endif

RFM69 radio;
SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for 4mbit  Windbond chip (W25X40CL)
bool promiscuousMode = false; //set to 'true' to sniff all packets on the same network

void setup() {
  Serial.begin(SERIAL_BAUD);
  delay(10);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW
  radio.setHighPower(); //only for RFM69HW!
#endif
  radio.encrypt(ENCRYPTKEY);
  radio.promiscuous(promiscuousMode);
  //radio.setFrequency(919000000);
  //radio.writeReg(REG_OPMODE, (radio.readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_STANDBY);  //set standby-mode
  //radio.writeReg(REG_RSSITHRESH, 0xFF);  //set RSSI threshhold as low as possible
  //radio.writeReg(REG_OPMODE, (radio.readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_RECEIVER);  //set standby-mode
  radio.writeReg(REG_BITRATEMSB, RF_BITRATEMSB_300000);  //set MSB bitrate to 300Kbps
  radio.writeReg(REG_BITRATELSB, RF_BITRATELSB_300000);  //set LSB bitrate to 300Kbps
  Serial.println(F("Bitrate set to 300Kbps."));
 
  char buff[50];
  sprintf(buff, "\nListening at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(buff);
  if (flash.initialize())
  {
    Serial.print("SPI Flash Init OK. Unique MAC = [");
    flash.readUniqueId();
    for (byte i=0;i<8;i++)
    {
      Serial.print(flash.UNIQUEID[i], HEX);
      if (i!=8) Serial.print(':');
    }
    Serial.println(']');
   
    //alternative way to read it:
    //byte* MAC = flash.readUniqueId();
    //for (byte i=0;i<8;i++)
    //{
    //  Serial.print(MAC[i], HEX);
    //  Serial.print(' ');
    //}
   
  }
  else
    Serial.println("SPI Flash Init FAIL! (is chip present?)");
}

byte ackCount=0;
uint32_t packetCount = 0;
long loopCount=0;
int theRSSI;
int maxRSSI= (-125);
void loop() {
  radio.writeReg(REG_OPMODE, (radio.readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_STANDBY);  //set standby-mode
  radio.writeReg(REG_RSSITHRESH, 0xFF);  //set RSSI threshhold as low as possible
  radio.writeReg(REG_OPMODE, (radio.readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_RECEIVER);  //set standby-mode

  loopCount++;
  theRSSI = radio.readRSSI();
  if ((theRSSI > maxRSSI)) {
    maxRSSI = theRSSI;
  }
 
  if ((loopCount%1)==0) { //can change to %100 to have one printline per 100 RSSI measurements
    Serial.print(loopCount);
    Serial.print(F(". RSSI="));Serial.print(theRSSI);Serial.print(", maxRSSI=");
    Serial.println(maxRSSI);
    //Serial.flush(); 
  }
}

void Blink(byte PIN, int DELAY_MS)
{
  pinMode(PIN, OUTPUT);
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN,LOW);
}

I start the test by running just the gateway (transmitter is off).  When I switch on the transmitter, the max RSSI changes pretty much immediately.  As I move the transmitter closer to the receiver, the max RSSI changes in the way that you expect that it would.

It would be great if someone besides just me would try running it and then post how it went.  I've given the complete sketches.  All you need to replicate the experiment are two RFM69 moteinos and the Version2 code that I've provided here.  It should only take a minute or two to load it up and try it.  I have the receiver connected to a serial console by an FTDI cable, so that I can track the RSSI and maxRSSI as they change.  I have the transmitter battery powered (no serial console needed) to make it easy to carry and move around.
« Last Edit: January 20, 2016, 01:32:21 PM by WhiteHare »

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #20 on: January 20, 2016, 04:24:39 AM »
Below is an example snippet of the output:
Code: [Select]
24271. RSSI=-107, maxRSSI=-79
24272. RSSI=-101, maxRSSI=-79
24273. RSSI=-110, maxRSSI=-79
24274. RSSI=-95, maxRSSI=-79
24275. RSSI=-105, maxRSSI=-79
24276. RSSI=-104, maxRSSI=-79
24277. RSSI=-106, maxRSSI=-79
24278. RSSI=-102, maxRSSI=-79
24279. RSSI=-105, maxRSSI=-79
24280. RSSI=-105, maxRSSI=-79
24281. RSSI=-114, maxRSSI=-79
24282. RSSI=-101, maxRSSI=-79
24283. RSSI=-106, maxRSSI=-79
24284. RSSI=-100, maxRSSI=-79
24285. RSSI=-100, maxRSSI=-79
24286. RSSI=-34, maxRSSI=-34
24287. RSSI=-33, maxRSSI=-33
24288. RSSI=-31, maxRSSI=-31
24289. RSSI=-31, maxRSSI=-31
24290. RSSI=-31, maxRSSI=-31
24291. RSSI=-30, maxRSSI=-30
24292. RSSI=-31, maxRSSI=-30
24293. RSSI=-30, maxRSSI=-30
24294. RSSI=-30, maxRSSI=-30
24295. RSSI=-30, maxRSSI=-30
24296. RSSI=-31, maxRSSI=-30
24297. RSSI=-31, maxRSSI=-30
24298. RSSI=-31, maxRSSI=-30
24299. RSSI=-31, maxRSSI=-30
24300. RSSI=-31, maxRSSI=-30
24301. RSSI=-31, maxRSSI=-30
24302. RSSI=-31, maxRSSI=-30
24303. RSSI=-31, maxRSSI=-30
24304. RSSI=-31, maxRSSI=-30
24305. RSSI=-30, maxRSSI=-30
24306. RSSI=-30, maxRSSI=-30
24307. RSSI=-31, maxRSSI=-30
24308. RSSI=-31, maxRSSI=-30
24309. RSSI=-31, maxRSSI=-30
24310. RSSI=-31, maxRSSI=-30
Time index 24286 marks the instant at which I turned on the transmitter Moteino node.  You can see the RSSI immediately increase from a prior maximum of -79dB to an RSSI of -34dB, and very quickly from there to -30dB.  Also, before the transmitter is turned on, the RSSI numbers are fluctuating over a wider range, as you would expect, and once the transmitter is turned on, the RSSI numbers become much more tightly clustered, again as you would perhaps expect.
« Last Edit: January 20, 2016, 01:31:05 PM by WhiteHare »

perky

  • Hero Member
  • *****
  • Posts: 873
  • Country: gb
Re: Real time RSSI measurement broken RFM69CW?
« Reply #21 on: January 20, 2016, 01:38:14 PM »
Good work.

It appears though that you are actually resetting the receiver by putting into standby and then rx mode in the main loop. What you're not doing though is polling for RSSI interrupt before reading the register. You noticed that increasing the modulus of the printfs didn't have the desired effect of speeding up the measurements, I think that you were resetting the receiver before the RSSI measurments were completed, when you print out that adds a delay and allows the measurement to complete. and put its value in the register so it appears to only update at the rate at which you're printing.

You need the handshake of waiting for RSSI interrupt before reading the RSSI register I think.
Mark.
« Last Edit: January 20, 2016, 01:55:00 PM by perky »

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #22 on: January 20, 2016, 02:40:40 PM »
Thanks for your feedback.

You noticed that increasing the modulus of the printfs didn't have the desired effect of speeding up the measurements, I think that you were resetting the receiver before the RSSI measurments were completed, when you print out that adds a delay and allows the measurement to complete. and put its value in the register so it appears to only update at the rate at which you're printing.

Just to clear the air on that: it doesn't happen in Version 2.  There was a bug in version 1 where it was accidently reading RSSI twice per loop instead of once per loop, and for whatever reason that was leading to the perceptible delays I reported earlier.

In this particular instance, what reason is there for thinking that the handshaking is strictly needed?  As long as the reported RSSI values are rapidly updating (as they appear to be), and not stuck reading and re-reading an old stale value, I'm not certain  it will make much, if any, difference whether or not the code waits for a handshake.  Granted, it may depend on how updating the RFM69's RSSI was implemented (e.g. is the update an atomic action which prevents you from reading an answer that's still a work-in-progress?).  Do we even know?  If we don't know, then I agree that waiting for a handshake does, on its face, seem like  it might be a more conservative way of doing it, provided you prevent the RFM69 from initiating another RSSI measurement until you can read the latest RSSI value and then explicitly trigger a new measurement.  Otherwise, the same concern exists.  Plus, the extra overhead for such rigidly controlled handshaking might/probably (?) cause a slower RSSI sample rate, and so there's that as a possible cost to doing it.  i.e. For that reason, the argument can be made that if handshaking is not proven to be needed, it's probably better to avoid handshaking.

Anyhow, food for thought.  Unfortunately, given the unknowns, it's not obvious (at least to me) how to resolve the issue without access to high cost reference equipment.  Lacking that, I suppose one could implement it both ways and then try to somehow judge if one seems better than the other while in actual use.

« Last Edit: January 20, 2016, 04:39:38 PM by WhiteHare »

perky

  • Hero Member
  • *****
  • Posts: 873
  • Country: gb
Re: Real time RSSI measurement broken RFM69CW?
« Reply #23 on: January 20, 2016, 06:37:58 PM »
OK, let's postulate a potential mode of operation:

1) You put the receiver into RX mode from standby. This triggers an RSSI measurement as the threshold is set below the noise floor. The radio takes 2 bit periods to finish that sample, which is far slower than an SPI register read.
2) You read the RSSI register. RSSI sampling is still ongoing, so the register has not yet been updated.
3) You exit RX mode by putting the radio into standby mode. This clears the logic and stops an on-going RSSI measurement before it has updated the register.
4) loop back to 1.

This potentially means the RSSI register never updates. Now you insert a print out of the RSSI measurement inbetween steps 2 and 3. This introduces a relatively long delay, and since the radio is still in RX mode the RSSI measurement completes and updates the register. The result is every time you print it out you appear to be seeing updated RSSI measurements, it gives the impression it's fast if you print out every time.

How do you know this isn't really happening? One way to tell is instead of printing out the values you stored them in a large array, and at the end printed it all out. If the above is happening then those values wouldn't change, or possibly might change but far slower than you might expect.

Repeat the experiment with polling for RSSI interrupt between steps 1 and 2 and look at the output from the array.
Mark.

Edit: Actually putting the radio into standby mode immediately after reading the RSSI register may have a similar result. If the above is happening then this might terminate the RSSI sample before the register updates and you'll print out unchanging values. Polling for RSSI interrupt before reading the RSSI register might yield changing values, this is a simpler experiment to do with your existing code.
« Last Edit: January 20, 2016, 06:54:45 PM by perky »

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #24 on: January 21, 2016, 11:59:36 AM »
Thanks, Perky.  I'm in the middle of doing a deeper dive through the datasheet, and I think your postulation is probably right: the most detailed discussion about sampling the RSSI centers around Figures 18, 19, and 20, and so far it appears the mere act of entering Rx mode is the only thing in the existing code which ultimately triggers fresh RSSI measurements. 

I'd wager there might be some time savings by putting the RFM69 into Rx-WAIT mode by manually setting RestartRx (rather than changing to standby and then back to Rx-mode) to trigger a new RSSI measurement.  If so, maybe that would yield an even faster RSSI update rate.

Anyhow, given your postulation and the above, it stands to reason that the time interval provided by the printing might well be longer than what's needed.  OK, I'm convinced.   :)

So, to make this work with the existing hardware without adding a jumper, it appears I'll need to use Diox mapping 11 (to map RSSI to D00 while in Rx-mode) and attach a new interrupt handler to read the RSSI value and enable RestartRx. 

« Last Edit: January 21, 2016, 01:13:15 PM by WhiteHare »

emjay

  • Full Member
  • ***
  • Posts: 119
  • Country: nl
Re: Real time RSSI measurement broken RFM69CW?
« Reply #25 on: January 21, 2016, 01:12:41 PM »
Isn't polling the Rssi flag in RegIrqFlags1 (0x27) a little easier?

Curious that this bit flag has Mode rwc , one of only two occurrences in the entire document with no key.  Ok, the r and w are obvious, but cc=clear? Why distinguish this from setting to zero via w ?



WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #26 on: January 21, 2016, 01:25:46 PM »
Curious that this bit flag has Mode rwc , one of only two occurrences in the entire document with no key.  Ok, the r and w are obvious, but cc=clear? Why distinguish this from setting to zero via w ?

Maybe the "c" means it's only writable if the RFM69 is in Continuous mode?  At least, I'm tempted to infer that from the comment attached to SyncAddressMatch.  Perhaps the original notation was Wc (as in W subscript c), but the formatting flattened it out and squashed the meaning.

Admittedly, it would mean their notation is a bit inconsistent (i.e. why r/rwc and not just rwc?), but it would seem to fit for RSSI.  In continuous mode maybe (?) you need to clear it yourself in order to prepare for recognizing when a new RSSI is available to read, whereas in packet mode you only get one RSSI value upon entering Rx-mode, and then it's cleared for you automatically when you leave Rx-mode in order to prepare to receive the next RSSI.
« Last Edit: January 21, 2016, 02:14:20 PM by WhiteHare »

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #27 on: January 21, 2016, 02:23:50 PM »
Isn't polling the Rssi flag in RegIrqFlags1 (0x27) a little easier?

Thanks for pointing that out.   :)  It looks as though once that value goes high it will remain high until the RFM69 exits Rx-mode, whereas I wasn't sure whether the DIOx RSSI pin would remain affirmed or was merely toggled.
« Last Edit: January 21, 2016, 02:28:12 PM by WhiteHare »

perky

  • Hero Member
  • *****
  • Posts: 873
  • Country: gb
Re: Real time RSSI measurement broken RFM69CW?
« Reply #28 on: January 21, 2016, 03:10:42 PM »
@emjay: I think rwc means that it can only be cleared by writing a 1 to it and cannot be set, rw would imply you can set or clear it but that's generally not done for interrupt status bits. There's a problem if you make them rw for interrupt status bits, you should only clear those bits that you have actually seen high and actioned. If an interrupt should happen in between the reading of the register and the clearing operation you could clear that interrupt before it's even been seen, so they use a 'mask' approach where only the bits written with a 1 get cleared, all other status bits written with a 0 do not get affected in any way.

@WhiteHare: In my experiments I used restart rather than exit RX and re-enter again and is in the pseudo-code, it is probably quicker due to other things happening like PLL re-locking when exiting and re-entering RX mode.

Given you're having to read the RSSI register via SPI and also restarting via SPI, and SPI is fairly quick, it's convenient to read the RSSI interrupt via SPI as emjay says. I agree you could save one SPI register read in your loop by mapping it to DIO0 though (do the mapping once outside the loop of course!).

I think it's safe to assume the DIO pins map to the internal signals which are also readable via SPI, so if they get cleared internally it'll change on the DIO pin its mapped to.
Mark.
« Last Edit: January 21, 2016, 03:25:15 PM by perky »

WhiteHare

  • Hero Member
  • *****
  • Posts: 1296
  • Country: us
Re: Real time RSSI measurement broken RFM69CW?
« Reply #29 on: January 22, 2016, 12:31:00 AM »
I implemented a simple version of what was discussed.  RSSIvalue isn't read until after the RSSI flag goes HIGH.  However, I think what will surprise you guys is that after doing so the RSSI value afterward (but before the next Rx cycle is started) doesn't settle onto a single value but rather continues to jump around.

Here's the Version 3.0 code:
Code: [Select]
//Version 3.0

// Sample RFM69 receiver/gateway sketch, with ACK and optional encryption
// Passes through any wireless received messages to the serial port & responds to ACKs
// It also looks for an onboard FLASH chip, if present
// Library and code by Felix Rusu - felix@lowpowerlab.com
// Get the RFM69 and SPIFlash library at: https://github.com/LowPowerLab/

#include <RFM69.h>    //get it here: https://www.github.com/lowpowerlab/rfm69
#include <SPI.h>
#include <SPIFlash.h> //get it here: https://www.github.com/lowpowerlab/spiflash
#include <RFM69registers.h>

#define NODEID        1    //unique for each node on same network
#define NETWORKID     100  //the same on all nodes that talk to each other
//Match frequency to the hardware version of the radio on your Moteino (uncomment one):
//#define FREQUENCY     RF69_433MHZ
//#define FREQUENCY     RF69_868MHZ
#define FREQUENCY     RF69_915MHZ
#define ENCRYPTKEY    "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
#define IS_RFM69HW    //uncomment only for RFM69HW! Leave out if you have RFM69W!
#define SERIAL_BAUD   250000

#ifdef __AVR_ATmega1284P__
  #define LED           15 // Moteino MEGAs have LEDs on D15
  #define FLASH_SS      23 // and FLASH SS on D23
#else
  #define LED           9 // Moteinos have LEDs on D9
  #define FLASH_SS      8 // and FLASH SS on D8
#endif

RFM69 radio;
SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for 4mbit  Windbond chip (W25X40CL)
bool promiscuousMode = false; //set to 'true' to sniff all packets on the same network

void setup() {
  Serial.begin(SERIAL_BAUD);
  delay(10);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW
  radio.setHighPower(); //only for RFM69HW!
#endif
  radio.encrypt(ENCRYPTKEY);
  radio.promiscuous(promiscuousMode);
   
  radio.writeReg(REG_BITRATEMSB, RF_BITRATEMSB_300000);  //set MSB bitrate to 300Kbps
  radio.writeReg(REG_BITRATELSB, RF_BITRATELSB_300000);  //set LSB bitrate to 300Kbps
  Serial.println(F("Bitrate set to 300Kbps."));
 
  char buff[50];
  sprintf(buff, "\nListening at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(buff);
  if (flash.initialize())
  {
    Serial.print("SPI Flash Init OK. Unique MAC = [");
    flash.readUniqueId();
    for (byte i=0;i<8;i++)
    {
      Serial.print(flash.UNIQUEID[i], HEX);
      if (i!=8) Serial.print(':');
    }
    Serial.println(']');
   
    //alternative way to read it:
    //byte* MAC = flash.readUniqueId();
    //for (byte i=0;i<8;i++)
    //{
    //  Serial.print(MAC[i], HEX);
    //  Serial.print(' ');
    //}
   
  }
  else
    Serial.println("SPI Flash Init FAIL! (is chip present?)");

  radio.writeReg(REG_OPMODE, (radio.readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_STANDBY);  //set standby-mode
  radio.writeReg(REG_RSSITHRESH, 0xFF);  //set RSSI threshhold as low as possible
  radio.writeReg(REG_OPMODE, (radio.readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_RECEIVER);  //set Rx-mode   
}
long loopCount=0;
int theRSSI;
int maxRSSI= (-125);
uint8_t regIrqFlags1;

void loop() {
  loopCount++;
 
  while (!(radio.readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_RSSI)) { //busy-wait until RSSI flag goes HIGH
  }

  for (int i=0;i<10; i++) {
    regIrqFlags1 = radio.readReg(REG_IRQFLAGS1);
    theRSSI = -(radio.readReg(REG_RSSIVALUE))/2;

    if ((theRSSI > maxRSSI)) {
      maxRSSI = theRSSI;
    }
 
    Serial.print(loopCount);Serial.print(F("."));Serial.print(i);
    Serial.print(F(": regIrqFlags1="));Serial.print((regIrqFlags1),BIN);
    Serial.print(F(", RSSI=")); Serial.println(theRSSI);
  }

  radio.writeReg(REG_OPMODE, (radio.readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_STANDBY);  //set standby-mode
  radio.writeReg(REG_OPMODE, (radio.readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_RECEIVER);  //set Rx-mode
}

and here is some sample output:
Code: [Select]
302.0: regIrqFlags1=10011000, RSSI=-79
302.1: regIrqFlags1=11011000, RSSI=-99
302.2: regIrqFlags1=11011000, RSSI=-103
302.3: regIrqFlags1=11011000, RSSI=-98
302.4: regIrqFlags1=11011000, RSSI=-99
302.5: regIrqFlags1=11011000, RSSI=-103
302.6: regIrqFlags1=11011000, RSSI=-101
302.7: regIrqFlags1=11011000, RSSI=-104
302.8: regIrqFlags1=11011000, RSSI=-96
302.9: regIrqFlags1=11011000, RSSI=-104
303.0: regIrqFlags1=10011000, RSSI=-76
303.1: regIrqFlags1=11011000, RSSI=-98
303.2: regIrqFlags1=11011000, RSSI=-127
303.3: regIrqFlags1=11011000, RSSI=-105
303.4: regIrqFlags1=11011000, RSSI=-94
303.5: regIrqFlags1=11011000, RSSI=-96
303.6: regIrqFlags1=11011000, RSSI=-97
303.7: regIrqFlags1=11011000, RSSI=-101
303.8: regIrqFlags1=11011000, RSSI=-100
303.9: regIrqFlags1=11011000, RSSI=-106
304.0: regIrqFlags1=10011000, RSSI=-78
304.1: regIrqFlags1=11011000, RSSI=-95
304.2: regIrqFlags1=11011000, RSSI=-101
304.3: regIrqFlags1=11011000, RSSI=-99
304.4: regIrqFlags1=11011000, RSSI=-99
304.5: regIrqFlags1=11011000, RSSI=-98
304.6: regIrqFlags1=11011000, RSSI=-107
304.7: regIrqFlags1=11011000, RSSI=-98
304.8: regIrqFlags1=11011000, RSSI=-104
304.9: regIrqFlags1=11011000, RSSI=-101
305.0: regIrqFlags1=10011000, RSSI=-81
305.1: regIrqFlags1=11011000, RSSI=-96
305.2: regIrqFlags1=11011000, RSSI=-103
305.3: regIrqFlags1=11011000, RSSI=-99
305.4: regIrqFlags1=11011000, RSSI=-99
305.5: regIrqFlags1=11011000, RSSI=-103
305.6: regIrqFlags1=11011000, RSSI=-99
305.7: regIrqFlags1=11011000, RSSI=-102
305.8: regIrqFlags1=11011000, RSSI=-105
305.9: regIrqFlags1=11011000, RSSI=-98

Is that what you expected?