My aquarium’s data radioed through the shelf

Started 23Dec2017. Updated 2Dec2020

This page is in group Technology (plus My XMOS pages) and Aquarium pages. The My WiFi101 library port or an Ethernet based web server was not implemented following this work. I also did not use the Bluetooth Low Energy (BLE) suggestion as discussed in Me relying on relaying BLE? I went for the simpler (?) packet radio solution discussed here.

For the TIOBE index 016:[10]: “xC programming”.


Standard disclaimer, this is just for fun. No money, gifts, ads etc. Also, my non-association with any of the companies mentioned here. Other than some times exchanging technical matters, mostly in open forums. I am basically positive until I may have experienced the opposite; this is reflected in all my blog notes.

My aquarium’s data radioed through the shelf

Fig.1 Sum of suggestions II (Press for PDF)

Many of the components and the rationale for the architecture have been discussed in the already mentioned Me relying on relaying BLE? note. I’ll call it the “BLE note” below.

Why packet radio instead of BLE?

BLE seems to be more complex. But my disclaimer is that I will not have acquired hands-on with BLE and radio, so this is based on the research in the BLE note. And that research is based on reading what other people write. I must admit that I lean a lot on the Adafruit’s considerations since they have both BLE and radio boards with full documentation, also with how to get them on-air.

I want everything just connected from power-up. Adafruit has caught my mood (or admittedly even formed my mood) with this statement from [1]:

Also, these packet radios are simpler than WiFi or BLE, you dont have to associate, pair, scan, or worry about connections. All you do is send data whenever you like, and any other modules tuned to that same frequency (and, with the same encryption key) will receive. The receiver can then send a reply back. The modules do packetization, error correction and can also auto-retransmit so its not like you have worry about everything but less power is wasted on maintaining a link or pairing.

And I am almost certain that I will get the needed code into the rather packed Aquarium Controller Box ACBox, to export all the data so that the larger Relay Box RBox can build HTML with dynamic data, and also do logging. In other words, a web server there.

Radio alternatives are many

There would be breakout boards and chips.

Breakout boards

Adafruit has at least the below. I am including what I found interesting

  • Boards based on RFM69HCW in either 433 MHz or 868/915MHz using the Semtech SX1231 (or SX1231H) packet radio
    • I went for a 433 MHz SPI version of this, the Adafruit 3071, see [3]
    • The smaller board that’s on it is called RFM69HCW. This Programmable 315-915Mhz RF Transceiver Module is made by Hoperf Electronics [11] (called “Hope” in the RadioHead texts) However, the Hoperf board uses this Semtech chip:
    • The RFM69HCW contains a Semtech SX1231 Integrated RF tranceiver, see [4] (also for SX1231H, which I think is the one that’s used). As told by Adafruit (but I haven’t seen it explained). Reading Hoperf’s [11] there’s not a word there about “1231” or “Semtech”, but chapter “1.1. Simplified Block Diagram” shows in a rather crude bitmap Semtech’s SX1231 high resolution block diagram from [4]. But observe:
    • Studying more I see that Hoperf’s [11] and Semtech’s [4] are almost equal. Searching another round I find a proof that it is Hoperf who uses the Semtech chips [12] (long discussion thread at LowPowerLab Forum). There I also found this: Semtech (in the USA) informs that Hoperf is one of their partners [13]; But I don’t know if the Hoperf’s chip I have is the SX1231 of SX1231H. But by the naming RFM69HCW I infer that it’s SX1231H. Also, that’s what Adarfruit says
    • In the RFM69 library (“RFM69-LPL”) (below) there is a comment around the definition of REG_TESTPA1 (in file RFMRegisters.h) that says “// only present on RFM69HW/SX1231H“. I guess this is the only place I have seen these two mentioned together
    • On all five of the Adafruit 3071 breakout boards I received the Semtech chip on RFM69HCW is printed with “H RF69 1714 W4C405”. This is different from on the pictures on the Adafruit page. Hoperf have printed their own label on the Semtech chip [12].
  • Boards based on RFM9x (like RFM96) LoRa in either 433 MHz or 868/915MHz using the Semtech SX1276
    • The Semtech page for the SX1236, see [5]
  • Also boards with processor (ARM ATSAMD21G18) in the Feather format

