Transmit Basic: iwanders/plainRFM69
My first Arduino client was based on the plainRFM69 library which looks fairly lightweight (it has in memory message queues). I started by adapting the plainRFM69 “Minimal” sample.
/* * Copyright (c) 2014, Ivor Wanders * MIT License, see the LICENSE.md file in the root folder. */ #include <SPI.h> #include <plainRFM69.h> // slave select pin. #define SLAVE_SELECT_PIN 10 // connected to the reset pin of the RFM69. #define RESET_PIN 9 // tie this pin down on the receiver. #define SENDER_DETECT_PIN 4 /* This is very minimal, it does not use the interrupt. Using the interrupt is recommended. */ plainRFM69 rfm = plainRFM69(SLAVE_SELECT_PIN); void sender(){ uint32_t start_time = millis(); uint32_t counter = 0; // the counter which we are going to send. while(true){ rfm.poll(); // run poll as often as possible. if (!rfm.canSend()){ continue; // sending is not possible, already sending. } if ((millis() - start_time) > 500){ // every 500 ms. start_time = millis(); // be a little bit verbose. Serial.print("Send:");Serial.println(counter); // rfm.dumpRegisters(Serial); // send the number of bytes equal to that set with setPacketLength. // read those bytes from memory where counter starts. rfm.send(&counter); counter++; // increase the counter. } } } void receiver(){ uint32_t counter = 0; // to count the messages. while(true){ rfm.poll(); // poll as often as possible. while(rfm.available()){ // for all available messages: uint32_t received_count = 0; // temporary for the new counter. uint8_t len = rfm.read(&received_count); // read the packet into the new_counter. // print verbose output. Serial.print("Packet ("); Serial.print(len); Serial.print("): "); Serial.println(received_count); if (counter+1 != received_count){ // if the increment is larger than one, we lost one or more packets. Serial.println("Packetloss detected!"); } // assign the received counter to our counter. counter = received_count; } } } void setup(){ Serial.begin(9600); SPI.begin(); bareRFM69::reset(RESET_PIN); // sent the RFM69 a hard-reset. rfm.setRecommended(); // set recommended paramters in RFM69. rfm.setPacketType(false, false); // set the used packet type. rfm.setBufferSize(2); // set the internal buffer size. rfm.setPacketLength(4); // set the packet length. rfm.setFrequency((uint32_t) 915*1000*1000); // set the frequency. // baudrate is default, 4800 bps now. rfm.dumpRegisters(Serial); rfm.receive(); // set it to receiving mode. pinMode(SENDER_DETECT_PIN, INPUT_PULLUP); delay(5); } void loop(){ if (digitalRead(SENDER_DETECT_PIN) == LOW){ Serial.println("Going Receiver!"); receiver(); // this function never returns and contains an infinite loop. } else { Serial.println("Going sender!"); sender(); // idem. } }

