From cacfc57e9fac9a86e18cefabfbbadd0f6c34f453 Mon Sep 17 00:00:00 2001 From: David Antliff Date: Thu, 23 Apr 2020 18:08:39 +1200 Subject: [PATCH] Add support for Parasitic Power mode, including secondary GPIO control of external "strong pull-up" circuit. --- README.md | 25 +++++++++++++++++++------ components/esp32-ds18b20 | 2 +- components/esp32-owb | 2 +- main/Kconfig.projbuild | 38 +++++++++++++++++++++++++++++++++++--- main/app_main.c | 34 ++++++++++++++++++---------------- sdkconfig.defaults | 4 ++++ 6 files changed, 78 insertions(+), 27 deletions(-) create mode 100644 sdkconfig.defaults diff --git a/README.md b/README.md index c4ed2f6..0fba9e5 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,13 @@ ## Introduction -This is an example application for the Maxim Integrated DS18B20 Programmable Resolution 1-Wire Digital Thermometer device. +This is an example application for the Maxim Integrated DS18B20 Programmable Resolution 1-Wire Digital Thermometer +device. It supports a single or multiple devices on the same 1-Wire bus. -It is written and tested for v3.3 of the [ESP-IDF](https://github.com/espressif/esp-idf) environment, using the xtensa-esp32-elf toolchain (gcc version 5.2.0, crosstool-ng-1.22.0-80-g6c4433a). +It is written and tested for v3.3 and v4.1-beta1 of the [ESP-IDF](https://github.com/espressif/esp-idf) environment, +using the xtensa-esp32-elf toolchain (gcc version 5.2.0, crosstool-ng-1.22.0-80-g6c4433a). Ensure that submodules are cloned: @@ -23,7 +25,8 @@ Build the application with: $ idf.py build $ idf.py -p (PORT) flash monitor -The program should detect your connected devices and periodically obtain temperature readings from them, displaying them on the console. +The program should detect your connected devices and periodically obtain temperature readings from them, displaying them +on the console. ## Dependencies @@ -34,17 +37,27 @@ This application makes use of the following components (included as submodules): ## Hardware -To run this example, connect one or more DS18B20 devices to a single GPIO on the ESP32. Use the recommended pull-up resistor of 4.7 KOhms, connected to the 3.3V supply. +To run this example, connect one or more DS18B20 devices to a single GPIO on the ESP32. Use the recommended pull-up +resistor of 4.7 KOhms, connected to the 3.3V supply. `idf.py menuconfig` can be used to set the 1-Wire GPIO. -If you have several devices and see occasional CRC errors, consider using a 2.2 kOhm pull-up resistor instead. Also consider adding decoupling capacitors between the sensor supply voltage and ground, as close to each sensor as possible. +If you have several devices and see occasional CRC errors, consider using a 2.2 kOhm pull-up resistor instead. Also +consider adding decoupling capacitors between the sensor supply voltage and ground, as close to each sensor as possible. + +If you wish to enable a second GPIO to control an external strong pull-up circuit for parasitic power mode, ensure +`CONFIG_ENABLE_STRONG_PULLUP=y` and `CONFIG_STRONG_PULLUP_GPIO` is set appropriately. + +See documentation for [esp32-ds18b20](https://www.github.com/DavidAntliff/esp32-ds18b20-example#parasitic-power-mode) +for further information about parasitic power mode, including strong pull-up configuration. + ## Features This example provides: - * External power supply mode. + * External power supply detection. + * Parasitic power supply detection. * Static (stack-based) or dynamic (malloc-based) memory model examples. * No global variables. * Device search. diff --git a/components/esp32-ds18b20 b/components/esp32-ds18b20 index ae81f86..e763961 160000 --- a/components/esp32-ds18b20 +++ b/components/esp32-ds18b20 @@ -1 +1 @@ -Subproject commit ae81f86e0ee1cd65b6d6a2ad59deb7ba295ab3c4 +Subproject commit e763961d445263cdfc93d0fe516f917ba95a43e1 diff --git a/components/esp32-owb b/components/esp32-owb index af25dd3..c678bad 160000 --- a/components/esp32-owb +++ b/components/esp32-owb @@ -1 +1 @@ -Subproject commit af25dd31dbb1e80364b99fad29815badfab0ceda +Subproject commit c678bad2af657359ebdab90473df2f65ff5ac83d diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index 27da83c..189c66b 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -2,13 +2,45 @@ menu "esp32-ds18b20-example Configuration" config ONE_WIRE_GPIO int "OneWire GPIO number" - range 0 34 - default 5 + range 0 33 + default 4 help GPIO number (IOxx) to access One Wire Bus. Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used. - GPIOs 35-39 are input-only so cannot be used to drive the One Wire Bus. + GPIOs 34-39 are input-only so cannot be used to drive the One Wire Bus. + +config ENABLE_STRONG_PULLUP_GPIO + bool "Enable strong pull-up controlled by GPIO (MOSFET)" + default n + help + An external circuit can be used to provide a strong pull-up to the One Wire Bus. + This is useful when the bus has parasitic-powered devices and extra current is + required to power them, such as during temperature ADC conversions. + + An example of such a circuit for the ESP32 is a P-channel MOSFET (such as the BS250) + connected Source-to-Drain between a current-limiting resistor (e.g. 270ohm for 12mA + max at 3.3V), itself connected to VCC, and the One Wire Bus data line. The Gate is + connected to the GPIO specified here. + +config STRONG_PULLUP_GPIO + int "Strong pull-up GPIO number" + range 0 33 + default 5 + help + GPIO number (IOxx) to control the strong pull-up on the One Wire Bus, perhaps + via a P-channel MOSFET between VCC and the One Wire Bus data line. + + This GPIO will be set as an output and driven high during temperature conversion. + This would enable the MOSFET providing current to the devices. + + At all other times it will be driven low, switching off the MOSFET and allowing + the One Wire Bus to operate normally. + + Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used. + + GPIOs 34-39 are input-only so cannot be used to drive the One Wire Bus. + depends on ENABLE_STRONG_PULLUP_GPIO endmenu diff --git a/main/app_main.c b/main/app_main.c index 14c99b9..e8bfafd 100644 --- a/main/app_main.c +++ b/main/app_main.c @@ -40,7 +40,6 @@ _Noreturn void app_main() { // Override global log level esp_log_level_set("*", ESP_LOG_INFO); - esp_log_level_set("*", ESP_LOG_DEBUG); // To debug, use 'make menuconfig' to set default Log level to DEBUG, then uncomment: //esp_log_level_set("owb", ESP_LOG_DEBUG); @@ -149,14 +148,23 @@ _Noreturn void app_main() // vTaskDelay(1000 / portTICK_PERIOD_MS); // } - // Check for parasitic-powered devices that require a strong-pullup - bool require_strong_pullup = false; - ds18b20_check_for_parasite_power(owb, &require_strong_pullup); - printf("Strong pullup (parasitic power) %srequired\n", require_strong_pullup ? "" : "not "); - if (require_strong_pullup) - { + // Check for parasitic-powered devices + bool parasitic_power = false; + ds18b20_check_for_parasite_power(owb, ¶sitic_power); + if (parasitic_power) { + printf("Parasitic-powered devices detected"); } + // In parasitic-power mode, devices cannot indicate when conversions are complete, + // so waiting for a temperature conversion must be done by waiting a prescribed duration + owb_use_parasitic_power(owb, parasitic_power); + +#ifdef CONFIG_ENABLE_STRONG_PULLUP_GPIO + // An external pull-up circuit is used to supply extra current to OneWireBus devices + // during temperature conversions. + owb_use_strong_pullup_gpio(owb, CONFIG_STRONG_PULLUP_GPIO); +#endif + // Read temperatures more efficiently by starting conversions on all devices at the same time int errors_count[MAX_DEVICES] = {0}; int sample_count = 0; @@ -164,21 +172,15 @@ _Noreturn void app_main() { TickType_t last_wake_time = xTaskGetTickCount(); - while (1) { + while (1) + { last_wake_time = xTaskGetTickCount(); ds18b20_convert_all(owb); // In this application all devices use the same resolution, // so use the first device to determine the delay - if (require_strong_pullup) { - ets_delay_us(750000); - gpio_set_level(5, 0); - } - else - { - ds18b20_wait_for_conversion(devices[0]); - } + ds18b20_wait_for_conversion(devices[0]); // Read the results immediately after conversion otherwise it may fail // (using printf before reading may take too long) diff --git a/sdkconfig.defaults b/sdkconfig.defaults new file mode 100644 index 0000000..4a89088 --- /dev/null +++ b/sdkconfig.defaults @@ -0,0 +1,4 @@ +# +# Log output +# +CONFIG_LOG_DEFAULT_LEVEL=4