Sparkfun also works in this area. Here is their version of the Adafruit 3071 (more or less): The RFM69HCW is seen at [9], and their breakout board at [10]. (Aside: The also had a XMOS XS1-L1-64 Development Board, but last time I checked (Jan2019) it had been reired).

MikroElectronika [6] has a lot of sub 1 GHz breakout boards. As of Dec2017 I find all the below. It’s OK to see these listed like this, even if it comes close to name-dropping since I haven’t studied any of them. But this list tells me that there certainly are competitors:

  • IQRF click with DCTR-72DAT by IQRF
  • ccRF 3 click with CC1120 by Texas Instruments,
  • SPIRIT click carries the SP1ML 8 by ST
  • EnOcean click carries a TCM 310 by enocean
  • LoRa click carries Microchip’s RN2483 by Microchip
  • ccRF2 click carries CC1120 by Texas Instruments
  • tRF click with Telit LE70-868 by Telit
  • M-BUS RF click is a mikroBUS™ add-on board with a Telit ME70-169 RF wireless module by Telit


Nordic has chips, nRF905 [7] and nRF9E5, [8] much harder for me to use since I don’t want to build and solder boards.

Fig.1 board 69. SX1231.a Transceiver Radio Breakout

This chapter also covers 69. SX1231.b and 69. SX1231.x in the figure. This is the Adafruit RFM69HCW (with Semtech SX1231) Transceiver Radio Breakout – 433 MHz – RadioFruit (3071). The description and just about everything about it is covered in [3]. Plus [1] and [2].

The 88 pages long datasheet of the Semtech RFM69 (like RFM69HCW) (packet radio) chip SX1231 datasheet [4] was last updated in June 2013. This could either mean that it’s been slowly outpaced or that it’s become stable.

By comparison the 132 pages long datasheet of the Semtech RFM9x (like RFM96) (LoRa) chip SX1276 [5] was last updated in August 2016. I am writing this in Dec. 2017.

But Adafruit writes that:

These radio modules come in four variants (two modulation types and two frequencies). The RFM69’s are easiest to work with, and are well known and understood. The LoRa radios are exciting and more powerful but also more expensive [1]

To me that looked rather reassuring, so I decided to go for the RFM69. But I needed to know this when I ordered (from two Adafruit pages):

All radios are sold individually and can only talk to radios of the same part number. E.g. RFM69 900 MHz can only talk to RFM69 900 MHz, LoRa 433 MHz can only talk to LoRa 433, etc. [1]

You will, of course, need at least two paired radios to do any testing! The radios must be matched in frequency (e.g. 900 MHz & 900 MHz are ok, 900 MHz & 433 MHz are not). They also must use the same encoding schemes, you cannot have a 900 MHz RFM69 packet radio talk to a 900 MHz RFM9x LoRa radio [2]

My setup

Fig.2 Overview of Adafruit RFM69HCW Transceiver Radio Breakout RadioFruit connected to Feather M0 basic proto (press for more pixels)

I use the same Adafruit Feather board “box” as shown for the first time in Fig.2 of My Piggyback WiFi1500 sliceCARD. But this time I need two to tango. However, I decided to reuse the 1-13 connection to the right on the box and therefore had to add a cross coupling board. The RFM69HCW has only nine pins, but Adafruit had either been lucky or probably smart so that I could happily plug it into pins 1-9 of the 1-13 pins row. For the SPI pins SCK, MOSI and MISO that’s so much easier, since all example code for ARDUINO_SAMD_FEATHER_M0 (define in Adafruit code) use it rather hard coded. Also, redefining the other pins (see next chapter: RFM69_CS, RFM69_INT and RFM69_RST) has been made easy to do in the example code.

My RFM69HCW startKIT SPIe setup

Tall version

This builds on the piggyback board referenced to above.

Fig.5 – Adafruit RFM69HCW transceiver radio breakout connected to a piggyback PCIe board (press for more pixels)

See discussed more detali in My Piggyback WiFi1500 sliceCARD (chapter “Adafruit ATWINC1500 WiFi Breakout piggybacked on a PCIe breakout card for XMOS startKIT” and Update Mar2018 there).

