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

Firmware burn automation. #157

Merged
merged 3 commits into from
Dec 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -122,9 +122,9 @@ void processTxAudio(uint8_t tempBuffer[], int bytesRead);

void setup() {
// Communication with Android via USB cable
Serial.begin(230400);
Serial.setRxBufferSize(USB_BUFFER_SIZE);
Serial.setTxBufferSize(USB_BUFFER_SIZE);
Serial.begin(230400);

// Configure watch dog timer (WDT), which will reset the system if it gets stuck somehow.
esp_task_wdt_init(10, true); // Reboot if locked up for a bit
Expand Down
2 changes: 1 addition & 1 deletion microcontroller-src/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ src_dir = kv4p_ht_esp32_wroom_32
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 921600
monitor_speed = 230400
build_flags =
-DARDUINO_RUNNING_CORE=1
-DARDUINO_EVENT_RUNNING_CORE=0
Expand Down
67 changes: 67 additions & 0 deletions pcb/KiCAD/esp32-test-code/kv4p-ht-v2-esp32-test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Firmware burning automation

Requirements:

* You can build and upload code from PlatformIO to the ESP32 boards. Both projects:
* `pcb/KiCAD/esp32-test-code/kv4p-ht-v2-esp32-test/`
* `microcontroller-src/`
* I think parts of `showmeconsole.ph` require a POSIX platform, specifically the `select()` call. Unknown what this will do on a non-POSIX platform (looking at you, Windows)

## Burning firmware

### Configure the script

* Open `pcb/KiCAD/esp32-test-code/kv4p-ht-v2-esp32-test/scripts/program.sh` in your editor of choice.
* If you use VScode, open `pcb/KiCAD/esp32-test-code/kv4p-ht-v2-esp32-test/` as a PlatformIO project.
* Update `KV4P_ROOT` to the path of the root of the [kv4p-ht git repo](https://github.com/VanceVagell/kv4p-ht) you have checked out on your system.
* You might need to update `PIO_BIN` to the path of your `platformio` executable if it can't be found with `which platformio`.

### Run the script

```bash
cd pcb/KiCAD/esp32-test-code/kv4p-ht-v2-esp32-test/scripts/
./program.sh
```

It does everything with absolute paths, so it shouldn't matter where you are when you run it.

It will:

* Find the first instance of `/dev/ttyUSB*`. If you don't have a board plugged in yet, it retries.
* Program the test code to the ESP32.
* Go into test mode.
* In this mode, the computer will:
* Output from the ESP32 is shown on the screen.
* Pressing `r<cr>` (r and Enter) will toggle RTS
* Pressing `d<cr>` (d and Enter) will toggle DTR
* Pressing `q<cr>` or just `<cr>` will exit test mode.
* While in test mode, the ESP32 will:
* Blink the "Main" LED, 500ms on, 500ms off.
* Cycle the NeoPixel through its colors: Red, Green, Blue, dark, dark. 900ms per state (Intentionally not sync'd with the main LED.)
* Print an approximate voltage reading of the +5v line, every 5 seconds.
* If an SA818 is installed, it will print the RSSI every 5 seconds.
* Pressing the different buttons will:
* Print on the console that a button has been pressed, and which one.
* Left PTT will light the Red LED on the NeoPixel
* Right PTT will light the Green LED on the NeoPixel
* Program will light the Blue LED on the NeoPixel
* Watch for:
* Boot up messages.
* If an SA818 is installed, it will perform a Handshake and Group. You'll see whether they succeed.
* Messages when buttons are pressed.
* A voltage reading every 5 seconds. It should be somewhere around 5v, give or take 0.2v (Turns out, the ADC on the ESP32 is not very linear at all!)
* An RSSI reading every 5 seconds.
* If any tests fail:
* Press Ctrl-C to quit `program.sh`
* Document the failure on a post-it and stick it to the board, put the board aside.
* Restart `program.sh` and move on to the next board.
* Assuming all tests succeed, press `<Enter>` to proceed.
* Program the production code to the ESP32.
* Go into test mode (again).
* The computer operates the same as the test mode above, but the ESP32 behaves differently.
* Wait 10 seconds.
* The ESP32 watchdog timer will expire and cause a reboot. You'll see the failure and restart messages.
* Yes, a "ZOMG WDT EXPIRED FAIL!" is a success criteria here. It means the new code is programmed and running. It won't stop rebooting until both an SA818 is connected, and the Android app is running to give it commands.
* Assuming all tests succeed, press `<Enter>` to proceed.
* It will sleep for 15 seconds before starting again, to give you a chance to remove the programmed board and reconnect a new fresh board.
* Loop around to the beginning and do it all again.
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 921600
monitor_port = /dev/ttyUSB0
monitor_speed = 460800
monitor_port = /dev/ttyUSB3

build_flags =
-DARDUINO_RUNNING_CORE=1
-DARDUINO_EVENT_RUNING_CORE=0
lib_deps =
plerup/EspSoftwareSerial@^8.2.0
adafruit/Adafruit NeoPixel@^1.12.3
adafruit/Adafruit NeoPixel@^1.12.3
https://github.com/fatpat/arduino-dra818.git#v1.0.1 ; v1.0.1 is the latest release, but has not been pushed to registry. Update later
99 changes: 99 additions & 0 deletions pcb/KiCAD/esp32-test-code/kv4p-ht-v2-esp32-test/scripts/program.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/bin/bash


source stdbuf -o=0

# Baud rate for the test and production code
BAUD=230400

# TODO Automate the discovery of this.
KV4P_ROOT="/home/mark/src/kv4p/kv4p-ht"
KV4P_TEST_CODE=${KV4P_ROOT}/pcb/KiCAD/esp32-test-code/kv4p-ht-v2-esp32-test
KV4P_SHIP_CODE=${KV4P_ROOT}/microcontroller-src

# Override if its not in the path.
PIO_BIN=$(which platformio)

FIRST=true
while true; do
if ! ${FIRST} ; then
echo -n "5 seconds."
sleep 2
echo -n " 3..."
sleep 1
echo -n " 2..."
sleep 1
echo -n " 1..."
sleep 1
echo "Go."
fi
FIRST=false

SERIAL_PORT=$(ls /dev/ttyUSB*)
if [ $? != 0 ]; then
echo "No serial port."
continue
fi

echo "Found serial port ${SERIAL_PORT}. Setting paremeters"
#stty -F ${SERIAL_PORT} ${BAUD}

if ! pushd ${KV4P_TEST_CODE} ; then
echo "Test code directory not found! Exiting."
exit 1
fi
echo "Programming test code."
$PIO_BIN run --target upload
RET=$?
if ! popd ; then
echo "popd failed. Not sure what's up with that."
exit 3
fi
if [ $RET != 0 ]; then
# TODO Make this red
echo "ERROR!!!!! PlatformIO returned a failure. Will start over. Press Enter to proceed."
read
continue
fi

echo ""
# TODO Make this green
echo "Succeeded."
echo "Test the board: Push buttons, look for LEDs, etc."
echo "Press Q<Ender> when ready to proceed, or Ctrl-C to stop."

./showmeconsole.py ${SERIAL_PORT} ${BAUD}

if ! pushd ${KV4P_SHIP_CODE} ; then
echo "Production code directory not found! Exiting."
exit 2
fi
echo "Programming production code."
$PIO_BIN run --target upload
RET=$?
if ! popd ; then
echo "popd failed. Not sure what's up with that."
exit 3
fi
if [ $RET != 0 ]; then
echo "PlatformIO returned a failure. Will start over. Press Enter to proceed."
read
continue
fi

echo ""
echo "Done. Check console for valid output."
echo "Press <Enter> when ready to proceed, or Ctrl-C to stop."

#stty -F ${SERIAL_PORT} cs8 -cstopb -parenb 230400
#sleep 1
#while ! read -t 0.1 foo ; do
# cat ${SERIAL_PORT}
#done
./showmeconsole.py ${SERIAL_PORT} ${BAUD}


echo "Pull board from USB and reconnect next board."

sleep 10
done
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#!/usr/bin/python

from time import sleep
from select import select
from sys import argv, stdin
import readchar
import serial

default_baud_rate = 460800

def usage():
print (f"Usage: {argv[0]} SERIAL_PORT [BAUD_RATE]")
print(" SERIAL_PORT is required, BAUD_RATE is optional (defaults to {default_baud_rate})")
exit(1)
try:
serial_port = argv[1]
except IndexError:
usage()

try:
baud_rate = argv[2]
except IndexError:
baud_rate = default_baud_rate

ser = None
prev_cts = None
prev_cd = None
prev_dsr = None
prev_rts = None
prev_dtr = None
prev_c = None

while True:
try:
if ser is None:
print(f"Trying {serial_port}")
ser = serial.Serial(serial_port, baud_rate)
print("Got Serial.")

cts = ser.cts
if cts != prev_cts:
print(f"CTS: {cts}")
prev_cts = cts

cd = ser.cd
if cd != prev_cd:
print(f"DCD: {cd}")
prev_cd = cd

dsr = ser.dsr
if dsr != prev_dsr:
print(f"DSR: {dsr}")
prev_dsr = dsr

rts = ser.rts
if rts != prev_rts:
print(f"RTS: {rts}")
prev_rts = rts

dtr = ser.dtr
if dtr != prev_dtr:
print(f"DTR: {dtr}")
prev_dtr = dtr

while ser.in_waiting > 0:
ch = ser.read(1)
try:
c = ch.decode(stdin.encoding)
except UnicodeDecodeError:
c = ch # just print the byte

print(c, end="")

# RTS=True, DTR=False, holds the ESP32 in reset.
# NOTE: This select() trick only works on POSIX systems.
if select([stdin], [], [], 0)[0]:
# Theres at least one character waiting on stdin
c = stdin.read(1)
if c == 'r':
ser.rts = not rts
elif c == 'd':
ser.dtr = not dtr
elif c == '\n' and (prev_c == '\n' or prev_c == 'q' or prev_c == None):
print("Exiting...")
exit(0)
prev_c = c

except OSError:
ser = None
print("Can't open serial...")
sleep(1)
Loading
Loading