Skip to content

Commit 7138dee

Browse files
committed
Add Support for BMS Tiltback
1 parent 1ad13ed commit 7138dee

File tree

6 files changed

+197
-8
lines changed

6 files changed

+197
-8
lines changed

package.lisp

+9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@
88
; Set firmware version:
99
(apply ext-set-fw-version (sysinfo 'fw-ver))
1010

11+
(if (eq (first (trap (get-bms-val 'bms-v-cell-min))) 'exit-ok) {
12+
(loopwhile (and (< (get-bms-val 'bms-can-id) 0) (< (secs-since 0) 10.0)) (yield 1000000))
13+
(if (>= (get-bms-val 'bms-can-id) 0){
14+
(import "src/bms.lisp" 'bms)
15+
(read-eval-program bms)
16+
(spawn bms-loop)
17+
})
18+
})
19+
1120
; Set to 1 to monitor debug variables
1221
(define debug 1)
1322

src/bms.c

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2024 Syler Clayton
2+
//
3+
// This file is part of the Refloat VESC package.
4+
//
5+
// Refloat VESC package is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by the
7+
// Free Software Foundation, either version 3 of the License, or (at your
8+
// option) any later version.
9+
//
10+
// Refloat VESC package is distributed in the hope that it will be useful, but
11+
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12+
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13+
// more details.
14+
//
15+
// You should have received a copy of the GNU General Public License along with
16+
// this program. If not, see <http://www.gnu.org/licenses/>.
17+
18+
#include "bms.h"
19+
20+
bool bms_is_fault_set(uint32_t fault_mask, BMSFaultCode fault_code) {
21+
if (fault_code < 1 || fault_code > 32) {
22+
return false;
23+
}
24+
return (fault_mask & (1U << (fault_code - 1))) != 0;
25+
}

src/bms.h

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2024 Syler Clayton
2+
//
3+
// This file is part of the Refloat VESC package.
4+
//
5+
// Refloat VESC package is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by the
7+
// Free Software Foundation, either version 3 of the License, or (at your
8+
// option) any later version.
9+
//
10+
// Refloat VESC package is distributed in the hope that it will be useful, but
11+
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12+
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13+
// more details.
14+
//
15+
// You should have received a copy of the GNU General Public License along with
16+
// this program. If not, see <http://www.gnu.org/licenses/>.
17+
18+
#pragma once
19+
20+
#include <stdbool.h>
21+
#include <stdint.h>
22+
23+
typedef enum {
24+
NONE = 0,
25+
BMS_CONNECTION = 1,
26+
BMS_OVER_TEMP = 2,
27+
BMS_CELL_OVER_VOLTAGE = 3,
28+
BMS_CELL_UNDER_VOLTAGE = 4,
29+
BMS_CELL_OVER_TEMP = 5,
30+
BMS_CELL_UNDER_TEMP = 6,
31+
BMS_CELL_BALANCE = 7
32+
} BMSFaultCode;
33+
34+
bool bms_is_fault_set(uint32_t fault_mask, BMSFaultCode fault_code);

src/bms.lisp

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
(defun bms-loop () {
2+
(var bms-vmin-limit-start (conf-get 'bms-vmin-limit-start))
3+
(var bms-vmax-limit-start (conf-get 'bms-vmax-limit-start))
4+
(var bms-tmax-limit-start (- (conf-get 'bms-t-limit-start) 3)) ; Start 3 degrees before Motor CFG -> BMS limiting functionality would happen.
5+
(var bms-tmin-limit-start 0)
6+
(var bms-cell-balance-start 0.5)
7+
(var bms-ic-tmax-limit-start (+ bms-tmax-limit-start 15)) ; Set bms temp limit to +15C past cell limit
8+
(var bms-config-update-time (systime))
9+
(var bms-fault 0u32)
10+
(var bms-fault-codes '(
11+
(NONE . 0)
12+
(BMS_CONNECTION . 1)
13+
(BMS_OVER_TEMP . 2)
14+
(BMS_CELL_OVER_VOLTAGE . 3)
15+
(BMS_CELL_UNDER_VOLTAGE . 4)
16+
(BMS_CELL_OVER_TEMP . 5)
17+
(BMS_CELL_UNDER_TEMP . 6)
18+
(BMS_CELL_BALANCE . 7)
19+
))
20+
(defun bms-set-fault (fault-code) {
21+
(if (eq fault-code 'NONE) {
22+
(setq bms-fault 0u32)
23+
}{
24+
(setq bms-fault (bitwise-or bms-fault (shl 1 (- (assoc bms-fault-codes fault-code) 1))))
25+
})
26+
})
27+
(loopwhile t {
28+
(if (and (<= (get-duty) 0.05) (> (secs-since bms-config-update-time) 1.0)) { ; Only bother updating config values while board is idle
29+
(setq bms-vmin-limit-start (conf-get 'bms-vmin-limit-start))
30+
(setq bms-vmax-limit-start (conf-get 'bms-vmax-limit-start))
31+
(setq bms-tmax-limit-start (- (conf-get 'bms-t-limit-start) 3))
32+
(setq bms-ic-tmax-limit-start (+ bms-tmax-limit-start 15))
33+
(setq bms-config-update-time (systime))
34+
})
35+
(if (>= (get-bms-val 'bms-msg-age) 2.0) {
36+
(bms-set-fault 'BMS_CONNECTION)
37+
} {
38+
(bms-set-fault 'NONE)
39+
(if (>= (get-bms-val 'bms-v-cell-max) bms-vmax-limit-start) (bms-set-fault 'BMS_CELL_OVER_VOLTAGE))
40+
(if (<= (get-bms-val 'bms-v-cell-min) bms-vmin-limit-start) (bms-set-fault 'BMS_CELL_UNDER_VOLTAGE))
41+
(if (>= (get-bms-val 'bms-temp-cell-max) bms-tmax-limit-start) (bms-set-fault 'BMS_CELL_OVER_TEMP))
42+
(if (<= (get-bms-val 'bms-temp-cell-max) bms-tmin-limit-start) (bms-set-fault 'BMS_CELL_UNDER_TEMP))
43+
(if (>= (abs (- v-cell-max v-cell-min)) bms-cell-balance-start) (bms-set-fault 'BMS_CELL_BALANCE))
44+
(if (>= (get-bms-val 'bms-temp-ic) bms-ic-tmax-limit-start) (bms-set-fault 'BMS_OVER_TEMP))
45+
})
46+
(apply ext-bms-set-fault bms-fault)
47+
(yield 10000)
48+
})
49+
})

src/main.c

+73-8
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "vesc_c_if.h"
2323

2424
#include "atr.h"
25+
#include "bms.h"
2526
#include "charging.h"
2627
#include "footpad_sensor.h"
2728
#include "lcm.h"
@@ -55,7 +56,14 @@ typedef enum {
5556
BEEP_SENSORS = 7,
5657
BEEP_LOWBATT = 8,
5758
BEEP_IDLE = 9,
58-
BEEP_ERROR = 10
59+
BEEP_ERROR = 10,
60+
BEEP_TEMP_CELL_UNDER = 11,
61+
BEEP_TEMP_CELL_OVER = 12,
62+
BEEP_CELL_LV = 13,
63+
BEEP_CELL_HV = 14,
64+
BEEP_CELL_BALANCE = 15,
65+
BEEP_BMS_CONNECTION = 16,
66+
BEEP_BMS_TEMP_OVER = 17
5967
} BeepReason;
6068

6169
static const FootpadSensorState flywheel_konami_sequence[] = {
@@ -194,6 +202,8 @@ typedef struct {
194202
Konami flywheel_konami;
195203
Konami headlights_on_konami;
196204
Konami headlights_off_konami;
205+
206+
uint32_t bms_fault;
197207
} data;
198208

199209
static void brake(data *d);
@@ -362,6 +372,8 @@ static void configure(data *d) {
362372
sizeof(headlights_off_konami_sequence)
363373
);
364374

375+
d->bms_fault = 0;
376+
365377
reconfigure(d);
366378

367379
if (d->state.state == STATE_DISABLED) {
@@ -671,7 +683,8 @@ static bool check_faults(data *d) {
671683
static void calculate_setpoint_target(data *d) {
672684
float input_voltage = VESC_IF->mc_get_input_voltage_filtered();
673685

674-
if (input_voltage < d->float_conf.tiltback_hv) {
686+
if ((input_voltage < d->float_conf.tiltback_hv) &&
687+
!bms_is_fault_set(d->bms_fault, BMS_CELL_OVER_VOLTAGE)) {
675688
d->tb_highvoltage_timer = d->current_time;
676689
}
677690

@@ -745,11 +758,18 @@ static void calculate_setpoint_target(data *d) {
745758
if (d->state.mode != MODE_FLYWHEEL) {
746759
d->state.sat = SAT_PB_DUTY;
747760
}
748-
} else if (d->motor.duty_cycle > 0.05 && input_voltage > d->float_conf.tiltback_hv) {
749-
d->beep_reason = BEEP_HV;
761+
} else if (d->motor.duty_cycle > 0.05 &&
762+
(input_voltage > d->float_conf.tiltback_hv ||
763+
bms_is_fault_set(d->bms_fault, BMS_CELL_OVER_VOLTAGE))) {
764+
if (bms_is_fault_set(d->bms_fault, BMS_CELL_OVER_VOLTAGE)) {
765+
d->beep_reason = BEEP_CELL_HV;
766+
} else {
767+
d->beep_reason = BEEP_HV;
768+
}
750769
beep_alert(d, 3, false);
751770
if (((d->current_time - d->tb_highvoltage_timer) > .5) ||
752-
(input_voltage > d->float_conf.tiltback_hv + 1)) {
771+
(input_voltage > d->float_conf.tiltback_hv + 1) ||
772+
bms_is_fault_set(d->bms_fault, BMS_CELL_OVER_VOLTAGE)) {
753773
// 500ms have passed or voltage is another volt higher, time for some tiltback
754774
if (d->motor.erpm > 0) {
755775
d->setpoint_target = d->float_conf.tiltback_hv_angle;
@@ -792,17 +812,42 @@ static void calculate_setpoint_target(data *d) {
792812
// The rider has 1 degree Celsius left before we start tilting back
793813
d->state.sat = SAT_NONE;
794814
}
795-
} else if (d->motor.duty_cycle > 0.05 && input_voltage < d->float_conf.tiltback_lv) {
815+
} else if (bms_is_fault_set(d->bms_fault, BMS_CELL_OVER_TEMP) ||
816+
bms_is_fault_set(d->bms_fault, BMS_CELL_UNDER_TEMP) ||
817+
bms_is_fault_set(d->bms_fault, BMS_OVER_TEMP)) {
818+
// Use the angle from Low-Voltage tiltback, but slower speed from High-Voltage tiltback
819+
beep_alert(d, 3, true);
820+
if (bms_is_fault_set(d->bms_fault, BMS_CELL_OVER_TEMP)) {
821+
d->beep_reason = BEEP_TEMP_CELL_OVER;
822+
} else if (bms_is_fault_set(d->bms_fault, BMS_CELL_UNDER_TEMP)) {
823+
d->beep_reason = BEEP_TEMP_CELL_UNDER;
824+
} else {
825+
d->beep_reason = BEEP_BMS_TEMP_OVER;
826+
}
827+
if (d->motor.erpm > 0) {
828+
d->setpoint_target = d->float_conf.tiltback_lv_angle;
829+
} else {
830+
d->setpoint_target = -d->float_conf.tiltback_lv_angle;
831+
}
832+
d->state.sat = SAT_PB_TEMPERATURE;
833+
} else if (d->motor.duty_cycle > 0.05 &&
834+
(input_voltage < d->float_conf.tiltback_lv ||
835+
bms_is_fault_set(d->bms_fault, BMS_CELL_UNDER_VOLTAGE))) {
796836
beep_alert(d, 3, false);
797-
d->beep_reason = BEEP_LV;
837+
if (bms_is_fault_set(d->bms_fault, BMS_CELL_UNDER_VOLTAGE)) {
838+
d->beep_reason = BEEP_CELL_LV;
839+
} else {
840+
d->beep_reason = BEEP_LV;
841+
}
798842
float abs_motor_current = fabsf(d->motor.current);
799843
float vdelta = d->float_conf.tiltback_lv - input_voltage;
800844
float ratio = vdelta * 20 / abs_motor_current;
801845
// When to do LV tiltback:
802846
// a) we're 2V below lv threshold
803847
// b) motor current is small (we cannot assume vsag)
804848
// c) we have more than 20A per Volt of difference (we tolerate some amount of vsag)
805-
if ((vdelta > 2) || (abs_motor_current < 5) || (ratio > 1)) {
849+
if ((vdelta > 2) || (abs_motor_current < 5) || (ratio > 1) ||
850+
bms_is_fault_set(d->bms_fault, BMS_CELL_UNDER_VOLTAGE)) {
806851
if (d->motor.erpm > 0) {
807852
d->setpoint_target = d->float_conf.tiltback_lv_angle;
808853
} else {
@@ -1443,6 +1488,17 @@ static void refloat_thd(void *arg) {
14431488
d->enable_upside_down = false;
14441489
d->state.darkride = false;
14451490
}
1491+
1492+
if (bms_is_fault_set(d->bms_fault, BMS_CONNECTION)) {
1493+
beep_alert(d, 3, true);
1494+
d->beep_reason = BEEP_BMS_CONNECTION;
1495+
}
1496+
1497+
if (bms_is_fault_set(d->bms_fault, BMS_CELL_BALANCE)) {
1498+
beep_alert(d, 3, true);
1499+
d->beep_reason = BEEP_CELL_BALANCE;
1500+
}
1501+
14461502
if (d->current_time - d->disengage_timer > 1800) { // alert user after 30 minutes
14471503
if (d->current_time - d->nag_timer > 60) { // beep every 60 seconds
14481504
d->nag_timer = d->current_time;
@@ -2582,6 +2638,14 @@ static lbm_value ext_set_fw_version(lbm_value *args, lbm_uint argn) {
25822638
return VESC_IF->lbm_enc_sym_true;
25832639
}
25842640

2641+
// Called from Lisp to pass in the fault code of the bms.
2642+
static lbm_value ext_bms_set_fault(lbm_value *args, lbm_uint argn) {
2643+
unused(argn);
2644+
data *d = (data *) ARG;
2645+
d->bms_fault = VESC_IF->lbm_dec_as_u32(args[0]);
2646+
return VESC_IF->lbm_enc_sym_true;
2647+
}
2648+
25852649
// Used to send the current or default configuration to VESC Tool.
25862650
static int get_cfg(uint8_t *buffer, bool is_default) {
25872651
data *d = (data *) ARG;
@@ -2701,6 +2765,7 @@ INIT_FUN(lib_info *info) {
27012765
VESC_IF->set_app_data_handler(on_command_received);
27022766
VESC_IF->lbm_add_extension("ext-dbg", ext_dbg);
27032767
VESC_IF->lbm_add_extension("ext-set-fw-version", ext_set_fw_version);
2768+
VESC_IF->lbm_add_extension("ext-bms-set-fault", ext_bms_set_fault);
27042769

27052770
return true;
27062771
}

ui.qml.in

+7
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,13 @@ Item {
867867
[8, "Low Battery"],
868868
[9, "Board Idle"],
869869
[10, "Other"],
870+
[11, "Cell Under Temp"],
871+
[12, "Cell Over Temp"],
872+
[13, "Cell Low Voltage"],
873+
[14, "Cell High Voltage"],
874+
[15, "Cell Balance"],
875+
[16, "BMS Connection"],
876+
[17, "BMS Over Temp"],
870877
])
871878

872879
property int beepReason: 0

0 commit comments

Comments
 (0)