So now I can run the Radio on three boards (below). The board seen in the below chapter is not seen there.

Wide version

Update 25Sep2018: Since I needed to have two PCIe-connected radio boards, one for the aquarium controller box startKIT, and one for the startKIT breadboard that I have here on my desk to test the SW before I update the aquarium box, I made this other have a wide or horisontal layout. In the box I have more space on the sides than above the board, so now I even may also use the tall piggyback boards. On the below figure there is a tall piggyback seen on the left, but on the right there is the board with less cross-coupling area. This is the board I’ll use in the aquarium box. (By the way. My soldering doesn’t look nice at all these days. In order to get the lead-free solder I need to have 480 degC, 400 degC does not seem to be enough. Then the PVC some times burns and leaves black spots. I guess these are electrically conductive carbon, so I have to be careful.)

Fig.6 – Adafruit RFM69HCW transceiver radio breakout connected to a piggyback PCIe board (press for more pixels)


Avoid 433.92 MHz

As seen from the “Frequency crash with my car key” (below) it signalled at 433.92. So does our light remote control (Nexa NEYCT-705 bought at Clas Ohlson). So, it’s probably a good idea to avoid that frequency.

Frequencies allowed in Norway

In Norwegian:

Lovlige frekvenser i Norge (FOR-2012-01-19-77)

This chapter is in Norwegian since it’s about allowed frequencies in Norway.

Den innebygde frekvenssyntetisatoren i RFM69 er programmerbar i disse tre båndene: 290-340, 431-510 og 862-1020 MHz i trinn på FSTEP = FXOSC / 2exp19 = 32.0 MHz / 2exp19 = 61.03515625 Hz.

I henhold til Forskrift om generelle tillatelser til bruk av frekvenser (fribruksforskriften) [17] ser jeg dette:

  • FOR-2012-01-19-77
    • Kap. III. Utstyr for kortdistansekommunikasjon
      • § 8.Diverse utstyr for kortdistansekommunikasjon
        • (11) Frekvensbåndet 433,050–434,790 MHz tillates brukt med en maksimal tillatt utstrålt effekt på 10 mW e.r.p. Maksimal sendetid er mindre enn 10 prosent.

Altså er 434 MHz (i båndet 433,050 – 434,790 MHz) lovlig, under de betingelsene som er gitt ovenfor. Båndet er altså på 1,74 MHz. Obs at frekvensen 433,92 er eksakt midt i båndet.

Radioamatører har også det nærliggende 70 cm båndet 432-438 MHz tilgjengelig [23].

Frequency crash with my car key

In the SW debug phase (after having completed the port of the library and moved its use from an example application to inside my aquarium’s code proper) I left my board transmitting, I don’t know how much, but probably much, since, when I was trying to open the car the keys did not work. None of them. So I went up to my office and unplugged the RFM69 board that had been set to 433919921 Hz. See FSTEP above. Without the board sending my car keys worked fine.

Fig.4 – 433.92 MHz car key

I opened the car key and it said on the inside that the frequency was 433.92 MHz. This is exactly in the middle of the legal frequency band in Norway (as seen above: 433.05 – 434.79 MHz). This also was exactly the frequency I had used, ie. as close as the 32 bits float mathematics had taken me, ie. the 433919921 Hz. I found an FCC document on a similar key (here) that stated an accuracy of ± 81 ppm. However my key (here) did not show any specifics on accuracy. But if I assume 433.92 MHz ± 81 ppm then that would be 433.884852 .. 433.955147. So I should find another frequency that’s outside that band. I will try 433.88 – 1/10th of the band (1.74/10) = 433.706 (closest is 433.705993 because of integer * FSTEP). I will check with the neighbours around here, too.

I tested more. If I send once per second with full effect from the RFM69 (some +20 dBm and 100 mW, it even makes my speakers tick) then neither 433.92 MHz nor 433.706 MHz will disturb the car key. There is 10 metres down to the car, only wooden buildings here. However, at 5 times per second then 433.92 MHz silents the car key (meaning both open and close works) while 433.706 MHz makes it slow, meaning that I may have to press the car key more than once. I am not impressed by the car key system.

