RFM69 (LowPowerLab) - Arduino Pro Mini to TeensyLC - old code not working anymore

Status
Not open for further replies.

MrGlasspoole

Well-known member
A long time i did nothing with Teensy/Arduino.

I have two RFM69 temp sensors but my old code seems not to work anymore.
One old sensor is working (Arduino Pro Mini). That tells me the Teensy (receiver) part is OK.

But when i upload the temp sensor code (sender) i found in my folder to another Pro Mini it does not work.
I'm looking into this since hours and cant figure it out. Maybe back then i made some changes to the code and did not save it or saved something that was not working.

Arduino Pro Mini:
Code:
/**************************************************************
* CONNECTION Pro Mini                                         *
***************************************************************
RFM69 MOSI <> D11 MOSI
RFM69 MISO <> D12 MISO
RFM69 DIO0 <> D2  IRQ
RFM69 NSS  <> D10 CS
RFM69 SCK  <> D13 SCK

DS18B20 Data  <> D3
DS18B20 Power <> D4

**************************************************************/

#include <RFM69.h>             // Get it here: github.com/lowpowerlab/rfm69
#include <RFM69_ATC.h>         // Get it here: github.com/lowpowerlab/rfm69
#include <SPI.h>               // Comes with Arduino IDE
#include <OneWire.h>           // Get it here: github.com/PaulStoffregen/OneWire
#include <DallasTemperature.h> // Get it here: github.com/milesburton/Arduino-Temperature-Control-Library
#include <JeeLib.h>            // Get it here: github.com/jcw/jeelib

ISR(WDT_vect) {Sleepy::watchdogEvent();} // Interrupt handler for JeeLabs Sleepy power saving

/**************************************************************
* RFM69 SETUP                                                 *
**************************************************************/
#define NODEID        82  // Unique for each node on same network
#define NETWORKID     80  // The same on all nodes that talk to each other
#define GATEWAYID     80
#define FREQUENCY     RF69_868MHZ // Frequency of the hardware version of the radio module
#define ENCRYPTKEY    "4+A8uQ)P<5e3U7f*" // Exactly the same 16 characters/bytes on all nodes!
// #define IS_RFM69HW    // Uncomment only for RFM69HW! Leave out if you have RFM69W!
#define ENABLE_ATC    // Comment out this line to disable AUTO TRANSMISSION CONTROL
#define ATC_RSSI      -85 // target RSSI

#define ACK_TIME      20 // Number of milliseconds to wait for an ack
#define RETRY_PERIOD  5  // How soon to retry (in seconds) if ACK didn't come in
#define RETRY_LIMIT   5  // Maximum number of times to retry

#ifdef ENABLE_ATC
  RFM69_ATC radio;
#else
  RFM69 radio;
#endif

/**************************************************************
* MISC SETUP                                                  *
**************************************************************/
#define DEBUG 1 // Set to 1 for serial port output

const uint32_t SERIAL_BAUD = 115200;  // Set serial 0 speed
const uint8_t ONE_WIRE_BUS = 3;       // DS18B20 Data pin is connected to pin D3
const uint8_t ONE_WIRE_POWER = 4;     // DS18B20 Power pin is connected to pin D4

OneWire oneWire(ONE_WIRE_BUS);       // Setup oneWire instance to communicate with any OneWire devices
DallasTemperature sensors(&oneWire); // Pass oneWire reference to Dallas Temperature

/**************************************************************
* READ BATTERY VOLTAGE                                        *
**************************************************************/
long readVcc() {
  bitClear(PRR, PRADC); ADCSRA |= bit(ADEN); // Enable the ADC
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // Read 1.1V reference against Vcc (ATmega328)
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring
  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
  uint8_t high = ADCH; // unlocks both
  long result = (high<<8) | low;
  result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  ADCSRA &= ~ bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power
  return result; // Vcc in millivolts
}

/**************************************************************
* RFM69 DATA STRUCTURE                                        *
**************************************************************/
typedef struct {
  uint16_t nVcc;  // Battery voltage
  int16_t nTemp;  // Temperature reading
  uint8_t nID;    // Store this nodeId
  uint8_t nTx;    // Transmit level of the node
} Payload;
Payload rfData;

