TinuDHT is a C library for working with the DHT11 temperature/humidity sensor intended to be used with the Tinusaur but should also work with any other board based on ATtiny85 or similar microcontroller.
There are of course may libraries (sometime called drivers) to work with DHT11 and the more advanced DHT21/DHT22 but they were written primarily for the Arduino environment and do not work well (or at all) with pure ATtiny boards. Here is a list of some of the popular libraries with short descriptions from their authors:
- Class for DHTxx sensors
http://playground.arduino.cc/Main/DHTLib
The DHT11, DHT21 and DHT22 are relative cheap sensors for measuring temperature and humidity. This article describes a library for reading both values from these sensors. - A DHT11 Class for Arduino
http://playground.arduino.cc/Main/DHT11Lib
The DHT11 is a relatively cheap sensor for measuring temperature and humidity. This article describes a small library for reading both from the sensor. The DHT22 is similar to the DHT11 and has greater accuracy. - Adafruit TinyDHT
https://github.com/adafruit/TinyDHT
This is an Arduino library for the Adafruit Trinket and Gemma mini microcontrollers for the DHT series of low cost temperature/humidity sensors. The library returns integer values to save space on the memory constrained ATTiny85 by not requiring the floating point library.
DHT11
The DHT11 is very basic, low-cost digital temperature and humidity sensor. It uses a capacitive humidity sensor and a thermistor for measurements, and sends out the info to the data pin. It is relatively simple to use it, but requires precise timing to retrieve the data correctly. One disadvantage of this sensor is that you can get new data from it no more often than once every 1 or 2 seconds.