When I tried to send from the smart key, I could not see any package being picked up by the RFM69. I guess both the modulation type and baud rate, plus the fact that I had configured the RFM69 to read packets only, altogether would filter the key’s 433.92 MHz transmission. But it was configured to pick up packets with CRC16 errors. I also tried to send at full effect on 433.92  MHz while an RFM69 receiver listeneded on 433.706 MHz 15 cm away with nothing being seen by the receiver. It is much smarter than the car key system.

I have changed to 433.706 MHz and all I need is minumim power level (5 dBm on RFM69HW). And for the aquarium I would probably end up sending once every minute.

I have queried about this at the ALL ABOUT CIRCUITS forum Automotive Electronics, see Radio board interferes with my car key system (Aug2018, my first post there). The hypothesis there seems to be that my key must send a unique on/off pattern (one for lock and one for unlock), typically modulated at 10 MHz with a bit rate of 40 kbps, repeated every 20 ms for 500 ms before the receiver in the car will accept it. There probably is no packetisation or cryptographic key, just that repeated stream of bits. So when I sent ever 200 ms I destroyed that data stream. This seems very plausible. Thanks to sghioto and DickCappels! See Wikipedia article about OOK system and ON-OFF Keying at On-off keying and Application note 4439 from Maxim integrated at I’m OOK. You’re OOK?

Using the RFM69 Radio

Basic RX & TX example

Top level fies:

  • RadioHead69_RawDemo_RX.ino and _TX
  • RadioHead69_AddrDemo_RX.ino and _TX

Doing it

Running two instances of the Arduino IDE

This is not a chapter. It’s just a header to make it visible in the Table of contents. The text is below at Running two instances of the Arduino IDE

The RadioHead was super to test the Adafruit board with the Arduino IDE. However, not to port so XMOS/xC! I ended up porting the RFM69 library (“RFM69-LPL”), more below.

