20
\$\begingroup\$

I have a cheap wireless pool thermometer (AcuRite 617 1) and I'd like to intercept the temperature data at the receiver and use it with a computerized data-logging system.

Conveniently, inside the receiver is a small break-out board that is connected to the antenna and has digital "V", "G", "D", and "SH" pins:

RF211 board

Here is a segment of captured data from the "D" pin during a transmission (these happen once per minute). Before this segment, there is what appears to be much-higher-rate data, but I believe that might be noise -- this is the beginning of the 1.36kHz / 680Hz data.

captured signal from "D" pin

I've googled a bit and can't find an encoding that looks quite like this, but if I were to guess what's going on, here's what I'm thinking:

  • the initial 4 cycles of 680 Hz are to synchronize the clocks but contain no data
  • the 13 cycles of 1.36 kHz (2x the initial rate) that follow appear to have one of two forms: they either drop low before the midpoint of the cycle or after it -- i'd assume one form is a logical one and the other is a zero.
  • after that, there appears to be a weird gap, but if you discount the part of the low that is part of the preceding "1", then the remaining gap is 735 µs, which is a (phase-correct!) continuation of the 680 Hz preamble.

Am I looking at this correctly? Is there a name for this encoding?

Some further notes on the break-out board:

  • the board is marked "RF211" and looks remarkably consistent with the MICRF211 "general purpose, 3V QwikRadio Receiver that operates at 433.92MHz"3
  • the MICRF211 data sheet has the following figure (with very little explanation), which looks tantalizingly like what i'm seeing except for the double-data-rate square wave as compared to my capture:
    data profile

2016-02-14 Update: I've revisited this project and appear to be getting a clean 64-bit stream between a 4-cycle preamble and a 1-cycle "postamble", after which the display board shuts down the RF module by pulling ^SH low (top line):

64 bits of data

According to Micrel's "33/66% PWM" scheme (which appears nowhere else on Google), that's

-_-_-_-_0000011110011000110000000000000000000000100011101000010010101010-_

So now I have to start manipulating the temperature to decode the bits. Here ("x") are the bits that seem to change without any apparent change in the display:

0000011110011000110000000000000000000000100011101000010010101010
------------------------------------------------x----xxxx----xxx

I assume these are either least-significant bits or battery-level (which is only shown as "Low" when it drops significantly).

2016-02-15 Update: I'm taking the show on the road to give the new "Reverse Engineering" stackexchange a crack at determining meaning: https://reverseengineering.stackexchange.com/questions/12048/what-is-contained-in-this-transmission-rf-pool-temperature-sensor-base-unit-re

\$\endgroup\$
  • \$\begingroup\$ BTW - Reading the user comments at the Home Depot web site for the AcuRite 617 unit does not give one a good feeling at the overall durability of this product. Actually it sounds like it is an outrite pos with respect to not leaking into the sender unit. \$\endgroup\$ – Michael Karas Dec 29 '14 at 6:11
  • \$\begingroup\$ oh, it is. mine has already leaked. but i've dried it out and disassembled it and have some degree of confidence that i can improve the sealing with some hot glue and/or silicone. the battery compartment appears to be designed well with a decent o-ring; it's the rest of the unit that's so bad, and that never needs to be opened again... \$\endgroup\$ – Rob Starling Dec 29 '14 at 6:31
  • \$\begingroup\$ Skimmed other answers but this is from appearance. Initial square wave is to get data slicer synchronised at 50% level. Pause before data is to ensure the "1" level has decayed. Then 2:1mk-spc = 1 say and 1:2 = 0. With hysteresis 50:50 does not toggle between prior 1 or 0 BUT should not happen during data stream. The preceding is "bad" as it does not attempt to preserve the mean 50:50 ratio and your dc level will drift if data has more 1's or 0's but if your DC level time constant is long compared to a msg length it doesn't matter. You then resynch again with 1:1 preamble for next msg. \$\endgroup\$ – Russell McMahon Dec 31 '14 at 0:34
  • \$\begingroup\$ A decoder could be an opamp with one input fed signal by RC filter to set mean DC level and other fed signal via a resistor plus +ve hysteresis feedback (maybe about 4R) so that a 1:1 signal does not flip output but a 2:1 or 1:2 does. A bit of playing with hysteresis % and DC RC time constant and it should work well enough. \$\endgroup\$ – Russell McMahon Dec 31 '14 at 0:37
  • \$\begingroup\$ A few granules of Calcium Carbide or metallic Calcium at bottom of housing should keep it dry and slightly pressurised :-). No, I've never tried that. \$\endgroup\$ – Russell McMahon Dec 31 '14 at 0:39