I added code to dump the all the Arduino Nano Radio Shield RFM69/95 registers so I could compare it with my Adafruit RFM69HCW Radio Bonnet configuration. I also modified the code to set the three frequency registers so they matched the sample values based on the calculation in the RFM69HCW datasheet. I spent a lot of time manually configuring individual registers on the Adafruit bonnet (ignoring registers like 0x24 RegRssiValue).
void bareRFM69::dumpRegisters(Stream& out) { for (int i = 0; i <= 0x3d; i++) { out.print("0x"); out.print(i, HEX); out.print(": 0x"); out.println(this->readRegister(i), HEX); } } void plainRFM69::setFrequency(uint32_t freq){ uint64_t frf = ((uint64_t)freq << 19) / 32000000; this->setFrf(frf); }
After much “trial and error” I found that my Arduino device would only receive messages from my Windows 10 IoT Core device when a third Arduino device was transmitting.
21:10:50.819 -> 0x0: 0x0 21:10:50.819 -> 0x1: 0x4 21:10:50.852 -> 0x2: 0x0 21:10:50.852 -> 0x3: 0x1A 21:10:50.852 -> 0x4: 0xB 21:10:50.886 -> 0x5: 0x0 21:10:50.886 -> 0x6: 0x52 21:10:50.886 -> 0x7: 0xE4 21:10:50.920 -> 0x8: 0xC0 21:10:50.920 -> 0x9: 0x0 21:10:50.920 -> 0xA: 0x41 21:10:50.954 -> 0xB: 0x40 21:10:50.954 -> 0xC: 0x2 21:10:50.954 -> 0xD: 0x92 21:10:50.988 -> 0xE: 0xF5 21:10:50.988 -> 0xF: 0x20 21:10:50.988 -> 0x10: 0x24 21:10:51.022 -> 0x11: 0x9F 21:10:51.022 -> 0x12: 0x9 21:10:51.056 -> 0x13: 0x1A 21:10:51.056 -> 0x14: 0x40 21:10:51.056 -> 0x15: 0xB0 21:10:51.089 -> 0x16: 0x7B 21:10:51.089 -> 0x17: 0x9B 21:10:51.089 -> 0x18: 0x88 21:10:51.124 -> 0x19: 0x55 21:10:51.124 -> 0x1A: 0x8B 21:10:51.124 -> 0x1B: 0x40 21:10:51.157 -> 0x1C: 0x80 21:10:51.157 -> 0x1D: 0x6 21:10:51.157 -> 0x1E: 0x10 21:10:51.191 -> 0x1F: 0x0 21:10:51.191 -> 0x20: 0x0 21:10:51.191 -> 0x21: 0x0 21:10:51.226 -> 0x22: 0x0 21:10:51.226 -> 0x23: 0x2 21:10:51.226 -> 0x24: 0xFF 21:10:51.260 -> 0x25: 0x0 21:10:51.260 -> 0x26: 0x5 21:10:51.293 -> 0x27: 0x80 21:10:51.293 -> 0x28: 0x0 21:10:51.293 -> 0x29: 0xFF 21:10:51.328 -> 0x2A: 0x0 21:10:51.328 -> 0x2B: 0x0 21:10:51.328 -> 0x2C: 0x0 21:10:51.363 -> 0x2D: 0x3 21:10:51.363 -> 0x2E: 0x98 21:10:51.363 -> 0x2F: 0x1 21:10:51.363 -> 0x30: 0x1 21:10:51.397 -> 0x31: 0x1 21:10:51.397 -> 0x32: 0x1 21:10:51.397 -> 0x33: 0x0 21:10:51.432 -> 0x34: 0x0 21:10:51.432 -> 0x35: 0x0 21:10:51.466 -> 0x36: 0x0 21:10:51.466 -> 0x37: 0x50 21:10:51.466 -> 0x38: 0x4 21:10:51.500 -> 0x39: 0x0 21:10:51.500 -> 0x3A: 0x0 21:10:51.500 -> 0x3B: 0x0 21:10:51.535 -> 0x3C: 0x1 21:10:51.535 -> 0x3D: 0x0 21:10:51.535 -> Going Receiver! 21:10:51.672 -> Packet (4): 27 21:10:51.672 -> Packetloss detected! 21:10:52.151 -> Packet (4): 28 21:10:52.665 -> Packet (4): 29 21:10:53.182 -> Packet (4): 30 21:10:53.664 -> Packet (4): 31 21:10:54.665 -> Packet (4): 33 21:10:54.699 -> Packetloss detected! 21:10:55.178 -> Packet (4): 34 21:10:56.177 -> Packet (4): 36 21:10:56.177 -> Packetloss detected! 21:10:56.660 -> Packet (4): 37 21:10:57.180 -> Packet (4): 38 21:10:57.666 -> Packet (4): 39 21:10:58.151 -> Packet (4): 40 21:10:58.669 -> Packet (4): 41 21:10:59.186 -> Packet (4): 42 21:10:59.668 -> Packet (4): 43 21:11:00.191 -> Packet (4): 44 21:11:00.666 -> Packet (4): 45 21:11:01.182 -> Packet (4): 46 21:11:01.664 -> Packet (4): 47 21:11:02.183 -> Packet (4): 48 21:11:02.664 -> Packet (4): 49 21:11:03.182 -> Packet (4): 50 21:11:03.664 -> Packet (4): 51
I think the interoperability problem was caused by timing differences caused by the plainRFM69 library using AutoMode (see datasheet section 4.4) to sequence the transmit process rather than manually changing the mode etc.
AutoMode option looks promising and warrants further investigation but interoperability will be an issue.
void plainRFM69::sendPacket(void* buffer, uint8_t len){ /* Just like with Receive mode, the automode is used. First, Rx mode is disabled by going into standby. Then the automode is set to start transmitting when FIFO level is above the thresshold, it stops transmitting after PacketSent is asserted. This results in a minimal Tx time and packetSent can be detected when automode is left again. */ this->setMode(RFM69_MODE_SEQUENCER_ON | RFM69_MODE_STANDBY); this->setAutoMode(RFM69_AUTOMODE_ENTER_RISING_FIFOLEVEL, RFM69_AUTOMODE_EXIT_RISING_PACKETSENT, RFM69_AUTOMODE_INTERMEDIATEMODE_TRANSMITTER); // perhaps RFM69_AUTOMODE_ENTER_RISING_FIFONOTEMPTY is faster? // set it into automode for transmitting // p22 - Turn on the high power boost registers in transmitting mode. if (this->tx_power_boosted) { this->setPa13dBm1(true); this->setPa13dBm2(true); } // write the fifo. this->state = RFM69_PLAIN_STATE_SENDING; // set the state to sending. this->writeFIFO(buffer, len); }
Looks like I need to investigate some of the other Arduino library options.
Pingback: iwanders/plainRFM69 revisited | devMobile's blog