adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
MIT License
3.97k stars 1.16k forks source link

Feather ESP32-V2 boards can't read the DS18B20 onewire sensors #7434

Closed DavidMKyle closed 8 months ago

DavidMKyle commented 1 year ago

CircuitPython version

Adafruit CircuitPython 8.0.0-beta.6 on 2022-12-21; Adafruit Feather ESP32 V2 with ESP32
Board ID:adafruit_feather_esp32_v2
UID:8EF9D6427042

Code/REPL

# ------------------------------------------------------------------------------------------
# Example:
# Success reading DS18X20 sensors on Feather RP2040(s)
# *** Failure reading all DS18X20 sensors on Feather ESP32-V2(s) ***
#    -I've tested two of each model Feather (RP2040 & ESP32-V2) each with 2 different
#     DS18X20 sensors, same results -- RP2040 works & ESP32-V2 fails
#
# Using CircuitPython 8.0.0 Beta 6 with latest v8 libs
# ------------------------------------------------------------------------------------------
# ------------------------------------------------------------------------------------------
# The following code is taken more-or-less directly from various Adafruit example code.

# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT

# ------------------------------------------------------------------------------------------
# Import Required Built-in modules - help("modules") for more info
# ------------------------------------------------------------------------------------------
import time
import board

# ------------------------------------------------------------------------------------------
# Import Required External modules
# ------------------------------------------------------------------------------------------
from adafruit_onewire.bus import OneWireBus
from adafruit_ds18x20 import DS18X20

# ------------------------------------------------------------------------------------------
# setup ds18x20 dallas one-wire temperature probe
# ------------------------------------------------------------------------------------------
# SPDX-FileCopyrightText: 2020 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
# Author: Tony DiCola

# A 4.7Kohm pullup between DS18B20 DATA and POWER is present in each case!
if board.board_id == 'adafruit_feather_rp2040':
    # Initialize one-wire bus on feather rp2040 board on pin D5.
    ow_bus = OneWireBus(board.D5)
if board.board_id == 'adafruit_feather_esp32_v2':
    # Initialize one-wire bus on feather esp32-v2 board on pin D14.
    ow_bus = OneWireBus(board.D14)

print("\n"+"="*20)
print(ow_bus)
print("="*20)

print("Resetting bus...", end="")
if ow_bus.reset():  # see attached reset/presence pulse comparison waveforms
    print("OK.")  # this branch always seems to execute, to here both boards seem to work
else:
    print("Nothing found on bus.")  # this never gets executed
print(" - delaying 10s ...")
time.sleep(10)  # delay for clarity of captured scope waveforms

The ESP32-V2 reset/presence waveform seems to show a healthy sensor on the bus with the following approximate timings:

print("="*20) print("Scanning bus...", end="") try:

Scan for sensors and grab the first one found.

devices = ow_bus.scan()  # see attached waveform comparison