8
\$\begingroup\$

Micrel refers to it as a 33/66% PWM scheme. It appears to be a fairly simple, but ad-hoc protocol.

PWM stands for pulse-width modulation. There is a Wikipedia page that goes into more detail, but in short, PWM is where you keep a fixed period, so here it is the time from rising edge to the next rising edge, but you vary the percentage of time spent in the high state by changing when the falling edge occurs. For this one, you can see that it is 33% high for a '1' and 66% high for a '0'.

The initial series of pulses are equal high and low times. This is usually done to allow the receiver to sync up before actual data is received.

See http://www.micrel.com/_PDF/App-Notes/an-22.pdf for some more details on what they expect for the module.

A typical way to be able to receive this sort of encoding would be to input this into a timer input capture pin of a microcontroller. Or, you can simply connect to a general input and have it sample at 4-5x the PWM period. The algorithm for decoding is not too hard from there.

Alternatively, as suggested by markt, you can work your way back to the temperature sensor itself. But, if it is an analog output signal, you will have to convert it to digital yourself and may have slightly different numbers in your logging from the original output.

\$\endgroup\$
3
\$\begingroup\$

People of my acquaintance usually call that encoding technique "PWM", which I suppose is a reasonable description.

My first thought looking at your data stream, and assuming that you're correctly guessing the polarity of the bits, is that it's a 12-bit ADC reading, LSB first, with a leading '1' as a start bit. I'm going with LSB first because the start of what is presumably the next reading shows a single-bit variation and it's unlikely that an ADC reading of (pool) temperature would vary by a 2nd or 3rd MSB in that short a time frame.

I'd dig a little further into the system, back to whatever is generating the data (as opposed to transmitting it), see if you can identify the temperature sensor, and look for some correlation between the transmitted data and the temperature.

\$\endgroup\$
  • \$\begingroup\$ It seems to me that @RobStarling should already be able to know what the transmitted temperature is by virtue of looking at the receiver device and seeing what is being displayed. \$\endgroup\$ – Michael Karas Dec 29 '14 at 4:43
  • 1
    \$\begingroup\$ true, but these things can be tricksy. e.g. the display is switchable between ˚F/˚C, so the transmission could be in absolute ˚C or ˚F or either relative to some weird offset or to some arbitrary fixed-point precision. also, there are 3 switchable station IDs ("A", "B", "C") and even though it says changing ID might help reception, i have a hunch it's just an identification prefix on the messages -- i'll switch it and see what changes on the data. \$\endgroup\$ – Rob Starling Dec 29 '14 at 5:38
  • \$\begingroup\$ @RobStarling - You could open up the sender unit to see if they are using a simple type of temperature sensor such as an LM75 or one of the other common I2C types. If so it is likely that the data being sent over the link as the temperature value simply follows that read from the temp sensor device. On the other hand if the sender uses an analog sensor such as a diode or BJT transistor as a sensor it would be more difficult to infer actual data sent. \$\endgroup\$ – Michael Karas Dec 29 '14 at 6:02
  • \$\begingroup\$ I suspect that the best chance you have to figure out the data content is to place the sender into a controlled situation where you can change the temperature slowly so that you can see reading change a bit at a time. You will have the receiver display to tell you what is actually being expected. \$\endgroup\$ – Michael Karas Dec 29 '14 at 6:04
  • \$\begingroup\$ @MichaelKaras - it's hard to see what the sensor is -- it's on a tiny board wedged in a little holder at the tip, potted in a dab of thermal paste to couple it to the outside wall under the water. \$\endgroup\$ – Rob Starling Dec 29 '14 at 6:07
2
\$\begingroup\$

Almost all RF transmission schemes are going to need to have several characteristics in their data encoding protocols. These would include:

  1. Consistent format preamble used to lock a receiver on frequency
  2. A sync pulse indicator to mark start if frame indication
  3. A method to encode data 1's and 0's with some sort of encoded clocking for data recovery.

The odd ball pulse that you noted is most surely the sync pulse indicator.

The data encoding appears to follow what I have seen referred to as pulse width encoding. This is a fairly common technique where the one transition direction follows a constant frequency leading to constant width bit cell times. During the bit cell the active pulse is presented as 25% of the bit cell time or 75% of the bit cell time. This scheme is not a pulse to pulse DC balanced encoding scheme like Manchester encoding offers. It is a common technique with pulse width encoding to provide DC balance within the message protocol by sending extra bits to create an overall balance in the whole message. In its simplest form the data is sent twice with the second copy logically inverted.

