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

#3 Impossible to use pin #9

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This project aims to turn the Raspberry Pi Pico into an USB Host Adapter to control each Digital Input/Output.

![](./schema.png)
[![](./schema.png)](https://datasheets.raspberrypi.com/pico/pico-datasheet.pdf)

## Install firmware on your Pico

Expand Down
2 changes: 1 addition & 1 deletion firmware/src/dio_request_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use rp2040_hal::gpio::DynPinId;
// USB Communications Class Device support
use usbd_serial::SerialPort;

const MAX_PINS: usize = 23;
const MAX_PINS: usize = 29;

type PinO = rp2040_hal::gpio::Pin<
rp2040_hal::gpio::DynPinId,
Expand Down
18 changes: 9 additions & 9 deletions firmware/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,8 @@ unsafe fn main() -> ! {
.build();

// --------------------------------------------------------------

let mut pins_id: [Option<DynPinId>; 23] = [
const MAX_PINS: usize = 29;
let mut pins_id: [Option<DynPinId>; MAX_PINS] = [
None, // 0 debug uart
None, // 1 debug uart
Some(pins.gpio2.into_dyn_pin().id()),
Expand All @@ -245,13 +245,13 @@ unsafe fn main() -> ! {
Some(pins.gpio20.into_dyn_pin().id()),
Some(pins.gpio21.into_dyn_pin().id()),
Some(pins.gpio22.into_dyn_pin().id()),
// None, // 23
// None, // 24
// None, // 25 led
// None, // 26
// None, // 27
// None,
// None,
None, // 23 Controls the on-board SMPS Power Save pin
None, // 24 VBUS sense - high if VBUS is present, else low
None, // 25 Connected to user LED
Some(pins.gpio26.into_dyn_pin().id()),
Some(pins.gpio27.into_dyn_pin().id()),
Some(pins.gpio28.into_dyn_pin().id())
// None, // 29 Used in ADC mode (ADC3) to measure VSYS/3
];
#[cfg(not(any(feature = "uart0_debug")))]
{
Expand Down
2 changes: 1 addition & 1 deletion test/robot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ Here ```Protobuf Python Version: 5.28.0```

You will need an Raspberry Pico with Panduza Firmware flashed.

To simplified testing we connecte GPIOs by pair, link so:
To simplified testing we connecte GPIOs by pair, like so:

![PicoBenchSetup](./images/PicoBenchSetup.png)

Expand Down
54 changes: 41 additions & 13 deletions test/robot/libraries/API_PicoHostAdapterDio.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ def setup_logging(

# ================== Class =====================
class PicoHostAdapterDio:
"""Main API class to control Pico Host Adapter Dio"""

def __init__(
self, serial_COM: str, baudrate: int = 9600, bytesize: int = 8, timeout: int = 2
):
Expand Down Expand Up @@ -88,10 +90,13 @@ def __picoha_dio_request(
)
except TypeError as err:
logging.error(f"TypeError: {err}")
raise PicoHostAdapterDio(err)
except AttributeError as err:
logging.error(f"AttributeError: {err}")
raise PicoHostAdapterDio(err)
except Exception as err:
logging.error(f"Request Error: {err}")
raise PicoHostAdapterDio(err)

def __picoha_dio_answer(self):
"""Wait answer on serial COM"""
Expand All @@ -111,35 +116,58 @@ def __picoha_dio_answer(self):
return picoha_dio_answer
except Exception as err:
logging.error(err)
raise PicoHostAdapterDio(err)

def is_connected(self) -> bool:
"""Check if the serial port is open"""
return self.__serialPort.is_open

def ping_info(self):
"""Get ping info"""
"""
Get ping info
return :
type : Status of the command
"""
self.__picoha_dio_request(dio.RequestType.PING)
return self.__picoha_dio_answer().type

def set_gpio_direction(self, gpio: int, direction: dio.PinValue) -> int:
"""Set direction of pin in INPUT/OUTPUT"""
"""
Set direction of pin in INPUT/OUTPUT
return :
type : Status of the command
"""
self.__picoha_dio_request(dio.RequestType.SET_PIN_DIRECTION, gpio, direction)
return self.__picoha_dio_answer().type

def set_gpio_value(self, gpio: int, value: dio.PinValue) -> int:
"""Set value of gpio as HIGH/LOW"""
"""
Set value of gpio as HIGH/LOW
return :
type : Status of the command
"""
self.__picoha_dio_request(dio.RequestType.SET_PIN_VALUE, gpio, value)
return self.__picoha_dio_answer().type

def get_gpio_direction(self, gpio: int) -> int:
"""Get direction of gpio in INPUT/OUTPUT"""
def get_gpio_direction(self, gpio: int):
"""
Get direction of gpio in INPUT/OUTPUT
return :
type : Status of the command
value : value of GPIO
"""
self.__picoha_dio_request(dio.RequestType.GET_PIN_DIRECTION, gpio)
return self.__picoha_dio_answer().value

def get_gpio_value(self, gpio: int) -> int:
"""Get value of gpio as HIGH/LOW"""
return self.__picoha_dio_answer()

def get_gpio_value(self, gpio: int):
"""
Get value of gpio as HIGH/LOW
return :
type : Status of the command
value : value of GPIO
"""
self.__picoha_dio_request(dio.RequestType.GET_PIN_VALUE, gpio)
return self.__picoha_dio_answer().value
return self.__picoha_dio_answer()


# ================== Main ======================
Expand All @@ -156,16 +184,16 @@ def get_gpio_value(self, gpio: int) -> int:
test.ping_info()

test.set_gpio_direction(gpio=2,direction=dio.PinValue.OUTPUT)
test.get_gpio_direction(gpio=2)
dir_of_2 = test.get_gpio_direction(gpio=2).value

test.set_gpio_direction(gpio=3,direction=dio.PinValue.INPUT)
test.get_gpio_direction(gpio=3)
dir_of_3 = test.get_gpio_direction(gpio=3).value

# Main
for i in range(0,4,1):
print()
time.sleep(0.5)
test.set_gpio_value(gpio=2,value=1-i%2)
time.sleep(0.5)
test.get_gpio_value(gpio=3)
test.get_gpio_value(gpio=3).value
"""
144 changes: 144 additions & 0 deletions test/robot/libraries/TestSuit_NonReg_Git_Issues.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#!/usr/bin/env python3
"""
Test Suite of no regretion
Describe small test senarios to help validation of Git issues
"""

import __future__

__author__ = "Jason PUEL"
__date__ = "12 Jan 2025"

# ================== Imports ===================

import logging

# local imports

import api_dio_pb2 as dio
from launcher_Python_test import *
from API_PicoHostAdapterDio import PicoHostAdapterDio

# ========= Test Suite of no regretion =========
# Check Git Issue


@test_launcher
def impossible_to_reset_pins(test: PicoHostAdapterDio):
"""
Impossible to reset Pins to INTPUT #2
After Set pin to OUTPUT, user is not able to Reset pin to INPUT
"""
logging.info("Impossible to reset Pins to INTPUT #2")
test.ping_info()
test.set_gpio_direction(gpio=2, direction=dio.PinValue.OUTPUT)
test.get_gpio_direction(gpio=2)
test.set_gpio_direction(gpio=2, direction=dio.PinValue.INPUT)
if test.get_gpio_direction(gpio=2).value != dio.PinValue.INPUT:
raise TestFailException("GPIO not re-set to INPUT.")


@test_launcher
def impossible_to_use_pin(test: PicoHostAdapterDio):
"""
Impossible to use pin 26, 27 #3
For some reason, Pin 26, 27 and 28 are not usable
"""
logging.info("Impossible to use pin 26, 27 #3")
test.ping_info()
test.set_gpio_direction(gpio=26, direction=dio.PinValue.OUTPUT)
get_26 = test.get_gpio_direction(gpio=26).value
test.set_gpio_direction(gpio=27, direction=dio.PinValue.OUTPUT)
get_27 = test.get_gpio_direction(gpio=27).value
test.set_gpio_direction(gpio=28, direction=dio.PinValue.OUTPUT)
get_28 = test.get_gpio_direction(gpio=28).value

# Check if Pin direction can be Set
if (
get_26 != dio.PinValue.OUTPUT
or get_27 != dio.PinValue.OUTPUT
or get_28 != dio.PinValue.OUTPUT
):
raise TestFailException("GPIO not set to expected value.")

set_26 = test.set_gpio_value(gpio=26, value=dio.PinValue.LOW)
set_27 = test.set_gpio_value(gpio=27, value=dio.PinValue.LOW)
set_28 = test.set_gpio_value(gpio=28, value=dio.PinValue.LOW)

# Check if Pin are usable
if (
set_26 != dio.AnswerType.SUCCESS
or set_27 != dio.AnswerType.SUCCESS
or set_28 != dio.AnswerType.SUCCESS
):
raise TestFailException("GPIO not set to expected value.")


@test_launcher
@timeout_wrapper(30)
def no_failure_when_using_not_existing_pins(test: PicoHostAdapterDio):
"""
No FAILURE when using not existing PINs #4
Here there is no FAILURE when using pin out of range AND it stuck the system
"""
logging.info("No FAILURE when using not existing PINs #4")

test.ping_info()
no_expected_error = ""

if (
test.set_gpio_direction(gpio=50, direction=dio.PinValue.OUTPUT)
!= dio.AnswerType.FAILURE
):
no_expected_error += "set_gpio_direction, "

if test.get_gpio_direction(gpio=50).type != dio.AnswerType.FAILURE:
no_expected_error += "get_gpio_direction, "

if test.set_gpio_value(gpio=50, value=dio.PinValue.HIGH) != dio.AnswerType.FAILURE:
no_expected_error += "set_gpio_value, "

test.ping_info()
if no_expected_error != "":
raise TestFailException(f"GPIO not set to expected value: {no_expected_error}")


@test_launcher
def fail_to_read_gpio_value(test: PicoHostAdapterDio):
"""
Failure to read GPIO value #8
When the OUTPUT GPIO's value is set to HIGH, we shall be able to 'GET_PIN_VALUE' with the INPUT GPIO
"""
logging.info("Failure to read GPIO value #8")
test.ping_info()
test.set_gpio_direction(gpio=4, direction=dio.PinValue.INPUT)
test.get_gpio_direction(gpio=4)
test.set_gpio_direction(gpio=5, direction=dio.PinValue.OUTPUT)
test.get_gpio_direction(gpio=5)

test.set_gpio_value(gpio=5, value=dio.PinValue.HIGH)
if test.get_gpio_value(gpio=4).value != dio.PinValue.HIGH:
raise TestFailException("GPIO not set to expected value.")

test.set_gpio_value(gpio=5, value=dio.PinValue.LOW)
if test.get_gpio_value(gpio=4).value != dio.PinValue.LOW:
raise TestFailException("GPIO not set to expected value.")


# ============= Main Fonctions =================

if __name__ == "__main__":
"""Run small test senarios to help in Git issues validation"""
from API_PicoHostAdapterDio import setup_logging

# Setup
setup_logging(loggingLevel=logging.DEBUG)
test = PicoHostAdapterDio("COM5")

# Main
impossible_to_reset_pins(test)
impossible_to_use_pin(test)
no_failure_when_using_not_existing_pins(test)
fail_to_read_gpio_value(test)

print_results()
6 changes: 3 additions & 3 deletions test/robot/libraries/gpio_keywords.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def set_gpio_direction(gpio: int, direction: dio.PinValue):

def get_gpio_direction(gpio: int):
"""Return the GPIO direction"""
direction = test.get_gpio_direction(gpio)
direction = test.get_gpio_direction(gpio).value
if direction == dio.PinValue.INPUT:
return "INPUT"
elif direction == dio.PinValue.OUTPUT:
Expand All @@ -94,7 +94,7 @@ def set_gpio_value(gpio: int, value):

def get_gpio_value(gpio: int):
"""Return GPIO direction"""
value = test.get_gpio_value(gpio)
value = test.get_gpio_value(gpio).value
if value == dio.PinValue.LOW:
return "LOW"
elif value == dio.PinValue.HIGH:
Expand All @@ -114,7 +114,7 @@ def check_gpio_direction(gpio: int, direction: str):
def check_gpio_value(gpio: int, value):
"""Verified for a given GPIO than its value is set by reading the input on its paired GPIO"""
if not get_gpio_value(gpio) == value:
raise ValueError(f"GPIO '{gpio} is not set as {value}")
raise ValueError(f"GPIO '{gpio}' is not set as {value}")
else:
return True

Expand Down
Loading