From d91c82e61856dda063bbbb8ad2eec379bcb27ca3 Mon Sep 17 00:00:00 2001 From: contactsimonwilson Date: Fri, 13 Mar 2026 16:44:03 +1300 Subject: [PATCH] Fix readme formatting Fix crash with wifi/ble because of heap Use custom tab title Reboot on pfailreset --- .gitignore | 1 + boosted_doctor/Makefile | 2 +- boosted_doctor/README.md | 31 +++++++++--- boosted_doctor/code.lbm | 104 +++++++++++++++++++++++---------------- boosted_doctor/ui.qml | 3 +- boosted_doctor/version | 2 +- 6 files changed, 91 insertions(+), 52 deletions(-) diff --git a/.gitignore b/.gitignore index 3442c8582..7dcd7c569 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.vescpkg confxml.c confxml.h +.DS_Store *.elf *.o diff --git a/boosted_doctor/Makefile b/boosted_doctor/Makefile index c767ea4c6..0d5ec3107 100644 --- a/boosted_doctor/Makefile +++ b/boosted_doctor/Makefile @@ -8,4 +8,4 @@ boosted_doctor.vescpkg: clean: rm -f boosted_doctor.vescpkg -.PHONY: all clean +.PHONY: all clean boosted_doctor.vescpkg diff --git a/boosted_doctor/README.md b/boosted_doctor/README.md index 653a5e5d8..9750b1b55 100644 --- a/boosted_doctor/README.md +++ b/boosted_doctor/README.md @@ -1,10 +1,29 @@ # Boosted Doctor (Boosted VESC Bridge) -This is a package for using Boosted Board (and Rev Scooter) batteries with VESC controllers or VESC Express modules. The package implements the commands and command parsing for Boosted's CAN communications and implements the battery ping needed for the battery to stay on for more than 10 minutes. +A VESC package for using Boosted Board (and Rev Scooter) batteries with VESC controllers or VESC Express modules. -In VESC tool, users are able to check individual cell voltages of their XR and Rev batteries. In the event of Red Light of Death (RLOD), users are also able to clear RLOD within VESC Tool. +## Overview -Robert Scullin - Boosted CANBUS Research: https://beambreak.org / https://github.com/rscullin/beambreak -Alex Krysl - Boosted CANBUS Research: https://github.com/axkrysl47/BoostedBreak -Simon Wilson - VESC Express Implementation: https://github.com/techfoundrynz -David Wang - Boosted CANBUS Research: https://www.xrgeneralhospital.com/ \ No newline at end of file +Boosted Doctor implements the CAN commands and response parsing for Boosted's proprietary battery protocol, including the periodic battery ping required to keep the battery powered on beyond 10 minutes. + +## Features + +- Compatible with Boosted XR and Rev Scooter battery packs +- Implements Boosted CAN communication protocol (commands + parsing) +- Sends periodic battery ping to prevent auto-shutdown +- View individual cell voltages in VESC Tool +- Clear Red Light of Death (RLOD) directly from VESC Tool + +## Credits & Acknowledgements + +**Robert Scullin** - Boosted CANBUS Research +[beambreak.org](https://beambreak.org) - [GitHub](https://github.com/rscullin/beambreak) + +**Alex Krysl** - Boosted CANBUS Research +[GitHub](https://github.com/axkrysl47/BoostedBreak) + +**Simon Wilson** - VESC Express Implementation +[GitHub](https://github.com/techfoundrynz) + +**David Wang** - Boosted CANBUS Research +[XR General Hospital](https://www.xrgeneralhospital.com/) \ No newline at end of file diff --git a/boosted_doctor/code.lbm b/boosted_doctor/code.lbm index 6d047ffcb..41411ca44 100644 --- a/boosted_doctor/code.lbm +++ b/boosted_doctor/code.lbm @@ -1,16 +1,6 @@ ; Boosted Board CAN Protocol Implementation -; --- Constants --- -(define COMM_GET_STATUS 1) -(define COMM_GET_CELLS 2) -(define COMM_PFAIL_RESET 3) - -(define BAT_TYPE_UNKNOWN 0) -(define BAT_TYPE_SRB 1) -(define BAT_TYPE_XRB 2) -(define BAT_TYPE_REV 3) - -; --- State Variables --- +; --- Mutable State Variables --- (define val-cell-count 12) ; Default to 12 (define cell-voltage-buffer (bufcreate 30)) (define AFE_RX_BUF_SIZE 256) @@ -23,6 +13,27 @@ (define debug-enable nil) (define tx-counter 0) +; --- Pre-allocated TX Buffers --- +; GETAFECELLS +(define afe-cells-payload1 (bufcreate 8)) +(bufset-u8 afe-cells-payload1 0 0x47) ; G +(bufset-u8 afe-cells-payload1 1 0x45) ; E +(bufset-u8 afe-cells-payload1 2 0x54) ; T +(bufset-u8 afe-cells-payload1 3 0x41) ; A +(bufset-u8 afe-cells-payload1 4 0x46) ; F +(bufset-u8 afe-cells-payload1 5 0x45) ; E +(bufset-u8 afe-cells-payload1 6 0x43) ; C +(bufset-u8 afe-cells-payload1 7 0x45) ; E +(define afe-cells-payload2 (bufcreate 5)) +(bufset-u8 afe-cells-payload2 0 0x4C) ; L +(bufset-u8 afe-cells-payload2 1 0x4C) ; L +(bufset-u8 afe-cells-payload2 2 0x53) ; S +(bufset-u8 afe-cells-payload2 3 0x0D) ; \r +(bufset-u8 afe-cells-payload2 4 0x0A) ; \n +; PING +(define ping-payload (bufcreate 8)) +(bufclear ping-payload) + (define last-boosted-bms-rx-time 0) (define last-vesc-bms-tx-time 0) (define last-cell-req-time 0) @@ -33,7 +44,7 @@ (define val-soc 0) (define val-pack-volt 0.0) -(define val-bat-type BAT_TYPE_UNKNOWN) +(define val-bat-type 0) ; BAT_TYPE_UNKNOWN (define val-cell-min 0.0) (define val-cell-max 0.0) (define val-ver-major 0) @@ -42,12 +53,23 @@ (define val-amps 0.0) (define val-btn-state 0) - - -; --- Parsing Helpers --- +; --- Parsing Result Globals --- (define parse-res-val 0) (define parse-res-idx 0) +@const-start + +; --- Constants --- +(define COMM_GET_STATUS 1) +(define COMM_GET_CELLS 2) +(define COMM_PFAIL_RESET 3) + +(define BAT_TYPE_UNKNOWN 0) +(define BAT_TYPE_SRB 1) +(define BAT_TYPE_XRB 2) +(define BAT_TYPE_REV 3) + +; --- Parsing Helpers --- (defun is-digit (c) (and (>= c 48) (<= c 57))) (defun parse-int-buf (buf idx limit) { @@ -253,28 +275,8 @@ }) (defun send-get-afe-cells () { - ; Msg 1: GETAFECE - (var payload1 (bufcreate 8)) - (bufset-u8 payload1 0 0x47) ; G - (bufset-u8 payload1 1 0x45) ; E - (bufset-u8 payload1 2 0x54) ; T - (bufset-u8 payload1 3 0x41) ; A - (bufset-u8 payload1 4 0x46) ; F - (bufset-u8 payload1 5 0x45) ; E - (bufset-u8 payload1 6 0x43) ; C - (bufset-u8 payload1 7 0x45) ; E - - ; Msg 2: LLS\r\n - (var payload2 (bufcreate 5)) - (bufset-u8 payload2 0 0x4C) ; L - (bufset-u8 payload2 1 0x4C) ; L - (bufset-u8 payload2 2 0x53) ; S - (bufset-u8 payload2 3 0x0D) ; \r - (bufset-u8 payload2 4 0x0A) ; \n - - (can-send-eid 0x10246110u32 payload1) - (can-send-eid 0x10146111u32 payload2) - + (can-send-eid 0x10246110u32 afe-cells-payload1) + (can-send-eid 0x10146111u32 afe-cells-payload2) (if debug-enable { (debug-print "TX: GETAFECELLS") }) @@ -305,6 +307,24 @@ (print "TX: PFAILRESET") }) +(defun send-reboot () { + ; Msg 1: REBOOT\r\n + (var payload1 (bufcreate 8)) + (bufset-u8 payload1 0 0x52) ; R + (bufset-u8 payload1 1 0x45) ; E + (bufset-u8 payload1 2 0x42) ; B + (bufset-u8 payload1 3 0x4F) ; O + (bufset-u8 payload1 4 0x4F) ; O + (bufset-u8 payload1 5 0x54) ; T + (bufset-u8 payload1 6 0x0D) ; \r + (bufset-u8 payload1 7 0x0A) ; \n + + (can-send-eid 0x10346110u32 payload1) + + (print "TX: REBOOT") +}) + + (defun process-afe-buffer () { ; Main Loop Processing of Ring Buffer (var loop-check t) @@ -372,8 +392,6 @@ }) ; --- Process CAN Messages --- - - (defun process-can-frame (id data) { (var header (bitwise-and (shr id 4) 0xFFFFF)) (var dlc (buflen data)) @@ -484,7 +502,6 @@ ((= header 0x33443) (if (>= dlc 8) { (setq last-boosted-bms-rx-time (systime)) - ; Use let for local variables instead of define (var bat-type (bufget-u8 data 0)) (var bat-ext (bufget-u8 data 4)) (var bat-type-enum BAT_TYPE_UNKNOWN) @@ -632,6 +649,7 @@ }) (if (= cmd COMM_PFAIL_RESET) { (send-pfail-reset) + (send-reboot) }) }) }) @@ -641,15 +659,13 @@ ) (defun send-ping () { - (var payload (bufcreate 8)) - (bufclear payload) ; Ensure zeros ; Construct ID: 0x10 << 24 | ID_ESC_PING_BASE << 4 | counter (4 bits) (var base-id 0x103434B0u32) (var ping-id (+ base-id (bitwise-and tx-counter 0xF))) ; Send Extended ID (debug-print (str-merge "TX Ping ID: " (str-from-n ping-id "0x%X"))) - (can-send-eid ping-id payload) + (can-send-eid ping-id ping-payload) ; Increment Counter (setq tx-counter (+ tx-counter 1)) @@ -696,6 +712,8 @@ }) }) +@const-end + ; --- Main Entry --- (print "Starting Boosted VESC Driver...") ;(can-update-baud 250) diff --git a/boosted_doctor/ui.qml b/boosted_doctor/ui.qml index 8a721f80b..d2ac96ca5 100644 --- a/boosted_doctor/ui.qml +++ b/boosted_doctor/ui.qml @@ -8,6 +8,7 @@ Rectangle { id: container anchors.fill: parent color: colorBg + property string tabTitle: "Boosted Doctor" property Commands mCommands: VescIf.commands() property bool connected: false @@ -209,7 +210,7 @@ Rectangle { width: parent.width // Match width of status bar MenuItem { - text: "Clear RLOD" + text: "Clear Red Light of Death" onTriggered: { var buffer = new ArrayBuffer(1); var dv = new DataView(buffer); diff --git a/boosted_doctor/version b/boosted_doctor/version index 6e8bf73aa..0ea3a944b 100644 --- a/boosted_doctor/version +++ b/boosted_doctor/version @@ -1 +1 @@ -0.1.0 +0.2.0