Debugging failure to detect OOK signals

For more remote OOK temperature sensors, occasionally transmissions arrive malformed, and can therefore not be detected as such or properly decoded. The Oregon Scientific THN128 protocol V1 sensor perfoms two transmissions spaced some 200ms apart. When the first transmission is received properly, it is easy to record the raw RSSI and OOK data from a RFM69 during the transmission of the repeated signal. I have recorded two of the transmissions where the first part was succesful, and the second part contained an error.

The errors are in the marked area’s. It appears that such a bit-error is a noise spike that only takes one sample in both cases. Although it is a bit early to proof, it is very likely that failures to detect weak OOK signals are often short time-scale (high frequency) noise on the OOK signal.

Noise

Recording a histogram of all ON and OFF durations of the second transmission, including the preceeding gap after the end of the first transmission gives better insight in the high frequency noise.
rfm69_ook_oscv1_pulse_dur_histo_4000bps_n10

The OFF (ZERO) peak at 1080µs belongs to the received OOK signal. The large distribution at the left hand side of the graph is noise. The red part indicate signal ON (ONE), and tend to be short between 40 and 100µs. For the OFF state the noise tail is a bit longer. It is clear that most noise energy is below the 200µs tiem-scale. Most remote control and sensor OOK pulse durations are above the 300µs time scale, so it should be possible to filter out the high frequency ON/OFF flips to clean-up the signal.

Filtering

So could the reception be improved by getting rid of this type of short spikes on the intended signal? I have been thinking about this. When not using an interupt driven approach to detect ON to OFF and OFF to ON transitions, but by just polling the DATA (DIO2) pin of the RFM69, I can easily implement a kind of moving average filter for the two-valued data. Sampling at for exmaple 40µs and averaging the last 5 samples removes spikes of one and two sample duration. I tested this and it improves the reception of weak signals way better then I expected. I am now collecting more data on the improved performance.

RFM69 Bandwidth investigations part 1

Usually there are several 433MHz devices around the house. Remote controls and various sensors. Normally the exact operating frequency is notknown. A lot of work described on the internet is done with wide-band receivers. The following graphs show the relation between the receiver bandwidth and the bandwidth of the received signal.

Frequency sweeps of continuous OOK transmission with different receiver bandwidth settings. The graphs show the variance on the sampled RSSI signal.

A rule of thumb is that the sweep is performed with the RFM69 receiver OOK-bandwidth being equal to the frequency step size of the sweep. This gives about 3 datapoints with elevated variance, providing good view to estimate the the peak frequency (433.81MHz for the KAKU remote)First a coarse sweep with steps of 100kHz can be perfoemd, followed by a narrow sweep with step size of 5 or 10kHz.

RFM69 AFC failure with OOK

I observed two issues with automatic frequency correction (AFC) and OOK reception:

  • The AFC value does not get cleared by switching to sleep mode and back to receive
  • AFC in continuous OOK mode can yield extreme values, setting the receiver totally off-band.


AFC should not be used in continuous OOK receive mode. I am not sure whether it is designed to work in this mode (I doubt it). When signal is detected by a high RSSI, an controlled AFC may very well be to late for the OOK pulse. But even not enabling AFC in OOK imposses a risk.

When switching between FSK-packet mode for communication with the sensor network, and receiving external OOK signals, the AFC does not get resetted to zero. It can only be done by a HW-reset or power cycle, Or by explicitely clearing the AFC Value:

template< typename SPI >
void RF69A<SPI>::setThd (uint8_t thd) {
    this->writeReg(REG_AFCFEI, (1<<1));
    this->setMode(MODE_SLEEP);
    this->writeReg(REG_OOKFIX, thd);
    chThdSleepMilliseconds(400);
    this->setMode(MODE_RECEIVE);
}