My wrap-up and findings.
Yes, it is possible to use RadioLib LoRaWAN 1.10/1.04 for OTAA and uplinks on CubeCell boards v1/v2.
RadioLib could be made working on 6 out of 6 CubeCells (4 x v1 and 2 x v2).
CUBECELL CLOCK DRIFT
HTCC AB01 has two clock sources: a HFCLK (driving the 48MHz) and LFCLK (32768kHz).
The HFCLK clock can be off by 2% or 20ppt, while the LFCLK clock is doing ok (< 1ppt off).
Drift values vary per board:
2x v1 (2021): 11ms, 12ms
2x v1 (2022): 16ms, 18ms
2x v2 (2025): 6ms, 10ms
(all at 20˚C)
EFFECT ON TIMING FUNCTIONS & QUICK HACK
Heltec firmware uses the accurate LFCLK for millis() and Timer_t events, while using the inferior HFCLK for delay(), delayMicroseconds() and micros().
RadioLib can apply a correction to the 4 timing functions it uses, by enabling and setting RADIOLIB_CLOCK_DRIFT_MS (BuildOpt.h).
Or (when using PlatformIO) add it to your project’s platformio.ini:
build_flags =
-D RADIOLIB_CLOCK_DRIFT_MS=xx
Because CubeCell millis() is accurate enough, it should be excluded from correction.
A quick hack for this in AppHAL.cpp (PlatformIO: in appropriate local .pio/libdeps entry):
RadioLibTime_t inline ArduinoHal::millis() {
// #if !defined(RADIOLIB_CLOCK_DRIFT_MS)
return(::millis());
// #else
// return (RadioLibTime_t)((uint64_t)::millis() * 1000ULL / (1000ULL + (uint64_t)RADIOLIB_CLOCK_DRIFT_MS));
// #endif
}
BTW, be sure to use RL ^7.6.0 which contains an important fix (uint64_t) for drift correction calculations. In earlier versions, uplinks would stop after approximately 1h:12m.
DEEP SLEEP
Code below shows the use of an accurate timer in combination with deep sleep lowPowerHandler() to replace delay() in RadioLib’s LoRaWAN_Starter.ino example.
void wakeup(void);
TimerEvent_t interval;
void setup() {
.
. (initialise radio, join network,...)
.
TimerInit(&interval, wakeup);
}
void wakeup() {
}
void loop() {
TimerSetValue(&interval, uplinkIntervalSeconds * 1000);
TimerStart(&interval);
.
. (gather sensor inputs, sending uplink,...)
.
// Wait until next uplink - observing legal & TTN FUP constraints
Serial.flush();
uint32_t t0 = micros();
while (micros() - t0 < 125) {
;
}
lowPowerHandler();
// delay(uplinkIntervalSeconds * 1000UL); // delay needs milli-seconds
}
TEMPERATURE EFFECT
Just a heads up: when CubeCells are used in environments with fluctuating temperatures, a fixed drift setting may not suffice.
See results of a quick freezer test (n = 1).
Haven’t done same for temperatures above 20oC.