From 930e9927703eeb8b90c9c951e3a310143379bf9a Mon Sep 17 00:00:00 2001 From: Corey Thompson Date: Fri, 2 Jan 2026 00:22:39 -0600 Subject: [PATCH 01/12] Fix Upload Firmware batch file path to tools subdirectory The build_release.sh script places upload_firmware.ps1 in the tools/ subdirectory, but the batch file was looking for it in the root directory. Updated batch file to reference tools\upload_firmware.ps1. --- Upload Firmware (Windows).bat | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Upload Firmware (Windows).bat b/Upload Firmware (Windows).bat index 0fcf3d4..f7885df 100644 --- a/Upload Firmware (Windows).bat +++ b/Upload Firmware (Windows).bat @@ -15,8 +15,8 @@ echo. REM Change to the directory where this script is located cd /d "%~dp0" -REM Run the PowerShell script with bypass execution policy -PowerShell -ExecutionPolicy Bypass -File "%~dp0upload_firmware.ps1" +REM Run the PowerShell script from tools subdirectory with bypass execution policy +PowerShell -ExecutionPolicy Bypass -File "%~dp0tools\upload_firmware.ps1" REM If PowerShell failed, show error if %ERRORLEVEL% NEQ 0 ( From d8590ae902033b18b48712bc38e5cfa441cbb209 Mon Sep 17 00:00:00 2001 From: Corey Thompson Date: Fri, 2 Jan 2026 00:27:22 -0600 Subject: [PATCH 02/12] Fix empty device display in PowerShell upload script When multiple USB devices are detected, the device names were not displaying properly, showing empty entries. Now displays the COM port number at minimum, and includes the full device name if available. This fixes the issue where users see empty device listings when connecting multiple USB devices to their computer. --- upload_firmware.ps1 | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/upload_firmware.ps1 b/upload_firmware.ps1 index e2e3e68..378fb00 100644 --- a/upload_firmware.ps1 +++ b/upload_firmware.ps1 @@ -357,7 +357,12 @@ function Select-Port { if ($ports.Count -eq 1) { $script:SelectedPort = $ports[0].Port - Write-Success "Found device: $($ports[0].Name)" + $displayName = if ($ports[0].Name -and $ports[0].Name -ne $ports[0].Port) { + "$($ports[0].Port) - $($ports[0].Name)" + } else { + $ports[0].Port + } + Write-Success "Found device: $displayName" Write-Host "" if (Ask-YesNo "Use this device?") { return $true @@ -366,7 +371,12 @@ function Select-Port { Write-Host "Multiple devices found:" -ForegroundColor White Write-Host "" for ($i = 0; $i -lt $ports.Count; $i++) { - Write-Host " $($i + 1)) $($ports[$i].Name)" + $displayName = if ($ports[$i].Name -and $ports[$i].Name -ne $ports[$i].Port) { + "$($ports[$i].Port) - $($ports[$i].Name)" + } else { + $ports[$i].Port + } + Write-Host " $($i + 1)) $displayName" } Write-Host "" From 36c7f34338ced2875cfc298c5e6a7826988657ce Mon Sep 17 00:00:00 2001 From: Corey Thompson Date: Fri, 2 Jan 2026 00:28:25 -0600 Subject: [PATCH 03/12] Fix firmware path in PowerShell upload script The script was looking for firmware in tools/arduino instead of source/arduino. Updated to find the source folder relative to the release package root directory. Path now correctly resolves to: release_root/source/arduino/JudgeController --- upload_firmware.ps1 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/upload_firmware.ps1 b/upload_firmware.ps1 index 378fb00..bd8e606 100644 --- a/upload_firmware.ps1 +++ b/upload_firmware.ps1 @@ -9,7 +9,11 @@ $ErrorActionPreference = "Stop" # Get the directory where this script is located $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path -$ArduinoDir = Join-Path $ScriptDir "arduino" + +# The Arduino source is in the source/ folder at the release root +# Script is in tools/, so go up one level and into source/ +$ReleaseRoot = Split-Path -Parent $ScriptDir +$ArduinoDir = Join-Path $ReleaseRoot "source" "arduino" # Global variables $script:SelectedPort = "" From 14cf7f760382c5a6518ec775f13b1864a3670a3c Mon Sep 17 00:00:00 2001 From: Corey Thompson Date: Fri, 2 Jan 2026 00:32:09 -0600 Subject: [PATCH 04/12] Remove flash firmware support - only support Arduino upload The pre-compiled firmware and flash scripts are untested and unused. Only support the Arduino CLI compile-from-source upload method. Changes: - Remove firmware compilation from build_release.sh - Remove flash_firmware.sh and flash_firmware.ps1 - Remove Flash Firmware (Windows).bat from release package - Update build_release.sh to only include source code and upload tools - Simplify UPLOAD_GUIDE.md to show only Arduino upload method - Update README.txt template to reflect source-only approach --- UPLOAD_GUIDE.md | 56 +++++------------------------------ build_release.sh | 77 +++++++----------------------------------------- 2 files changed, 17 insertions(+), 116 deletions(-) diff --git a/UPLOAD_GUIDE.md b/UPLOAD_GUIDE.md index eb3c962..a202b73 100644 --- a/UPLOAD_GUIDE.md +++ b/UPLOAD_GUIDE.md @@ -9,9 +9,8 @@ The latest SledLink release package is available on GitHub: **[Download Latest Release](https://github.com/thompcd/SledLink/releases/latest)** Each release includes: -- Pre-compiled firmware binaries (ready to flash) -- Upload and flash scripts -- Source code +- Arduino source code for both controllers +- Upload scripts for Windows, Mac, and Linux - This guide --- @@ -21,50 +20,16 @@ Each release includes: 1. **Your SledLink controller** (either the Sled or Judge unit) 2. **A USB cable** (micro-USB, the same type used for many Android phones) 3. **A computer** (Windows, Mac, or Linux) -4. **An internet connection** (only needed the first time to download tools) +4. **An internet connection** (needed to download tools on first use) --- -## Two Options +## Upload Firmware -There are two ways to upload firmware: - -| Method | Best For | What It Does | -|--------|----------|--------------| -| **Flash Pre-Compiled** | Field use, quick updates | Uses ready-to-go firmware files | -| **Compile from Source** | Developers, customization | Builds firmware from source code | - -**For most users, we recommend "Flash Pre-Compiled"** - it's faster and simpler. +The firmware is compiled fresh from source code during the upload process. --- -## Option 1: Flash Pre-Compiled Firmware (Recommended) - -This is the **easiest method**. Use this if you downloaded a release package. - -### Windows - -1. **Download the SledLink release** and unzip it -2. **Double-click** `Flash Firmware (Windows).bat` -3. **Follow the prompts** on screen - -### Mac / Linux - -1. **Download the SledLink release** and unzip it -2. **Open Terminal** in that folder -3. **Run:** - ``` - chmod +x flash_firmware.sh # only needed once - ./flash_firmware.sh - ``` -4. **Follow the prompts** on screen - ---- - -## Option 2: Compile from Source - -Use this if you need to modify the firmware or don't have pre-compiled binaries. - ### Windows 1. **Download the SledLink folder** to your computer @@ -106,20 +71,13 @@ Use this if you need to modify the firmware or don't have pre-compiled binaries. --- -## What the Scripts Do - -### Flash Script (Pre-Compiled) -1. **Checks for esptool** - A simple flashing tool. Installs it if needed. -2. **Asks which controller** - Sled or Judge -3. **Finds your controller** - Detects the connected USB device -4. **Flashes the firmware** - Writes the pre-compiled binary to the controller +## What the Upload Script Does -### Upload Script (From Source) 1. **Checks for Arduino CLI** - The build tool. Installs it if needed. 2. **Sets up ESP32 support** - Downloads ESP32 tools (first time only) 3. **Asks which controller** - Sled or Judge 4. **Finds your controller** - Detects the connected USB device -5. **Compiles and uploads** - Builds from source and writes to controller +5. **Compiles and uploads** - Builds fresh firmware from source and writes to your controller ## Troubleshooting diff --git a/build_release.sh b/build_release.sh index e34e96c..3f9f004 100644 --- a/build_release.sh +++ b/build_release.sh @@ -68,47 +68,13 @@ mkdir -p "$OUTPUT_DIR/firmware" mkdir -p "$OUTPUT_DIR/tools" mkdir -p "$OUTPUT_DIR/source" -# Compile SledController -echo "" -echo "Compiling SledController..." -arduino-cli compile --fqbn esp32:esp32:esp32 \ - --output-dir "$OUTPUT_DIR/firmware/SledController" \ - "$SCRIPT_DIR/arduino/SledController" - -# Compile JudgeController -echo "" -echo "Compiling JudgeController..." -arduino-cli compile --fqbn esp32:esp32:esp32 \ - --output-dir "$OUTPUT_DIR/firmware/JudgeController" \ - "$SCRIPT_DIR/arduino/JudgeController" - -# Copy only the .bin files we need and rename for clarity -echo "" -echo "Organizing firmware files..." -cp "$OUTPUT_DIR/firmware/SledController/SledController.ino.bin" "$OUTPUT_DIR/firmware/SledController.bin" -cp "$OUTPUT_DIR/firmware/SledController/SledController.ino.bootloader.bin" "$OUTPUT_DIR/firmware/SledController.bootloader.bin" -cp "$OUTPUT_DIR/firmware/SledController/SledController.ino.partitions.bin" "$OUTPUT_DIR/firmware/SledController.partitions.bin" - -cp "$OUTPUT_DIR/firmware/JudgeController/JudgeController.ino.bin" "$OUTPUT_DIR/firmware/JudgeController.bin" -cp "$OUTPUT_DIR/firmware/JudgeController/JudgeController.ino.bootloader.bin" "$OUTPUT_DIR/firmware/JudgeController.bootloader.bin" -cp "$OUTPUT_DIR/firmware/JudgeController/JudgeController.ino.partitions.bin" "$OUTPUT_DIR/firmware/JudgeController.partitions.bin" - -# Clean up intermediate build directories -rm -rf "$OUTPUT_DIR/firmware/SledController" -rm -rf "$OUTPUT_DIR/firmware/JudgeController" - -# Copy upload tools +# Copy upload tools for compiling from source echo "Copying upload tools..." cp "$SCRIPT_DIR/upload_firmware.sh" "$OUTPUT_DIR/tools/" cp "$SCRIPT_DIR/upload_firmware.ps1" "$OUTPUT_DIR/tools/" cp "$SCRIPT_DIR/Upload Firmware (Windows).bat" "$OUTPUT_DIR/" chmod +x "$OUTPUT_DIR/tools/upload_firmware.sh" -# Copy flash scripts for pre-compiled binaries -cp "$SCRIPT_DIR/flash_firmware.sh" "$OUTPUT_DIR/" 2>/dev/null || true -cp "$SCRIPT_DIR/flash_firmware.ps1" "$OUTPUT_DIR/tools/" 2>/dev/null || true -cp "$SCRIPT_DIR/Flash Firmware (Windows).bat" "$OUTPUT_DIR/" 2>/dev/null || true - # Copy source code echo "Copying source code..." cp -r "$SCRIPT_DIR/arduino" "$OUTPUT_DIR/source/" @@ -132,47 +98,24 @@ RELEASE INFORMATION Build Date: $(date +%Y-%m-%d) Download: https://github.com/thompcd/SledLink/releases/tag/$VERSION -This release contains pre-compiled firmware and tools for the SledLink system. +This release contains source code and tools to compile and upload firmware to the SledLink system. CONTENTS -------- - firmware/ - Pre-compiled firmware binaries - SledController.bin - Firmware for the sled unit - JudgeController.bin - Firmware for the judge display unit - *.bootloader.bin - ESP32 bootloader files - *.partitions.bin - ESP32 partition tables - - tools/ - Upload utilities - upload_firmware.sh - Mac/Linux upload script (compiles from source) - upload_firmware.ps1 - Windows PowerShell upload script - source/ - Arduino source code arduino/SledController/ - Sled controller source - arduino/JudgeController/- Judge controller source + arduino/JudgeController/ - Judge controller source - Flash Firmware (Windows).bat - Double-click to flash pre-compiled firmware - Upload Firmware (Windows).bat - Double-click to compile & upload from source - - -QUICK START - FLASHING PRE-COMPILED FIRMWARE ---------------------------------------------- -This is the EASIEST method - uses pre-compiled binaries, no compilation needed. - -Windows: - 1. Connect the controller via USB - 2. Double-click "Flash Firmware (Windows).bat" - 3. Follow the prompts + tools/ - Upload utilities + upload_firmware.sh - Mac/Linux upload script + upload_firmware.ps1 - Windows PowerShell upload script -Mac/Linux: - 1. Connect the controller via USB - 2. Open Terminal in this folder - 3. Run: ./flash_firmware.sh - 4. Follow the prompts + Upload Firmware (Windows).bat - Double-click to upload firmware -ALTERNATIVE - COMPILE FROM SOURCE ---------------------------------- -Use this if you've modified the source code or prefer to compile fresh. +QUICK START - UPLOAD FIRMWARE +----------------------------- +The firmware is compiled fresh from source code during upload. Windows: 1. Connect the controller via USB From e78d7ea02d0c0ba8aca53f41799ae00ed3b465b9 Mon Sep 17 00:00:00 2001 From: Corey Thompson Date: Fri, 2 Jan 2026 00:40:46 -0600 Subject: [PATCH 05/12] Fix Join-Path error in PowerShell upload script Join-Path only accepts 2 positional arguments. Nested the calls to properly construct the path to the Arduino source directory. Old: Join-Path $ReleaseRoot "source" "arduino" New: Join-Path (Join-Path $ReleaseRoot "source") "arduino" --- upload_firmware.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/upload_firmware.ps1 b/upload_firmware.ps1 index bd8e606..5f41d6f 100644 --- a/upload_firmware.ps1 +++ b/upload_firmware.ps1 @@ -13,7 +13,7 @@ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path # The Arduino source is in the source/ folder at the release root # Script is in tools/, so go up one level and into source/ $ReleaseRoot = Split-Path -Parent $ScriptDir -$ArduinoDir = Join-Path $ReleaseRoot "source" "arduino" +$ArduinoDir = Join-Path (Join-Path $ReleaseRoot "source") "arduino" # Global variables $script:SelectedPort = "" From 609a877777d7251ec24e975ac55dadc9a30fb2c0 Mon Sep 17 00:00:00 2001 From: Corey Thompson Date: Fri, 2 Jan 2026 00:48:18 -0600 Subject: [PATCH 06/12] Make batch file work in both repo and release contexts The batch file now checks for upload_firmware.ps1 in two locations: 1. tools/upload_firmware.ps1 (release package structure) 2. upload_firmware.ps1 (local repository structure) This allows the batch file to work whether you're testing locally or using the release package, and provides helpful error messages if the script can't be found. --- Upload Firmware (Windows).bat | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/Upload Firmware (Windows).bat b/Upload Firmware (Windows).bat index f7885df..163f319 100644 --- a/Upload Firmware (Windows).bat +++ b/Upload Firmware (Windows).bat @@ -15,8 +15,28 @@ echo. REM Change to the directory where this script is located cd /d "%~dp0" -REM Run the PowerShell script from tools subdirectory with bypass execution policy -PowerShell -ExecutionPolicy Bypass -File "%~dp0tools\upload_firmware.ps1" +REM Check if we're in a release package (tools subdirectory exists) or local repo +if exist "%~dp0tools\upload_firmware.ps1" ( + REM Release package structure + PowerShell -ExecutionPolicy Bypass -File "%~dp0tools\upload_firmware.ps1" +) else if exist "%~dp0upload_firmware.ps1" ( + REM Local repository structure + PowerShell -ExecutionPolicy Bypass -File "%~dp0upload_firmware.ps1" +) else ( + echo. + echo ============================================ + echo ERROR: upload_firmware.ps1 not found! + echo ============================================ + echo. + echo Could not find the PowerShell script in: + echo - %~dp0tools\upload_firmware.ps1 (release package) + echo - %~dp0upload_firmware.ps1 (local repo) + echo. + echo Make sure you're running this from the correct directory. + echo. + pause + exit /b 1 +) REM If PowerShell failed, show error if %ERRORLEVEL% NEQ 0 ( From 3447f2b9d6ed32d850fbb75e18c2ba90c2fa7535 Mon Sep 17 00:00:00 2001 From: Corey Thompson Date: Fri, 2 Jan 2026 01:01:46 -0600 Subject: [PATCH 07/12] Improve serial port detection in PowerShell script Changed port detection method to be more reliable: 1. Primary method: Use .NET SerialPort.GetPortNames() to reliably get COM ports 2. Friendly names: Query WMI for device descriptions when available 3. Fallback: Use WMI-only search if primary method fails This ensures COM port numbers are always displayed, even if device names are unavailable, fixing the empty device listing issue. --- upload_firmware.ps1 | 60 +++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/upload_firmware.ps1 b/upload_firmware.ps1 index 5f41d6f..71241f3 100644 --- a/upload_firmware.ps1 +++ b/upload_firmware.ps1 @@ -275,40 +275,52 @@ function Select-Controller { ############################################################################# function Get-SerialPorts { - # Get COM ports from WMI + # Get COM ports - try multiple methods for compatibility $ports = @() - # Method 1: Check for USB Serial devices + # Method 1: Use .NET SerialPort to get actual COM ports try { - $usbPorts = Get-WmiObject Win32_PnPEntity | Where-Object { - $_.Name -match "COM\d+" -and ( - $_.Name -match "USB" -or - $_.Name -match "Serial" -or - $_.Name -match "CH340" -or - $_.Name -match "CP210" -or - $_.Name -match "FTDI" -or - $_.Name -match "Silicon Labs" - ) - } - - foreach ($port in $usbPorts) { - if ($port.Name -match "(COM\d+)") { - $ports += @{ - Port = $Matches[1] - Name = $port.Name + $comPorts = [System.IO.Ports.SerialPort]::GetPortNames() + foreach ($port in $comPorts) { + # Try to get friendly name from WMI + $friendlyName = $port + try { + $deviceInfo = Get-WmiObject Win32_PnPEntity | Where-Object { + $_.Name -match $port + } | Select-Object -First 1 + + if ($deviceInfo) { + $friendlyName = $deviceInfo.Name } + } catch {} + + $ports += @{ + Port = $port + Name = $friendlyName } } } catch {} - # Method 2: Fallback to checking all COM ports + # Fallback Method 2: Check WMI for USB devices with COM ports if ($ports.Count -eq 0) { try { - $comPorts = [System.IO.Ports.SerialPort]::GetPortNames() - foreach ($port in $comPorts) { - $ports += @{ - Port = $port - Name = $port + $usbPorts = Get-WmiObject Win32_PnPEntity | Where-Object { + $_.Name -match "COM\d+" -and ( + $_.Name -match "USB" -or + $_.Name -match "Serial" -or + $_.Name -match "CH340" -or + $_.Name -match "CP210" -or + $_.Name -match "FTDI" -or + $_.Name -match "Silicon Labs" + ) + } + + foreach ($port in $usbPorts) { + if ($port.Name -match "(COM\d+)") { + $ports += @{ + Port = $Matches[1] + Name = $port.Name + } } } } catch {} From d77bfb01aa2214499b92e992688171118656539d Mon Sep 17 00:00:00 2001 From: Corey Thompson Date: Fri, 2 Jan 2026 01:05:12 -0600 Subject: [PATCH 08/12] Fix device display by simplifying variable assignment The previous inline if statement in Write-Host was causing the display to show empty values. Changed to assign port/name to variables first, then use them in Write-Host calls. Also removed debug output now that we've verified port detection works. --- upload_firmware.ps1 | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/upload_firmware.ps1 b/upload_firmware.ps1 index 71241f3..26ed12e 100644 --- a/upload_firmware.ps1 +++ b/upload_firmware.ps1 @@ -373,12 +373,15 @@ function Select-Port { if ($ports.Count -eq 1) { $script:SelectedPort = $ports[0].Port - $displayName = if ($ports[0].Name -and $ports[0].Name -ne $ports[0].Port) { - "$($ports[0].Port) - $($ports[0].Name)" + $port = $ports[0].Port + $name = $ports[0].Name + + # Show port and name for clarity + if ($name -and $name -ne $port) { + Write-Success "Found device: $port - $name" } else { - $ports[0].Port + Write-Success "Found device: $port" } - Write-Success "Found device: $displayName" Write-Host "" if (Ask-YesNo "Use this device?") { return $true @@ -387,12 +390,15 @@ function Select-Port { Write-Host "Multiple devices found:" -ForegroundColor White Write-Host "" for ($i = 0; $i -lt $ports.Count; $i++) { - $displayName = if ($ports[$i].Name -and $ports[$i].Name -ne $ports[$i].Port) { - "$($ports[$i].Port) - $($ports[$i].Name)" + $port = $ports[$i].Port + $name = $ports[$i].Name + + # Show port and name separately for clarity + if ($name -and $name -ne $port) { + Write-Host " $($i + 1)) $port - $name" } else { - $ports[$i].Port + Write-Host " $($i + 1)) $port" } - Write-Host " $($i + 1)) $displayName" } Write-Host "" From 8c43d4e3fb47969cc4f2026bb1e6a6e10a0dcec8 Mon Sep 17 00:00:00 2001 From: Corey Thompson Date: Fri, 2 Jan 2026 01:06:12 -0600 Subject: [PATCH 09/12] Add safety checks for device property access Added defensive programming to handle different data structure types and ensure port numbers are always displayed even if properties are empty or missing. Falls back to 'COM?' if port is not found. --- upload_firmware.ps1 | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/upload_firmware.ps1 b/upload_firmware.ps1 index 26ed12e..a399086 100644 --- a/upload_firmware.ps1 +++ b/upload_firmware.ps1 @@ -372,9 +372,21 @@ function Select-Port { } if ($ports.Count -eq 1) { - $script:SelectedPort = $ports[0].Port - $port = $ports[0].Port - $name = $ports[0].Name + # Access properties safely + if ($ports[0] -is [hashtable]) { + $port = $ports[0]['Port'] + $name = $ports[0]['Name'] + } else { + $port = $ports[0].Port + $name = $ports[0].Name + } + + # Ensure we have at least the port number + if (-not $port) { + $port = "COM?" + } + + $script:SelectedPort = $port # Show port and name for clarity if ($name -and $name -ne $port) { @@ -390,8 +402,19 @@ function Select-Port { Write-Host "Multiple devices found:" -ForegroundColor White Write-Host "" for ($i = 0; $i -lt $ports.Count; $i++) { - $port = $ports[$i].Port - $name = $ports[$i].Name + # Access properties safely + if ($ports[$i] -is [hashtable]) { + $port = $ports[$i]['Port'] + $name = $ports[$i]['Name'] + } else { + $port = $ports[$i].Port + $name = $ports[$i].Name + } + + # Ensure we have at least the port number + if (-not $port) { + $port = "COM?" + } # Show port and name separately for clarity if ($name -and $name -ne $port) { From b8a5a65ccd91e6e23cd14ea53a168aa19caa8848 Mon Sep 17 00:00:00 2001 From: Corey Thompson Date: Fri, 2 Jan 2026 01:19:58 -0600 Subject: [PATCH 10/12] Rewrite Get-SerialPorts function for clarity and correctness Simplified the function to: 1. Use .NET GetPortNames() as primary method (most reliable) 2. Build a map of port->device name from WMI for friendly names 3. Explicitly create port objects ensuring Port is always set 4. Use 'return , $ports' to properly return array without unwrapping 5. Fall back to WMI-only if GetPortNames fails This should fix the empty Port values issue. --- upload_firmware.ps1 | 61 +++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/upload_firmware.ps1 b/upload_firmware.ps1 index a399086..13e63bc 100644 --- a/upload_firmware.ps1 +++ b/upload_firmware.ps1 @@ -275,58 +275,59 @@ function Select-Controller { ############################################################################# function Get-SerialPorts { - # Get COM ports - try multiple methods for compatibility + # Get COM ports using .NET which is most reliable $ports = @() - # Method 1: Use .NET SerialPort to get actual COM ports try { + # Get all available COM ports $comPorts = [System.IO.Ports.SerialPort]::GetPortNames() - foreach ($port in $comPorts) { - # Try to get friendly name from WMI - $friendlyName = $port + + if ($comPorts -and $comPorts.Count -gt 0) { + # Try to get friendly names from WMI try { - $deviceInfo = Get-WmiObject Win32_PnPEntity | Where-Object { - $_.Name -match $port - } | Select-Object -First 1 + $devices = Get-WmiObject Win32_PnPEntity | Where-Object { $_.Name -match "COM\d+" } + $deviceMap = @{} + foreach ($device in $devices) { + if ($device.Name -match "(COM\d+)") { + $deviceMap[$Matches[1]] = $device.Name + } + } + } catch { + $deviceMap = @{} + } - if ($deviceInfo) { - $friendlyName = $deviceInfo.Name + # Create port objects with both Port and Name + foreach ($comPort in $comPorts) { + $displayName = if ($deviceMap.ContainsKey($comPort)) { + $deviceMap[$comPort] + } else { + $comPort } - } catch {} - $ports += @{ - Port = $port - Name = $friendlyName + $ports += @{ + Port = $comPort + Name = $displayName + } } } } catch {} - # Fallback Method 2: Check WMI for USB devices with COM ports + # If no ports found, try WMI as fallback if ($ports.Count -eq 0) { try { - $usbPorts = Get-WmiObject Win32_PnPEntity | Where-Object { - $_.Name -match "COM\d+" -and ( - $_.Name -match "USB" -or - $_.Name -match "Serial" -or - $_.Name -match "CH340" -or - $_.Name -match "CP210" -or - $_.Name -match "FTDI" -or - $_.Name -match "Silicon Labs" - ) - } - - foreach ($port in $usbPorts) { - if ($port.Name -match "(COM\d+)") { + $devices = Get-WmiObject Win32_PnPEntity | Where-Object { $_.Name -match "COM\d+" } + foreach ($device in $devices) { + if ($device.Name -match "(COM\d+)") { $ports += @{ Port = $Matches[1] - Name = $port.Name + Name = $device.Name } } } } catch {} } - return $ports + return , $ports } function Select-Port { From 641cab7e166359b835b49885a85836a4ddcf5d01 Mon Sep 17 00:00:00 2001 From: Corey Thompson Date: Fri, 2 Jan 2026 01:21:03 -0600 Subject: [PATCH 11/12] Fix firmware path detection for repo vs release contexts The path resolution now checks if source/arduino exists relative to the script location to determine context: - Local repo: upload_firmware.ps1 at root, arduino in source/arduino - Release package: upload_firmware.ps1 in tools/, arduino in ../source/arduino This fixes the 'Firmware folder not found' error when running from the repo. --- upload_firmware.ps1 | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/upload_firmware.ps1 b/upload_firmware.ps1 index 13e63bc..1355170 100644 --- a/upload_firmware.ps1 +++ b/upload_firmware.ps1 @@ -10,10 +10,23 @@ $ErrorActionPreference = "Stop" # Get the directory where this script is located $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path -# The Arduino source is in the source/ folder at the release root -# Script is in tools/, so go up one level and into source/ -$ReleaseRoot = Split-Path -Parent $ScriptDir -$ArduinoDir = Join-Path (Join-Path $ReleaseRoot "source") "arduino" +# Determine if we're in a release package or local repo +# Release: C:\SledLink-v1.0.0\tools\upload_firmware.ps1 -> look for C:\SledLink-v1.0.0\source\arduino +# Repo: C:\GitRepos\SledLink\upload_firmware.ps1 -> look for C:\GitRepos\SledLink\source\arduino + +if ((Test-Path (Join-Path $ScriptDir "source" "arduino")) -or + (Test-Path (Join-Path $ScriptDir "arduino"))) { + # Script is at the root level (local repo) + $ArduinoDir = Join-Path $ScriptDir "source" "arduino" + if (-not (Test-Path $ArduinoDir)) { + # Fallback for development (arduino folder at root) + $ArduinoDir = Join-Path $ScriptDir "arduino" + } +} else { + # Script is in tools/ subdirectory (release package) + $ReleaseRoot = Split-Path -Parent $ScriptDir + $ArduinoDir = Join-Path (Join-Path $ReleaseRoot "source") "arduino" +} # Global variables $script:SelectedPort = "" From d0aaee501857616cee57b2b754c8b2ef25f7ac7e Mon Sep 17 00:00:00 2001 From: Corey Thompson Date: Fri, 2 Jan 2026 01:28:18 -0600 Subject: [PATCH 12/12] path detection fix --- upload_firmware.ps1 | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/upload_firmware.ps1 b/upload_firmware.ps1 index 1355170..3180971 100644 --- a/upload_firmware.ps1 +++ b/upload_firmware.ps1 @@ -12,18 +12,18 @@ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path # Determine if we're in a release package or local repo # Release: C:\SledLink-v1.0.0\tools\upload_firmware.ps1 -> look for C:\SledLink-v1.0.0\source\arduino -# Repo: C:\GitRepos\SledLink\upload_firmware.ps1 -> look for C:\GitRepos\SledLink\source\arduino - -if ((Test-Path (Join-Path $ScriptDir "source" "arduino")) -or - (Test-Path (Join-Path $ScriptDir "arduino"))) { - # Script is at the root level (local repo) - $ArduinoDir = Join-Path $ScriptDir "source" "arduino" - if (-not (Test-Path $ArduinoDir)) { - # Fallback for development (arduino folder at root) - $ArduinoDir = Join-Path $ScriptDir "arduino" - } +# Repo: C:\GitRepos\SledLink\upload_firmware.ps1 -> look for C:\GitRepos\SledLink\arduino + +# Check if we're at the repo root with source/arduino structure +$SourceArduinoPath = Join-Path (Join-Path $ScriptDir "source") "arduino" +if (Test-Path $SourceArduinoPath) { + # Release package structure with source/ subfolder + $ArduinoDir = $SourceArduinoPath +} elseif (Test-Path (Join-Path $ScriptDir "arduino")) { + # Local repo structure with arduino/ at root + $ArduinoDir = Join-Path $ScriptDir "arduino" } else { - # Script is in tools/ subdirectory (release package) + # Must be in tools/ subdirectory (release package) $ReleaseRoot = Split-Path -Parent $ScriptDir $ArduinoDir = Join-Path (Join-Path $ReleaseRoot "source") "arduino" }