Skip to content

add retries and delays to work around ESP32-S3 problems #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 19, 2022

Conversation

dhalbert
Copy link
Contributor

@dhalbert dhalbert commented Nov 10, 2022

ESP32-S3 has some issues with the clock-stretching and sleeping done by the LC709203F. See adafruit/circuitpython#6311.

  • Add retries when scanning for the device, and also add some delays during setup. This seems to mostly ameliorate the problems on the S3.
  • Raise ValueError for bad args, not AttributeError.
  • Raise OSError instead of RuntimeError on CRC failure. This makes it easier to catch all read/write failures so you can retry.

Tested with this program. Note the try-except which catches OSError. There can still be occasional failures, so it's good to catch and retry.

import time
import board
import busio
from adafruit_lc709203f import LC709203F, PackSize

uart = board.UART()
battery_monitor = LC709203F(board.I2C())
battery_monitor.pack_size = PackSize.MAH400

while True:
    try:
        print("Battery Percent: {:.2f} %".format(battery_monitor.cell_percent))
        print("Battery Voltage: {:.2f} V".format(battery_monitor.cell_voltage))

        uart.write(b"Battery Percent: {:.2f} %\r\n".format(battery_monitor.cell_percent))
        uart.write(b"Battery Voltage: {:.2f} V\r\n".format(battery_monitor.cell_voltage))
    except OSError:
        print("retrying reads")

    time.sleep(2)

@Gingertrout @BeatArnet @mopore @ThomasAtBBTF Could you try this changed version and see if it works for you? Thank you. You just need to copy the adafruit_lc709203f.py file in this pull request to your CIRCUITPY drive, which will override what is in your lib/. You should be able to remove the i2c.scan() code from your existing programs, since this does approximately the same thing.

New code is available at https://github.com/adafruit/Adafruit_CircuitPython_LC709203F/blob/1007e4c96bc465204de0cb5a3684022e9e0fb71b/adafruit_lc709203f.py

@BeatArnet
Copy link

After downloading the latest version of the adafruit_lc709203f.mpy library and running your sample code on my feather_s3_tft I got the following errors:

%Run -c $EDITOR_CONTENT
Zurückverfolgung (jüngste Aufforderung zuletzt):
Datei "", Zeile 7, in
Datei "adafruit_lc709203f.py", Zeile 132, in init
Datei "adafruit_lc709203f.py", Zeile 136, in init_RSOC
Datei "adafruit_lc709203f.py", Zeile 257, in _write_word
OSError: [Errno 116] ETIMEDOUT

@dhalbert
Copy link
Contributor Author

@BeatArnet
Copy link

BeatArnet commented Nov 10, 2022 via email

@dhalbert
Copy link
Contributor Author

@BeatArnet hmm, I saw a few missing reads, but not continuous as you did 🙁 . Are you using exactly the same test program, and which board are you testing on?

@BeatArnet
Copy link

BeatArnet commented Nov 10, 2022 via email

Copy link
Member

@tekktrik tekktrik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All makes sense to me! Question of of curiosity, why is ValueError what's being raised by the failed instancing of I2CDevice and not something like OSError itself?

Copy link
Member

@tekktrik tekktrik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I missed the ongoing conversation. Requesting changes so it doesn't show as "approved" until that's sorted out, my bad!

Copy link
Contributor

@FoamyGuy FoamyGuy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes look good to me. I think it's worthwhile to go ahead and merge this improvement even if there is still some situations that can still be problematic for other reasons.

I tested the code posted in this PR on a Feather S3 TFT with 8.0.0.beta.5. It has run successfully for several minutes for me with the branch from this PR.

@dhalbert or @tekktrik Do we have any specific reason to hold off merging this? It seems like there may still be underlying issues from upstream that can cause trouble, but the improvements here seem to stand on their own as well for this library.

@tekktrik
Copy link
Member

I'll defer to @dhalbert but I agree with you.

Also, I didn't fully realize until now that CircuitPython implemented the for/else combination, cool! I think this is the first time I've actually seen it in action.

@dhalbert
Copy link
Contributor Author

@FoamyGuy @tekktrik I did not merge it because @BeatArnet still had trouble. But it may be particular samples. So ok, let's merge it, and it will fix the problem at least some of the time.

@FoamyGuy FoamyGuy merged commit 38bd02f into adafruit:main Dec 19, 2022
@dhalbert dhalbert deleted the esp32-s3-retries branch December 19, 2022 17:49
@BeatArnet
Copy link

I could solve the problems, using the following code:

# The following code for scanning the I2C addresses is necessary so that the voltage can be measured
BATTERY_MON_ADDRESS = 0x0B  # Address for ESP32-s3 tft Feather

def hack_for_i2c_issue():
    i2c = board.I2C()
    while not i2c.try_lock():
        pass
    running = True
    try:
        while running:
            print("I2C addresses found:", 
                [hex(device_address) for device_address in i2c.scan()]
            )
            # time.sleep(2)
            running = False
        return i2c
    finally:  # unlock the i2c bus when ctrl-c'ing out of the loop
        i2c.unlock()

try:
    print("Searching for battery monitor...")

    i2c = hack_for_i2c_issue()
    battery_monitor = LC709203F(i2c)

For me, the problem is solved with the above hack.

@dhalbert
Copy link
Contributor Author

@BeatArnet The code I added is similar to your hack, but only tries three times to wake up the LC709203F. However, if it doesn't succeed, it will throw an exception. So I don't know why your eventually gets read failures. Perhaps the sensor is going back to sleep in a scenario I hadn't envisioned. We could retry reads a few times as well.

adafruit-adabot added a commit to adafruit/Adafruit_CircuitPython_Bundle that referenced this pull request Dec 20, 2022
Updating https://github.com/adafruit/Adafruit_CircuitPython_LC709203F to 2.2.10 from 2.2.9:
  > Merge pull request adafruit/Adafruit_CircuitPython_LC709203F#21 from dhalbert/esp32-s3-retries
  > Add .venv to .gitignore

Updating https://github.com/adafruit/Adafruit_CircuitPython_TLC59711 to 2.0.9 from 2.0.8:
  > Merge pull request adafruit/Adafruit_CircuitPython_TLC59711#22 from tcfranks/main
  > Add .venv to .gitignore
  > Update .pylintrc for v2.15.5
  > Fix release CI files
  > Update pylint to 2.15.5
  > Updated pylint version to 2.13.0
  > Switching to composite actions

Updating https://github.com/adafruit/Adafruit_CircuitPython_Wiznet5k to 1.12.17 from 1.12.16:
  > Merge pull request adafruit/Adafruit_CircuitPython_Wiznet5k#76 from BiffoBear/Rename_example_to_prevent_clash_with_pytest

Updating https://github.com/adafruit/Adafruit_CircuitPython_framebuf to 1.5.0 from 1.4.14:
  > Merge pull request adafruit/Adafruit_CircuitPython_framebuf#48 from philsuth/rgb565
  > Add .venv to .gitignore
  > Update .pylintrc for v2.15.5
  > Fix release CI files
  > Update pylint to 2.15.5
  > Updated pylint version to 2.13.0
  > Switching to composite actions

Updating https://github.com/adafruit/Adafruit_CircuitPython_Bundle/circuitpython_library_list.md to NA from NA:
  > Updated download stats for the libraries
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants