Monday, December 17, 2012

A state machine for decoding 433 MHz signals

The figure above are a plot of the response at 433 MHz versus time. If one would decode this signal there are three different states one should consider:


  • 0 - Wait for signal. In this state we have not seen any signals yet.
  • 1 - Peak detected. We want to determine if this is a valid peak for us.
  • 2 - Delay detected. Here we want to determine if the delay is valid. It should not be to short, not to long and it could also be a "0" or a "1". If we have recieved all our expected bits we should store the packet and look for more packets.



Instead of hacking with some microcontroller, that eventually will do this decoding, I wrote up a python program to do this offline. Files from the logic analyser running at 1 MHz sampling rate are sendt through the python program. The program calls a function everytime the input changes, simulating a interrupt pin on a MCU. It also increases a count for each entry in the file, simulating a 1MHz timer.

 #return the "port" state, 1 if transmission otherwise 0  
 def readport(line):  
      return int(line.split('\t')[1])  
 # a pulse is ca 387  
 # init ca 9617  
 # 1 is ca 4600  
 # 0 is ca 2060  
 #state  
 # 0 - wait for pulse  
 # 1 - make sure the pulse is of correct length, 200 to 500  
 # 2 - measure delay, "init", "0","1" or "illegal" delay  
 # simulate interrupt due to pin state change  
 def statechange():  
      global state, counter, res, timer  
      if nextportstate == 1: # we are going from 0 -> 1  
           transition = 1  
      else:  
           transition = 2 #from 1 -> 0  
      #print debugtime, state, res  
      if state == 0 and transition == 1: # possible transmission/pulse detected  
           state = 1  
           timer = 500 #time out after 500  
           counter = 0 # reset timer  
           return  
      if state == 0 and transition == 2: # disregard  
           state = 0  
           timer = 0  
           counter = 0  
           return  
      if state == 1: #(and transition == 2):  
           if transition ==1 or counter < 200: #200  
                #print "counter " , counter  
                #print "ERROR in state==1"  
                state = 0  
                timer = 0  
                counter = 0 # reset timer  
           else: # we detected a legal pulse, determine delay length  
                # 0 < delay 1500 illegal, goto state 0  
                # 1500 < delay < 2500 legal, "0"  
                # 2500 < delay <5000 legal "1"  
                # 5000 < delay < 8000 illegal, goto state 0  
                # 9000 < delay 11000 legal, init delay  
                # 11000 < delay illegal, state 0  
                state = 2  
                timer = 10000  
                counter = 0 # reset timer  
           return  
      if state == 2: #(and transition == 1)  
           if transition == 2: #and counter < 8000:  
                print "ERROR in state==2"  
                state = 0  
                timer = 0  
                counter = 0  
           else: #legal init delay  
                #print "counter state==2 ",counter  
                if counter > 9000: # init pulse, reset data  
                     print "RES", res  
                     res = ''  
                     state = 1  
                     timer = 500  
                     counter = 0  
                elif counter > 4000: #got a "1"  
                     res = res + "1"  
                     #print res  
                     state = 1  
                     timer = 500  
                     counter = 0  
                elif counter > 1700: #got a "0"  
                     res = res + "0"  
                     #print res  
                     state = 1  
                     timer = 500  
                     counter = 0  
                else: # illegal, to short  
                     res = ""  
                     state = 0  
                     timer = 0  
                     counter = 0  
                if len(res) == 28:  
                     print "RES", res  
                     res = ''  
                     state = 0  
                     timer = 0  
                     counter = 0  
           return  
 #simulate interrupt due to timer  
 #if something times out it is du to a to long pulse or delay  
 # we will return to state==0  
 def timerint():  
      global state, counter, timer  
      state = 0  
      timer = 0  
      counter = 0  
 #fp = open("untitled.tsv", "r") #noisy data  
 fp = open("untitled13.tsv", "r") 
 data = fp.readlines()  
 fp.close()  
 # timer  
 # 0 do not time out  
 #   
 timer = 0   
 print "file read"  
 transition = 0  
 # 0 no change  
 # 1 low to high  
 # 2 high to low  
 counter = 0 # simulate an interrupt counting  
 portstate = 0  
 nextportstate = 0  
 debugtime = -1  
 res = "XXX"  
 timer = 0  
 state = 0  
 for l in data:  
      #print debugtime, state, counter,timer  
      if timer > 0:  
           if counter>= timer:  
                timerint()  
                #counter = 0  
      counter = counter + 1  
      debugtime = debugtime + 1  
      #print debugtime, portstate       
      if portstate != nextportstate:  
           callint = 1  
      else:  
           callint = 0  
      portstate = nextportstate  
      nextportstate = readport(l)  
      if callint==1:  
           statechange()  
 #res 0100010100011111100100110100  
 #    0100010100011111100100110100  

This python program works as expected, at least as long as the signal quality is good.

