diff --git a/package_README.md b/package_README.md
index a36a7d41..661cf619 100644
--- a/package_README.md
+++ b/package_README.md
@@ -5,6 +5,11 @@ A full-featured self-balancing skateboard package.
## New in 1.3
This version reworks a lot of the core control mechanisms and adds Setpoint Smoothing to all Tilts. Due to this, boards will behave slightly differently and tunes might need adjusting.
+### Recent additions
+- LED status bar can now be disabled above a configurable speed while still allowing duty/current utilization indicators to remain active
+- New GUI options for the LED speed cutoff and enable/disable toggle
+- Improved compatibility with config restore workflows when new settings are introduced
+
Changelog highlights:
- Reworked internal timing for better vibration rejection and more consistent tune behavior across setups
- Setpoint Smoothing for all Tilts (ATR, Torque Tilt, Brake Tilt, Turn Tilt, Remote)
diff --git a/src/Makefile b/src/Makefile
index ed18783d..12a9114a 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -28,6 +28,8 @@ $(REFLOAT_SOURCES): $(CONF_GEN_HEADERS) conf/conf_general.h
$(CONF_GEN_FILES) &: conf/settings.xml
$(VESC_TOOL) --xmlConfToCode conf/settings.xml
+ sed -i 's/conf->leds.status.speed_off_threshold, 10000/conf->leds.status.speed_off_threshold, 1/g' conf/confparser.c
+ sed -i 's/conf->leds.status.speed_off_threshold = buffer_get_float16(buffer, 10000/conf->leds.status.speed_off_threshold = buffer_get_float16(buffer, 1/g' conf/confparser.c
# !!! make xml config loading in vesc_tool work with LTO !!!
sed -i "s/^uint8_t data_/__attribute__((used)) uint8_t data_/g" conf/confxml.c
diff --git a/src/conf/datatypes.h b/src/conf/datatypes.h
index d7c22bd8..a5222dfc 100644
--- a/src/conf/datatypes.h
+++ b/src/conf/datatypes.h
@@ -130,6 +130,8 @@ typedef struct {
typedef struct {
uint16_t idle_timeout;
+ bool disable_soc_above_speed;
+ float speed_off_threshold;
float motor_utilization_threshold;
float red_bar_percentage;
bool show_sensors_while_running;
diff --git a/src/conf/settings.xml b/src/conf/settings.xml
index 568dc2ff..9c06bd19 100644
--- a/src/conf/settings.xml
+++ b/src/conf/settings.xml
@@ -2746,6 +2746,7 @@ p, li { white-space: pre-wrap; }
Rainbow Fade
Rainbow Roll
+
Front Brightness
1
@@ -3440,6 +3441,40 @@ p, li { white-space: pre-wrap; }
CFG_DFLT_LEDS_STATUS_SHOW_SENSORS_WHILE_RUNNING
1
+
+ Disable SOC Status Above Speed
+ 5
+ 1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Roboto'; ; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">When enabled, the normal SOC/status bar turns fully off once the board is moving faster than the configured cutoff speed. Duty cycle / motor utilization still shows if it crosses its threshold.</p></body></html>
+ CFG_DFLT_LEDS_STATUS_DISABLE_SOC_ABOVE_SPEED
+ 0
+
+
+ Status Off Speed Threshold
+ 1
+ 1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Roboto'; ; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Board speed in km/h above which the normal SOC/status bar is turned off when the toggle above is enabled. The duty cycle and motor utilization indicators still override this cutoff when their thresholds are reached.</p></body></html>
+ CFG_DFLT_LEDS_STATUS_SPEED_OFF_THRESHOLD
+ 0
+ 1
+ 0
+ 80
+ 0
+ 0
+ 1
+ 4
+ 1
+ km/h
+ 7
+
Motor Utilization Threshold
1
@@ -4188,6 +4223,8 @@ p, li { white-space: pre-wrap; }
leds.status.brightness_headlights_on
leds.status.show_sensors_while_running
leds.status.motor_utilization_threshold
+ leds.status.disable_soc_above_speed
+ leds.status.speed_off_threshold
leds.status.red_bar_percentage
leds.status.idle_timeout
leds.status_idle.mode
@@ -4446,6 +4483,8 @@ p, li { white-space: pre-wrap; }
leds.status.brightness_headlights_on
leds.status.show_sensors_while_running
leds.status.motor_utilization_threshold
+ leds.status.disable_soc_above_speed
+ leds.status.speed_off_threshold
leds.status.red_bar_percentage
leds.status.idle_timeout
::sep::Status Idle
diff --git a/src/leds.c b/src/leds.c
index a998edac..019d53ee 100644
--- a/src/leds.c
+++ b/src/leds.c
@@ -544,6 +544,9 @@ static void status_animate(
float blend,
float idle_blend
) {
+ const float speed_kph = fabsf(motor->speed);
+ const bool moving = speed_kph > 0.5f;
+
if (fabsf(VESC_IF->mc_get_rpm()) > ERPM_MOVING_THRESHOLD) {
leds->status_idle_time = current_time;
}
@@ -565,6 +568,44 @@ static void status_animate(
rate_limitf(&leds->status_utilization_blend, 0.0f, SB_RATE);
}
+ const bool soc_off_by_speed =
+ leds->cfg->status.disable_soc_above_speed && moving &&
+ speed_kph >= leds->cfg->status.speed_off_threshold;
+ const float soc_off_hyst = 1.0f;
+ const float soc_on_threshold = leds->cfg->status.speed_off_threshold - soc_off_hyst;
+ const bool soc_should_be_off =
+ leds->cfg->status.disable_soc_above_speed &&
+ (soc_off_by_speed ||
+ (leds->status_soc_blend < 0.5f && moving && speed_kph > soc_on_threshold));
+
+ float target_soc_blend = 1.0f;
+ if (leds->cfg->status.disable_soc_above_speed) {
+ if (!moving) {
+ target_soc_blend = 1.0f;
+ } else if (speed_kph >= leds->cfg->status.speed_off_threshold) {
+ target_soc_blend = 0.0f;
+ } else if (speed_kph <= soc_on_threshold && leds->status_soc_blend <= 0.5f) {
+ target_soc_blend = 1.0f;
+ } else {
+ target_soc_blend = leds->status_soc_blend;
+ }
+ }
+ if (soc_should_be_off) {
+ target_soc_blend = 0.0f;
+ }
+ rate_limitf(&leds->status_soc_blend, target_soc_blend, SB_RATE);
+
+ float soc_blend = leds->status_soc_blend;
+ if (soc_should_be_off || target_soc_blend <= 0.05f) {
+ idle_blend = 0.0f;
+ soc_blend = 0.0f;
+ }
+
+ if (soc_should_be_off && leds->status_utilization_blend <= 0.0f) {
+ strip_set_color(leds, strip, 0x00000000, 0.0f, 1.0f);
+ return;
+ }
+
if (idle_blend > 0.0f) {
if (strip == &leds->front_strip) {
strip_set_color(leds, strip, 0x00000000, strip->brightness, blend);
@@ -580,10 +621,16 @@ static void status_animate(
if (idle_blend < 1.0f) {
const bool reverse = strip == &leds->front_strip;
+
if (leds->status_utilization_blend < 1.0f) {
const float battery = VESC_IF->mc_get_battery_level(NULL);
anim_battery_bar(
- leds, strip, battery, reverse, fminf(blend, 1.0f - idle_blend), current_time
+ leds,
+ strip,
+ battery,
+ reverse,
+ fminf(blend, soc_blend),
+ current_time
);
}
@@ -601,7 +648,13 @@ static void status_animate(
}
anim_progress_bar(
- leds, strip, max_sat, max_color, true, reverse, leds->status_utilization_blend
+ leds,
+ strip,
+ max_sat,
+ max_color,
+ true,
+ reverse,
+ leds->status_utilization_blend * blend
);
}
@@ -798,6 +851,7 @@ void leds_init(Leds *leds) {
leds->motor_utilization_threshold = 0.0f;
leds->status_utilization_blend = 0.0f;
leds->status_idle_blend = 0.0f;
+ leds->status_soc_blend = 1.0f;
leds->status_idle_time = 0.0f;
leds->status_animation_start = 0.0f;
diff --git a/src/leds.h b/src/leds.h
index 3b07bb4c..284a7d73 100644
--- a/src/leds.h
+++ b/src/leds.h
@@ -55,6 +55,7 @@ typedef struct {
float motor_utilization_threshold;
float status_utilization_blend;
float status_idle_blend;
+ float status_soc_blend;
float status_idle_time;
float status_animation_start;
diff --git a/version b/version
index 81ccd3a0..adb03c3a 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-1.3.1-beta1
+1.3.1-beta2