In your example it is odd to see pulse width modulated data occurring before the sync pulse. However it is still a feasible scheme if the data decoding algorithm is designed the accept the received data with the sync in this position. It is possible that the unit is sending one type of data before the sync and one after. The split could be between sensor address / temp data OR true data / inverted data.

Edit:

It is interesting to note that it almost looks like the transmitter unit is using a different software algorithm for formulating the positive pulse widths for data cells before the sync pattern than for the pulse width at and after the sync pattern. This implies that there may be a separate hunk of software generating the earlier pattern than that for the subsequent part of the pattern. This difference of pattern could imply that the data source in each case required different handling in terms of how it was accessed bit by bit. The difference seen in the timing diagram could simply be an instruction timing or two difference in the pattern generation loops.

\$\endgroup\$
  • \$\begingroup\$ i wonder if this is: preamble (square) + start bit (1) + unique id (12 bit) + sync pulse + data. (oh, like you suggested... e.g. maybe it expects the µC to get ready for data during the sync pulse) \$\endgroup\$ – Rob Starling Dec 29 '14 at 5:47
2
\$\begingroup\$

I've started decoding the Acurite 617 and here are my initial observations. I can tell you that the last byte is some sort of "check" byte and the next to the last three bytes contain the temperature. These byte are also sent with using the 7th bit to make even parity and only the lower nibble of each byte is used. I've written an Arduino program to capture the data and have seen the following messages/temperature.

40 ce c0 00 00 0c 03 be
(00 0C 03) => 0C3 => 67F

40 ce c0 00 00 0c 84 39
(00 0C 04) => 0C4 => 67F

40 ce c0 00 00 0c 05 b8
(00 0C 05) => 0C5 => 67F

Other data/temps I have seen are:

E2 => 73F

F5 => 76F

108 => 80F (81 00 88)

109 => 80F

Using this you should be able to do the "straight line" (assumption) conversion.

Since I do not have a good scope (and the fact that the data is sent once a minute) I am not sure about my timing. I see the sync HI and LO as being 720 usec and the data bits being 240 and 480 usec.

Hopefully I will have more info later. I have a bunch of these. As soon as they start to leak I remove them from the pool and dry them out for use around the house. The later 617 modules (with the screw off bottom and O-ring) seem to last longer.


I did some more decoding. The last byte (check byte) makes the XOR of all eight bytes equal to 0FFH. For example for "40 CE C0 00 00 8D 0C 30", 40 xor CE xor C0 xor 00 xor 00 xor 8D xor 0C xor 30 is equal to 0FF.

Also, I took the temperature down to 34F and the count was 10 decimal (i,e., 00 00 0A) and at 80F the count was 264 decimal (i.e., 81 00 88 or 108H).

From this I am using Temp(F) = 0.1811 * Count + 32.1889. I might get a bigger span to get some better data if I see any error.

Looking at Rob Starling's string on 2016-02-14:

00000111/10011000/11000000/00000000/00000000/10001110/10000100/10101010 07 98 C0 00 00 8E 84 AA

XOR = FF

Count = 0E4 or 228

Temp = 73.5F

\$\endgroup\$
  • \$\begingroup\$ Thanks guys!!! i'm pretty sure that the number isn't just a "count", but rather the exact temperature in 0.1C -- that is, the "math" for decoding 228 is that it's 22.8C. For Farenheit, do the usual F=C*9/5+32. \$\endgroup\$ – Rob Starling Sep 26 '16 at 1:45
  • \$\begingroup\$ summarized over on the Reverse Engineering SE: reverseengineering.stackexchange.com/a/13593/15076 \$\endgroup\$ – Rob Starling Sep 26 '16 at 2:06
  • 1
    \$\begingroup\$ Rob, you are correct - I should of seen that. F = 0.18 * Count + 32.0. Good thing you pointed that out, I was soon going to put it in real hot water to get a better "m" and "x" using a wider span. \$\endgroup\$ – Ken S Sep 27 '16 at 14:41
  • \$\begingroup\$ You still might want to do the calibration to get more accurate numbers, as several reviewers complained about the display being off by a couple of degrees. That, however, might also just reflect the fact that it's only ≈4" below the surface and most old-school pool thermometers are on a long string. \$\endgroup\$ – Rob Starling Sep 27 '16 at 14:48
  • \$\begingroup\$ Update: i wrote an Arduino library -- github.com/robstarling/ArduRight -- let me know if it works for you! It has an example and everything. Referencing the picture in this post, you'll need to solder wires to the "SH", "D", and "G" pins. To run the example sketch, connect those wires to pins 2, 7, and GND, respectively. \$\endgroup\$ – Rob Starling Apr 20 '17 at 8:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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