Okay, node and gateway code for 2 default stock Motes not connected to anything else.
Gateway code#include <RFM69.h>
#include <RFM69registers.h>
#include <SPI.h>
//*********************************************************************************************
// *********** IMPORTANT SETTINGS - YOU MUST CHANGE/ONFIGURE TO FIT YOUR HARDWARE *************
//*********************************************************************************************
#define NETWORKID 100 //the same on all nodes that talk to each other - 170 is 10101010 DC free value
#define RECEIVER 1 //unique ID of the gateway/receiver
#define SENDER 2
#define NODEID RECEIVER //change to "SENDER" if this is the sender node (the one with the button)
#define FREQUENCY RF69_915MHZ //Match frequency to the hardware version of the radio on your Moteino (uncomment one):
//#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W!
//*********************************************************************************************
#define SERIAL_BAUD 115200
RFM69 radio;
uint16_t Last_Packet, Curr_Packet, Packets_Received, Packets_Missed;
int32_t LT_RSSI;
void setup() {
Serial.begin(SERIAL_BAUD);
// Assume default settings, we will override them next
radio.initialize(FREQUENCY,NODEID,NETWORKID);
// Make the changes to bring the bitrate up to 300kbps and turn CRC off allowing for packets <16 bytes
radio.writeReg( REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF | RF_OPMODE_STANDBY );
radio.writeReg( REG_DATAMODUL, RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_00 ); // 0x02
radio.writeReg( REG_BITRATEMSB, RF_BITRATEMSB_300000 ); // 0x03
radio.writeReg( REG_BITRATELSB, RF_BITRATELSB_300000 ); // 0x04
radio.writeReg( REG_FDEVMSB, RF_FDEVMSB_300000 ); // 0x05
radio.writeReg( REG_FDEVLSB, RF_FDEVLSB_300000 ); // 0x06
radio.writeReg( REG_FRFMSB, RF_FRFMSB_915 ); // 0x07
radio.writeReg( REG_FRFMID, RF_FRFMID_915 ); // 0x08
radio.writeReg( REG_FRFLSB, RF_FRFLSB_915 ); // 0x09
radio.writeReg( REG_RXBW, RF_RXBW_DCCFREQ_111 | RF_RXBW_MANT_16 | RF_RXBW_EXP_0 ); // 0x19
radio.writeReg( REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01 ); // 0x25
radio.writeReg( REG_DIOMAPPING2, RF_DIOMAPPING2_CLKOUT_OFF ); //0x26
radio.writeReg( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN ); // 0x28
radio.writeReg( REG_RSSITHRESH, 220 ); // 0x29
radio.writeReg( REG_PREAMBLELSB, 6 ); // 0x2D
radio.writeReg( REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_3 | RF_SYNC_TOL_0 ); // 0x2E
radio.writeReg( REG_SYNCVALUE1, 0x88 ); // 0x2F
radio.writeReg( REG_SYNCVALUE2, NETWORKID ); // 0x30
radio.writeReg( REG_SYNCVALUE3, 0x88 ); // 0x2F
radio.writeReg( REG_PACKETCONFIG1, RF_PACKET1_FORMAT_VARIABLE | RF_PACKET1_DCFREE_OFF | RF_PACKET1_CRC_OFF | RF_PACKET1_CRCAUTOCLEAR_OFF | RF_PACKET1_ADRSFILTERING_OFF ); // 0x37
radio.writeReg( REG_PAYLOADLENGTH, 66 ); // 0x38
radio.writeReg( REG_FIFOTHRESH, RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY | RF_FIFOTHRESH_VALUE ); // 0x3C
radio.writeReg( REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_2BITS | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF ); // 0x3D
radio.writeReg( REG_TESTDAGC, RF_DAGC_IMPROVED_LOWBETA0 ); // 0x6F
radio.setPowerLevel(0);
radio.encrypt(null);
Serial.print("Listening at ");
Serial.print(FREQUENCY);
Serial.println("Mhz...");
}
void loop() { // Loop Forever
int16_t RSSI;
uint8_t SenderID;
//check if something was received (could be an interrupt from the radio)
if (radio.receiveDone()) {
if (radio.ACKRequested()) { //check if sender wanted an ACK
radio.sendACK(); // send the ACK
Serial.print(" - ACK sent");
}
RSSI = radio.RSSI;
LT_RSSI += RSSI;
if (radio.SENDERID == 2) {
//print message received to serial
Serial.print("Vcc: ");
uint16_t rbgv = radio.DATA[1]<<8 | radio.DATA[0];
uint16_t voltage = ((1125300/rbgv)+5)/10;
Serial.print(voltage);
Serial.print("VDC\tPacket Counter: ");
// Work out PER statistics
Curr_Packet = radio.DATA[3]<<8 | radio.DATA[2];
if (!( Curr_Packet == ++Last_Packet ) && Packets_Received ) Packets_Missed += (Curr_Packet - Last_Packet);
Last_Packet = Curr_Packet;
Serial.print(Curr_Packet);
Serial.print("\tMissed: ");
Serial.print(Packets_Missed);
Serial.print("\tReceived: ");
Serial.print(++Packets_Received);
Serial.print("\tPER: ");
Serial.print( 100 * Packets_Missed / Packets_Received );
Serial.print("%\tRX_RSSI:");
Serial.print(RSSI);
Serial.print(" | ");
Serial.print(LT_RSSI/Packets_Received);
Serial.println();
}
} // End if
_delay_us(10);
} // End Loop
Node Code#include <RFM69.h>
#include <RFM69Registers.h>
#include <SPI.h>
#include <LowPower.h>
// Define various ADC prescaler
#define ADC_PS_16 (1 << ADPS2)
#define ADC_PS_32 (1 << ADPS2) | (1 << ADPS0)
#define ADC_PS_64 (1 << ADPS2) | (1 << ADPS1)
#define ADC_PS_128 (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0)
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define START_ADC_CONVERSION sbi(ADCSRA, ADSC); // start a conversion
#define ENABLE_ADC cbi(PRR, PRADC); sbi(ADCSRA, ADEN); //ADCSRA |= bit(ADEN); // Enable the ADC
#define DISABLE_ADC cbi(ADCSRA, ADEN); sbi(PRR, PRADC); // Disable the ADC to save power
#define DEBUG 0
//*********************************************************************************************
// *********** IMPORTANT SETTINGS - YOU MUST CHANGE/ONFIGURE TO FIT YOUR HARDWARE *************
//*********************************************************************************************
#define NETWORKID 100 //the same on all nodes that talk to each other
#define RECEIVER 1 //unique ID of the gateway/receiver
#define SENDER 2
#define NODEID SENDER //change to "SENDER" if this is the sender node (the one with the button)
//#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W!
#define FREQUENCY RF69_915MHZ
RFM69 radio; //Create an instance of the object
static inline void Fast_ADC_Init(void) {
sei();
// Timer 0 initialization from wiring.c for a ATmega 328P (Arduino Uno rev 3) + 12 bytes to sketch size
TCCR0A = _BV(WGM01) | _BV(WGM00); // set timer 0 prescale factor to 64
TCCR0B = _BV(CS01) | _BV(CS00); // set timer 0 prescale factor to 64
TIMSK0 = _BV(TOIE0); // enable timer 0 overflow interrupt
// Timer 2 initialization from wiring.c for an ATmega 328P (Arduino Uno rev 3) + 20 bytes to sketch size
TCCR2A |= _BV(COM2A1) | _BV(WGM20); // Enable timer 2 to _delay_ms() works properly
TCCR2B |= CS22; // set clkT2S/64 (From prescaler)
// ADC Housekeeping
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // Set the multiplexer to read the internal bandgap voltage
//ADCSRA &= ~ADC_PS_128; // Unset the bits set by init()
ADCSRA |= ADC_PS_32; // set our own prescaler to 32
// Make unused pins outputs to reduce power consumption
//DDRB |= (1<<PB1) | (1<<PB0);
//DDRC |= (1<<PC1) | (1<<PC0);
//DDRD |= (1<<PD7) | (1<<PD6)| (1<<PD5) | (1<<PD4) | (1<<PD3);
}
int main(void) {
uint8_t data[4]; //16-bit temp, 16-bit RH, 16-bit Vcc, 16-bit packet counter
uint16_t packet_cnt = 0; // 16-bit packet counter to measure PER
#if DEBUG
uint16_t startT, elapsed;
startT = micros(); // ==================== START THE CLOCK ====================
#endif
Fast_ADC_Init(); // Initialize the AVR registers needed
radio.initialize(FREQUENCY,NODEID,NETWORKID);
radio.encrypt(null);
radio.setPowerLevel(0);
radio.sleep();
// Make the changes to bring the bitrate up to 300kbps and turn CRC off allowing for packets <16 bytes
radio.writeReg( REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF | RF_OPMODE_STANDBY );
radio.writeReg( REG_DATAMODUL, RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_00 ); // 0x02
radio.writeReg( REG_BITRATEMSB, RF_BITRATEMSB_300000 ); // 0x03
radio.writeReg( REG_BITRATELSB, RF_BITRATELSB_300000 ); // 0x04
radio.writeReg( REG_FDEVMSB, RF_FDEVMSB_300000 ); // 0x05
radio.writeReg( REG_FDEVLSB, RF_FDEVLSB_300000 ); // 0x06
radio.writeReg( REG_FRFMSB, RF_FRFMSB_915 ); // 0x07
radio.writeReg( REG_FRFMID, RF_FRFMID_915 ); // 0x08
radio.writeReg( REG_FRFLSB, RF_FRFLSB_915 ); // 0x09
radio.writeReg( REG_RXBW, RF_RXBW_DCCFREQ_111 | RF_RXBW_MANT_16 | RF_RXBW_EXP_0 ); // 0x19
radio.writeReg( REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01 ); // 0x25
radio.writeReg( REG_DIOMAPPING2, RF_DIOMAPPING2_CLKOUT_OFF ); //0x26
radio.writeReg( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN ); // 0x28
radio.writeReg( REG_RSSITHRESH, 220 ); // 0x29
radio.writeReg( REG_PREAMBLELSB, 6 ); // 0x2D
radio.writeReg( REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_3 | RF_SYNC_TOL_0 ); // 0x2E
radio.writeReg( REG_SYNCVALUE1, 0x88 ); // 0x2F
radio.writeReg( REG_SYNCVALUE2, NETWORKID ); // 0x30
radio.writeReg( REG_SYNCVALUE3, 0x88 ); // 0x2F
radio.writeReg( REG_PACKETCONFIG1, RF_PACKET1_FORMAT_VARIABLE | RF_PACKET1_DCFREE_OFF | RF_PACKET1_CRC_OFF | RF_PACKET1_CRCAUTOCLEAR_OFF | RF_PACKET1_ADRSFILTERING_OFF ); // 0x37
radio.writeReg( REG_PAYLOADLENGTH, 66 ); // 0x38
radio.writeReg( REG_FIFOTHRESH, RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY | RF_FIFOTHRESH_VALUE ); // 0x3C
radio.writeReg( REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_2BITS | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF ); // 0x3D
radio.writeReg( REG_TESTDAGC, RF_DAGC_IMPROVED_LOWBETA0 ); // 0x6F
//initTWI(); // Initialize the I2C bus at 400kHz
#if DEBUG
elapsed = micros()-startT; // ==================== STOP THE CLOCK ====================
Serial.begin(115200);
Serial.print("\nInitialization took ");
Serial.print(elapsed);
Serial.print(" us");
_delay_ms(6);
#else
cbi(PRR, PRUSART0); // Turn off the UART since we won't be using it
#endif
for(;;) { // Loop forever
#if DEBUG
startT = micros(); // ==================== START THE CLOCK ====================
#endif
ENABLE_ADC; // Turn on the ADC just prior to needing it
START_ADC_CONVERSION; // start a conversion
_delay_us(70); // Give some time for the ADC conversion to finish
data[0] = ADCL; // Avoid 16-bit math in this loop since it adds 40us
data[1] = ADCH; // Read back the results of the ADC
data[2] = (++packet_cnt & 0xFF); // Increment packet_count and stash the LSB
data[3] = (packet_cnt >> 8); // Stash the MSB of the packet counter
DISABLE_ADC; // Turn off the ADC to save power
radio.send(RECEIVER, data, 4, 0); //target node Id, message as string or byte array, message length, ack requested
radio.sleep();
#if DEBUG
elapsed = micros()-startT; // ==================== STOP THE CLOCK ====================
Serial.print("\nVcc: ");
Serial.print(112296/(data[1]<<8 | data[0]));
Serial.print("\tPacket Count: ");
Serial.print((uint16_t)(data[3]<<8 | data[2]));
Serial.print("\t\tLoop took: ");
Serial.print(elapsed);
Serial.print(" us");
_delay_ms(4); // Give the UART time to get our output across
Serial.flush();
#endif
uint8_t sleep_count=0;
do LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
while (++sleep_count < 1);
} // end for
} // end main
DEBUG on the node should be defined as 0 when doing actual PER testing. For just getting things set up, feel free to define it as 1 and open a serial monitor to ensure that your node is behaving appropriately.