Skip to content
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

I2C on RP2040 has problems #4

Open
ilukinov opened this issue Jun 5, 2023 · 14 comments
Open

I2C on RP2040 has problems #4

ilukinov opened this issue Jun 5, 2023 · 14 comments

Comments

@ilukinov
Copy link

ilukinov commented Jun 5, 2023

Hi, thanks for the working on this)
Please provide examples for microcontrollers if possible.
Thanks

EDIT: see below #4 (comment) for actual issue/problem.

@2bndy5
Copy link
Owner

2bndy5 commented Jun 5, 2023

In Python?

@ilukinov
Copy link
Author

ilukinov commented Jun 5, 2023

yes

@2bndy5
Copy link
Owner

2bndy5 commented Jun 5, 2023

Sorry, I thought this was my Arduino-based lib for the same sensor.

The examples provided work with RP2040-based boards, but you just have to change the pin numbers.

@2bndy5
Copy link
Owner

2bndy5 commented Jun 5, 2023

I know because I tested it. Last time I tested it, the I2C interface on the itsybitsy RP2040 is buggy (not a lib issue - it was a circuitpython issue). SPI works fine on the itsbitsy RP2040.

@2bndy5
Copy link
Owner

2bndy5 commented Jun 5, 2023

Just in case you didn't find them, the examples are hosted with the lib here on github. You can also browse the docs and copy the examples' code from the docs' examples page.

@2bndy5 2bndy5 closed this as completed Jun 5, 2023
@ilukinov
Copy link
Author

ilukinov commented Jun 5, 2023

Thanks, I found examples right away. Maybe I'm doing something wrong here. When I use example below it will say that device is not found (I'm using rp2040 Zero board, it doesn't have board.I2C() so I have to do it manually):

import time
import board
import busio
from digitalio import DigitalInOut
from circuitpython_cirque_pinnacle import (
    PinnacleTouchSPI,
    PinnacleTouchI2C,
    RelativeReport,
    PINNACLE_RELATIVE,
)


print("-- Using I2C interface.")
dr_pin = DigitalInOut(board.GP1)
i2c = busio.I2C(board.GP27, board.GP26)
trackpad = PinnacleTouchI2C(i2c, dr_pin=dr_pin)

trackpad.data_mode = PINNACLE_RELATIVE  # ensure mouse mode is enabled
trackpad.relative_mode_config(True)  # enable tap detection

# an object to hold the data reported by the Pinnacle
data = RelativeReport()


def print_data(timeout=6):
    """Print available data reports from the Pinnacle touch controller
    until there's no input for a period of ``timeout`` seconds."""
    print(
        "Touch the trackpad to see the data. Exits after",
        timeout,
        "seconds of inactivity.",
    )
    start = time.monotonic()
    while time.monotonic() - start < timeout:
        while trackpad.available():  # is there new data?
            trackpad.read(data)
            print(data)
            start = time.monotonic()

output:
Using I2C interface. Traceback (most recent call last): File "code.py", line 16, in <module> File "/lib/circuitpython_cirque_pinnacle.py", line 905, in __init__ ValueError: No I2C device at address: 0x2a
Which is odd, because if I try code below it works just fine and outputs 42(0x2a)

import busio
import board

i2c = busio.I2C(board.GP27, board.GP26)
i2c.try_lock()
print('\n i2c scan: ' + str(i2c.scan()))
i2c.unlock()

output:
i2c scan: [42]

Now if I change your example code to:

import time
import board
import busio
from digitalio import DigitalInOut
from circuitpython_cirque_pinnacle import (
    PinnacleTouchSPI,
    PinnacleTouchI2C,
    RelativeReport,
    PINNACLE_RELATIVE,
)


print("-- Using I2C interface.")
dr_pin = DigitalInOut(board.GP1)
i2c = busio.I2C(board.GP27, board.GP26)
i2c.try_lock()
print('\n i2c scan: ' + str(i2c.scan()))
i2c.unlock()
trackpad = PinnacleTouchI2C(i2c, dr_pin=dr_pin)