/**************************************************************
* SEND PAYLOAD DATA                                           *
**************************************************************/
static void rfwrite() {

  #ifdef DEBUG
      Serial.print("Sending ");
      Serial.print(sizeof(rfData));
      Serial.println(" bytes...");
      Serial.print("Node:");
      Serial.print(rfData.nID);
      Serial.print(", Temp:");
      Serial.print(rfData.nTemp);
      Serial.print(", Vcc:");
      Serial.print(rfData.nVcc);
      Serial.print(", TX Level:");
      Serial.println(rfData.nTx); // Current transmit level used by this sender
      Serial.flush();
  #endif // END DEBUG
  if (radio.sendWithRetry(GATEWAYID, (const void*)(&rfData), sizeof(rfData), RETRY_LIMIT, ACK_TIME)) {
    int16_t savedMy_RSSI = radio.getAckRSSI(); // Save this value for later before printing

    #ifdef DEBUG
      Serial.print("ACK received! ");
      Serial.print("RSSI:");
      Serial.println(savedMy_RSSI,DEC); // This sender's RSSI acked back from the receiving node (Gateway)
      Serial.flush();
    #endif // END DEBUG

    // NOW is when you MUST receive the gateway's response IF you want to have the gateway's ATC work
    for (int i=0; i<5; i++) { // Give the gateway up to 100 mS to respond (if it is)
      if (radio.receiveDone()) {
        if (radio.ACKRequested()) {
          radio.sendACK();
          #ifdef DEBUG
            Serial.println("ACK sent!");
            Serial.flush();
          #endif // END DEBUG
        }
        break; // Stop the loop if you receive a response from the gateway
      }
      delay(20);
    }
    Serial.println();
    radio.sleep(); // Put radio to sleep
  } else {
    #ifdef DEBUG
      Serial.println("No ACK response!");
      Serial.println();
      Serial.flush();
    #endif // END DEBUG
    Sleepy::loseSomeTime(RETRY_PERIOD * 1000); // If no ack received wait and try again
  }

}

/**************************************************************
* SETUP                                                       *
**************************************************************/
uint8_t pinD[] = {5, 6, 7, 8, 9};                    // Array of unused digital pins
uint8_t pinDCount = sizeof(pinD) / sizeof(pinD[0]);  // Count unused digital pins
uint8_t pinA[] = {A0, A1, A2, A3, A4, A5, A6, A7};   // Array of unused analog pins
uint8_t pinACount = sizeof(pinA) / sizeof(pinA[0]);  // Count unused analog pins

void setup() {
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  radio.encrypt(ENCRYPTKEY);
  #ifdef IS_RFM69HW
    radio.setHighPower(); // Only for RFM69HW!
  #endif
  #ifdef ENABLE_ATC
    radio.enableAutoPower(ATC_RSSI); // Enables auto transmit power control with a targetRSSI of -85dB
  #endif
  
  radio.sleep(); // Put radio to sleep

  PRR = bit(PRTIM1); // Only keep timer 0 going
  
  ADCSRA &= ~ bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power

  for (byte i = 0; i < pinDCount; i++) {
    pinMode(pinD[i], INPUT_PULLUP); // Set unused digital pins as input and enable internal pull-up
  }

  for (byte i = 0; i < pinACount; i++) {
    pinMode(pinA[i], INPUT_PULLUP); // Set unused digital pins as input and enable internal pull-up
  }

  sensors.setResolution(11);       // Set DS18B20 sensor resolution
  pinMode(ONE_WIRE_POWER, OUTPUT); // Set power pin for DS18B20 to output

  startupTasks(); // Run tasks
}