Technical parameters of DHT11:
- Humidity: 20-90 % RH, ±5%RH
- Temperature:0-50 ℃, ±2℃ 1
- Power supply: 3.0 – 5.5 V DC
Pinout:
- 1: Vdd – Power supply.
- 2: Data – Serial data.
- 3: N/C – Not connected.
- 4: GND – Ground.
Sending/Receiving:
- The host (MCU, microcontroller) sends short 18ms LOW to the data pin, then waits a little – 20-40 us and then waits for the DHT to start sending data back. The short HIGH’s are “0” and the long HIGH’s are “1”.
Library
The primary problem with the direct use of the Arduino libraries is that the ATtiny85 and Tinusaur in particular do not have enough resource to handle the send/receive process properly, i.e. not enough CPU power, in result of which the timing of the signals that are sent to the sensor and received from it become messed up. In addition those libraries use Arduino specific code and/or C++ specific syntax which makes them incompatible with the plain C language.
This library is based on DHT11Lib code. It was adapted for ATtiny, removed Arduino dependencies and timing was adjusted to work well on ATtiny85 at 1 MHz. There are few other changes and optimizations for speed and size.
TinuDHT is written in plain C and does not require any additional libraries to function except those that come with the WinAVR SDK.
The library consists of 2 file:
- tinudht.h
- tinudht.c
Source Code
Here is the source code of the TinuDHT library.
Some of the comments were striped out to save space on the screen.
tinudht.h
/*
* Tinu DHT - Tinusaur DHT11 Library
*
* @file: tinudht.h
* @created: 2014-07-08
* @author: neven
*
* Source code available at: https://bitbucket.org/tinusaur/tinudht
*
*/
#ifndef TINUDHT_H
#define TINUDHTDHT_H
#define TINUDHT_OK 0
#define TINUDHT_ERROR_CHECKSUM -1
#define TINUDHT_ERROR_TIMEOUT -2
typedef struct {
uint16_t humidity;
uint16_t temperature;
} TinuDHT;
uint8_t tinudht_read(TinuDHT *ptinudht, uint8_t dht_pin);
#endif
tinudht.c
/*
* Tinu DHT - Tinusaur DHT11 Library
*
* @file: tinudht.c
* @created: 2014-07-08
* @author: neven
*
* Source code available at: https://bitbucket.org/tinusaur/tinudht
*
*/
#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>
#include "tinudht.h"
#define TINUDHT_RCV_TIMEOUT 255
#define TINUDHT_RCV_DELAY 10
#define TINUDHT_RCV_LENGTH 2
uint8_t tinudht_read(TinuDHT *ptinudht, uint8_t dht_pin) {
// Buffer to received data
uint8_t data[5];
// Empty the buffer
data[0] = data[1] = data[2] = data[3] = data[4] = 0;
// Send request
DDRB |= (1 << dht_pin); // Set port as output
PORTB &= ~(1 << dht_pin); // Set to 0
_delay_ms(18); // Wait 18 ms
PORTB |= (1 << dht_pin); // Set to 1
_delay_us(40); // Wait 40 us
// Receive response
DDRB &= ~(1 << dht_pin); // Set port as input
uint8_t timeout;
// Acknowledge
timeout = TINUDHT_RCV_TIMEOUT;
while(bit_is_clear(PINB, dht_pin)) // Wait for 1
if (timeout-- == 0)
return TINUDHT_ERROR_TIMEOUT;
timeout = TINUDHT_RCV_TIMEOUT;
while(bit_is_set(PINB, dht_pin)) // Wait for 0
if (timeout-- == 0)
return TINUDHT_ERROR_TIMEOUT;
uint8_t bit_index = 7;
uint8_t byte_index = 0;
// READ OUTPUT - 40 BITS => 5 BYTES or TIMEOUT
for (uint8_t i = 0; i < 40; i++)
{
// Wait for start
timeout = TINUDHT_RCV_TIMEOUT;
while(bit_is_clear(PINB, dht_pin)) // Wait for 1
if (timeout-- == 0)
return TINUDHT_ERROR_TIMEOUT;
// Determine the bit value
uint8_t len = 0;
while(bit_is_set(PINB, dht_pin)) { // Wait for 0
_delay_us(TINUDHT_RCV_DELAY);
if (len++ == TINUDHT_RCV_TIMEOUT)
return TINUDHT_ERROR_TIMEOUT;
}
if (len >= TINUDHT_RCV_LENGTH) data[byte_index] |= (1 << bit_index);
if (bit_index == 0) // next byte?
{
bit_index = 7; // restart at MSB
byte_index++; // next byte!
}
else bit_index--;
}
uint8_t checksum = data[0] + data[2];
if (data[4] != checksum) return TINUDHT_ERROR_CHECKSUM;
// On DHT11 data[1],data[3] are always zero so not used.
ptinudht->humidity = data[0];
ptinudht->temperature = data[2];
return TINUDHT_OK;
}
Please note that the source code above may improve or change so check the latest version at the source code repository on this address: https://bitbucket.org/tinusaur/tinudht.
Usage
Using the TinuDHT library is very simple.
#include "../tinudht/tinudht.h"
#define TINUDHT_PIN PB0
void main(void) {
TinuDHT tinudht;
tinudht_read(&tinudht, TINUDHT_PIN);
debug_print_dec(tinudht.humidity);
debug_print_dec(tinudht.temperature);
}
}
We need a buffer for the data tinudht and the pin where the data will be sent/received. Then we call the tinudht_read funcation. Note that we pass the buffer by address.
The function returns “0” for success or negative for errors.
tinudht_read(&amp;amp;amp;tinudht, TINUDHT_PIN);
The result is available as tinudht.humidity and tinudht.temperature.
Testing Program
Below is a simple program that reads the data from a DHT11 and shows it on a LCD screen.
The LCD screen is based on PCD8544 but is more popular under the Nokia 5110/3310 LCD name.
/*
* Tinu DHT - Tinusaur DHT11 Library
*
* @file: main.c
* @created: 2014-07-08
* @author: neven
*
* Source code available at: https://bitbucket.org/tinusaur/tinudht
*
*/
#include <stdlib.h>
#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
#include "lcdddd.h"
#include "lcddddf.h"
// #define LCD_PIN_RESET PB0 // RST, Pin 1 on LCD - RESET
// #define LCD_PIN_SCE PB1 // CE, Pin 2 on LCD - Chip Enable
// #define LCD_PIN_DC PB2 // DC, Pin 3 on LCD - Data/Command mode select
// #define LCD_PIN_SDIN PB3 // DIN, Pin 4 on LCD - Serial Data In line
// #define LCD_PIN_SCLK PB4 // CLK, Pin 5 on LCD - Serial Clock line
// // ---------------------- // Vcc, Pin 6 on LCD
// // ---------------------- // Lit, Pin 7 on LCD
// // ---------------------- // GND, Pin 8 on LCD
// NOTE/IMPORTANT: The RESET wire of te LCD module should be connected directly
// to the RESET pin of the MCU - pin 1 on the chip.
#include "../tinudht/tinudht.h"
#define TINUDHT_PIN PB0
int main(void) {
lcdddd_init(); // Initialize the LCD
lcdddd_clear();
_delay_ms(100); // Delay for DHT11 to stabilize (REQUIRED on power on)
while (1) {
lcdddd_gotoxy(0, 0);
lcdddd_print_string("TinuDHT Test");
// --------------------------------------------------------------------
TinuDHT tinudht;
tinudht_read(&tinudht, TINUDHT_PIN);
// --------------------------------------------------------------------
lcdddd_gotoxy(0, 4);
lcdddd_print_string("H:");
lcdddd_print_dec_padded(tinudht.humidity);
lcdddd_print_string(" %");
lcdddd_gotoxy(0, 5);
lcdddd_print_string("T:");
lcdddd_print_dec_padded(tinudht.temperature);
lcdddd_print_string(" C");
_delay_ms(1000);
// IMPORTANT: Do not query the DHT11 more often than 1 time per second.
}
return 0;
}
The source code of this testing program along with the LCDDDD library to control the LCD screen is available at the source code repository in the “tinudht_test” folder.
External Resources
The source code of the TinuDHT is available at https://bitbucket.org/tinusaur/tinudht.
DHT11 Datasheet and specification (PDF): http://www.micro4you.com/files/sensor/DHT11.pdf
Hi!
First, congratulations for your project!
I was trying to upload your code to my Attiny85, within the Arduino 1.7.6, and it gave me the following error while compiling:
“tinudht.c:64:2: note: use option -std=c99 or -std=gnu99 to compile your code”
Do you have any clue on how can I solve this problem?
Ah, okay. This is because we use some C language constructions that are relatively new.
The C/C++ compiler that comes with the Arduino 1.7 dev environment should be capable of doing this – you only need to specify the options mentioned above. Unfortunately, I don’t know at the moment where’s that done – somewhere in system settings maybe.