2

The code below runs on an Arduino Pro Mini (8MHz 328p) sending temperature readings using an inexpensive ASK transmitter. I use OneWire to read the DS18B20s, and RadioHead to manage the radio.

The original problem was the send() calls at the top of the loop always worked, but the send() call in the temperature-reading loop never did.

The fix was to insert a call to setModeTx() ahead of the send() call. I'm pleased it works, but it's a hollow victory because I can't figure out why it works.

OneWire uses no timers and no interrupts. I wait for the temperature conversion using _delay_ms() which is a spin delay.

I've read and re-read the OneWire and RH_ASK code and am still puzzled. Can anyone explain?

Many thanks

Here's the gist of the code…

RH_ASK radio(1024, 0, 10, 0, false);
OneWire ow(2);

void loop() { radio.send(/* build info /); // always works radio.send(/ battery health */); // always works ow.reset_search(); while (ow.search(addr)) { read_thermometer(addr);

    // the following send() works ONLY
    // when preceded by setModeTx()
    // It *never* works without it
    radio.setModeTx();
    radio.send(/* one temp reading */);
} 

}

UPDATE

@timemage was correct in that there are also calls to Serial (which resolve to HardwareSerial) interspersed. I'm no closer to solving it; however, by rearranging calls I can get the failure to happen more- or less often.

In a way this highlights the distinction between diagnosis and repair. I may in the end discover an ordering of the calls that makes the failure exceedingly rare, and in this case the problem will have been repaired; though not diagnosed.

Eric Nelson
  • 135
  • 5

1 Answers1

1

Finally had time to get back to this. I connected the data-out line from the sender to the data-in line of the receiver, and discovered it always works. So it's not any sort of collision between OneWire and RadioHead, curious or otherwise. There's something amiss with the radio link… but what?

Have a look at the following oscilloscope traces. The magenta line is the input to the transmitter. Cyan is the output from the receiver (an SYN480R if you're curious). Yellow is just there to trigger the scope (a digitalWrite() just before sending the problem message).

The packet from the transmitter begins with a series of training pulses for the receiver to establish things like gain and threshold for the demodulator. Thereafter, the data is encoded in a series of long and short pulses.

Note how the receiver (cyan line) syncs up with the training pulses, and is in lock-step with the transmitter... until ... IT GETS LOST and thinks everything is a zero for awhile. It eventually re-syncs with the transmitter, but by this point the packet is corrupt, gets rejected by the decoder, and that is why I'm losing the packet at the receiver.

enter image description here

But, one wonders, why this particular packet and not any of the others? The answer to that question is pretty much out of band for a software forum, but here goes. Let's add a trace to the scope display.

The following image includes the demodulator threshold in blue. That's an analog value that the demodulator uses to decide if it's looking at a one or a zero. For the SYN480R chip, it's the output of a low pass filter, which produces an average over the recent bits.

In this case, notice how the threshold rises during the early part of the packet, then settles down. My conjecture is there are too many ones in the packet encoding thus far (i.e. many more ones than zeroes), and this shifts the threshold high enough that the demodulator thinks everything it sees is a zero. This is confirmed in the previous image. Seeing all zeroes, the threshold settles down and the demodulator can sync up again.

Interestingly, just touching the scope probe to the threshold capacitor (to get the blue trace) disturbs the threshold enough to slow the rise and keep the packets working.

Thus, OneWire is definitely off the hook, as is any interaction with RadioHead. Moving on, I either need to make some tweaks to the RadioHead RH_ASK driver packet encoder, or change out the threshold capacitor in the receiver. That in itself is a balance, because you want it to be able to track changes in the received signal, yet not be so sensitive to packet encoding.

Hope you found this interesting. Many thanks to everyone who took a look and offered your insight.

enter image description here

Eric Nelson
  • 135
  • 5