except Exception as e: print("*** Error: No DS18x20 sensor found! Errorcode: ", e) pass
print("Devices:",devices) # for ESP32-V2 nothing found from scan @ line 73, see attached waveforms, need logic analyzer... for d in devices: print("ROM={}\tFamily=0x{:02x}".format(d.rom, d.family_code)) print(" - delaying 10s ...") time.sleep(10) # delay for clarity of captured waveforms

  The ESP32-V2 scan waveform seems to begin with a bus reset (see datasheet pg18 example #2), again healthy with the following approximate timings:
    - Bus Master TX Reset Pulse: 628us  -why so long?
    - DS18X20 Waits: 32us
    - DS18X20 Presence Pulse: 112us
    about 604us later the Bus Master sends 'Search ROM' [F0h] sequence:
      - Bus Master creates Write "0" Slot (~88us + 8us recovery + 76us)
      - Bus Master creates Write "0" Slot (~72us + 4us recovery + 56us), these slot timings seem to vary a lot 
      - Bus Master creates 2 more Bus Master W "0" Slots
      - Bus Master creates 4 Write "1" Slots
    then the Bus Master expects to rcv data back from the sensor, so it initiates a slot:
    - Bus Master creates the first Read Slot, sensor sends '0'
    - Bus Master creates the second Read Slot, sensor sends '1'
    - It seems that the Bus Master doesn't initiate another Read Slot - eveything stops

print("="20) ds18 = DS18X20(ow_bus, devices[0]) # get first sensor found (only one sensor was attached at a time to either board*)

Main loop to print the temperature every 3 seconds.

while True: print("Temperature: {0:0.3f}C".format(ds18.temperature)) time.sleep(3.0)


### Behavior

main.py output:

==================== <OneWireBus object at 0x3f80bc40>

Resetting bus...OK.

Code done running.



[waveform_comparison.xlsx](https://github.com/adafruit/circuitpython/files/10378303/waveform_comparison.xlsx)
![DS18B20_feathers_waveform_comparison](https://user-images.githubusercontent.com/10212546/211444656-70748901-48e3-4cc5-911f-bac231cce32e.png)
![ESP32_V2](https://user-images.githubusercontent.com/10212546/211444884-217e2417-055e-45c3-99fa-0a6705615ef5.png)
![RP2040](https://user-images.githubusercontent.com/10212546/211445056-fd41c88e-082d-4558-a34a-0481b9ebb15b.png)
[ESP32-V2_TDS754_waveform.CSV](https://github.com/adafruit/circuitpython/files/10378314/ESP32-V2_TDS754_waveform.CSV)
[RP2040_TDS754_waveform.CSV](https://github.com/adafruit/circuitpython/files/10378315/RP2040_TDS754_waveform.CSV)

### Description

- Tested with:
    2 - Feather ESP32-V2 boards (PID: 5400)
         ( I've not tested with the Feather ESP32-S2 board as I don't currently have those )
    2 - Feather RP2040 boards (PID: 4884)
    2 - DS18B20 sensors (PID: 381)
- Feather ESP32-V2 boards can't successfully scan for the DS18B20 onewire device(s).  Feather RP2040 boards work correctly.

In all test cases the Feather ESP32-V2s fail the scan for the DS18B20 sensor and the Feather RP2040s are able to successfully scan for the DS18B20 sensors. It looks to me like the issue might relate to the onewire.c bitbang timings, here:
[https://github.com/adafruit/circuitpyth ... /OneWire.c](https://github.com/adafruit/circuitpython/blob/main/shared-module/onewireio/OneWire.c)
but this is really just a guess at this point

Above I've attached example TDS754 waveform files from each board and an image of the first parts of each compared. There you can see where after what look like clean bus resets and presence pulses the ESP32-V2 board seems to stop talking on the onewire bus.

- might be related to:
https://github.com/adafruit/circuitpython/issues/3822
https://github.com/adafruit/circuitpython/pull/5866
https://github.com/adafruit/circuitpython/issues/964
https://forum.micropython.org/viewtopic.php?t=1792

### Additional information

Digging deeper I'm seeing both read and write issues on the bus.

I've made timing changes within 'shared-module>onewireio>OneWire.c' to try and speed up 'common_hal_onewireio_onewire_read_bit' and 'common_hal_onewireio_onewire_write_bit', but it seems I can't fully resolve the issues this way. I can now sometimes get up to 10 clean temperature reads of the ds18b20 sensor before unrecoverable errors occur. Next, as a timing sanity check, I tried just toggling the bus without delays as fast as possible (with the pull-up but without the sensor attached) and found these bit times aren't consistent - ranging from 500ns to 60us. I'm starting to think that as configured 'gpio_hal_set_level' is likely not reliable for these timings.

Then I found this:
https://esp32.com/viewtopic.php?t=713
DavidMKyle commented 1 year ago

I've grabbed a couple of Feather ESP32-S2 boards and they too appear to fail with the ds18b20 sensors on the onewire bus in the same way as the Feather ESP32-V2. I've not yet looked closely at the timings on these boards using a logic analyzer or scope.

dhalbert commented 8 months ago

Related to #5865, probably.