Making the signal weaker tend to split the peaks into several, shorter peaks, sending the routine back to state "0" without recording any transmission. It is not clear if this should be adressed.

Only a real test on an MCU could provide that answer.

Tuesday, December 11, 2012

Replacing toner in my Brother HL-2030

During the weekend the toner lamp in my laser printer turned on.

Checking the largest online suppliers here in Sweden, I noticed that they wanted almost as much for a 2500 pages toner cartridge as I had paid for the laser printer itself.

This situation reminded me somewhat of the situation with ink jet printers, they are sold cheap or given away with computer purchases. The trick being that the ink in the printer are almost empty already, forcing their unsuspecting customers to a buy expensive ink almost immediately.

Probably a wise thing to do as well, I have never considered the ink/toner level in a printer when I considered buying it.

According to Brother the HL-2030 came with a 1500 page toner supply. There exists a standard, ISO/IEC-19752 that defines a standard page. I can not complain, pressing the "Go" button on the printer three times produced a page telling me that I had printed out 1594 pages.

After some "googling" I found a company, nordicink.se, that promised to deliver a toner cartridge for approximately one-third of the price of the original toner cartridge sold by my regular office material suppliers.

I ordered the cartridge on a Saturday, the following Monday I received an SMS telling me that it were in the postal system and today, Tuesday it were in my mailbox. Not bad. The replacement instructions were understandable and the first pages printed looks completely as expected. Now all that remains to discover are when the toner lamp turn on again.

Saturday, December 8, 2012

Writing data to the Denver TRC-1480

One useful aspect of knowing the protocol used by a wireless thermometer would be to add own sensors. The Denver TRC-1480 have three available channels where one could display custom data. It is also possible to buy additional sensors from Denver.

By sending a temperature packet identical to a packet the Denver sensor could have sent one may check how sensitive the Denver decoder are to timing issues.

The test revealed that the decoder only scans for data a few seconds each time it expects a transmission, but once this were addressed the Denver decoder were not very picky about the timing and bits sent.

Sending "01111" as bits 32 - 36 always displayed the intended temperature so the purpose of these bits are somewhat unclear.

Thursday, December 6, 2012

Observing the 433MHz band

I recently "stumbled" over a 433 MHz transmitter-receiver set from iteadstudio. Hooking the receiver up to my logic analyzer I could observe three different signals that appeared regularly, 30 - 60 seconds,

Signal 1

Signal 2


Signal 3








Signal 1 were repeated 12 times in a burst and signal 3 were repeated a little bit more than 8 times, leaving the ninth repetition partially complete.

Signal 1 were easy to identify, it disappeared when I stopped my wireless thermometer...

Signal 1, decoding the Denver TRC-1480

The Denver TRC-1480 have the possibility to read from three different temperature sensors.
All pulses are of the same length, 0.55 ms with different delays in between. Each packet starts with a pulse and a 4.4 ms delay. Each "1" is a pulse with a 2.45 ms delay and a "0" is a pulse with a 1.45 ms delay.
By varying different parameters the following information were revealed:

bit 1 - 8   sensor ID
bit 9       0 indicates low battery
bit 10      always 0
bit 11 - 12 channel-1
bit 13 - 24 temperature * 10 as two's complement (invert all bits,
                 add 1 and negate for numbers starting with "11".
bit 25 - 28 always 1
bit 29 - 31 always 0
bit 32 - 36 some sort of checksum?


Some readings from channel 3

In addition channel 1 sends at 57 seconds interval, channel 2 at 67 seconds and channel 3 at 80 seconds.

Signal 2, unknown origin

Transmits every 48 seconds. Consists of 0.5 ms "short" pulses and 1.5 ms "long pulses. A short pulse indicates a "0" and a long pulse a "1". The transmission starts with eight "0". The signal are sometimes very weak.

Bit 17 to 24 may be correlated to the outside temperature by subtracting 234 and dividing by 10. There have to be more to this since the temperature reading with those eight bits are limited to -23.4 to 2.1C. [EDIT:] Or the temperature may be stored as two's complement as well.[]
I do not yet know the brand of this thermometer.

Signal 3, unknown origin

Transmits every 36 seconds. Consists of 0.4 ms pulses with either 4.6 ms ("1") or 2.4 ms ("0") delays. Each signal frame starts with a pulse followed by a 9.6 ms. delay.

Bits 17 to 24 correlates to the temperature by subtracting 238 and dividing by 10.
[EDIT:] Or the temperature may be stored as two's complement as well.[]
As with signal 2, clearly more data are needed to assign the different bits.


Sources used

A description of some Lacrosse sensors,  Jean-Paul ROUBELAT - F6FBB @ http://www.f6fbb.org
A very informative series from spook @ http://lucsmall.com regarding Fine Offset Electronics instruments.
An eye opener from bertrik.

More important things yet to be followed up