Files
PhotonVision/docs/source/docs/hardware/customhardware.md
Alan Everett 467f22bfdc Use diozero for GPIO (#2171)
The old GPIO abstraction was replaced with
[`diozero`](https://www.diozero.com), which supports most hardware
running Linux due to its use of GPIO character devices provided by the
Linux kernel. `diozero` also supports [alternate
providers](https://www.diozero.com/concepts/providers.html#providers) if
for some reason the character device API is insufficient. Certain
capabilities outside of the character device API is also implemented for
common hardware.

Custom GPIO commands are implemented via a custom `diozero` provider.
The configuration for custom GPIO will need manually updated according
to the Hardware Config documentation page.

The status LED class was also reworked to support additional statuses or
LED indication types, although none have been added yet.

This was tested on a RPi 5 with LL3 illumination LEDs and an RGB status
led attached. All capabilities worked as expected. All 8 status LED
colors were tested and functional via modifying the code. Basic
functionality of custom GPIO was tested with dummy commands.
2025-12-11 22:28:18 -06:00

5.5 KiB

Deploying on Custom Hardware

Configuration

By default, PhotonVision attempts to make minimal assumptions of the hardware it runs on. However, it may be configured to enable custom LED control, branding, and other functionality.

hardwareConfig.json is the location for this configuration. It is included when settings are exported, and can be uploaded as part of a .zip, or on its own.

LED Support

When running on Linux, PhotonVision can use diozero to control IO pins. The mapping of which pins control which LED's is part of the hardware config. The illumination LED pins are active-high: set high when LED's are commanded on, and set low when commanded off.

.. tab-set-code::
   .. code-block:: json

      {
        "ledPins" : [ 13 ],
        "ledsCanDim" : true,
        "ledBrightnessRange" : [ 0, 100 ],
        "ledPWMFrequency" : 0,
        "statusRGBPins" : [ ],
        "statusRGBActiveHigh" : false,
      }

:::{note} No hardware boards with status RGB LED pins or non-dimming LED's have been tested yet. Please reach out to the development team if these features are desired, they can assist with configuration and testing. :::

GPIO Pinout

::::{tab-set}

:::{tab-item} Raspberry Pi

The following diagram shows the GPIO pin numbering of the 40-pin header on Raspberry Pi hardware, courtesy of pinout.xyz. Compute modules use the pin numbering from their respective datasheet.

:alt: Raspberry Pi GPIO Pinout

::: ::::

Custom GPIO

If your hardware does not support diozero's default provider, custom commands can be provided to interact with the GPIO lines. The examples below show what parameters are provided to each command, which can be used in any order or multiple times as needed.

.. tab-set-code::
   .. code-block:: json

      {
        "getGPIOCommand" : "getGPIO {p}",
        "setGPIOCommand" : "setGPIO {p} {s}",
        "setPWMCommand" : "setPWM {p} {v}",
        "setPWMFrequencyCommand" : "setPWMFrequency {p} {f}",
        "releaseGPIOCommand" : "releseGPIO {p}",
      }

The following template strings are used to input parameters to the commands:

Template Parameter Values
{p} pin number integers
{s} state true/false
{v} value 0.0-1.0
{f} frequency integers

If you were using custom LED commands from 2025 or earlier and still need custom GPIO commands, they can likely be copied over. ledSetCommand can be reused as setGPIOCommand. ledDimCommand can be reused with edits as setPWMCommand, replacing any occurrences of {v} with $(awk 'BEGIN{ print int({v}*100) }') if your command requires integer percentages.

Hardware Interaction Commands

For Non-Raspberry-Pi hardware, users must provide valid hardware-specific commands for some parts of the UI interaction (including performance metrics, and executing system restarts).

Leaving a command blank will disable the associated functionality.

.. tab-set-code::
   .. code-block::  json

      {
        "cpuTempCommand" : "",
        "cpuMemoryCommand" : "",
        "cpuUtilCommand" : "",
        "gpuMemoryCommand" : "",
        "gpuTempCommand" : "",
        "ramUtilCommand" : "",
        "restartHardwareCommand" : "",
      }

:::{note} These settings have no effect if PhotonVision detects it is running on a Raspberry Pi. See the MetricsBase class for the commands utilized. :::

Known Camera FOV

If your hardware contains a camera with a known field of vision, it can be entered into the hardware configuration. This will prevent users from editing it in the GUI.

.. tab-set-code::
   .. code-block:: json

      {
        "vendorFOV" : 98.9
      }

Cosmetic & Branding

To help differentiate your hardware from other solutions, some customization is allowed.

.. tab-set-code::
   .. code-block:: json

      {
        "deviceName" : "Super Cool Custom Hardware",
        "deviceLogoPath" : "",
        "supportURL" : "https://cat-bounce.com/",
      }

:::{note} Not all configuration is currently presented in the User Interface. Additional file uploads may be needed to support custom images. :::

Example

Here is a complete example hardwareConfig.json:

.. tab-set-code::
   .. code-block:: json

      {
        "deviceName" : "Blinky McBlinkface",
        "deviceLogoPath" : "",
        "supportURL" : "https://www.youtube.com/watch?v=b-CvLWbfZhU",
        "ledPins" : [2, 13],
        "ledsCanDim" : true,
        "ledBrightnessRange" : [ 0, 100 ],
        "ledPWMFrequency" : 0,
        "statusRGBPins" : [ ],
        "statusRGBActiveHigh" : false,
        "getGPIOCommand" : "getGPIO {p}",
        "setGPIOCommand" : "setGPIO {p} {s}",
        "setPWMCommand" : "setPWM {p} {v}",
        "setPWMFrequencyCommand" : "setPWMFrequency {p} {f}",
        "releaseGPIOCommand" : "releseGPIO {p}",
        "cpuTempCommand" : "",
        "cpuMemoryCommand" : "",
        "cpuUtilCommand" : "",
        "gpuMemoryCommand" : "",
        "gpuTempCommand" : "",
        "ramUtilCommand" : "",
        "restartHardwareCommand" : "",
        "vendorFOV" : 72.5
      }