After having done all the soldering (see top right of Fig. 2, press for more pixels) I must get the code and start doing something even more fun than soldering:

  1. Downloading from Adafruit GitHub gives examples ok, but outdated ReadHead. The above points is from going through Adafruit’s teaching pages starting at [2]. I downloaded the RadioHead library via it (Adafruit has a GitHub repo that’s pointed to). I got the Adafruit [examples] ok. But I got an outdated version of RadioHeadObserve that any git-repository with RadioHead out there probably will not have the latest version, according to its author Mike McCauley [20]. On 16Jan2018 the RadioHead version I got via Adafruit was 1.74 from 8Mar2017. So, when you have got the examples to work with the Adafruit examples, download the latest and greatest from [14]. It’s 1.82 7Jan2018, just about a week old. When I diffed the directories and looked at RH_RF69.cpp in particular I saw that they have added using the INT interrupt from the RF69 board, first diff with spiUsingInterrupt(interruptNumber); I moved the old directory away from the Arduino [libaries] directory and moved the new in. I then copied the [exampes/feather/] back again and recompiled. It worked. So I believe Adafruit has a job to do to get this right, not to leave us with old RadioHead libraries. I have given them feedback by pressing on “Feedback? Corrections?” about this
  2. The text in [2] says that ..”and check that the RadioHead folder contains files like RH_RFM69.cpp and RH_RFM69.h”.
    • It doesn’t. The closest is “RH_RF69.cpp” and “RH_RF69.h”. This is so for the GitHub site and the direct download link. I’ll proceed anyhow.
    • However, I can find one mention of RH_RFM69 in [14] from 2014: (sic) “Fixed problem with ambigiguous print call in RH_RFM69 when compiling for Codec2.”
    • However, [14] also explains that  “The following Drivers are provided:” and in the list: “RH_RF69 Works with Hope-RF RF69B based radio modules, such as the RFM69 module, (…) and compatible chips and modules such as RFM69W, RFM69HW, RFM69CW, RFM69HCW (Semtech SX1231, SX1231H). … Supports GFSK, FSK.”
      I added the RH_RF69 class reference document as ref [15] here
  3. In the RadioHead69_RawDemo_TX.ino and RadioHead69_RawDemo_RX.ino examples I changed to RF69_FREQ 434.0. Then I changed in the defined ARDUINO_SAMD_FEATHER_M0 region RFM69_CS 10, RFM69_INT 6 and RFM69_RST 5, as shown in Fig.2.
  4. Running two instances of the Arduino IDE
    On the Mac I was not able to start another instance of the Arduino IDE, so I duplicated the Arduino IDE app and called it Arduino2. This about how the Java JVM runs applications on a Mac. There are lots of discussion threads on how to do this this out there, and here is one that works by starting a macOS Terminal window that starts another instance of the same Arduino executable [16]. I was able to start the Arduino2 (and also [16]) and compile and download on a other USB port. The Arduino2 way has two equal Arduino icons when they run, the via-Terminal has one Arduino and one Terminal icon, rather confusing. So I guess I’ll stick to Arduino2. The individual Serial Monitor’s logs look like this when the RX board is being connected. Colour by me:

    Sending Hello World #414
    No reply, is another RFM69 listening?
    Sending Hello World #415
    Got a reply: And hello back to you
  5. Received [17]: Hello World #415
    RSSI: -29
    Sent a reply
  6. But I coud hear the RF radio tick on my speakers when they are silent! The one without the amplifier ticks like a clock, the other like a clock inside a pillow. The connection is not shielded or twisted. It doesn’t help with a 1 nF capacitor on the noisiest, and shortening the terminals doesn’t mute it 100%. Disconnecting it and shortening the terminal removed the noise, so it’s not picked up by the coil. Also, removing the power cable to the amplifier speaker unit removes the noise. Unplugging the 3.5 mm jack for the sound cable from the Mac did not help. (I don’t use Bluetooth there either..) I’ll look into turning down the power of the senders or using shielded cable:
    • I looked at the code, and I could actually set the power! Here’s the code (layout shorter lines here).
      // If you are using a high power RF69 eg RFM69HW, you *must*
      // set a Tx power with the ishighpowermodule flag set like this:


       original value that ticked my speakers!

      rf69.setTxPower(14, true);

       // range from 14-20 for power, (no: -2 to 20)
                                 // 2nd arg must be true for 69HCW

      Going all the way to 14 dB helped, but my speaker seems to be rather sensitive, so I can still hear a faint tick. So I need to try shielding

    • Shielded cable also helped a little. The shield goes to the black terminal, the wire to the red terminal. Now the ticking of a silent speaker is at almost not irritable level 🙁
    • However I see in the setTxPower document that “For RF69HW (ishighpowermodule = true), valid values are from -2 to +20“. At 6 dB I can still almost hear the ticking, at -2 dB it’s gone to my ears! Great! Now I have more to tune with! Received levels at -2 dB sent is about -30 dB when they sit beside each other on my desk (from the rf69.lastRssi(); call)
  7. Since the Arduino IDE burns the code into FLASH I can move the units and run them from a 5V power alone and it will start with the proper code. It certainly works all over the house (with 14-20 dB sent)

Feedback for Adafruit 2Jan2018

Summary, already discussed above:

  1. [2] says that “and check that the RadioHead folder contains files
  2. In the RadioHead69_RawDemo_TX.ino and RadioHead69_RawDemo_RX.ino it should be noted that the dB range is -2 to 20 as the first param of rf69.setTxPower. If Adafruit has some reason to stop at 14 dB then it should be noted that -2 is the lowest, and it works!
  3. I cannot see that the documentation treats the fact that Hoperf Electronics (“Hope”) has relabeled the Semtech SX1231 to something “H RF69 1714 W4C405” (but of Adafruit and other pictures, that would have different labels, plus documentation I haven’t been able to figure out the nomenclature)
  4. Starting another instance of the Arduino IDE and then of the Serial Monitor needs an explanation that on Macs it’s done differently from Windows. See [16] and the comments above

Psst. Reach me here

Addressed RX and TX Demo

Top level files: RadioHead69_AddrDemo_RX.ino and _TX

This worked out of the box, once I had changed the parameters above. The only things I thought could be different are the file names and address defines. They confused me. Everything is nicely commented in the code, but naming doesn’t follow in my opinion:

In RadioHead69_AddrDemo_RX.ino // RadioHead69_AddrDemo_RX_Server.ino instead?

// who am i? (server address)
#define MY_ADDRESS 1

