|
22 | 22 | #include "vesc_c_if.h"
|
23 | 23 |
|
24 | 24 | #include "atr.h"
|
| 25 | +#include "bms.h" |
25 | 26 | #include "charging.h"
|
26 | 27 | #include "footpad_sensor.h"
|
27 | 28 | #include "lcm.h"
|
@@ -55,7 +56,14 @@ typedef enum {
|
55 | 56 | BEEP_SENSORS = 7,
|
56 | 57 | BEEP_LOWBATT = 8,
|
57 | 58 | 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 |
59 | 67 | } BeepReason;
|
60 | 68 |
|
61 | 69 | static const FootpadSensorState flywheel_konami_sequence[] = {
|
@@ -194,6 +202,8 @@ typedef struct {
|
194 | 202 | Konami flywheel_konami;
|
195 | 203 | Konami headlights_on_konami;
|
196 | 204 | Konami headlights_off_konami;
|
| 205 | + |
| 206 | + uint32_t bms_fault; |
197 | 207 | } data;
|
198 | 208 |
|
199 | 209 | static void brake(data *d);
|
@@ -362,6 +372,8 @@ static void configure(data *d) {
|
362 | 372 | sizeof(headlights_off_konami_sequence)
|
363 | 373 | );
|
364 | 374 |
|
| 375 | + d->bms_fault = 0; |
| 376 | + |
365 | 377 | reconfigure(d);
|
366 | 378 |
|
367 | 379 | if (d->state.state == STATE_DISABLED) {
|
@@ -671,7 +683,8 @@ static bool check_faults(data *d) {
|
671 | 683 | static void calculate_setpoint_target(data *d) {
|
672 | 684 | float input_voltage = VESC_IF->mc_get_input_voltage_filtered();
|
673 | 685 |
|
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)) { |
675 | 688 | d->tb_highvoltage_timer = d->current_time;
|
676 | 689 | }
|
677 | 690 |
|
@@ -745,11 +758,18 @@ static void calculate_setpoint_target(data *d) {
|
745 | 758 | if (d->state.mode != MODE_FLYWHEEL) {
|
746 | 759 | d->state.sat = SAT_PB_DUTY;
|
747 | 760 | }
|
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 | + } |
750 | 769 | beep_alert(d, 3, false);
|
751 | 770 | 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)) { |
753 | 773 | // 500ms have passed or voltage is another volt higher, time for some tiltback
|
754 | 774 | if (d->motor.erpm > 0) {
|
755 | 775 | d->setpoint_target = d->float_conf.tiltback_hv_angle;
|
@@ -792,17 +812,42 @@ static void calculate_setpoint_target(data *d) {
|
792 | 812 | // The rider has 1 degree Celsius left before we start tilting back
|
793 | 813 | d->state.sat = SAT_NONE;
|
794 | 814 | }
|
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))) { |
796 | 836 | 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 | + } |
798 | 842 | float abs_motor_current = fabsf(d->motor.current);
|
799 | 843 | float vdelta = d->float_conf.tiltback_lv - input_voltage;
|
800 | 844 | float ratio = vdelta * 20 / abs_motor_current;
|
801 | 845 | // When to do LV tiltback:
|
802 | 846 | // a) we're 2V below lv threshold
|
803 | 847 | // b) motor current is small (we cannot assume vsag)
|
804 | 848 | // 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)) { |
806 | 851 | if (d->motor.erpm > 0) {
|
807 | 852 | d->setpoint_target = d->float_conf.tiltback_lv_angle;
|
808 | 853 | } else {
|
@@ -1443,6 +1488,17 @@ static void refloat_thd(void *arg) {
|
1443 | 1488 | d->enable_upside_down = false;
|
1444 | 1489 | d->state.darkride = false;
|
1445 | 1490 | }
|
| 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 | + |
1446 | 1502 | if (d->current_time - d->disengage_timer > 1800) { // alert user after 30 minutes
|
1447 | 1503 | if (d->current_time - d->nag_timer > 60) { // beep every 60 seconds
|
1448 | 1504 | d->nag_timer = d->current_time;
|
@@ -2582,6 +2638,14 @@ static lbm_value ext_set_fw_version(lbm_value *args, lbm_uint argn) {
|
2582 | 2638 | return VESC_IF->lbm_enc_sym_true;
|
2583 | 2639 | }
|
2584 | 2640 |
|
| 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 | + |
2585 | 2649 | // Used to send the current or default configuration to VESC Tool.
|
2586 | 2650 | static int get_cfg(uint8_t *buffer, bool is_default) {
|
2587 | 2651 | data *d = (data *) ARG;
|
@@ -2701,6 +2765,7 @@ INIT_FUN(lib_info *info) {
|
2701 | 2765 | VESC_IF->set_app_data_handler(on_command_received);
|
2702 | 2766 | VESC_IF->lbm_add_extension("ext-dbg", ext_dbg);
|
2703 | 2767 | 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); |
2704 | 2769 |
|
2705 | 2770 | return true;
|
2706 | 2771 | }
|
|
0 commit comments