vedderb / bldc

The VESC motor control firmware
2.09k stars 1.31k forks source link

VESC C Interface for Package - request for additional functions #596

Open surfdado opened 1 year ago

surfdado commented 1 year ago

I'd like to see the following APIs added before the 6.2 release:

1) general, to know which firmware version we're dealing with get_firmware_version() // returns firmware version (either string, or we can have major/minor/beta as numbers)

2) BMS related (to enable BMS based user alerts in lieu of current limiting) bms_get_temp_max_cell // returns the highest temperature reported by the BMS bms_get_voltage_max_cell // returns the highest cell voltage reported by the BMS bms_get_voltage_min_cell // returns the lowest cell voltage reported by the BMS

3) Misc mc_set_erpm_limits(min,max) // allow changing erpm limits on the fly (to deal with situations like wheelslip) mc_get_fieldweakening_current (or get_id_current)

I'd be happy to implement some of them myself, just didn't want to do the work if you already had something up your sleeve. Thanks! Dado

vedderb commented 1 year ago
  1. and 2.

I think it is best to get these from the lisp interface, especially the BMS-values. Otherwise I have to lock the bms_values data structure for future compatibility with the C library, which makes future updates more tricky.

To get them from lisp into C you can use extensions. One approach is to handle the logic on how to deal with these things in lisp and another approach is to pass all the data to C and handle it from there. When it comes to user alerts it makes sense to handle it from lisp as that makes it easier to tweak that code from VESC Tool without having to recompile the package. You can then just read the lisp, adjust it and write it back.

This example shows how to pass the firmware version to C from lisp using an extension. Then you have to write the logic that deals with that in C.

static lbm_value ext_test(lbm_value *args, lbm_uint argn) {
    int major = VESC_IF->lbm_dec_as_i32(args[0]) ;
    int minor = VESC_IF->lbm_dec_as_i32(args[1]) ;
    int beta = VESC_IF->lbm_dec_as_i32(args[2]) ;
    ...
    return VESC_IF->lbm_enc_sym_true;
}

INIT_FUN(lib_info *info) {
    ...

    VESC_IF->lbm_add_extension("ext-set-fw-version", ext_set_fw_version);   

    ...
}

Then from lisp you can call that function like

; Here apply just means that we pass the list that (sysinfo 'fw-ver) returns
; as arguments to ext-set-fw-version
(apply ext-set-fw-version (sysinfo 'fw-ver))

3. I have added some FOC-functions now: https://github.com/vedderb/bldc/commit/7ae56c0a7198008936d3d9c623700506d5b1e79b

You can already change erpm and current limits on the fly with

VESC_IF->set_cfg_float(CFG_PARAM_l_min_erpm, value);
VESC_IF->set_cfg_float(CFG_PARAM_l_max_erpm, value);

That can be done on the fly without stopping the motor, but to store them in eeprom you need to use VESC_IF->store_cfg which stops the motor.

surfdado commented 1 year ago

This is all very helpful, thank you!! I'll give that a try

surfdado commented 1 year ago

It looks like only temp_max_cell and overall SoC is available today for BMS values. Still trying to figure out how I'd identify situations where one cell reaches a min/max threshold without processing a whole bunch of data in Lisp

vedderb commented 1 year ago

Here is how to get the min and max voltage and print them

(let (
        (volts-sorted
            (sort < ; Sort list with voltages in ascending order
                (map
                    (fn (x) (get-bms-val 'bms-v-cell x)) ; For every index in the list get the cell voltage
                    (range 0 (get-bms-val 'bms-cell-num)) ; Generate a list from 0 to cell-num - 1
        )))
        (volts-min (ix volts-sorted 0)) ; First element is lowest voltage
        (volts-max (ix volts-sorted -1)) ; Last element is highest voltage
    )
    (print (list volts-min volts-max))
)

I haven't tested it, but hopefully it works.

surfdado commented 1 year ago

Great thanks, so instead of print we'd do (apply ext-set-bms-stats (volts-min volts-max (get-bms-val 'bms-temp-cell-max))) and create the matching C-extension?

Also, can I assume that the get-bms-val calls return 0 when there's no VESC BMS connected?

vedderb commented 1 year ago

Almost, you have to make them into a list if you use apply. Easier would be to pass them as arguments directly though:

(ext-set-bms-stats volts-min volts-max (get-bms-val 'bms-temp-cell-max))

The only reason we use apply with (sysinfo 'fw-ver) is that it returns a list and we can use apply to use the elements in a list as arguments to a function. We could also make ext-set-fw-version take a list as one argument instead of multiple arguments. There is more than one way to do the same thing.