Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
7f5d403
Migrate GPIO control to diozero
thatcomputerguy0101 Nov 9, 2025
88b374c
Update documentation to reflect the use of diozero
thatcomputerguy0101 Nov 9, 2025
cf8683c
Remove custom gpio commands
thatcomputerguy0101 Nov 9, 2025
8a574c2
Update tests for diozero
thatcomputerguy0101 Nov 9, 2025
eedec14
Calculate brightness percentage as a floating point number
thatcomputerguy0101 Nov 9, 2025
5c5af2d
Make for loops consistent in VisionLED
thatcomputerguy0101 Nov 9, 2025
b4c1ffa
Deduplicate code in VisionLED.setINternal
thatcomputerguy0101 Nov 9, 2025
e00aaa1
Calculate brightness as a double
thatcomputerguy0101 Nov 9, 2025
d046ce9
Add custom GPIO diozero provider
thatcomputerguy0101 Nov 9, 2025
531c3ca
Synchronize ShellExec `doProcess` to prevent race condition on gobblers
thatcomputerguy0101 Nov 9, 2025
d90f001
Add license header to new files
thatcomputerguy0101 Nov 9, 2025
3c69052
Add missing fields to HardwareConfig string
thatcomputerguy0101 Nov 9, 2025
77cfd39
Fix usage of default device factory in native gpio test
thatcomputerguy0101 Nov 9, 2025
3176d23
Replace Arrays.asList with List.of
thatcomputerguy0101 Nov 10, 2025
1dcb5e1
Replace Closable with AutoClosable
thatcomputerguy0101 Nov 10, 2025
b4cf56a
Use coercion instead of casting
thatcomputerguy0101 Nov 10, 2025
76d48c3
Remove unused device name from Custom GPIO adapter
thatcomputerguy0101 Nov 10, 2025
8ad20a5
Fix ledBrightnessRange config naming in the docs
thatcomputerguy0101 Nov 13, 2025
18a11f2
Restore ledPWMFrequency option
thatcomputerguy0101 Nov 13, 2025
4f9a636
Fix VisionLED constructor in tests
thatcomputerguy0101 Nov 14, 2025
4d2a779
Remove old ledPWMRange option from LL2+ config
thatcomputerguy0101 Nov 15, 2025
a9fab73
Add configurable status LED polarity
thatcomputerguy0101 Nov 15, 2025
47915b0
Use custom blink task to reduce thread count
thatcomputerguy0101 Nov 22, 2025
2641219
Status LED refactor
thatcomputerguy0101 Nov 23, 2025
78409e5
Revert "Synchronize ShellExec `doProcess` to prevent race condition o…
thatcomputerguy0101 Nov 28, 2025
5d67ba8
Use a different ShellExec per thread for GPIO
thatcomputerguy0101 Nov 28, 2025
35e798c
Add comments to CustomDigitalInputOutputDevice.setMode
thatcomputerguy0101 Dec 4, 2025
34c2d56
Add documentation for GPIO pinout on Raspberry Pi platforms
thatcomputerguy0101 Dec 7, 2025
942e3fb
Clean up Custom GPIO member initialization
thatcomputerguy0101 Dec 7, 2025
7202492
Early return from updateStatus
thatcomputerguy0101 Dec 7, 2025
9750cf6
Use arrow case labels in StatusLED.updateLED
thatcomputerguy0101 Dec 7, 2025
0556cb9
Move member definition in StatusLED
thatcomputerguy0101 Dec 7, 2025
f8695d8
Get system property strings from consuming classes
thatcomputerguy0101 Dec 8, 2025
bd07258
Explicitly pass around device factory to avoid system properties
thatcomputerguy0101 Dec 8, 2025
9e30b1a
Fix hardware tests
thatcomputerguy0101 Dec 9, 2025
e2798a3
Remove native device factory constructors from Status and Vision LED …
thatcomputerguy0101 Dec 9, 2025
f5bce58
Only create a deviceFactory if it will be used
thatcomputerguy0101 Dec 9, 2025
3907a78
Make deviceFactory lazily instantiated
thatcomputerguy0101 Dec 10, 2025
6a2b29b
Fix import from rebase
thatcomputerguy0101 Dec 10, 2025
2932fc6
Make logged error running GPIO commands more detailed
thatcomputerguy0101 Dec 10, 2025
97c89c9
Move and tweak VisionLED state comment
thatcomputerguy0101 Dec 11, 2025
6d46eac
Reorganize HardwareTest custom gpio initialization
thatcomputerguy0101 Dec 11, 2025
91aed38
Switch GPIO command error to use string concatenation
thatcomputerguy0101 Dec 12, 2025
f66d866
Make GPIO package lowercase
thatcomputerguy0101 Dec 12, 2025
9c68847
Reorder imports for spotless
thatcomputerguy0101 Dec 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"supportURL" : "https://limelightvision.io",
"ledPins" : [ 13, 18 ],
"ledsCanDim" : true,
"ledPWMRange" : [ 0, 100 ],
"ledPWMFrequency" : 30000,
"vendorFOV" : 75.76079874010732
}
64 changes: 53 additions & 11 deletions docs/source/docs/hardware/customhardware.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,69 @@ By default, PhotonVision attempts to make minimal assumptions of the hardware it

