Open icebreaker87 opened 3 weeks ago
If I run the I2C scan (https://learn.adafruit.com/scanning-i2c-addresses/circuitpython), it does see the device at 0x50, but can't "speak" to it
It's hard to be sure without looking at the signals on the bus, but it looks like the seesaw device is crashing leaving the SCL line pulled low, that's why you get a timeout when the CircuitPython side waits on clock stretching, and it fails the test for pull-up resistors (because the line is kept low by the other side). Might be some combination of a bug in the seesaw device code, and different timings on different ports?
Try setting the I2C busio frequency to 400000: Replace:
i2c_bus = board.STEMMA_I2C()
with
import busio
# ...
i2c_bus = busio.I2C(board.SCL, board.SDA, frequency=400000)
There's a thread here: https://forums.adafruit.com/viewtopic.php?p=978381 that suggests that at least in some circumstances, that helps. That thread was about an RPi (not Pico).
As for the motor controller you mentioned in your forum thread, I have written to Kitronik, because I don't know whether there are pull-up resistors on their board. They don't appear to publish a schematic.
I have tried with your code, sadly shows exactly the same behavoir.
@deshipu but with arduino code it seems to work fine. This is why i thought, it would be more on the circuit python side, as the hardware is the same, just running a different code on. Sadly I don't have the equipment for testing the bus, I only own a multimeter.
I tried a similar seesaw board, Adafruit ANO Rotary Navigation Encoder to I2C Stemma QT Adapter, and was able to reproduce the problem, with both frequency=100000
and frequency=400000
. However, the program does not get ETIMEDOUT
with:
i2c_bus = busio.I2C(board.SCL, board.SDA, frequency=50000)
Try that and see if it lets you proceed.
This happens to me on the lilygo_twatch_s3
when files are being written with usb and the board is in it's low power state @ 40Mhz.
It's not related to a specific i2c library.
i2c_bus = busio.I2C(board.SCL, board.SDA, frequency=50000)
With this speed, it works perfect.
@bill88t if I run this code:
import microcontroller
microcontroller.cpu.frequency
the output is:
240000000
which to me sounds like full speed
@dhalbert If I test again with the motor driver, it's working now too. The only thing I have changed, is a bigger power supply (LiPo wit DC-DC Stepdown). Nothing changed in the code.
@icebreaker87 Glad to hear on both counts. I will check about the 50000 speed requirement internally. And it sounds like it was power sag on the motor driver.
This could be an artifact of our tick speed change from 100 to 1000. That shortens timeouts like: https://github.com/adafruit/circuitpython/blob/830294ebb533af1691e6afe0d58f5d4733fa099d/ports/espressif/common-hal/busio/I2C.c#L176
We should change the timeouts to be tick speed agnostic.
I'm having a very similar issue with I2C on QT-PY-ESP32-S2. I've come at it all kinds of ways, with one or multiple I2C devices and varying the I2C bus speed from 10_000 to 400_000.
With these i2c devices:
When I do a i2c.scan() it never shows any devices, but I can "speak" to the rotaryio. When I enable the ssd1306, I get:
main.py output:
sys.implementation=(name='circuitpython', version=(9, 1, 1), _machine='Adafruit QT Py ESP32S2 with ESP32S2', _mpy=262)
I2C_FREQ : 100000
I2C_DO_SCAN : True
I2C_USE_SSD1306: True
I2C_USE_SEESAW : True
Scanning I2C addresses: []
Position: 0
cnt_loops = 16 / sec
Traceback (most recent call last):
File "main.py", line 69, in <module>
File "adafruit_ssd1306.py", line 219, in show
File "adafruit_ssd1306.py", line 287, in write_framebuf
OSError: [Errno 116] ETIMEDOUT
If I never do the i2c.scan(), seesaw-rotaryio and ssd1306 appear to work fine (I've tried different instances of ssd1306 hardware).
In the case where I use only the seesaw-rotaryio and do i2c.scan(), the scan still shows no devices, I can communicate with the seesaw-rotario and my code speed decreases dramatically, e.g. 100+ loops/second becomes ~15 loops/second.
Code below. Can anyone shed some light on this?
Thanks, Casa
# ==============================================================================
#
from micropython import const
import busio
import board
import sys
from adafruit_ticks import ticks_ms, ticks_add, ticks_less
I2C_FREQ = const(100_000)
I2C_DO_SCAN: bool = True
I2C_USE_SSD1306: bool = True
I2C_USE_SEESAW: bool = True
MS_ONE_SECOND = const(1000)
# ------------------------------------------------------------------------------
print(f"{sys.implementation=}")
print(f"I2C_FREQ : {I2C_FREQ:6d}")
print(f"I2C_DO_SCAN : {I2C_DO_SCAN}")
print(f"I2C_USE_SSD1306: {I2C_USE_SSD1306}")
print(f"I2C_USE_SEESAW : {I2C_USE_SEESAW}")
# ------------------------------------------------------------------------------
def print_I2C_Scan(i2c: busio.i2c) -> None:
while not i2c.try_lock():
pass
print("Scanning I2C addresses:", [hex(i).upper() for i in i2c.scan()])
i2c.unlock()
# ------------------------------------------------------------------------------
# Set up i2c0, OLED, seesaw rotaryio
#
i2c0 = busio.I2C(board.SCL, board.SDA, frequency=I2C_FREQ)
if I2C_USE_SSD1306:
import adafruit_ssd1306
ADDR = const(0x3C)
WIDTH = const(128)
HEIGHT = const(64)
oled = adafruit_ssd1306.SSD1306_I2C(WIDTH, HEIGHT, i2c0, addr=ADDR)
if I2C_USE_SEESAW:
from adafruit_seesaw import seesaw, rotaryio #, digitalio
seesaw = seesaw.Seesaw(i2c0, 0x36)
encoder = rotaryio.IncrementalEncoder(seesaw)
last_position = None
# ------------------------------------------------------------------------------
if I2C_DO_SCAN:
print_I2C_Scan(i2c0) # PROBLEM HERE
# ------------------------------------------------------------------------------
cnt_loops: int = 0
cnt_printed: int = 0
ms_target: int = ticks_add(ticks_ms(), MS_ONE_SECOND)
try:
while True:
cnt_loops += 1
if not ticks_less(ticks_ms(), ms_target):
ms_target = ticks_add(ticks_ms(), MS_ONE_SECOND)
if cnt_printed < 10:
cnt_printed += 1
print(f"cnt_loops = {cnt_loops} / sec")
cnt_loops = 0
if I2C_USE_SSD1306:
oled.fill(0)
oled.show()
# oled.line(X_MAX, Y_MAX, X_MIN, Y_MIN, 1)
oled.vline(WIDTH // 2, 0, HEIGHT, 1)
oled.show()
if I2C_USE_SEESAW:
if (position := -encoder.position) != last_position:
last_position = position
print("Position: {}".format(position))
except KeyboardInterrupt:
print("Caught KeyboardInterrupt, exiting")
as a workaround, I switched to bitbangio.I2C
for my qtpy esp32-s2.
This could be an artifact of our tick speed change from 100 to 1000. That shortens timeouts like:
I did try changing the number of ticks to 1000 in I2C.c
. Unfortunately, I still got the same ETIMEDOUT. I agree it should be fixed as you mentioned.
@Casa-Machinalia I could not duplicate the OP problem on ESP32-S2, so I've made your issue be a separate issue: https://github.com/adafruit/circuitpython/issues/9561.
I tested with a seesaw board on an ESP32-S3. I get ETIMEDOUT starting at CircuitPython 9.0.0. It works in 8.2.10. There have been no significant changes to ports/espressif/common-hal/busio/I2C.c
for several years, so I think it's an ESP-IDF upgrade issue. I also rebuilt 9.1.2 with
-CONFIG_FREERTOS_HZ=1000
+CONFIG_FREERTOS_HZ=100
and it still fails. CONFIG_FREERTOS_HZ
was changed to 1000 post 9.0.0 anyway.
I started working on updating to the new 5.x.x ESP-IDF driver, @tannewt pointed out esp-camera is not yet updated, and the two drivers can't coexist. So I'll put any update on hold. @tannewt has done some of this update already.
I think this might be the issue: https://github.com/espressif/esp-idf/issues/13962
I'll update the IDF now to 5.3.1.
CircuitPython version
Code/REPL
Behavior
Traceback (most recent call last): File "", line 33, in
File "adafruit_seesaw/seesaw.py", line 342, in pin_mode_bulk
File "adafruit_seesaw/seesaw.py", line 329, in _pin_mode_bulk_x
File "adafruit_seesaw/seesaw.py", line 520, in write
OSError: [Errno 116] ETIMEDOUT
Description
This is the example code from adafruits gamepad qt guide. Get this everytime I try to run the code. After multiple tries, there is an error : Traceback (most recent call last): File "", line 27, in
RuntimeError: No pull up found on SDA or SCL; check your wiring
Bus this goes away if you unplug the board and power back on. On RP2040 based boards, it works out of the box (same CP version). If I use the same hardware but with arduino code (also from gamepad qt guide), it works always.
Additional information
No response