void startupTasks() {
  #ifdef DEBUG
    char buff[50];
    Serial.begin(SERIAL_BAUD); // Open serial communications and wait for port to open
    while (!Serial) {;}        // Wait for serial port to connect
    sprintf(buff, "\nThe frequency is %d Mhz, Kenneth!", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
    Serial.println(buff);
    #ifdef ENABLE_ATC
      Serial.println("RFM69_ATC Enabled (Auto Transmission Control)\n");
    #endif
    Serial.flush();
  #endif // END DEBUG
}

/**************************************************************
* LOOP                                                        *
**************************************************************/
void loop() {

  digitalWrite(ONE_WIRE_POWER, HIGH); // Turn DS18B20 on

  delay(5); // Allow 5ms for the sensor to be ready

  sensors.begin(); // Start Dallas Temperature library
  sensors.requestTemperatures(); // Get the temperature
  rfData.nTemp = sensors.getTempCByIndex(0) * 100; // Read first sensor and convert to int > 26.38 would go to 2638

  digitalWrite(ONE_WIRE_POWER, LOW); // Turn DS18B20 off

  rfData.nID = NODEID;
  rfData.nTx = radio._transmitLevel; // Current transmit level used by this sender
  rfData.nVcc = readVcc();           // Get battery voltage

  rfwrite(); // Send data via RF

  Sleepy::loseSomeTime(30000);
}

TeensyLC:
Code:
/**************************************************************
* CONNECTION TEENSY LC                                        *
***************************************************************
RFM69 MOSI <> D11 MOSI
RFM69 MISO <> D12 MISO
RFM69 DIO0 <> D2  IRQ
RFM69 NSS  <> D10 CS
RFM69 SCK  <> D14 SCK

**************************************************************/

#include <RFM69.h>             // Get it here: github.com/lowpowerlab/rfm69
#include <RFM69_ATC.h>         // Get it here: github.com/lowpowerlab/rfm69
#include <SPI.h>               // Comes with Arduino IDE

/**************************************************************
* RFM69 SETUP                                                 *
**************************************************************/
#define NODEID        80  // Unique for each node on same network
#define NETWORKID     80  // The same on all nodes that talk to each other
#define FREQUENCY     RF69_868MHZ // Frequency of the hardware version of the radio module
#define ENCRYPTKEY    "4+A8uQ)P<5e3U7f*" // Exactly the same 16 characters/bytes on all nodes!
#define IS_RFM69HW    // Uncomment only for RFM69HW! Leave out if you have RFM69W!
#define ENABLE_ATC    // Comment out this line to disable AUTO TRANSMISSION CONTROL
#define ATC_RSSI      -69 // target RSSI

#define ACK_TIME      20 // Number of milliseconds to wait for an ack
#define RETRY_PERIOD  5  // How soon to retry (in seconds) if ACK didn't come in
#define RETRY_LIMIT   5  // Maximum number of times to retry

/**************************************************************
* RFM69 TEENSY SPECIFIC                                       *
**************************************************************/
const uint8_t rfmClockPin = 14; // RFM69 SPI SCK pin on Teensy LC
const uint8_t rfmCsPin = 10;    // RFM69 SPI CS pin on Teensy LC
const uint8_t rfmIrqPin = 2;    // RFM69 IRQ pin on Teensy LC

#ifdef IS_RFM69HW
  bool isRFM69HW = true;
#else
  bool isRFM69HW = false;
#endif

#ifdef ENABLE_ATC
  RFM69_ATC radio(rfmCsPin, rfmIrqPin, isRFM69HW);
#else
  RFM69 radio(rfmCsPin, rfmIrqPin, isRFM69HW);
#endif

/**************************************************************
* MISC SETUP                                                  *
**************************************************************/
#define DEBUG 1 // Set to 1 for serial port output

const uint32_t SERIAL_BAUD = 115200;     // Set serial 0 speed
const uint8_t LED = 13;                  // Teensy LC onboard LED is on pin D13

/**************************************************************
* RFM69 DATA STRUCTURE                                        *
**************************************************************/
typedef struct {
  uint16_t nVcc;  // Battery voltage
  int16_t nTemp;  // Temperature reading
  uint8_t nID;    // Store this nodeId
  uint8_t nTx;    // Transmit level of the node
} Payload;
Payload rfData;

/**************************************************************
* SETUP                                                       *
**************************************************************/
void setup() {
  SPI.setSCK(rfmClockPin);   // Set SPI SCK pin for RFM69
  pinMode(rfmIrqPin, INPUT); // Enable INPUT mode on RFM69 IRQ pin
  
  radio.initialize(FREQUENCY, NODEID, NETWORKID);
  radio.encrypt(ENCRYPTKEY);
  #ifdef IS_RFM69HW
    radio.setHighPower(); // Only for RFM69HW!
  #endif
  #ifdef ENABLE_ATC
    radio.enableAutoPower(ATC_RSSI); // Enables auto transmit power control with a targetRSSI of -85dB
  #endif

  pinMode(LED, OUTPUT);   // Set LED pin as output
  digitalWrite(LED, LOW); // Turn LED off
  
  startupTasks(); // Run tasks

}

void startupTasks() {
  #ifdef DEBUG
    Serial.begin(SERIAL_BAUD); // Open serial communications
    while (!Serial) {;}        // Wait for serial port to connect
    char buff[50];
    sprintf(buff, "\nThe radio frequency is %d Mhz, Kenneth!", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
    Serial.println(buff);
    #ifdef ENABLE_ATC
      Serial.println("RFM69 ATC Enabled (Auto Transmission Control)\n");
    #endif
    Serial.flush();
  #endif // END DEBUG
}

/**************************************************************
* LOOP                                                        *
**************************************************************/
byte ackCount=0;

void loop() {
  int16_t savedRSSI;                  // Room for temporary copies
  Payload tempPayload;                // Room for temporary copies
  uint8_t savedDataLen;               // Room for temporary copies
  static int16_t savedMy_RSSI = -120; // This is static so it persists across multiple loops since it doesn't get updated often

  if (radio.receiveDone()) {
    savedRSSI = radio.RSSI;                 // Need to save this NOW, to print it later
    tempPayload = *(Payload*)radio.DATA;    // Need to save this NOW, to print it later
    savedDataLen = radio.DATALEN;           // Need to save this NOW, to print it later

    // RIGHT after the receiveDone call - DON'T PRINT BEFORE DOING THIS!
    if (radio.ACKRequested()) { // When a node requests an ACK, respond to the ACK
      uint8_t theNodeID = radio.SENDERID;
      radio.sendACK();
      #ifdef DEBUG
        Serial.println("ACK sent!");
      #endif // END DEBUG
      if (ackCount++%3==0) {
        #ifdef DEBUG
          Serial.print("Pinging node ");
          Serial.print(theNodeID);
          Serial.print(" - ACK... ");
        #endif // END DEBUG
        delay(3); // Need this when sending right after reception .. ?
        if (radio.sendWithRetry(theNodeID, "ACK TEST", 8, 0)) {  // 0 = only 1 attempt, no retries
          // HERE you can get the info on the gateway's RSSI and target level...
          savedMy_RSSI = radio.getAckRSSI();  // This works HERE because you received a ACK to your sendWithRetry()
          #ifdef DEBUG
            Serial.println("ok!");
          #endif // END DEBUG
        } else {
          #ifdef DEBUG
            Serial.println("nothing");
          #endif // END DEBUG
        }
      }
    } // END radio.ACKRequested
 
    if (savedDataLen != sizeof(Payload)) {  // Note: Using SAVED value
      #ifdef DEBUG
        Serial.print("Invalid Payload received!");
      #endif // END DEBUG
    } else {
      rfData = tempPayload; // Assume radio.DATA actually contains our struct and not something else. USING Saved value here
      #ifdef DEBUG
        Serial.print("Received ");
        Serial.print(sizeof(rfData));
        Serial.println(" bytes!");
        Serial.print("Node:");
        Serial.print(rfData.nID);
        Serial.print(", Temp:");
        Serial.print(rfData.nTemp);
        Serial.print(", Vcc:");
        Serial.print(rfData.nVcc);
        Serial.print(", TX Level:");
        Serial.print(rfData.nTx);
        Serial.print(", RSSI:");
        Serial.print(savedRSSI);     // The nodes RSSI. Need to use value saved earlier
        Serial.println();
        // The next lines are totally meaningless UNLESS you have just done a radio.sendWithRetry() - these values only get updated on a sendWithRetry()!
        Serial.print("Gateway TX Level:");
        Serial.print(radio._transmitLevel,DEC); // Current transmit level used by this sender
        Serial.print(", Gateway RSSI:");
        Serial.println(savedMy_RSSI,DEC);       // This gateway's RSSI acked back from the receiving node 
        Serial.println();
      #endif // END DEBUG 
    } // END radio.DATALEN

  } // END radio.receiveDone

} // END loop
 
Status
Not open for further replies.
Back
Top