433 MHZ temperature sensor decoding

Hey,

I have yet another 433 MHz temperature sensor to decode. The model is the remote sensor that belongs to a TCM 214698 station that only displays temperature.
The code I use to read the signals from the receiver goes like this (mostly nicked from somewhere else on this forum):

#define PBSIZE 256
#define MINBITPULSE 1500

void setup() {

  Serial.begin(115200);
  Serial.println();
  Serial.println("Start!");

  pinMode(2, INPUT);
  attachInterrupt(0, rx433Handler, CHANGE);
}

volatile unsigned int pulsbuf[PBSIZE]; // ring buffer storing LOW pulse lengths
volatile unsigned int hibuf[PBSIZE]; // ring buffer storing HIGH pulse lengths
volatile byte pbread,pbwrite;  // read and write index into ring buffer

void rx433Handler()
{
  static long rx433LineUp, rx433LineDown;
  long LowVal, HighVal;
  int rx433State = digitalRead(2); // current pin state
  if (rx433State) // pin is now HIGH
  {
    rx433LineUp=micros(); // line went HIGH after being LOW at this time
    LowVal=rx433LineUp - rx433LineDown; // calculate the LOW pulse time
    if (LowVal > MINBITPULSE){
      pulsbuf[pbwrite]=LowVal; // store the LOW pulse length
      pbwrite++;  // advance write pointer in ringbuffer
      if (pbwrite>=PBSIZE) pbwrite=0; // ring buffer is at its end
    }
  }
  else 
  {
    rx433LineDown=micros(); // line went LOW after being HIGH
    HighVal=rx433LineDown - rx433LineUp; // calculate the HIGH pulse time
    if (HighVal>31999) HighVal=31999; // we will store this as unsigned int
    hibuf[pbwrite]=HighVal; // store the HIGH pulse length
  }
}


void loop() {
  // put your main code here, to run repeatedly:
  long lowtime, hitime;
  if (pbread!=pbwrite) // check for data in ring buffer
  {
    lowtime=pulsbuf[pbread]; // read data from ring buffer
    hitime=hibuf[pbread];
    Serial.print(pbread);Serial.print("\t");
    Serial.print(lowtime);Serial.print("\t");Serial.println(hitime);
    
    cli(); // Interrupts off while changing the read pointer for the ringbuffer
    pbread++;
    if (pbread>=PBSIZE) pbread=0;
    sei(); // Interrupts on again

  }  
}

The signal I receive beyond noise has 49 pairs of HI and LO pulses each either ca 2000us or ca 4000us and ends with a long LO.
The output shows
pulse #, LO time, HI time (in us)

Start!
0	13420	560
1	13036	172
2	1836	20
3	14712	464
4	13324	396
5	1976	16
6	2408	84
7	3576	372
8	2256	16
9	3828	2036
10	3864	2020
11	3884	1984
12	1992	1980
13	2008	3856
14	2008	3864
15	3920	3848
16	3908	1952
17	3920	1948
18	3908	1952
19	2012	1952
20	3924	3844
21	3920	1948
22	3920	1940
23	2012	1952
24	3924	3844
25	3916	1944
26	3928	1944
27	3924	1936
28	2048	1928
29	2100	3792
30	3984	3772
31	3984	1880
32	2080	1888
33	2080	3780
34	2064	3792
35	2072	3796
36	3972	3788
37	3968	1900
38	3960	1896
39	2056	1912
40	2052	3804
41	2040	3820
42	2048	3820
43	3952	3808
44	2044	1924
45	2048	3812
46	2044	3828
47	3948	3812
48	2028	1928
49	2044	3828
50	2044	3816
51	2040	3828
52	3944	3820
53	3928	1928
54	2036	1932
55	2028	3832
56	3940	3832
57	2032	1924
58	22280	316
59	2116	52
60	3816	2376
61	3844	2020
62	3880	2004
63	1972	1988
64	2004	3872
65	2012	3852
66	3904	3860
67	3920	1952
68	3908	1952
69	3920	1952
70	2000	1952
71	3924	3856
72	3920	1936
73	3904	1952
74	2012	1956
75	3912	3856
76	3924	1948
77	3916	1944
78	3940	1936
79	2052	1912
80	2096	3804
81	3988	3764
82	3976	1884
83	2080	1888
84	2064	3792
85	2072	3796
86	2068	3788
87	3956	3804
88	3964	1904
89	3948	1908
90	2056	1912
91	2036	3820
92	2052	3820
93	2052	3808
94	3940	3820
95	2048	1920
96	2036	3824
97	2048	3824
98	3948	3812
99	2044	1924
100	2044	3816
101	2028	3828
102	2040	3832
103	3928	3832
104	3940	1932
105	2036	1920
106	2036	3832
107	3940	3824
108	2020	1932
109	22212	320
110	4884	24
111	3840	2048
112	3860	2008
113	3884	1992
114	1980	1980
115	2012	3868
116	2000	3860
117	3920	3856
118	3920	1940
119	3912	1948
120	3924	1948
121	2016	1948
122	3920	3844
123	3908	1952
124	3916	1952
125	2012	1940
126	3908	3860
127	3928	1948
128	3920	1940
129	3944	1932
130	2044	1920
131	2100	3800
132	3992	3760
133	3972	1884
134	2080	1888
135	2076	3792
136	2072	3784
137	2060	3800
138	3968	3800
139	3964	1892
140	3944	1912
141	2056	1916
142	2040	3816
143	2052	3820
144	2048	3808
145	3940	3824
146	2048	1920
147	2036	3820
148	2044	3828
149	3936	3824
150	2040	1928
151	2044	3816
152	2040	3832
153	2044	3816
154	3932	3828
155	3944	1928
156	2036	1916
157	2036	3836
158	3940	3824
159	2024	1932
160	21464	316
161	3816	2096
162	3860	2012
163	3880	1996
164	1980	1980
165	2008	3872
166	2012	3848
167	3924	3856
168	3924	1936
169	3908	1948
170	3920	1952
171	2000	1952
172	3924	3856
173	3908	1948
174	3920	1952
175	2012	1940
176	3912	3856
177	3924	1948
178	3916	1944
179	3940	1936
180	2040	1924
181	2100	3800
182	3992	3764
183	3972	1880
184	2084	1888
185	2064	3792
186	2072	3796
187	2072	3788
188	3956	3800
189	3968	1904
190	3948	1908
191	2052	1912
192	2040	3820
193	2052	3820
194	2052	3804
195	3940	3824
196	2048	1920
197	2032	3824
198	2044	3828
199	3948	3812
200	2040	1928
201	2040	3820
202	2032	3828
203	2040	3828
204	3944	3820
205	3932	1928
206	2036	1928
207	2024	3836
208	3940	3836
209	2036	1920
210	15944	316
211	1896	40

From my initial research into this subject, this pattern doesn't match with BP-M style encoding b/c in BP-M short HI and LO pulses come in pairs. In my pattern there's plenty of short HI pulses framed by two long LOs or short LO pulses framed by two long HIs.

So, what code is this and how can I decode it?

Thx

You need lots of examples of messages before you can start decoding.

Overview of the process at Reverse Engineer Wireless Temperature / Humidity / Rain Sensors — Part 1 « RAYSHOBBY.NET

I have seen ray's page, thx. His sensor transmits in OOK for which you find plenty of examples for decoding software. My sensor signal is different. I first need to find out how to turn it into ones and zeros.

Is what you describe NOT OOK? If so, what are these "pulses"? Please elaborate.

If you could post a trace by Audacity, that would help.

I posted the trace of the pulses in my first post.
You find there a table that has the number of the pulse in the first column, the duration of the low phase in microseconds in the second column and the duration of the high phase in the third column.

The signature from the sensor apparently starts with pulse 9: 4ms low, followed by 2ms high.
Periods of low and high signal with durations of 2 or 4ms continue until pulse 57.
Pulse 58 seems to be a long stop bit of 22ms.

The next transmission starts at pulse 60 until the stop bit in pulse 109. Next burst from 111 to 160. Last burst in this recording from 161 to 210.