## LED Support

For Raspberry-Pi based hardware, PhotonVision can use [PiGPIO](https://abyz.me.uk/rpi/pigpio/) to control IO pins. The mapping of which pins control which LED's is part of the hardware config. The pins are active-high: set high when LED's are commanded on, and set low when commanded off.
When running on Linux, PhotonVision can use [diozero](https://www.diozero.com) 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.

```{eval-rst}
.. tab-set-code::
.. code-block:: json

{
"ledPins" : [ 13 ],
"ledSetCommand" : "",
"ledsCanDim" : true,
"ledPWMRange" : [ 0, 100 ],
"ledPWMSetRange" : "",
"ledBrightnessRange" : [ 0, 100 ],
"ledPWMFrequency" : 0,
"ledDimCommand" : "",
"ledBlinkCommand" : "",
"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](https://pinout.xyz). Compute modules use the pin numbering from their respective datasheet.

```{image} https://raw.githubusercontent.com/pinout-xyz/Pinout.xyz/master/resources/raspberry-pi-pinout.png
: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.

```{eval-rst}
.. 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).
Expand Down Expand Up @@ -101,14 +141,16 @@ Here is a complete example `hardwareConfig.json`:
"deviceLogoPath" : "",
"supportURL" : "https://www.youtube.com/watch?v=b-CvLWbfZhU",
"ledPins" : [2, 13],
"ledSetCommand" : "",
"ledsCanDim" : true,
"ledPWMRange" : [ 0, 100 ],
"ledPWMSetRange" : "",
"ledBrightnessRange" : [ 0, 100 ],
"ledPWMFrequency" : 0,
"ledDimCommand" : "",
"ledBlinkCommand" : "",
"statusRGBPins" : [ ],
"statusRGBActiveHigh" : false,
"getGPIOCommand" : "getGPIO {p}",
"setGPIOCommand" : "setGPIO {p} {s}",
"setPWMCommand" : "setPWM {p} {v}",
"setPWMFrequencyCommand" : "setPWMFrequency {p} {f}",
"releaseGPIOCommand" : "releseGPIO {p}",
"cpuTempCommand" : "",
"cpuMemoryCommand" : "",
"cpuUtilCommand" : "",
Expand Down
1 change: 1 addition & 0 deletions photon-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ dependencies {
// These stay as implementation dependencies since they don't have native code that gets packaged
implementation 'org.zeroturnaround:zt-zip:1.14'
implementation "org.xerial:sqlite-jdbc:3.41.0.0"
implementation 'com.diozero:diozero-core:1.4.1'

// The JNI libraries use wpilibNatives, the java libraries use implementation
if (jniPlatform == "linuxarm64") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,18 @@ public class HardwareConfig {

// LED control
public final ArrayList<Integer> ledPins;
public final String ledSetCommand;
public final boolean ledsCanDim;
public final ArrayList<Integer> ledBrightnessRange;
public final String ledDimCommand;
public final String ledBlinkCommand;
public final int ledPWMFrequency;
public final ArrayList<Integer> statusRGBPins;
public final boolean statusRGBActiveHigh;

// Custom GPIO
public final String getGPIOCommand;
public final String setGPIOCommand;
public final String setPWMCommand;
public final String setPWMFrequencyCommand;
public final String releaseGPIOCommand;

// Metrics
public final String cpuTempCommand;
Expand All @@ -55,12 +61,16 @@ public HardwareConfig(
String deviceLogoPath,
String supportURL,
ArrayList<Integer> ledPins,
String ledSetCommand,
boolean ledsCanDim,
ArrayList<Integer> ledBrightnessRange,
String ledDimCommand,
String ledBlinkCommand,
int ledPwmFrequency,
ArrayList<Integer> statusRGBPins,
boolean statusRGBActiveHigh,
String getGPIOCommand,
String setGPIOCommand,
String setPWMCommand,
String setPWMFrequencyCommand,
String releaseGPIOCommand,
String cpuTempCommand,
String cpuMemoryCommand,
String cpuUtilCommand,
Expand All @@ -76,12 +86,16 @@ public HardwareConfig(
this.deviceLogoPath = deviceLogoPath;
this.supportURL = supportURL;
this.ledPins = ledPins;
this.ledSetCommand = ledSetCommand;
this.ledsCanDim = ledsCanDim;
this.ledBrightnessRange = ledBrightnessRange;
this.ledDimCommand = ledDimCommand;
this.ledBlinkCommand = ledBlinkCommand;
this.ledPWMFrequency = ledPwmFrequency;
this.statusRGBPins = statusRGBPins;
this.statusRGBActiveHigh = statusRGBActiveHigh;
this.getGPIOCommand = getGPIOCommand;
this.setGPIOCommand = setGPIOCommand;
this.setPWMCommand = setPWMCommand;
this.setPWMFrequencyCommand = setPWMFrequencyCommand;
this.releaseGPIOCommand = releaseGPIOCommand;
this.cpuTempCommand = cpuTempCommand;
this.cpuMemoryCommand = cpuMemoryCommand;
this.cpuUtilCommand = cpuUtilCommand;
Expand All @@ -100,12 +114,16 @@ public HardwareConfig() {
deviceLogoPath = "";
supportURL = "";
ledPins = new ArrayList<>();
ledSetCommand = "";
ledsCanDim = false;
ledBrightnessRange = new ArrayList<>();
ledDimCommand = "";
ledBlinkCommand = "";
ledPWMFrequency = 0;
statusRGBPins = new ArrayList<>();
statusRGBActiveHigh = false;
getGPIOCommand = "";
setGPIOCommand = "";
setPWMCommand = "";
setPWMFrequencyCommand = "";
releaseGPIOCommand = "";
cpuTempCommand = "";
cpuMemoryCommand = "";
cpuUtilCommand = "";
Expand All @@ -127,7 +145,7 @@ public final boolean hasPresetFOV() {
}

/**
* @return True if any command has been configured to a non-default empty, false otherwise
* @return True if any info command has been configured to be non-empty, false otherwise
*/
public final boolean hasCommandsConfigured() {
return cpuTempCommand != ""
Expand All @@ -137,11 +155,21 @@ public final boolean hasCommandsConfigured() {
|| cpuUptimeCommand != ""
|| gpuMemoryCommand != ""
|| ramUtilCommand != ""
|| ledBlinkCommand != ""
|| gpuMemUsageCommand != ""
|| diskUsageCommand != "";
}

/**
* @return True if any gpio command has been configured to be non-empty, false otherwise
*/
public final boolean hasGPIOCommandsConfigured() {
return getGPIOCommand != ""
|| setGPIOCommand != ""
|| setPWMCommand != ""
|| setPWMFrequencyCommand != ""
|| releaseGPIOCommand != "";
}

@Override
public String toString() {
return "HardwareConfig[deviceName="
Expand All @@ -152,18 +180,26 @@ public String toString() {
+ supportURL
+ ", ledPins="
+ ledPins
+ ", ledSetCommand="
+ ledSetCommand
+ ", ledsCanDim="
+ ledsCanDim
+ ", ledBrightnessRange="
+ ledBrightnessRange
+ ", ledDimCommand="
+ ledDimCommand
+ ", ledBlinkCommand="
+ ledBlinkCommand
+ ", ledPWMFrequency="
+ ledPWMFrequency
+ ", statusRGBPins="
+ statusRGBPins
+ ", statusRGBActiveHigh"
+ statusRGBActiveHigh
+ ", getGPIOCommand="
+ getGPIOCommand
+ ", setGPIOCommand="
+ setGPIOCommand
+ ", setPWMCommand="
+ setPWMCommand
+ ", setPWMFrequencyCommand="
+ setPWMFrequencyCommand
+ ", releaseGPIOCommand="
+ releaseGPIOCommand
+ ", cpuTempCommand="
+ cpuTempCommand
+ ", cpuMemoryCommand="
Expand Down

This file was deleted.

Loading
Loading