Development Blog

-June 2017+


  • Entries (3)
  • Comments (1065)


DHT for 32 MHz PICAXE 

Friday, October 5, 2012 12:00:00 AM Categories: PICAXE

The PICAXE program and PEBBLE circuit are available here.

The DHT range of sensors are very cheap sensors that provides both temperature and humidity in a digital form.  This means that actual numbers are provided for both temperature and humidity which is an advantage over other methods that include non-linear thermistors and capacitor based humidity sensors both of which require specific calibration and/or more advanced circuits.

The DHT111 retails for as little as $1.50 per sensor, while temperature sensors such as DS18B20 start at $2 and humidity sensors such as HS1101 start at $4.50.  There are other more expensive models in the DHT family such as DHT21/HM2301/AM2301 (from about $5.50) and DHT22/HM2302/AM2302 (from about $5.20) that have greater temperature and humidity ranges, with greater precision (i.e. decimal values).   

All of these DHT sensors share the same communication protocol, however this is also the disadvantage.  The timing of the DHT communication is so short as to not be accessible by PICAXE.  The times are  26-28 us up time for 0 bit, 70 us up time for 1 bit and 50 us down “lead” time for both 0 and 1 bit.

The PICAXE running at even 64 MHz can’t process the data this quickly and therefore the DHT would normally be ruled out.  

The problem is that “missed” bits occur.  The standard DHT output is simply too quick for PICAXE which means that PICAXE takes longer than 50us to read a pulse length into memory and issue the command to read the next pulse length.  

An interesting approach was taken by a French enthusiast Maguin Michel utilising a 555 IC.  This approach lengthens the lead time (to about 65 us) at the expense of the up time of the 0 and 1 bit up times.  This additional couple of μs enables the 64 MHz PICAXE (X2 chips) to use DHT sensor.  However, this increased time is still too short for the 32 MHz PICAXE (M2 and M2+ range), therefore rulling out this sensor for these chips.  

I’d never seen a 555 IC before so I read up about what this chip was it was and what it could do.  Out of that I have come up with an alternative approach also based on the 555 IC.  My implementation uses different logic, adjusting the 555 so that it triggers only on the 1 bit, and ignoring all 0 bits.  This provides 110 us, more than double the time for the PICAXE to process the data.

The circuit achieves this by having a timer/charge length greater than the up time of the 0 bit, and resetting the 555 on every pull down.  Therefore, before the timing capacitor is fully charged on the 0 bit it is discharged but the 1 bit allows enough time to fully charge and therefore trigger the 555.

This process is important so I’ll restate with the actual values for this 555:
555 is triggered on the pull up, which occurs for both 0 and 1 bit.  
The 555’s capacitor/resistor combination takes 60μs to charge.
If a pull down occurs before 60μs (which occurs on the zero bit) the 555 is reset.
If a pull down doesn't occur before 60μs the 555 is charged the 555 pulses.

Because both the timer and the pulse are reset on a pull down the charge cycle is 60μs but the pulse length (occuring only on a 1 bit) is 10 μs.

This means there are no outputs for zero bits and a single pulse of 10μs for a 1 bit.  Although there are no outputs for zero bits, they can still be calculated through the time delay between 1 bits and this value can be confirmed with the check-sum value supplied by the DHT.

For each read:
1 bit 110 μs
0 bit 76-78 μs

The time taken from the end of 1 bit to pulse of the next 1 bit:
Consecutive 1 bits (11):
110 μs between pulses.

Additional time for 0 bit occurring between 1 bits (101)
110 + (76 to 78) = (186 to 188)

Additional time for two 0 bits occurring between 1 bits (1001)
110 + (76 to 78) + (76 to 78) = (262 to 266)

The time is always terminated in a 1, and the leading 1 is not important as it has already previously been recorded as a previous termination.  Therefore to reconstruct the bits we have 1 prefixed by zero or more zeros.

The prefix (Z) zero bits can be calculated as:
Equation 1:
Z = (t - 110) / 76
in the example of “1001” (where we actually only care about 001), the time of 262 to 266 calculates as either:
Z = (262 - 110) / 76 = 2
Z = (266 - 110) / 76 = 2.05 (which on a PICAXE with no zero handling calculates out to 2).

The minimum pulse length is 110 μs, with all other combinations being larger.

