Library 13- Reading temperature with Dallas DS18B20 on STM32F4
In the last post, I show OneWire library. Today, I will use that library to show how to read temperature with Dallas’s temperature sensor DS18B20.
DS18B20 Features
- 9 to 12 bits resolution
- -55°C to 125°C Celsius
- 64bit unique ROM number
- Alarm temperatures enable or disable
- Search devices with alarm flag set
- Can be parasite-powered
Library
Features
- Search sensors
- Read temperature
- Set resolution for each device
- Start temperature conversion on all devices simultaneously
- Set alarm low and high temperatures
- Disable alarm temperatures
- Search devices with alarm flag set
- Data pin depends on Onewire library pin
- Version 2.0 – January 04, 2015
Dependencies
- CMSIS
- STM32F4xx
- STM32F4xx RCC
- STM32F4xx GPIO
- TM
- TM ONEWIRE
- TM DELAY
- defines.h
- TM ONEWIRE
Resolution0 | 9bits | 10bits | 11bits | 12bits |
---|---|---|---|---|
Conversion time | 93.75ms | 187.5ms | 375ms | 750ms |
LSB | 0.5°C | 0.25°C | 0.125°C | 0.0625°C |
Before we can start a temperature conversion, we have to know ROM code of DS18B20. If you don’t know it, then use search, that will do this for you. In example on the bottom, search for devices is included.
Start temperature conversion
You can start temperature conversion for specific sensor, or for all sensors simultaneously. Do this with
1 2 3 4 5 6 |
//Start temperature conversion for specific DS18B20 with ROM address //As parameter you have to tell pointer to first element of ROM address TM_DS18B20_Start(&OneWire, ROM); //You can start temperature conversion on all DS18B20 sensors at the same time on one onewire port TM_DS18B20_StartAll(&OneWire); |
Reading temperature
Because DS18B20 needs some time (table on top) we can not immediately read temperature, if you try, you will not get correct value. If we know resolution od DS18B20 device, we can just put some delay after temperature conversions has started, or if you want to exactly know when it finished with conversion, you can use
1 2 |
//Wait until all devices convert temperature while (!TM_DS18B20_AllDone(&OneWire)); |
When all devices finish with conversion, you are able to read data from them. To read temperature you have to know ROM address number. Read temperature with
1 2 3 |
//Read temperature from device with ROM starting at &ROM[0] address //Save temperature to float variable "temp" TM_DS18B20_Read(&OneWire, ROM, &temp); |
Set/Get resolution
Every DS18B20 has it’s own resolution number from 9 to 12 bits. Higher resolution is, more time sensor needs to convert temperature. If you want to set resolution to DS18B20, you can do this with
1 2 3 4 5 6 7 8 9 |
/* * Resolutions available: * - TM_DS18B20_Resolution_9bits * - TM_DS18B20_Resolution_10bits * - TM_DS18B20_Resolution_11bits * - TM_DS18B20_Resolution_12bits */ //Set 9bits resolution to specific DS18B20 with ROM address TM_DS18B20_SetResolution(&OneWire, ROM, TM_DS18B20_Resolution_9bits); |
You are also able to read resolution. Function will return 9 – 12 bits or 0 if device is not DS18B20.
1 2 |
//Get resolution for specific DS18B20 TM_DS18B20_GetResolution(&OneWire, ROM); |
Alarm high/low temperature
Every DS18B20 can trigger an alarm flag if temperature is greater than high temp, or lower than low temp. High and low temperatures are stored in DS18B20’s internal EEPROM. You can set temperatures with
1 2 3 4 |
//Set high temperature alarm 25°C TM_DS18B20_SetAlarmHighTemperature(&OneWire, ROM, 25); //Set low temperature alarm to 15°C TM_DS18B20_SetAlarmLowTemperature(&OneWire, ROM, 15); |
Remember: You can only select integer numbers between -55 to 125°C. Also know, that these values are stored in EEPROM and are not deleted after power is down.
Disable alarm
If you don’t want to use alarm on specific device, you can disable it. To this with
1 2 |
//Disable alarm temperatures TM_DS18B20_DisableAlarmTemperature(&OneWIre, ROM); |
Check alarm flag
If there are sensors with active alarm, we have somehow recognize devices that has set it. DS18B20 has specific command for search devices which have set alarm flag. You can search for ROM’s that have alarm set with
1 2 3 4 5 6 7 8 |
alarm_count = 0; uint8_t alarm_device[MAX_DEVICES_NUMBER_HERE][8]; //Check if any device has alarm flag set while (TM_DS18B20_AlarmSearch(&OneWire)) { //Store ROM of device which has alarm flag set TM_OneWire_GetFullROM(&OneWire, &alarm_device[i][0]); alarm_count++; } |
Functions and enumerations
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
/** * Resolutions available * * Parameters: * - TM_DS18B20_Resolution_9bits: * DS18B20 9 bits * - TM_DS18B20_Resolution_10bits: * DS18B20 10 bits * - TM_DS18B20_Resolution_11bits: * DS18B20 11 bits * - TM_DS18B20_Resolution_12bits: * DS18B20 12 bits */ typedef enum { TM_DS18B20_Resolution_9bits = 9, TM_DS18B20_Resolution_10bits = 10, TM_DS18B20_Resolution_11bits = 11, TM_DS18B20_Resolution_12bits = 12 } TM_DS18B20_Resolution_t; /** * Start temperature conversion for specific DS18B20 on specific onewire channel * * Parameters: * - TM_OneWire_t* OneWireStruct: * Pointer to OneWire working struct (channel) * - uint8_t *ROM: * Pointer to first byte of ROM address * * Returns 1 if device is DS18B20 or 0 if not */ extern uint8_t TM_DS18B20_Start(TM_OneWire_t* OneWireStruct, uint8_t* ROM); /** * Start temperature conversion for all DS18B20 devices on specific onewire channel * * Parameters: * - TM_OneWire_t* OneWireStruct: * Pointer to OneWire working struct (channel) * * No return */ extern void TM_DS18B20_StartAll(TM_OneWire_t* OneWireStruct); /** * Read temperature from DS18B20 * * Parameters: * - TM_OneWire_t* OneWireStruct: * Pointer to OneWire working struct (channel) * - uint8_t* ROM: * Pointer to first byte of ROM address * - float* destination: * Pointer to float variable to store temperature * * Returns 1 if temperature is read OK or 0 if device is not DS18B20 or conversion is not done yet or CRC failed */ extern uint8_t TM_DS18B20_Read(TM_OneWire_t* OneWireStruct, uint8_t* ROM, float* destination); /** * Get resolution for temperature conversion * * Parameters: * - TM_OneWire_t* OneWireStruct: * Pointer to OneWire working struct (channel) * - uint8_t* ROM: * Pointer to first byte of ROM address * * Returns 0 if device is not DS18B20 or bits number (9 - 12) */ extern uint8_t TM_DS18B20_GetResolution(TM_OneWire_t* OneWireStruct, uint8_t* ROM); /** * Set resolution for specific DS18B20 device * * Parameters: * - TM_OneWire_t* OneWireStruct: * Pointer to OneWire working struct (channel) * - uint8_t* ROM: * Pointer to first byte of ROM address * - TM_DS18B20_Resolution_t resolution: * Set resolution for DS18B20 device: * - TM_DS18B20_Resolution_9bit: 9bits resolution * - TM_DS18B20_Resolution_10bit: 10bits resolution * - TM_DS18B20_Resolution_11bit: 11bits resolution * - TM_DS18B20_Resolution_12bit: 12bits resolution * * Returns 0 if device is not DS18B20 or 1 if resolution is set */ extern uint8_t TM_DS18B20_SetResolution(TM_OneWire_t* OneWireStruct, uint8_t* ROM, TM_DS18B20_Resolution_t resolution); /** * Check if device is DS18B20 with specific ROM number * * Parameters: * - uint8_t* ROM: * Pointer to first byte of ROM address * * Returns 1 if device is DS18B20, otherwise 0 */ extern uint8_t TM_DS18B20_Is(uint8_t* ROM); /** * Set high alarm temperature to specific DS18B20 sensor * * Parameters: * - TM_OneWire_t* OneWireStruct: * Pointer to OneWire working struct (channel) * - uint8_t* ROM: * Pointer to first byte of ROM address * - int8_t temp: * Temperature between -55 and 125°C * * Returns 0 if device is not DS18B20, otherwise 1 */ extern uint8_t TM_DS18B20_SetAlarmHighTemperature(TM_OneWire_t* OneWireStruct, uint8_t* ROM, int8_t temp); /** * Set low alarm temperature to specific DS18B20 sensor * * Parameters: * - TM_OneWire_t* OneWireStruct: * Pointer to OneWire working struct (channel) * - uint8_t* ROM: * Pointer to first byte of ROM address * - int8_t temp: * Temperature between -55 and 125°C * * Returns 0 if device is not DS18B20, otherwise 1 */ extern uint8_t TM_DS18B20_SetAlarmLowTemperature(TM_OneWire_t* OneWireStruct, uint8_t* ROM, int8_t temp); /** * Disable alarm temperature on specific DS18B20 sensor * * Parameters: * - TM_OneWire_t* OneWireStruct: * Pointer to OneWire working struct (channel) * - uint8_t* ROM: * Pointer to first byte of ROM address * * Returns 0 if device is not DS18B20, otherwise 1 */ extern uint8_t TM_DS18B20_DisableAlarmTemperature(TM_OneWire_t* OneWireStruct, uint8_t* ROM); /** * Search for devices with alarm flag set * * Parameters: * - TM_OneWire_t* OneWireStruct: * Pointer to OneWire working struct (channel) * * Returns 1 if any device has flag, otherwise 0 */ extern uint8_t TM_DS18B20_AlarmSearch(TM_OneWire_t* OneWireStruct); /** * Check if all DS18B20 sensors are done with temperature conversion * * Parameters: * - TM_OneWire_t* OneWireStruct: * Pointer to OneWire working struct (channel) * * Return 1 if they are, otherwise 0 */ extern uint8_t TM_DS18B20_AllDone(TM_OneWire_t* OneWireStruct); |
Example
In example below I used two DS18B20 sensors connected to PD0 pin, with 4k7 pull up resistor.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
/** * Keil project for DS18B20 library example * * This example first search for all devices on 1wire bus * Set some parameters, described down in code * Start conversion on all devices * Read temperatures and display it * Checks for devices with alarm flag set * * Before you start, select your target, on the right of the "Load" button * * @author Tilen Majerle * @email tilen@majerle.eu * @website http://stm32f4-discovery.net * @ide Keil uVision 5 * @packs STM32F4xx Keil packs version 2.2.0 or greater required * @stdperiph STM32F4xx Standard peripheral drivers version 1.4.0 or greater required */ /* Include core modules */ #include "stm32f4xx.h" /* Include my libraries here */ #include "defines.h" #include "tm_stm32f4_delay.h" #include "tm_stm32f4_onewire.h" #include "tm_stm32f4_usart.h" #include "tm_stm32f4_ds18b20.h" #include "tm_stm32f4_disco.h" #include <stdio.h> /* How many sensors we are expecting on 1wire bus? */ #define EXPECTING_SENSORS 2 int main(void) { char buf[40]; uint8_t devices, i, j, count, alarm_count; uint8_t device[EXPECTING_SENSORS][8]; uint8_t alarm_device[EXPECTING_SENSORS][8]; float temps[EXPECTING_SENSORS]; /* OneWire working struct */ TM_OneWire_t OneWire1; /* Initialize system */ SystemInit(); /* Initialize delay */ TM_DELAY_Init(); /* Initialize OneWire on pin PD0 */ TM_OneWire_Init(&OneWire1, GPIOD, GPIO_Pin_0); /* Initialize USART, TX: PB6, RX: PB7 */ TM_USART_Init(USART1, TM_USART_PinsPack_2, 115200); /* Initialize Leds */ TM_DISCO_LedInit(); /* Turn leds on */ TM_DISCO_LedOn(LED_ALL); /* Checks for any device on 1-wire */ count = 0; devices = TM_OneWire_First(&OneWire1); while (devices) { /* Increase counter */ count++; /* Get full ROM value, 8 bytes, give location of first byte where to save */ TM_OneWire_GetFullROM(&OneWire1, device[count - 1]); /* Get next device */ devices = TM_OneWire_Next(&OneWire1); } /* If any devices on 1wire */ if (count > 0) { sprintf(buf, "Devices found on 1-wire: %d\n", count); TM_USART_Puts(USART1, buf); /* Display 64bit rom code for each device */ for (j = 0; j < count; j++) { for (i = 0; i < 8; i++) { sprintf(buf, "0x%02X ", device[j][i]); TM_USART_Puts(USART1, buf); } TM_USART_Puts(USART1, "\n"); } } else { TM_USART_Puts(USART1, "No devices on OneWire.\n"); } /* Go through all connected devices and set resolution to 12bits */ for (i = 0; i < count; i++) { /* Set resolution to 12bits */ TM_DS18B20_SetResolution(&OneWire1, device[i], TM_DS18B20_Resolution_12bits); } /* Set high temperature alarm on device number 0, 25 degrees celcius */ TM_DS18B20_SetAlarmHighTemperature(&OneWire1, device[0], 25); /* Disable alarm temperatures on device number 1 */ TM_DS18B20_DisableAlarmTemperature(&OneWire1, device[1]); while (1) { /* Start temperature conversion on all devices on one bus */ TM_DS18B20_StartAll(&OneWire1); /* Wait until all are done on one onewire port */ while (!TM_DS18B20_AllDone(&OneWire1)); /* Read temperature from each device separatelly */ for (i = 0; i < count; i++) { /* Read temperature from ROM address and store it to temps variable */ if (TM_DS18B20_Read(&OneWire1, device[i], &temps[i])) { /* Print temperature */ sprintf(buf, "Temp %d: %3.5f; \n", i, temps[i]); TM_USART_Puts(USART1, buf); } else { /* Reading error */ TM_USART_Puts(USART1, "Reading error;\n"); } } /* Reset alarm count */ alarm_count = 0; /* Check if any device has alarm flag set */ while (TM_DS18B20_AlarmSearch(&OneWire1)) { /* Store ROM of device which has alarm flag set */ TM_OneWire_GetFullROM(&OneWire1, alarm_device[alarm_count]); /* Increase count */ alarm_count++; } /* Format string and send over USART for debug */ sprintf(buf, "Devices with alarm: %d\n", alarm_count); TM_USART_Puts(USART1, buf); /* Any device has alarm flag set? */ if (alarm_count > 0) { /* Show rom of this devices */ for (j = 0; j < alarm_count; j++) { TM_USART_Puts(USART1, "Device with alarm: "); for (i = 0; i < 8; i++) { sprintf(buf, "0x%02X ", alarm_device[j][i]); TM_USART_Puts(USART1, buf); } TM_USART_Puts(USART1, "\n "); } TM_USART_Puts(USART1, "ALARM devices recognized!\n\r"); } /* Print separator */ TM_USART_Puts(USART1, "----------\n"); /* Some delay */ Delayms(1000); } } |
Project available on Github, download library below.
DS18B20 Temperature sensor library
Recent comments