Using machine Pin class no way to get pin number or channel when running on Pi Pico?
-
- Posts: 144
- Joined: Mon Jul 25, 2022 9:45 pm
Using machine Pin class no way to get pin number or channel when running on Pi Pico?
Using machine Pin class no way to get pin number or channel when running on Pi Pico? If I print using repr on the pin object, I can see a GPIO pin number, GPIO0 for example. but can't seem to figure out a way to access that property or attribute?
For example, using repr(thePin) returns "Pin(WL_GPIO0, mode=OUT)" which is the Pin assignment and configured mode.
Trying to develop a generic callback for handing the pin state, where I don't have to pass in the Pin object, the callback can just figure out which pin is applicable. RPi.GPIO does this in that the pin call back gets a channel int or number that tells you the pin applicable, but MicroPython rp2 module does not seem to support similar methodology?
I could create a class and jump through some hoops, tracking the Pin info, but when it is right there already?
For example, using repr(thePin) returns "Pin(WL_GPIO0, mode=OUT)" which is the Pin assignment and configured mode.
Trying to develop a generic callback for handing the pin state, where I don't have to pass in the Pin object, the callback can just figure out which pin is applicable. RPi.GPIO does this in that the pin call back gets a channel int or number that tells you the pin applicable, but MicroPython rp2 module does not seem to support similar methodology?
I could create a class and jump through some hoops, tracking the Pin info, but when it is right there already?
Re: Using machine Pin class no way to get pin number or channel when running on Pi Pico?
you could try:
but I'm not sure this is "Future-safe".
It works here for RPi2040.
Code: Select all
baddr=bytes(array('O', [pin]))
mem32[int.from_bytes(baddr, 'little')+4]
It works here for RPi2040.
Re: Using machine Pin class no way to get pin number or channel when running on Pi Pico?
Hello Jibun,
I'm not sure I understood your question.
Perhaps this is what you are looking for:
returns
['D26', 'A12']
['GPIO_AD_B1_14']
for me on Teensy 4.1
I'm not sure I understood your question.
Perhaps this is what you are looking for:
Code: Select all
from machine import Pin
pin1 = Pin('A12', Pin.OUT)
print(list((name for name, code in Pin.board.__dict__.items() if code == pin1)))
# or
print(list((name for name, code in Pin.cpu.__dict__.items() if code == pin1)))
['D26', 'A12']
['GPIO_AD_B1_14']
for me on Teensy 4.1
Re: Using machine Pin class no way to get pin number or channel when running on Pi Pico?
Hey Scruss,
Pin('LED') works for me on Teensy 4.1 and this name is revealed indeed if I look it up in Pin.board.__dict__.items() like posted above.
In RPI Pico I don't find Pin.board or Pin.cpu (those nasty inconsistencies in different ports .., is there something similar at least?). So the only way apart form extracting from repr string seems to be the array('O' , [pin]) thing?
BTW: In the official docs the array typecode 'O' does not exist. I 'stole' this part of code and can only assume that O might stand for Object.
Greetings,
Raul
Pin('LED') works for me on Teensy 4.1 and this name is revealed indeed if I look it up in Pin.board.__dict__.items() like posted above.
In RPI Pico I don't find Pin.board or Pin.cpu (those nasty inconsistencies in different ports .., is there something similar at least?). So the only way apart form extracting from repr string seems to be the array('O' , [pin]) thing?
BTW: In the official docs the array typecode 'O' does not exist. I 'stole' this part of code and can only assume that O might stand for Object.
Greetings,
Raul
Re: Using machine Pin class no way to get pin number or channel when running on Pi Pico?
You are right: I flashed the nightly build and now pin('LED') is possible even on RPI Pico! Nice.
Re: Using machine Pin class no way to get pin number or channel when running on Pi Pico?
On boards which have a repr of Pin(number) could use a regex:
Boards which uses a combination of characters and numbers, need a different regex and the value could not return as an int.
PS: I have tested this only on ESP32 and RP2040. I don't have a board with character in Pin mapping.
Code: Select all
import re
import micropython
from machine import Pin
pin_regex = micropython.const(re.compile(r"(\d+)"))
def pin_number(pin: Pin):
if match := pin_regex.search(repr(pin)):
return int(match.group(1))
return -1
# Tested with esp32 and rp2
p1 = Pin(22)
p2 = Pin(23)
p3 = Pin(25, mode=Pin.OUT, value=0)
for p in (p1, p2, p3):
print(pin_number(p))
Code: Select all
import re
import micropython
from machine import Pin
# I'm not sure if micropython.const is here useful
pin_char_digit_regex = micropython.const(re.compile("\((\d+)|'(\w+\d+)'\)"))
def pin_number(pin: Pin):
if match := pin_char_digit_regex.search(repr(pin)):
for group in match.groups():
if not group:
continue
try:
return int(group)
except ValueError:
return group
p1 = Pin(22)
p2 = Pin(23)
p3 = Pin(25, mode=Pin.OUT, value=0)
for p in (p1, p2, p3):
print(pin_number(p))
Re: Using machine Pin class no way to get pin number or channel when running on Pi Pico?
I could not get those to work,
I wrote the following function:
def extract_gpio_pin(pin_struct):
# Use a regular expression to find the GPIO number in the pin struct since .id() and .pin() don't work
match = re.search(r"GPIO(\d+)", str(pin_struct))
if match:
# Convert the extracted number to an integer to remove any leading zeros
return int(match.group(1))
else:
# Return None if no match is found (or raise an exception if that's preferable)
return None
This seems to work for me on the Pico RP2.
p1 = Pin(1)
p2 = Pin(23)
p3 = Pin(25, mode=Pin.OUT, value=0)
for p in (p1, p2, p3):
print(str(p))
print(extract_gpio_pin(p))
Returns:
Pin(GPIO1, mode=ALT, pull=PULL_DOWN, alt=31)
1
Pin(GPIO23, mode=ALT, pull=PULL_DOWN, alt=31)
23
Pin(GPIO25, mode=OUT)
25
I wrote the following function:
def extract_gpio_pin(pin_struct):
# Use a regular expression to find the GPIO number in the pin struct since .id() and .pin() don't work
match = re.search(r"GPIO(\d+)", str(pin_struct))
if match:
# Convert the extracted number to an integer to remove any leading zeros
return int(match.group(1))
else:
# Return None if no match is found (or raise an exception if that's preferable)
return None
This seems to work for me on the Pico RP2.
p1 = Pin(1)
p2 = Pin(23)
p3 = Pin(25, mode=Pin.OUT, value=0)
for p in (p1, p2, p3):
print(str(p))
print(extract_gpio_pin(p))
Returns:
Pin(GPIO1, mode=ALT, pull=PULL_DOWN, alt=31)
1
Pin(GPIO23, mode=ALT, pull=PULL_DOWN, alt=31)
23
Pin(GPIO25, mode=OUT)
25