At the outset I noted that the cause of the read problem centred around the duration required for PICAXE to read the length of a pulse into memory and then issue the next read.  The duration of this processing delay is unknown but must be greater than 50 μs and will be consistent (plus or minus) a margin of error.  Therefore a 10μs pulse length (which would occur in the process outlined above) is too brief.  The PICAXE fails to reset and reissue the PulsIN command at 50 μs, so 10 μs cannot work.

The 10 μs delay is created due to the circuit automatically resetting on the pull down of the one bit of the DHT.  The solution to this brief delay is to μse a second 555 with a pulse length of 110 μs, triggered by the first 555.  This extends any pulse out to 110 μs, while still only triggering on 1 bits.  For simplicity I’ll call the first 555 A which triggers on the 1 bit and the second one B which extends this trigger to 110 μs.

As long as the processing delay required to store the previous read and issue another PulsIN command is less than 110 μs this process will work for 32MHz PICAXE. The 110 μs delay is more than double the time the PICAXE had previosly (50μs).  The the time between pulses of consecutive 1 bits is now 10 μs and therefore this process maximises the pulse length at the expense of the time between pulses and at the expense of directly measuring zero bits.  

Equation 1 can be restated given the reduction of time of 100 μs, however 10 μs is so small as to not be needed in the calculation.
Equation 2:
Z = (t ) / 76

A further adjustment needs to occur to Equation 2 for the consideration is the time unit measured in PulsIN.  Equation 2 above  For a 32 Mhz frequency it is 1.25 and for a 64 MHz frequency it is 0.625.  The adjusted equations for these frequencies are:

For 32 MHz:
Equation 3:
Z = (t) / 60

For 64 MHz:
Equation 4:
Z = (t) / 121

As 64 MHz has already been covered by other techniques I’ll only focus on 32MHz here.
Time for two 0 bits occurring between 1 bits (1001)
Z = (t ) / 60
Z = (129.6 to 132.8) / 60
Z = (2.16 to 2.21)

This approach is further enabled by the DHT by the header process which will generate a single up pulse at the beginning of the communication process, and a constant up state at the end of communication process.  These steps result a "beginning" front for the communication as well as a timeout at the end of the transmission.

The header adds 10 μs to the initial pulse (20 us in total not included in equation 2), but again this value is so small as to be inconsequential.

An overview of the data transfer (1100101):

>60  (50)     70     (50)     70      (50)  27   (50)   27   (50)     70     (50)   27   (50)    70

555 A:
   10   (110)    10     (110)     10               (264)                       10          (187)           10

555 B:
          110      (10)    110    (10)     110                 (164)                  110           (87)

Each value in brackets is read into the picaxe and they mean, in order:
(10) = 1
time is less than 76 and therefore no zeros
(10) = 1
time is less than 76 and therefore no zeros
(164) = 001

Z = 164 / 76 = 2 zeros

(87) = 01
Z = 87 / 76 = 1 zero

A recap of the flow overheads cab be seen above with  the 50 μs time frame of the DHT is too short to read in the results of a PulsIN and then re-issue a PulsIN.  With the 555 A output this would be reduced to 10 μs and again is too short.  With the 555 B output this is increased to 110 μs to read in the results of a PulsIN and then re-issue a PulsIN.  Therefore I've more than double the time available for the PICAXE.

An overview of the initialisation:

                MCU                  DHT ->
---\_______ … ________/--------\______/--------\_____/    Data transfer begins
              (18000)           20-40     (80)     80      (50)

555 A (whatever state it was in, it is reset at the start of communications)
                                 (18110)                      10   (120) or greater               
555 B:
                                (18120 )                               110        (20) or greater               

The DHT documentation states that the PICAXE should pull down for more than 18 ms, but as I’ve indicated above the PICAXE should pull down for 20 ms, then read the pulsin.  The initialisation of 20 ms pull down ensures that the first read is always the first bit.  

The additional 10 μs length to the first bit (or first set of bits, i.e. 001 would be 174 μs in length) has no impact on the calculation.  In fact, over 20 zeros in a row would be required before the additional length lead to incorrect calculation.

An overview of the termination:

--------\_____/----\____/--------\____/----------------(DHT pulls up voltage until next transmission)
   70   (50)    27  (50)   70     (50)

555 A
       10          (187)           10   (110)             

555 B:
                 110        (87)        Timeout 0

The PICAXE must be allowed to Timeout.  There is no way of guaranteeing that the final bit will be a one, and therefore there’s no way of knowing we have measured all bits unless a timeout occurs.