This is not regular OOK, b/c there the high periods would have similar lengths. In my signal highs are either 2ms or 4ms long, as are lows. I can't interpret the signal as B-PM, either.

How can I turn the highs and lows into 1s and 0s?

I posted the trace of the pulses in my first post.

Not successfully. It would make great sense to post a picture like this:

 int rx433State = digitalRead(2); // current pin state
  if (rx433State) // pin is now HIGH
  {
    rx433LineUp=micros(); // line went HIGH after being LOW at this time

When using digitalRead() to distinguish between high and low states of an input, you are assuming OOK (On Off Keying).

The problem you appear to face is the typical one of converting the timing between highs and lows into 1s and 0s. In doing that, it is much easier to look at a picture like the above than a table of numbers.

__=__=__=_=_==_==__==__=__=__=_=__==__=__=_=__==__=_=__==__=__=_=_==_==_==_==_==__==__=__=_=_==_==_==__==_=_==_==__==_=_==__==_=_==_==__==__=__=_=

_  2ms low
__ 4ms low
=  2ms high
== 4ms high

That is a good start, but not like any encoding I've seen before.

Following the outline of the Ray's Hobby blog article, I would collect several messages for different known temperatures, for example -1, 0, 1, 2, 4, ... degrees C and look to see what changes in the message. That will give strong hints on how to interpret 1s and 0s.

ok, here goes

In the attached file you find the development of temperature reading (times 10), the battery status and the level codes received.

The pattern I can observe is

__=__=__=_=_==_==_aaaaaaaa=__=_=_==__==__=_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb=_==_==__==__=__=_cccccccc==__==__=_=_==_ddddddddddddddddddddddddddddddd=

battery OK
a: _==__=__
c: =_==_==_

battery Low 
a: ==_==__=
c: _=__=_=_

a and c seem to depend on the battery status, although one reading is not consistent with this. I tend to consider this a reading error on my behalf, though.

b (30 symbols) and d (31 symbols) go like this

temp	bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb	ddddddddddddddddddddddddddddddd
-80	_=__=_=__==__=__=__=__=__=__=_	==_==__==_=_==_==_==_==_==_==_=
-80	_=__=_=__==__=__=__=__=__=__=_	==_==__==_=_==_==_==_==_==_==_=
-80	_=__=_=__==__=__=__=__=__=__=_	==_==__==_=_==_==_==_==_==_==_=
-80	_=__=_=__==__=__=__=__=__=__=_	==_==__==_=_==_==_==_==_==_==_=
-60	_=__=__=_=_==__==__=__=__=__=_	==_==_==__==__=_=_==_==_==_==_=
-40	_=__=__=_=__==__=__=__=__=__=_	==_==_==__==_=_==_==_==_==_==_=
-20	_=__=__=__=_=__==__=__=__=__=_	==_==_==_==__==_=_==_==_==_==_=
0	_=__=__=__=__=__=__=__=__=_=_=	==_==_==_==_==_==_==_==_==__==_
0	_=__=__=__=__=_=__==_=__==_=_=	==_==_==_==_==__==_=__==_=__==_
29	_=__=__=__=_=__==_=__==__=_=_=	==_==_==_==__==_=__==_=_==__==_
39	_=__=__=__=_=_==_==__==__=_=_=	==_==_==_==__==__=__=_=_==__==_
50	_=__=__=_=__==_=__==__=__=__=_	==_==_==__==_=__==_=_==_==_==_=
63	_=__=__=_=_==__==__=__=_=_==_=	==_==_==__==__=_=_==_==__==__=_
63	_=__=__=_=_==__==__=__=_=_==_=	==_==_==__==__=_=_==_==__==__=_
65	_=__=__=_=_==__==__=_=__==_=_=	==_==_==__==__=_=_==__==_=__==_
67	_=__=__=_=_==__==__=_=_==_==_=	==_==_==__==__=_=_==__==__=__=_
72	_=__=__=_=_==_==__==__=_=__==_	==_==_==__==__=__=_=_==__==_=_=
74	_=__=__=_=_==_==__==_=__==__=_	==_==_==__==__=__=_=__==_=_==_=
79	_=__=__=_=_==_==_==__==__=_=_=	==_==_==__==__=__=__=_=_==__==_
88	_=__=_=__==__=__=_=__==__=__=_	==_==__==_=_==_==__==_=_==_==_=
91	_=__=_=__==__=_=__==__=__=_=_=	==_==__==_=_==__==_=_==_==__==_
94	_=__=_=__==__=_=__==_=__==__=_	==_==__==_=_==__==_=__==_=_==_=
117	_=_=__==__=__=_=__==_=_==_==_=	==__==_=_==_==__==_=__==__=__=_
122	_=_=__==__=_=__==__=__=_=__==_	==__==_=_==__==_=_==_==__==_=_=
123	_=_=__==__=_=__==__=__=_=_==_=	==__==_=_==__==_=_==_==__==__=_
131	_=_=__==__=_=_==__==__=__=_=_=	==__==_=_==__==__=_=_==_==__==_
134	_=_=__==__=_=_==__==_=__==__=_	==__==_=_==__==__=_=__==_=_==_=
137	_=_=__==__=_=_==__==_=_==_==_=	==__==_=_==__==__=_=__==__=__=_
139	_=_=__==__=_=_==_==__==__=_=_=	==__==_=_==__==__=__=_=_==__==_
141	_=_=__==_=__==__=__=__=__=_=_=	==__==_=__==_=_==_==_==_==__==_
144	_=_=__==_=__==__=__=_=__==__=_	==__==_=__==_=_==_==__==_=_==_=
146	_=_=__==_=__==__=__=_=_==__==_	==__==_=__==_=_==_==__==__=_=_=
150	_=_=__==_=__==_=__==__=__=__=_	==__==_=__==_=__==_=_==_==_==_=
152	_=_=__==_=__==_=__==__=_=__==_	==__==_=__==_=__==_=_==__==_=_=
156	_=_=__==_=__==_=__==_=_==__==_	==__==_=__==_=__==_=__==__=_=_=
158	_=_=__==_=__==_=_==__==__=__=_	==__==_=__==_=__==__=_=_==_==_=
159	_=_=__==_=__==_=_==__==__=_=_=	==__==_=__==_=__==__=_=_==__==_
160	_=_=__==_=_==__==__=__=__=__=_	==__==_=__==__=_=_==_==_==_==_=
166	_=_=__==_=_==__==__=_=_==__==_	==__==_=__==__=_=_==__==__=_=_=
172	_=_=__==_=_==_==__==__=_=__==_	==__==_=__==__=__=_=_==__==_=_=
178	_=_=__==_=_==_==_==__==__=__=_	==__==_=__==__=__=__=_=_==_==_=
185	_=_=_==__==__=__=__=_=__==_=_=	==__==__=_=_==_==_==__==_=__==_
191	_=_=_==__==__=_=__==__=__=_=_=	==__==__=_=_==__==_=_==_==__==_
197	_=_=_==__==__=_=__==_=_==_==_=	==__==__=_=_==__==_=__==__=__=_
198	_=_=_==__==__=_=_==__==__=_=_=	==__==__=_=_==__==__=_=_==__==_
199	_=_=_==__==__=_=_==__==__=_=_=	==__==__=_=_==__==__=_=_==__==_
200	=__==__=__=__=__=__=__=__=__=_	_==_=_==_==_==_==_==_==_==_==_=
200	=__==__=__=__=__=__=__=__=__=_	_==_=_==_==_==_==_==_==_==_==_=
200	=__==__=__=__=__=__=__=__=__=_	_==_=_==_==_==_==_==_==_==_==_=
201	=__==__=__=__=__=__=__=__=_=_=	_==_=_==_==_==_==_==_==_==__==_
202	=__==__=__=__=__=__=__=_=__==_	_==_=_==_==_==_==_==_==__==_=_=
203	=__==__=__=__=__=__=__=_=_==_=	_==_=_==_==_==_==_==_==__==__=_
207	=__==__=__=__=__=__=_=_==_==_=	_==_=_==_==_==_==_==__==__=__=_
210	=__==__=__=__=_=__==__=__=__=_	_==_=_==_==_==__==_=_==_==_==_=
223	=__==__=__=_=__==__=__=_=_==_=	_==_=_==_==__==_=_==_==__==__=_
223	=__==__=__=_=__==__=__=_=_==_=	_==_=_==_==__==_=_==_==__==__=_
231	=__==__=__=_=_==__==__=__=_=_=	_==_=_==_==__==__=_=_==_==__==_
232	=__==__=__=_=_==__==__=_=__==_	_==_=_==_==__==__=_=_==__==_=_=
234	=__==__=__=_=_==__==_=__==__=_	_==_=_==_==__==__=_=__==_=_==_=
236	=__==__=__=_=_==__==_=_==__==_	_==_=_==_==__==__=_=__==__=_=_=
240	=__==__=_=__==__=__=__=__=__=_	_==_=_==__==_=_==_==_==_==_==_=
243	=__==__=_=__==__=__=__=_=_==_=	_==_=_==__==_=_==_==_==__==__=_
249	=__==__=_=__==__=_=__==__=_=_=	_==_=_==__==_=_==__==_=_==__==_
254	=__==__=_=__==_=__==_=__==__=_	_==_=_==__==_=__==_=__==_=_==_=
260	=__==__=_=_==__==__=__=__=__=_	_==_=_==__==__=_=_==_==_==_==_=
265	=__==__=_=_==__==__=_=__==_=_=	_==_=_==__==__=_=_==__==_=__==_
266	=__==__=_=_==__==__=_=_==__==_	_==_=_==__==__=_=_==__==__=_=_=
282	=__==_=__==__=__=__=__=_=__==_	_==_=__==_=_==_==_==_==__==_=_=
292	=__==_=__==__=_=__==__=_=__==_	_==_=__==_=_==__==_=_==__==_=_=
299	=__==_=__==__=_=_==__==__=_=_=	_==_=__==_=_==__==__=_=_==__==_
305	=_==__==__=__=__=__=_=__==_=_=	_==__=_=_==_==_==_==__==_=__==_
307	=_==__==__=__=__=__=_=_==_==_=	_==__=_=_==_==_==_==__==__=__=_

You may note that at the two temperature readings of 0C (shown as 0) I read two different patterns. From the full data attached you can see that the difference in the two readings is the patterns in a and c. This is where I am unsure whether my battery status reading is correct.

Negative temperatures are displayed by the weather station without decimals.

level_codes.txt (10.8 KB)

My assumption in the post earlier was wrong. I took more readings around zero degrees where the battery starts to get weak. The codes in a and c do not change upon battery status, but on sign of the temperature.
so

a: ==_==__=
c: _=__=_=_

when the temperature is negative and 

a: _==__=__
c: =_==_==_

when the temperature is positive

Looks like a Manchester code, possibly a differential Manchester encoding to me. There is either a transition in the middle of a bit interval, or not.

AFAIU both manchester codings require level transitions to happen at the borders of bit intervals. Effectively, this means that I can have only = and = code elements.
I can't find a way, however, to cut my code such that I don't get lots of == and __ also in the middle of the signal. Apparently these type of signals are only used to terminate the signal in manchester code.

Effectively, this means that I can have only = and = code elements.

Not true with differential Manchester encoding, which is exactly why I suggested it. There seems to be quite a bit of confusion on the web about Manchester vs. differential Manchester, though.

This post explains the difference between the two a bit more clearly, and shows how you get double length intervals: http://www.pcbheaven.com/wikipages/manchester_coding/

Help me.

The explanation you linked says "In the middle of each clock pulse, a transition occurs, regardless of the bit that was sent or is about to be sent".

This means, however, that a pattern like
===
cannot occur: first two bits == say no transition, then comes the required transition, next two bits __ say no transition, again comes a required transition, third pair =_ means there is a transition, so far so good.
But the next bit would require a transition to = as it would be in the middle of the clock pulse. Only there is no transition in violation of the code.

If the data bit boundaries were shifted by one code bit we'd ignore the first bit =, look at the next two =_ and find a transition, but after that the level has to change as per the code definition. But it doesn't so my example doesn't match the description of differential Manchester code.

My readings are full with such sequences.

Yep, as I said, there is a lot of confusion and poor explanation on the web.

For "middle of the clock pulse" in that link read "rising edge".

So one way to transmit differential Manchester is as follows:

(1) make a transition in the output line at the rising edge of the clock pulse.
(2) at the falling edge of the clock pulse, sample the data input line.
(3) if the data bit is a "1" make a transition on the output line.
(4) if the data bit is a "0" DO NOT make a transition on the output line.

For the other way to transmit differential Manchester, swap "0" and "1" in (3) and (4). All output bits are just inverted.

Reverse this process to decode.

Example from one of your data posts. I started with the first T=200 line, after converting _ to 0 and = to 1, and ignored the first 001001001

200 0 00100100101011011001100100100101011001100101001100100100100100100100100101011011001100100101011011011001100101011001101011011011011011011011011011

The picture below shows two ways to decode the "signal", depending on whether a transmitter output transition on the falling clock edge happens if the transmitter data input line is a 0 or a 1.

CK = reconstructed clock signal.

[in line display of incorrect diagram removed]

Of course, the more interesting part of the message would be where the bits are changing as the temp rises from 200 to 201, etc.

There is a surprising dearth of code examples on the web for this process, so if you get that far, your efforts would be welcomed. On the other hand, this is the only temperature sensor I've encountered that uses this method of encoding.

thanks for efforts, I appreciate that.

I still struggle, b/c you say "(1) make a transition in the output line at the rising edge of the clock pulse."

You can see in your sketch that example code does not make a transition at every rising edge of the clock pulse. So that condition needs to go in the present coding.

Oops, you are right.

After some thought, it is clear that this signal can't be either Manchester or differential Manchester. Neither of those encoding schemes will allow three consecutive bits to be the same, i.t. the sequence "000".

If you have decoded the pulse timing correctly, this is some other type of encoding.

My code does not have three consecutive bits that are the same and still violates the manchester conditions as demonstrated by yourself above.

OK, so here is the code:

The TCM transmitter labelled C-846 sends High (=) and Low (_) signals of 2 and 4 ms durations. Assuming a 2ms bit clock period, a long pulse transmits two code bits and a short pulse covers one.

Every 30 or so seconds the transmitter sends bursts of 146 code bits followed by a long Low stop bit.
The first code bit is always Low and the last bit before the long stop Low is always High.

In between there are 144 code bits comprising 48 data bits of 3 code bits each. For each data bit state (0 or 1) there are two code triplets:

code   data
_=_      0
==_      0
=_=      1
=__      1

Other possible triplets are not found in the code.

The 48 data bits come in two groups of 24, the second group are a bit inverted copy of the first 24.

                        ________________________
00CC11SBIIIIITTTOOOODDDD00CC11SBIIIIITTTOOOODDDD

CC        Channel
S         Sign of temperature
B         Battery low warning
IIII(I)   Transmitter ID
(T)TTT    Tens of temperature
OOOO      Ones of temperature
DDDD      Decimal of temperature

The transmitter allows for a channel number to be selected. In order for the new channel number to be sent the transmitter needs to be reset. Upon each reset the transmitter sends a different, apparently randomly chosen four or five-bit ID.
ATM I can't tell how to assign the one bit I put in brackets. In my data samples I find two different codes for that bit, but both mean 0.

The temperature is BCD encoded in degree Celsius, three or four bits for the tens digit, four bits for the ones and decimal digits.

For decoding it is sufficient to look at the middle bit of the code triplets to derive the data bit, = means 0 and _ means 1.

Currently I am looking at ways for efficient signal recording and decoding as reception quality is an issue. If I just censor pulses that are too short, I am losing quite a few transmissions. So if anyone can point me to cunning schemes for signal recording and clock recovery of a noisy signal I'd be grateful.

I have a similar signal type from my DG-R8X sensor (for TH8868). The sync signal is 6 longer hi and 6 longer low, followed by 41 bits (high and low).

Do you know how I can read the bits with Arduino considering this strange sync signal? All libraries I found seems to work with a sync signal that is low or high for a greater period of time.

Regards,
Adi