trackpad.data_mode = PINNACLE_RELATIVE  # ensure mouse mode is enabled
trackpad.relative_mode_config(True)  # enable tap detection

# an object to hold the data reported by the Pinnacle
data = RelativeReport()


def print_data(timeout=6):
    """Print available data reports from the Pinnacle touch controller
    until there's no input for a period of ``timeout`` seconds."""
    print(
        "Touch the trackpad to see the data. Exits after",
        timeout,
        "seconds of inactivity.",
    )
    start = time.monotonic()
    while time.monotonic() - start < timeout:
        while trackpad.available():  # is there new data?
            trackpad.read(data)
            print(data)
            start = time.monotonic()

print_data()

output:
i2c scan: [42] 7 58 Touch the trackpad to see the data. Exits after 6 seconds of inactivity.
it will find trackpad now, but trackpad.available() will always be False (I tried with and without dr_pin)
I know that it can find touchpad because I added line to output firmware version to your code

print(firmware_id, firmware_ver)

it outputs:
7 58(0x3A)

Any advice on how to figure out what is happening?

p.s. R1 is removed on the touchpad.

@2bndy5
Copy link
Owner

2bndy5 commented Jun 5, 2023

Yeah, that's the bug I hit in CircuitPython. You already found the workaround. You have to manually check the device exists before init-ing the PinnacleTouch object. After that, everything worked fine.

To be clear, this is a bug in CircuitPython on the RP2040 boards. The same lib code works fine on the ATSAMD51 chip.

@2bndy5
Copy link
Owner

2bndy5 commented Jun 5, 2023

I also asked about this problem at the Adafruit Forums but got no response. So maybe its time to elevate this as a new issue over at adafruit/circuitpython repo.

FYI, this problem seems similar to adafruit/circuitpython#5871, but that was for espressif chips. Also this issue adafruit/circuitpython#4621 for the RP2040 boards seems related.

@ilukinov
Copy link
Author

ilukinov commented Jun 5, 2023

Well that's a bummer :( But as I mention even after workaround it still doesn't work for me

@2bndy5
Copy link
Owner

2bndy5 commented Jun 5, 2023

trackpad.available() will always be False (I tried with and without dr_pin)

I didn't catch that. Does track.pad.feed_enable == True?

@2bndy5
Copy link
Owner

2bndy5 commented Jun 5, 2023

IDK if you're proficient in C/C++, but I have a CirquePinnacle lib that explicitly supports the PicoSDK (includes specific examples). That lib tested much better on the same RP2040 board that hit that CircuitPython bug. In my experience, C/C++ is significantly faster on microcontrollers. But if you're tied to other dependencies/libs in CircuitPython, then that solution won't be entirely feasible.

@ilukinov
Copy link
Author

ilukinov commented Jun 5, 2023

trackpad.feed_enable is True. I am not that proficient in C/C++ :( I planned to use your lib with kmk firmware to have wireless keyboard with touchpad as a mouse (after making it work on rp2040 plan was to move to nrf52840).

@2bndy5
Copy link
Owner

2bndy5 commented Jun 5, 2023

Sorry I haven't hit any problems like "available() always False". I suppose you could also directly check the DR pin without using available(), but that seems redundant given how basic this lib's src code is around the dr_pin.
I think this might be another RP2040-specific problem, and will try to investigate/reproduce soon...

@2bndy5 2bndy5 reopened this Jun 5, 2023
@2bndy5 2bndy5 changed the title RP 2040 example? I2C on RP2040 has problems Jun 5, 2023
@2bndy5
Copy link
Owner

2bndy5 commented Jun 5, 2023

I don't recall testing this on my various nRF52 boards (which were purchased to develop for nRF24 org). Please raise a new issue if you find other problems.

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

No branches or pull requests

2 participants