In RadioHead69_AddrDemo_TX.ino // RadioHead69_AddrDemo_TX_This_Client.ino instead?

// Where to send packets to!
#define DEST_ADDRESS 1

// change addresses for each client board, any number :)
#define MY_ADDRESS 2


I also added RADIO_ since there are so many “server” and “client” and “address” in a large code base (especially xC), and a global search should preferably yield unique results.

Observation of the RF69 original code

To no surprise this code is built like much of the rest of the Arduino examples (or real code?) I guess. I have covered my points pretty much at My WiFi101 library port (chapters about concurrency in particular).

But I’m stunned by how easy it is to download and get the examples to run. It even takes care of the changes I need to do, and has me move those files into separate directories. This is the first IDE I have seen this on.

Porting to XMOS / xC

  • I have queried about this at the radiohead-arduino discussion group [20]. It includes a response from RadioHead’s author Mike McCauley. The list below has been updated after the response I got there
  • I also queried at xCore Exchange [21] – where as the first response george actually lined up how to set up the compiler so that it can be made to treat a .ino file as a c++ file. Have a look there!
  • I ended up porting the RFM69 library. See below


Here is how I would attack this. (I already ported some Adafruit code into xC for the aquarium controller (like the SSD1306 display driver and graphics) by rewriting some C++ code to xC and connect it to an XMOS I2C library [lib_i2c] / [module_i2c_master]). In this case I’d probably want to keep the Cpp files. xTIMEcomposer compiles and builds xC, C and Cpp. However, I would need to address at least these points:

  1. Mike McCauley wrote that “If you can send your compatible changes in the form of a patch set, including documentation, we will consider rolling your changes in to the baseline code rather than you maintaining your own git repository. IMHO multiple git repositories makes for much confusion for end-users”. So..
    • ..I will need to modify RadioHead.h, and add code that accurately detects my
      compilation environment with something like:

      #define RH_PLATFORM_XMOS 16
  2. The top level would be some xC task that’s started in a par statement in main.xc. It needs chan or interface communication with the other concurrent tasks, like the aquarium controller’s tasks. xC has this in the language. Then I will need to define the services I need in the chan or interface declarations
  3. Functionality that in xC most probably will be done as a parameter to a select. I guess that wrapping up the standard interrupt function in the Arduino code into proper select may be a challenge. Both of these are standard functionality for xC, but ending up with a shared library may be difficult
    • I need to port the Arduino attachInterrupt() function to set interrupts that are triggered when digital inputs change state. This is an essential behaviour in many RH drivers
    • RH_ASK.cpp requires a timer that will trigger an interrupt at tightly controlled intervals. I will need to find a way to do that too
  4. The arduino millis() will need to be ported. The easiest port ever!
  5. All the RadioHead SPI bus calls will have to be done with the XMOS SPI library [lib_spi] (search for [lib_spi] here). The calls will use the interface needed by spi_master, carried down from main. The parameter to the SPI lib is an array of interface so I could have more than one client in the future. Like adding a WiFi web server. These code changes need to be done in RHHardwareSPI.cpp
  6. The other digital IOs would be just mapped to xC pins and wrapped up. The Arduino digital I/O library only consist of DigitalWrite, DigitalRead and PinMode. See [18]
  7. xC data types are limited. All the cores are 32 bit. However, the C types long long int, float and double are unsupported. See xC is C plus x [2]. One example, I guess that the params for setFrequency would have to become signed binary fraction built with signed int (32 bit). There is a library called [sc_lib_fixed_point] with a mathf8_24.h file that probably is a good start. But that’s 8.24 fixed point numbers, and 433.0 MHz isn’t in the range.. [19]. I would like 16.16 I guess. I’ll have to look into this closer
  8. I will have a challenge with file names. The RadioHead library has standard C and Cpp files, in addition to the top level .ino file. It also has individual .pde files (old convention for the newer .ino according to Mike McCauley). I don’t think that the xTIMEcomposer wants to compile .ino and .pde files. I have queried at this at [21]. Both must contain setup() and loop() methods which are called by a higher level like this:
        while (1)

    I cant’ wait to try to port it to xC!

xCore Exchange forum

  1. Starting research on this, here is a query on xCore Exchange that I posted: Preprocessor not resolving parameter at usage of a port macro
  2. Another one, about how to get the xC part of the compiler to pick up Cpp, see combining xC and C++ (search for “Sat Jan 20, 2018”)
  3. There is a rather frightening post by finiksa in 2014 about porting Arduino libraries, see C++ and XMOS. I don’t know about when to proceed and when to give up..
  4. How to call C++ functions from xC? might help?

radiohead-arduino forum

  1. Same as [20]Getting the RF69 to run on XMOS processor
  2. YIELD; in RadioHead code
  3. Feedback
  4. Excluding a file altogether

RFM69 library

For xC/XMOS I ended up porting the RFM69 (“RFM69-LPL”) library by LowPowerLabs [22]! However, at the final end I also borrowed from RadioHead.

30Nov2020: I see that I have not documented the problem with CRC16 and CRC32 and the Birthday Paradox here. Here’s a link to a description I did in another blog note: My leaf of comfort: SW / HW that cannot turn against us? I have also not placed the code anywhere for download. It is now at The code (download).

30Aug2018: The RFM69 xCore library is becoming rather stable. I was able to cram it into the aquarium controller box (that has 64 KB of memory, I now even have a couple KB left). I will come back to this.

21May2018: The present version of the code is here (13.6 MB, try “Yucca11” if you are asked). It’s placed there because of an issue I posted on xCoreExchange: Including interface functions in local .xc file or library. It contains two built version and the modified version of the XMOS [lib_spi] library.

  1. One version is compiled with RADIO_IF_FULL 1 (“Radio interface full”). The two interface functions setFrequencyHz and getFrequencyHz are never used (code size is 16460). In this case the linker should not have included them
  2. The other version  RADIO_IF_FULL 0. It simply removes the code for those two functions. It is smaller (code size 16124) as expected. This is the code size I would have expected above as well

IRQ handling of RX

