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:
TeensyLC:
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