├── LICENSE
├── README.md
├── component.mk
├── ds18b20.c
├── ds18b20.h
└── main.c
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2018 Filip Grzywok @feelfreelinux
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Simple library for single DS18B20 on ESP32
2 | # Usage
3 | Put ds18b20.c and ds18b20.h in the same directory as your project code.
4 | Include library with #include ds18b20.h
5 | To initialize library, call ds18b20_init(GPIO);
6 | To get temperature(in Celcius), call ds18b20_get_temp();
7 | For example, see this code.
8 |
--------------------------------------------------------------------------------
/component.mk:
--------------------------------------------------------------------------------
1 | # Make file
2 | include $(IDF_PATH)/make/component_common.mk
3 |
--------------------------------------------------------------------------------
/ds18b20.c:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License as published by
4 | the Free Software Foundation, either version 3 of the License, or
5 | (at your option) any later version.
6 |
7 | This program is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 |
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see .
14 | */
15 | #include "freertos/FreeRTOS.h"
16 | #include "freertos/task.h"
17 | #include "driver/gpio.h"
18 | #include "esp32/rom/ets_sys.h"
19 | #include "ds18b20.h"
20 |
21 | // OneWire commands
22 | #define GETTEMP 0x44 // Tells device to take a temperature reading and put it on the scratchpad
23 | #define SKIPROM 0xCC // Command to address all devices on the bus
24 | #define SELECTDEVICE 0x55 // Command to address all devices on the bus
25 | #define COPYSCRATCH 0x48 // Copy scratchpad to EEPROM
26 | #define READSCRATCH 0xBE // Read from scratchpad
27 | #define WRITESCRATCH 0x4E // Write to scratchpad
28 | #define RECALLSCRATCH 0xB8 // Recall from EEPROM to scratchpad
29 | #define READPOWERSUPPLY 0xB4 // Determine if device needs parasite power
30 | #define ALARMSEARCH 0xEC // Query bus for devices with an alarm condition
31 | // Scratchpad locations
32 | #define TEMP_LSB 0
33 | #define TEMP_MSB 1
34 | #define HIGH_ALARM_TEMP 2
35 | #define LOW_ALARM_TEMP 3
36 | #define CONFIGURATION 4
37 | #define INTERNAL_BYTE 5
38 | #define COUNT_REMAIN 6
39 | #define COUNT_PER_C 7
40 | #define SCRATCHPAD_CRC 8
41 | // DSROM FIELDS
42 | #define DSROM_FAMILY 0
43 | #define DSROM_CRC 7
44 | // Device resolution
45 | #define TEMP_9_BIT 0x1F // 9 bit
46 | #define TEMP_10_BIT 0x3F // 10 bit
47 | #define TEMP_11_BIT 0x5F // 11 bit
48 | #define TEMP_12_BIT 0x7F // 12 bit
49 |
50 | uint8_t DS_GPIO;
51 | uint8_t init=0;
52 | uint8_t bitResolution=12;
53 | uint8_t devices=0;
54 |
55 | DeviceAddress ROM_NO;
56 | uint8_t LastDiscrepancy;
57 | uint8_t LastFamilyDiscrepancy;
58 | bool LastDeviceFlag;
59 |
60 | /// Sends one bit to bus
61 | void ds18b20_write(char bit){
62 | if (bit & 1) {
63 | gpio_set_direction(DS_GPIO, GPIO_MODE_OUTPUT);
64 | noInterrupts();
65 | gpio_set_level(DS_GPIO,0);
66 | ets_delay_us(6);
67 | gpio_set_direction(DS_GPIO, GPIO_MODE_INPUT); // release bus
68 | ets_delay_us(64);
69 | interrupts();
70 | } else {
71 | gpio_set_direction(DS_GPIO, GPIO_MODE_OUTPUT);
72 | noInterrupts();
73 | gpio_set_level(DS_GPIO,0);
74 | ets_delay_us(60);
75 | gpio_set_direction(DS_GPIO, GPIO_MODE_INPUT); // release bus
76 | ets_delay_us(10);
77 | interrupts();
78 | }
79 | }
80 |
81 | // Reads one bit from bus
82 | unsigned char ds18b20_read(void){
83 | unsigned char value = 0;
84 | gpio_set_direction(DS_GPIO, GPIO_MODE_OUTPUT);
85 | noInterrupts();
86 | gpio_set_level(DS_GPIO, 0);
87 | ets_delay_us(6);
88 | gpio_set_direction(DS_GPIO, GPIO_MODE_INPUT);
89 | ets_delay_us(9);
90 | value = gpio_get_level(DS_GPIO);
91 | ets_delay_us(55);
92 | interrupts();
93 | return (value);
94 | }
95 | // Sends one byte to bus
96 | void ds18b20_write_byte(char data){
97 | unsigned char i;
98 | unsigned char x;
99 | for(i=0;i<8;i++){
100 | x = data>>i;
101 | x &= 0x01;
102 | ds18b20_write(x);
103 | }
104 | ets_delay_us(100);
105 | }
106 | // Reads one byte from bus
107 | unsigned char ds18b20_read_byte(void){
108 | unsigned char i;
109 | unsigned char data = 0;
110 | for (i=0;i<8;i++)
111 | {
112 | if(ds18b20_read()) data|=0x01<> 4) & 0x0f));
246 | }
247 | return crc;
248 | }
249 |
250 | bool ds18b20_isAllZeros(const uint8_t * const scratchPad) {
251 | for (size_t i = 0; i < 9; i++) {
252 | if (scratchPad[i] != 0) {
253 | return false;
254 | }
255 | }
256 | return true;
257 | }
258 |
259 | float ds18b20_getTempF(const DeviceAddress *deviceAddress) {
260 | ScratchPad scratchPad;
261 | if (ds18b20_isConnected(deviceAddress, scratchPad)){
262 | int16_t rawTemp = calculateTemperature(deviceAddress, scratchPad);
263 | if (rawTemp <= DEVICE_DISCONNECTED_RAW)
264 | return DEVICE_DISCONNECTED_F;
265 | // C = RAW/128
266 | // F = (C*1.8)+32 = (RAW/128*1.8)+32 = (RAW*0.0140625)+32
267 | return ((float) rawTemp * 0.0140625f) + 32.0f;
268 | }
269 | return DEVICE_DISCONNECTED_F;
270 | }
271 |
272 | float ds18b20_getTempC(const DeviceAddress *deviceAddress) {
273 | ScratchPad scratchPad;
274 | if (ds18b20_isConnected(deviceAddress, scratchPad)){
275 | int16_t rawTemp = calculateTemperature(deviceAddress, scratchPad);
276 | if (rawTemp <= DEVICE_DISCONNECTED_RAW)
277 | return DEVICE_DISCONNECTED_F;
278 | // C = RAW/128
279 | // F = (C*1.8)+32 = (RAW/128*1.8)+32 = (RAW*0.0140625)+32
280 | return (float) rawTemp/128.0f;
281 | }
282 | return DEVICE_DISCONNECTED_F;
283 | }
284 |
285 | // reads scratchpad and returns fixed-point temperature, scaling factor 2^-7
286 | int16_t calculateTemperature(const DeviceAddress *deviceAddress, uint8_t* scratchPad) {
287 | int16_t fpTemperature = (((int16_t) scratchPad[TEMP_MSB]) << 11) | (((int16_t) scratchPad[TEMP_LSB]) << 3);
288 | return fpTemperature;
289 | }
290 |
291 | // Returns temperature from sensor
292 | float ds18b20_get_temp(void) {
293 | if(init==1){
294 | unsigned char check;
295 | char temp1=0, temp2=0;
296 | check=ds18b20_RST_PULSE();
297 | if(check==1)
298 | {
299 | ds18b20_send_byte(0xCC);
300 | ds18b20_send_byte(0x44);
301 | vTaskDelay(750 / portTICK_RATE_MS);
302 | check=ds18b20_RST_PULSE();
303 | ds18b20_send_byte(0xCC);
304 | ds18b20_send_byte(0xBE);
305 | temp1=ds18b20_read_byte();
306 | temp2=ds18b20_read_byte();
307 | check=ds18b20_RST_PULSE();
308 | float temp=0;
309 | temp=(float)(temp1+(temp2*256))/16;
310 | return temp;
311 | }
312 | else{return 0;}
313 |
314 | }
315 | else{return 0;}
316 | }
317 |
318 | void ds18b20_init(int GPIO) {
319 | DS_GPIO = GPIO;
320 | gpio_pad_select_gpio(DS_GPIO);
321 | init = 1;
322 | }
323 |
324 | //
325 | // You need to use this function to start a search again from the beginning.
326 | // You do not need to do it for the first search, though you could.
327 | //
328 | void reset_search() {
329 | devices=0;
330 | // reset the search state
331 | LastDiscrepancy = 0;
332 | LastDeviceFlag = false;
333 | LastFamilyDiscrepancy = 0;
334 | for (int i = 7; i >= 0; i--) {
335 | ROM_NO[i] = 0;
336 | }
337 | }
338 | // --- Replaced by the one from the Dallas Semiconductor web site ---
339 | //--------------------------------------------------------------------------
340 | // Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing
341 | // search state.
342 | // Return TRUE : device found, ROM number in ROM_NO buffer
343 | // FALSE : device not found, end of search
344 |
345 | bool search(uint8_t *newAddr, bool search_mode) {
346 | uint8_t id_bit_number;
347 | uint8_t last_zero, rom_byte_number;
348 | bool search_result;
349 | uint8_t id_bit, cmp_id_bit;
350 |
351 | unsigned char rom_byte_mask, search_direction;
352 |
353 | // initialize for search
354 | id_bit_number = 1;
355 | last_zero = 0;
356 | rom_byte_number = 0;
357 | rom_byte_mask = 1;
358 | search_result = false;
359 |
360 | // if the last call was not the last one
361 | if (!LastDeviceFlag) {
362 | // 1-Wire reset
363 | if (!ds18b20_reset()) {
364 | // reset the search
365 | LastDiscrepancy = 0;
366 | LastDeviceFlag = false;
367 | LastFamilyDiscrepancy = 0;
368 | return false;
369 | }
370 |
371 | // issue the search command
372 | if (search_mode == true) {
373 | ds18b20_write_byte(0xF0); // NORMAL SEARCH
374 | } else {
375 | ds18b20_write_byte(0xEC); // CONDITIONAL SEARCH
376 | }
377 |
378 | // loop to do the search
379 | do {
380 | // read a bit and its complement
381 | id_bit = ds18b20_read();
382 | cmp_id_bit = ds18b20_read();
383 |
384 | // check for no devices on 1-wire
385 | if ((id_bit == 1) && (cmp_id_bit == 1)) {
386 | break;
387 | } else {
388 | // all devices coupled have 0 or 1
389 | if (id_bit != cmp_id_bit) {
390 | search_direction = id_bit; // bit write value for search
391 | } else {
392 | // if this discrepancy if before the Last Discrepancy
393 | // on a previous next then pick the same as last time
394 | if (id_bit_number < LastDiscrepancy) {
395 | search_direction = ((ROM_NO[rom_byte_number]
396 | & rom_byte_mask) > 0);
397 | } else {
398 | // if equal to last pick 1, if not then pick 0
399 | search_direction = (id_bit_number == LastDiscrepancy);
400 | }
401 | // if 0 was picked then record its position in LastZero
402 | if (search_direction == 0) {
403 | last_zero = id_bit_number;
404 |
405 | // check for Last discrepancy in family
406 | if (last_zero < 9)
407 | LastFamilyDiscrepancy = last_zero;
408 | }
409 | }
410 |
411 | // set or clear the bit in the ROM byte rom_byte_number
412 | // with mask rom_byte_mask
413 | if (search_direction == 1)
414 | ROM_NO[rom_byte_number] |= rom_byte_mask;
415 | else
416 | ROM_NO[rom_byte_number] &= ~rom_byte_mask;
417 |
418 | // serial number search direction write bit
419 | ds18b20_write(search_direction);
420 |
421 | // increment the byte counter id_bit_number
422 | // and shift the mask rom_byte_mask
423 | id_bit_number++;
424 | rom_byte_mask <<= 1;
425 |
426 | // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
427 | if (rom_byte_mask == 0) {
428 | rom_byte_number++;
429 | rom_byte_mask = 1;
430 | }
431 | }
432 | } while (rom_byte_number < 8); // loop until through all ROM bytes 0-7
433 |
434 | // if the search was successful then
435 | if (!(id_bit_number < 65)) {
436 | // search successful so set LastDiscrepancy,LastDeviceFlag,search_result
437 | LastDiscrepancy = last_zero;
438 |
439 | // check for last device
440 | if (LastDiscrepancy == 0) {
441 | LastDeviceFlag = true;
442 | }
443 | search_result = true;
444 | }
445 | }
446 |
447 | // if no device found then reset counters so next 'search' will be like a first
448 | if (!search_result || !ROM_NO[0]) {
449 | devices=0;
450 | LastDiscrepancy = 0;
451 | LastDeviceFlag = false;
452 | LastFamilyDiscrepancy = 0;
453 | search_result = false;
454 | } else {
455 | for (int i = 0; i < 8; i++){
456 | newAddr[i] = ROM_NO[i];
457 | }
458 | devices++;
459 | }
460 | return search_result;
461 | }
462 |
--------------------------------------------------------------------------------
/ds18b20.h:
--------------------------------------------------------------------------------
1 | /*
2 | This program is free software: you can redistribute it and/or modify
3 | it under the terms of the GNU General Public License as published by
4 | the Free Software Foundation, either version 3 of the License, or
5 | (at your option) any later version.
6 |
7 | This program is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 |
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see .
14 | */
15 | #include
16 |
17 | #ifndef DS18B20_H_
18 | #define DS18B20_H_
19 |
20 | #define noInterrupts() portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;taskENTER_CRITICAL(&mux)
21 | #define interrupts() taskEXIT_CRITICAL(&mux)
22 |
23 | #define DEVICE_DISCONNECTED_C -127
24 | #define DEVICE_DISCONNECTED_F -196.6
25 | #define DEVICE_DISCONNECTED_RAW -7040
26 | #define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
27 | #define pgm_read_byte(addr) (*(const unsigned char *)(addr))
28 |
29 | typedef uint8_t DeviceAddress[8];
30 | typedef uint8_t ScratchPad[9];
31 |
32 | // Dow-CRC using polynomial X^8 + X^5 + X^4 + X^0
33 | // Tiny 2x16 entry CRC table created by Arjen Lentz
34 | // See http://lentz.com.au/blog/calculating-crc-with-a-tiny-32-entry-lookup-table
35 | static const uint8_t dscrc2x16_table[] = {
36 | 0x00, 0x5E, 0xBC, 0xE2, 0x61, 0x3F, 0xDD, 0x83,
37 | 0xC2, 0x9C, 0x7E, 0x20, 0xA3, 0xFD, 0x1F, 0x41,
38 | 0x00, 0x9D, 0x23, 0xBE, 0x46, 0xDB, 0x65, 0xF8,
39 | 0x8C, 0x11, 0xAF, 0x32, 0xCA, 0x57, 0xE9, 0x74
40 | };
41 |
42 | /* *INDENT-OFF* */
43 | #ifdef __cplusplus
44 | extern "C" {
45 | #endif
46 | /* *INDENT-ON* */
47 |
48 | void ds18b20_init(int GPIO);
49 |
50 | #define ds18b20_send ds18b20_write
51 | #define ds18b20_send_byte ds18b20_write_byte
52 | #define ds18b20_RST_PULSE ds18b20_reset
53 |
54 | void ds18b20_write(char bit);
55 | unsigned char ds18b20_read(void);
56 | void ds18b20_write_byte(char data);
57 | unsigned char ds18b20_read_byte(void);
58 | unsigned char ds18b20_reset(void);
59 |
60 | bool ds18b20_setResolution(const DeviceAddress tempSensorAddresses[], int numAddresses, uint8_t newResolution);
61 | bool ds18b20_isConnected(const DeviceAddress *deviceAddress, uint8_t *scratchPad);
62 | void ds18b20_writeScratchPad(const DeviceAddress *deviceAddress, const uint8_t *scratchPad);
63 | bool ds18b20_readScratchPad(const DeviceAddress *deviceAddress, uint8_t *scratchPad);
64 | void ds18b20_select(const DeviceAddress *address);
65 | uint8_t ds18b20_crc8(const uint8_t *addr, uint8_t len);
66 | bool ds18b20_isAllZeros(const uint8_t * const scratchPad);
67 | bool isConversionComplete();
68 | uint16_t millisToWaitForConversion();
69 |
70 | void ds18b20_requestTemperatures();
71 | float ds18b20_getTempF(const DeviceAddress *deviceAddress);
72 | float ds18b20_getTempC(const DeviceAddress *deviceAddress);
73 | int16_t calculateTemperature(const DeviceAddress *deviceAddress, uint8_t* scratchPad);
74 | float ds18b20_get_temp(void);
75 |
76 | void reset_search();
77 | bool search(uint8_t *newAddr, bool search_mode);
78 |
79 | /* *INDENT-OFF* */
80 | #ifdef __cplusplus
81 | }
82 | #endif
83 | /* *INDENT-ON* */
84 |
85 | #endif
86 |
--------------------------------------------------------------------------------
/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include "ds18b20.h"
3 | #include "freertos/FreeRTOS.h"
4 | #include "freertos/task.h"
5 | #include "driver/gpio.h"
6 |
7 | // Temp Sensors are on GPIO26
8 | #define TEMP_BUS 26
9 | #define LED 2
10 | #define HIGH 1
11 | #define LOW 0
12 | #define digitalWrite gpio_set_level
13 |
14 | DeviceAddress tempSensors[2];
15 |
16 | void getTempAddresses(DeviceAddress *tempSensorAddresses) {
17 | unsigned int numberFound = 0;
18 | reset_search();
19 | // search for 2 addresses on the oneWire protocol
20 | while (search(tempSensorAddresses[numberFound],true)) {
21 | numberFound++;
22 | if (numberFound == 2) break;
23 | }
24 | // if 2 addresses aren't found then flash the LED rapidly
25 | while (numberFound != 2) {
26 | numberFound = 0;
27 | digitalWrite(LED, HIGH);
28 | vTaskDelay(100 / portTICK_PERIOD_MS);
29 | digitalWrite(LED, LOW);
30 | vTaskDelay(100 / portTICK_PERIOD_MS);
31 | // search in the loop for the temp sensors as they may hook them up
32 | reset_search();
33 | while (search(tempSensorAddresses[numberFound],true)) {
34 | numberFound++;
35 | if (numberFound == 2) break;
36 | }
37 | }
38 | return;
39 | }
40 |
41 | void app_main(void){
42 | gpio_reset_pin(LED);
43 | /* Set the GPIO as a push/pull output */
44 | gpio_set_direction(LED, GPIO_MODE_OUTPUT);
45 |
46 | ds18b20_init(TEMP_BUS);
47 | getTempAddresses(tempSensors);
48 | ds18b20_setResolution(tempSensors,2,10);
49 |
50 | printf("Address 0: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x \n", tempSensors[0][0],tempSensors[0][1],tempSensors[0][2],tempSensors[0][3],tempSensors[0][4],tempSensors[0][5],tempSensors[0][6],tempSensors[0][7]);
51 | printf("Address 1: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x \n", tempSensors[1][0],tempSensors[1][1],tempSensors[1][2],tempSensors[1][3],tempSensors[1][4],tempSensors[1][5],tempSensors[1][6],tempSensors[1][7]);
52 |
53 | while (1) {
54 | ds18b20_requestTemperatures();
55 | float temp1 = ds18b20_getTempF((DeviceAddress *)tempSensors[0]);
56 | float temp2 = ds18b20_getTempF((DeviceAddress *)tempSensors[1]);
57 | float temp3 = ds18b20_getTempC((DeviceAddress *)tempSensors[0]);
58 | float temp4 = ds18b20_getTempC((DeviceAddress *)tempSensors[1]);
59 | printf("Temperatures: %0.1fF %0.1fF\n", temp1,temp2);
60 | printf("Temperatures: %0.1fC %0.1fC\n", temp3,temp4);
61 |
62 | float cTemp = ds18b20_get_temp();
63 | printf("Temperature: %0.1fC\n", cTemp);
64 | vTaskDelay(1000 / portTICK_PERIOD_MS);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------