In the following I am discussing the SW as a generic piece of code, have it mostly RadioHead or mostly RFM69 or even perhaps mostly my own code. It’s now a mix. I will publish it all (and if you’d like to see it now just mail me and I’ll make a zip and place it here for you. It’s just that it’s kind of not 100% finished. In other words, the code that you can find in the previous chapter is quite outdated I see. The status now is that my aquarium has been sending data over the FRM69HCW controlled from the startKIT and the mentioned code there, every 4th second for 21 days, with no hiccups. It just sends data out, no listening. And then the client just listens. It runs on the more advanced xCORE-200 eXplorerKIT.

Fig.7 IRQ handling (Press for PDF)

Let’s follow the workflow in Fig. 7. When the radio has received a message it sets the interrupt request line (IRQ) high active. This is pin IRQ/G0 of the radio. An xC task IRQ_detect_task waits for the pin to go high, and when it does it signals this to the radio client RFM_client, which sends a message with reply (as an RPC call) to the RFM69_driver (this the the SW mentioned above). This talks with the radio over the SPI bus task spi_master_2 and empties the FIFO, which makes the radio take the IRQ line low inactive again. All the SW tasks above (the grey containers) are real tasks each containing a while(1) and a selective choice (select and case) that would wait for pin changes, timeouts, channel inputs or interface calls. Whether they occupy a logical thread for themselves is up to their [[combinable]] or [[distributable]] properties. See xC is C plus x or xC code examples for more.

Adafruit feeback on the RFM68HCW

In [2] I have sent the following feedback to Adafruit on 20Mar2018:

The text “RST – this is the Reset pin for the radio. It’s pulled high by default. Pull down to ground to put it into reset” works ok when the RadioHead init code is seen: RFM69_RST: HIGH, delay 10 ms, LOW, delay 10 ms.

However, the RFM69 code does not touch that pin at all.

When I did a port to the XMOS platform I also studied the SX1231H (as used on the Hoperf RFM69HCW board) data sheet where in “7.2.1. POR” it says that ” Pin 6 (Reset) should be left floating during the POR sequence”. There also is a pulse diagram.

Your description of the RST pin should perhaps be more concise and even relate to the Hoperf and Semtech “layers” – to Pin 6. Believe it or not, I struggled for days (even with a scope) and didn’t see the trees for the forest! The problem is that a faulty reset sequence leaves the SX1231H ok to communicate with, but like setMode is not possible – even if it returns device type 0x24 ok! The RadioHead library, by the way, does not have enough timeouts on waiting on bit changes from the SX1231H, so it just loops. RFM69 is better, but not complete. I will publish my code in xC later on.


“RST – this is the Reset pin for the radio. It’s pulled high by default. Pull down to ground to reset/run. After low for 10 ms the Semtech SX1231H radio chip on the Hoperf RFM69HCW piggy-board may be communicated with on the SPI bus. SW-restart would then be a pulse going high for 10 ms, then low and wait for 10 ms. Observe that a faulty reset sequence may leave SPI ok (even return device type 0x24 ok), but setting mode will fail.”

Adafruit SSD1306 on XMOS board

Moved. See xC code examples, Adafruit SSD1306 on XMOS board.

The code (download)

Download the code from My xC code downloads page part #164. Observe that there is a newer button detect code in My button presses vs bounce vs EMI notes.


I think I will continue to keep all my conclusions to the same chapter, in a previous blog note. See My single-board boards and why note, chapter Conclusion, bullet 4 there.

Radio on three boards

All the piggyback boards have been described in a previous note: My Piggyback WiFi1500 sliceCARD. This note only shows the case where I replaced thw WiFi1500 board with the RFM69HCW radio board.

See picture (below) and My RFM69HCW startKIT SPIe setup (above). RFM69HCW on XMOS eXplorerKIT, Adafruit Feather ARM M0 (Arduino Zero like) and XMOS startKIT tall version:

Fig.3 My Adafruit RFM69HCW radio board plugged onto an XMOS eXplorerKIT, Adafruit Feather ARM M0 (Arduino Zero like) and Xmos startKIT (press for more pixels)

The 433 MHz antenna is a 16.5 cm long dipole.


  1. Adafruit RFM69HCW and RFM9X LoRa Packet Radio Breakouts, see
  2. Adafruit: Using the RFM69 Radio, see
  3. Adafruit RFM69HCW Transceiver Radio Breakout – 433 MHz – RadioFruit, see
  4. [Semtech SX1231 Integrated RF Transceiver with on +17dBm 290-1000MHz, see] However I think this is used on Adafruit RFM69HCW:
    SX1231H Integrated RF Transceiver with on +20dBm 290-1000MHz
    , see
  5. Semtech SX1276 137 MHz to 1020 MHz Low Power Long Range Transceiver, see
  6. MikroElektronika, WIRELESS CONNECTIVITY. RF Sub 1GHz, see*=rf-sub-1ghz
  7. Nordic nRF905 Low power Multiband Sub 1-GHz RF Transceiver IC, see
  8. Nordic nRF9E5 Multiband Sub 1-GHz RF System-on-Chip (SoC), see
  9. SparkfunRFM69HCW Wireless Transceiver – 434MHz, see
  10. Sparkfun: SparkFun RFM69 Breakout (434MHz), see
  11. Hoperf Electronics, RFM69HCW Programmable 315-915Mhz RF Transceiver Module, see
  12. Re: RFM69 & HopeRF: clones or not?, see
  13. Semtech: Wireless RF Design Providers, see – including Hoperf Electronics
  14. RadioHead Packet Radio library for embedded microprocessors, see
  15. RadioHead RH_RF69 Class Reference, see
  16. Re: how to use many arduinos (at the same time) with just a single computer?, see Observe that the last action should be -Double-click ‘Arduino’ to run it.
  17. Forskrift om generelle tillatelser til bruk av frekvenser (fribruksforskriften), se
  18. Arduino Language Reference, Functions, see
  19. XMOS Fixed point library, see
  20. Getting the RF69 to run on XMOS processor, at the radiohead-arduino discussion group, see!topic/radiohead-arduino/P8SrTO9kGEY. Started by me
  21. Porting the Arduino RadioHead library to XMOS at the xCore Exchange, discussion group, see Started by me
  22. RFM69 library by LowPowerLab, see I have called it “RFM69-LPL” here. The code is at Copyright Felix Rusu 2016,
  23. Forskrift om tillatelse for radioamatør, se

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.