1. PICAXE pulls down 20 ms
2. PICAXE measures a pulse with a leading edge pulling down - and terminating in a pull up - through PulsIn.  Repeat for as many times as there are variables, or if processing permits until the value of the PulsIn is = 0.
3. Each PulsIn value is divided by the appropriate value based on the frequency (see Equation 3 and 4).  This determines if there is a one
4. Bytes are manually reconstructed based on the values collected in step 2 and the calculations in step 3

These timings may be useful:
Actual timing
Number of Zeros: Bit representation = Duration
0: 1 = 10
1: 01 = 87
2: 001 = 164
3: 0001 = 241
4: 00001 = 318
5: 000001 = 395
6: 0000001 = 472
7: 00000001 = 549
8: 000000001 = 626
9: 0000000001 = 703
10: 00000000001 = 780

PulsIn value at 32 MHz
0: 1 = 8
1: 01 = 69.6
2: 001 = 131.2
3: 0001 = 192.8
4: 00001 = 254.4
5: 000001 = 316
6: 0000001 = 377.6
7: 00000001 = 439.2
8: 000000001 = 500.8
9: 0000000001 = 562.4
10: 00000000001 = 624

0.08192 s timeout
81920 μs

Limitations and Points to note:
The timings are very exacting and this means that precision parts are required for accurate timing.  For instance, my capacitor has a “k” rating, indicating it is plus or minus 10%.  Given a 110 μs time requirement on the 555 B system, a 10% defect could result in 121 μs which would be so large as to make the entire process fail.

As such I needed to use a 10k trimpot and calibrate the timings

With the given code the processing will only work with 13 or fewer one bits.  This is acceptable given that no decimal values are used on the DTH11, however if decimals are required the M2 chip users may wish to use some of the system word variables (note that this would also take extra coding), while X2 users should use the extra variables that are available.

Note that reading into an incrementing byte pointer will not work, the pulse in value is likely to be higher than 255 for some readings.  Also, attempting to read into a word variable then poke that value into RAM will also fail as this adds on too much time to processing.

I found the DHT11 so poor in temperature and humidity measurement as to not be usable for my purposes (a thermostat for an Air Conditioner).  I would suggest that DHT22 be used instead.

Other Resources:


  • Ultra low cost
  • 3.5 to 5V power and I/O
  • 2.5mA max current use during conversion (while requesting data)
  • Humidity 20-95% 4-5% accuracy 1% resolution ±1% repeatability ±0.5% drift per year
  • Temperature 0-50°C temperature readings ±2°C accuracy 1°C resolution ±1% repeatability
  • No more than 1 Hz sampling rate (once every second)
  • Body size 15.5mm x 12mm x 5.5mm
  • Colour normally blue
  • 4 pins with 0.1" spacing


  • Low cost
  • 3 to 5V power and I/O
  • 2.5mA max current use during conversion (while requesting data)
  • Humidity 0-100% with 3-5% accuracy 0.1% resolution ± 1% repeatability ± 0.5% drift per year
  • Temperature -40 to 80°C ±1°C accuracy 0.1°C resolution ±2°C repeatability
  • No more than 0.5 Hz sampling rate (once every 2 seconds)
  • Body size 15.1mm x 25mm x 7.7mm
  • Colour normally black
  • 4 pins with 0.1" spacing


  • Low cost
  • 3.5 to 5V power and I/O
  • 2.5mA max current use during conversion (while requesting data)
  • Humidity 0-100% 2-5% accuracy 0.1% resolution ± 0.3% repeatability ± 0.5% drift per year
  • Temperature -40 to 125°C ±0.2°C accuracy 0.1°C resolution ±0.2°C repeatability
  • No more than 0.5 Hz sampling rate (once every 2 seconds)
  • Body size 15.1mm x 25mm x 7.7mm
  • Colour normally white
  • 4 pins with 0.1" spacin


Example output:

RH = 52.0
Temp = 24.0
Crosscheck confirmed

And from the actual device:

DHT Serial Output

DHT11 on PICAXE 18M2+

In the images below, the orange wire is negative power, the blue and white wire is positive, the blue wire is "initiate" transmission and the green wire receives the DHT transmission (after shaping through the 2x 555 ICs)

DHT11 for PICAXE 32MHz



Pic N Axe Batteries 

Monday, October 1, 2012 12:00:00 AM

The full documentation and program is available here: PicNAxeBatteries Circuit Diagram is here: Circuit (based on Pebble)

