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.

6
  • 1
    I would expect RH_ASK radio(1024, 0, 10, 0, false); to interfere with Serial, but I have no way of testing that. But, you don't appear to be using Serial, but then you indicate it's not the complete code. But then... I don't know why .setModeTx() would have the effect it's having. In any case, it's not clear to me that 0 can mean "unused" there and is maybe something to fix regardless.
    – timemage
    Jan 3 at 0:15
  • @timemage you're on to something. I had earlier dismissed interaction with Serial, which as you surmise I am using. Still looking… Jan 3 at 3:15
  • I'm not even sure I'd go that far. I've seen some libraries use -1 as an indicator of "not used" or "not applicable". What I did was look the RadioHead library to see how it would interpret it. For the benefit of anyone that thinks this is an "answer" I feel the need to spell this out: No it's not. At it's an observation of something that should probably be fixed regardless and may or may not have any bearing at all on the actual problem as stated in the question. I'm not going to write it an an answer because there's no particularly good reason to think it is the answer or even an answer.
    – timemage
    Jan 3 at 15:41
  • If you find out that it helps and why, you can write your own answer, because you'll actually know that it's the answer and ideally why.
    – timemage
    Jan 3 at 15:42
  • I could imagine two thngs that might happen (or not ;-)). First there is a code line somewhere in your code that configures the ASk driver for RX. Second the first two sends fill the write buffer and the third send does not work, because there is not enough place in the buffer to add the new data. The setModeTx might clean the buffer or simply needs some time the ASK driver needs to send the remaining data. Isn't there a waitPacketSent() method to wait before new data can be written? Perhaps worth I try??? Jan 7 at 17:28

1 Answer 1

0

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.