PicNAxeBatteries is a PICAXE microcontroller application that tests battery levels.  It provides a bar based graphic, numeric percentage and numeric voltage reading of battery levels which allows the user to “Pic” out the good batteries and give old batteries the “Axe”.

The program was initially written to measure the PICAXE's supply battery level.  This allows me to identify when PICAXE based project batteries are running low and need replacing.

As batteries are used the volts they produce reduce and this can affect components of the project, such as dimming LCD back lighting and contrast.  This can programmatically be handled by adjusting a digital potentiometer to maintain a consistent output voltage to the LCD but this can only be done if the supply voltage is known.

A natural extension was to also measure the backup 3V CR3032 button battery level. In fact, any battery type can be measured with appropriate min/max levels and appropriate circuitry to support it.

This program is therefore an extension of the code required to achieve the above tasks.  The most valuable coding are the final two subprocedures, “Divide” and “Multiply” which enable a type of floating point division and multiplication.  This is discussed in the Mathematics section in this documentation.

This program is a multi-battery tester without the need for any buttons.  Instead of buttons I check each pin and if there if there is a battery connected the program measures the volts and report on it.  If no pins have a battery attached the program measures the internal battery and reports on it.  Each voltage input pin is unique for each battery type.

To be accurate a Battery is actually two or more cells (i.e. the individual battery is actually called a cell).  However, even Google defines a Battery as ONE or more cells, which is the common usage I've adopted throughout this project.

The complete Project

Project Overview

Overview of Battery Types

Batteries Overview

Internal Battery Measurement (Supply Voltage)

Internal Battery Pack

Internal Battery Pack Multimeter

Alkaline Battery (standard AA)

Alkaline In Position

Mostly Empty

Alkaline Low

Alkaline Low MM

New out of the Packet

Alkaline Full

Alkaline Full MM

CR3032 Button Battery

CR3032 in place

CR3032 Battery

CR3032 MM

Nickle Metal Hydride (NiMH) / Nickle Cadnium (NiCd) * NiMH used Here

NiMH or NiCd

NiMH or NiCd MM

Interestingly both the CR3032 and NiMH/NiCd readings aren't as accurate as internal and Alkaline batteries  I'm still unsure how much of this is due to slight variations of the PICAXE's ReadADC command issued on different pins and how much of this is due to the batteries.


Pin C.0 may be slightly differently calibrated to C.1.  If this is the case slight variations in the calculations could be issued to compensate for these slight variations.


The batteries may be under a slight load in the circuit, reducing their volts.  When not connected to the circuit and only connected to the Multimeter the battery isn't under load.

Either way I don't know the cause but the values shown are what the project and Multimeter produced.

Remote Control Programming 

Friday, February 17, 2012 8:00:00 AM

I recently purchased a key remote control and receiver to operate an old garage door.  The system worked but it only has one remote, so I purchased another 2.  The problem is that there was very little information on how to get the additional 2 devices to work with the existing receiver. I'm detailing it here so that any other bargain hunters can get a cheap and effective system working.

After extensive searching I found that the chips I had purchased are common fixed-code chips.  I purchased SC2260 transmitter (key remote) and SC2272-M4 receiver (connects to garage switch).  These chips are coded through solder pads, which appears to be standard for this and similar chips (PT2260, PT2262/PT2272, PT2294, SC2262/SC2272).

The transmitter chip SC2260 (compatible with PT2260) is paired with a receiver chip SC2270 (compatible with PT2270). The PT2272 is clearly similar enough as this working the current system I have.  Both need to use the same address in order to operate.  The SC2260 chip can also be used with a "Learning" receiver - but an address should still be set for security reasons.

The chip on the key (transmitter) has its address set by soldering.  The chip on the receiver also has its code set by soldering.  The two need to match.

To activate the key for a existing ST2270/PT22700 receiver the existing address needs to be viewed and that code soldered into the key.

The data sheet for PT2270 can be found here, and the PT2260 can be found here.

The SC2272M4 - receiver chip is shown below.

SC2272 Receiver IC

Here's the solder coding pattern on the back of the chip. H means "high", and indicates the ON while L means low and indicates OFF.  Obviously I'm not going to show my code so you'll have to look at your own chip to see the code.

Transmitter chip (originally purchased with the above receiver).

SC2260 Transmitter IC

The new chips I purchased:

SC2260-R4 Transmitter

Here's the back of the chip, called the soldering pad.  To set a code solder between the centre and H (top) for ON and the centre and L (bottom) for OFF. It should match the back of the receiver (and any existing keys).

Soldering Pad