LiamBindle / PyVESC

PyVESC is an easy to use and robust Python implementation of the VESC - Open Source ESC communication protocol
https://pyvesc.readthedocs.io/en/latest/
Creative Commons Attribution 4.0 International
67 stars 52 forks source link

How to determine sensor_mode of foc #33

Open MelvinWarnet opened 1 month ago

MelvinWarnet commented 1 month ago

My goal is to create a Python script with the same functionality as the VESCTOOL setupwizardfoc. I am using the Pyvesc library to encode and decode messages for the VESC. I send the COMM_DETECT_APPLY_ALL_FOC message, the motor runs correctly, and I receive a response corresponding to the COMM_GET_MCCONF message. So far, I am following the same logic that I observed in the VESCTOOL source code.

What I do not understand is the logic VESCTOOL uses to analyze the mcconf of the VESC and deduce the foc_sensor_mode. In the COMM_GET_MCCONF message that I receive, there are many parameters, as you can see in the text below. However, the only parameter whose value changes depending on the Sensor mode in the FOC tab of VESCTOOL is the following:

foc_duty_dowmramp_ki: 0.0 in sensorless
foc_duty_dowmramp_ki: 2.802596928649634e-45 in hall sensor
foc_duty_dowmramp_ki: 1.401298464324817e-45 in encoder

Message sent by the VESC in response to COMM_DETECT_APPLY_ALL_FOC:

pwm_mode: 131.0
comm_mode: 214.0
motor_type: 32.0
sensor_mode: 122.0
l_current_max: 2.351132194607322e-38
l_current_min: 38.619998931884766
l_in_current_max: -38.619998931884766
l_in_current_min: 99.0
l_abs_current_max: -60.0
l_min_erpm: 150.0
l_max_erpm: -100000.0
l_erpm_start: 100000.0
l_max_erpm_fbrake: 0.800000011920929
l_max_erpm_fbrake_cc: 300.0
l_min_vin: 1500.0
l_max_vin: 8.0
l_battery_cut_start: 57.0
l_battery_cut_end: 10.199999809265137
l_slow_abs_current: 65.0
l_temp_fet_start: 2.5243551976337916e-29
l_temp_fet_end: 85.0
l_temp_motor_start: 100.0
l_temp_motor_end: 85.0
l_temp_accel_dec: 100.0
l_min_duty: 0.15000000596046448
l_max_duty: 0.004999999888241291
l_watt_max: 0.949999988079071
l_watt_min: 1500000.0
sl_min_erpm: -1500000.0
sl_min_erpm_cycle_int_limit: 1.0
sl_max_fullbreak_current_dir_change: 1.0
sl_cycle_int_limit: 1.0
sl_phase_advance_at_br: 150.0
sl_cycle_int_rpm_br: 1100.0
sl_bemf_coupling_k: 10.0
hall_table_0: 66.0
hall_table_1: 120.0
hall_table_2: 0.0
hall_table_3: 0.0
hall_table_4: 63.0
hall_table_5: 76.0
hall_table_6: -52.0
hall_table_7: -51.0
hall_sl_erpm: 80000.0
foc_current_kp: 600.0
foc_current_ki: -1.7148602891164896e+38
foc_f_sw: 6.301567357904227e-36
foc_dt_us: 2000.0
foc_encoder_inverted: 61.0
foc_encoder_offset: 1.396456972987105e-20
foc_encoder_ratio: -4.076628851033237e-19
foc_sensor_mode: 195.0
foc_pll_kp: 8606176256.0
foc_pll_ki: -71.5005111694336
foc_motor_l: 1.1921019904548302e-07
foc_motor_r: -3.68937652243493e+19
foc_motor_flux_linkage: -8.828180325246348e-44
foc_observer_gain: -8.828180325246348e-44
foc_observer_gain_slow: -769658912768.0
foc_duty_dowmramp_kp: -769658912768.0
foc_duty_dowmramp_ki: 0.0
foc_openloop_rpm: 2000.0
foc_sl_openloop_hyst: 30000.0
foc_sl_openloop_time: 3.867000123136677e-05
foc_sl_d_current_duty: 0.0
foc_sl_d_current_factor: 0.08049999922513962
foc_hall_table_0: 59.0
foc_hall_table_1: 250.0
foc_hall_table_2: 105.0
foc_hall_table_3: 190.0
foc_hall_table_4: 75.0
foc_hall_table_5: 130.0
foc_hall_table_6: 157.0
foc_hall_table_7: 128.0
foc_sl_erpm: 0.05000000074505806
foc_sample_v0_v7: 65.0
foc_sample_high_current: 32.0
foc_sat_comp: 2.413596474953065e-41
foc_temp_comp: 0.0
foc_temp_comp_base_temp: 6.261674161866159e-39
s_pid_kp: 8.828180325246348e-44
s_pid_ki: 2.7200758163159178e+23
s_pid_kd: 107374592.0
s_pid_min_erpm: 6.162975822039155e-33
s_pid_allow_braking: 10.0
p_pid_kp: 5.507985782829056e-40
p_pid_ki: 9.925151316279335e-27
p_pid_kd: -1.1886727691035048e-07
p_pid_ang_div: 2.4923494486481196e-41
cc_startup_boost_duty: 0.0
cc_min_current: 1.2611686178923354e-44
cc_gain: -759.199951171875
cc_ramp_step_max: -136315920.0
m_fault_stop_time_ms: -1610612672.0
m_duty_ramp_step: -9.10844001811131e-44
m_current_backoff_gain: 1.0842109612795128e-19
m_encoder_counts: 4194304000.0
m_sensor_port_mode: 65.0
m_invert_direction: 58.0
m_drv8301_oc_mode: 131.0
m_drv8301_oc_adj: 18.0
m_bldc_f_sw_min: 3.992451074025009e+28
m_bldc_f_sw_max: 2.2168541705618606e-41
m_dc_f_sw: -107603880.0
m_ntc_motor_beta: -71.62945556640625
RKajay2001 commented 1 month ago

Can you share your code for COMM_GET_MCCONF and then how to change the value of above parameter

MelvinWarnet commented 1 month ago

In the repository that I use github.com/MXMP/PyVESC-FW3.33 there is a COMM_GET_MCCONF message in getters.py so the librairy parse it. For the moment, I didn't send any COMM_GET_MCCONF message. The one that I get is send by vesc after receive the COMM_DETECT_APPLY_ALL_FOC. The COMM_GET_MCCONF is parse by pyvesc but I think fields type aren't the good one so it explained that my values are no consistent. I will try to change those types following what I can observe in vesctool and I will share the message if parsing the message is a succes. For the moment what I have for you is :

define the message class (already define in the repository I share) :

    id = 14  # COMM_GET_MCCONF
    can_id = None

    fields = [
        ('pwm_mode', 'B', 1),
        ('comm_mode', 'B', 1),
        ('motor_type', 'B', 1),
        ('sensor_mode', 'B', 1),
        ('l_current_max', 'f', 1),
        ('l_current_min', 'f', 1),
        ('l_in_current_max', 'f', 1),
        ('l_in_current_min', 'f', 1),
        ('l_abs_current_max', 'f', 1),
        ('l_min_erpm', 'f', 1),
        ('l_max_erpm', 'f', 1),
        ('l_erpm_start', 'f', 1),
        ('l_max_erpm_fbrake', 'f', 1),
        ('l_max_erpm_fbrake_cc', 'f', 1),
        ('l_min_vin', 'f', 1),
        ('l_max_vin', 'f', 1),
        ('l_battery_cut_start', 'f', 1),
        ('l_battery_cut_end', 'f', 1),
        ('l_slow_abs_current', 'B', 1),
        ('l_temp_fet_start', 'f', 1),
        ('l_temp_fet_end', 'f', 1),
        ('l_temp_motor_start', 'f', 1),
        ('l_temp_motor_end', 'f', 1),
        ('l_temp_accel_dec', 'f', 1),
        ('l_min_duty', 'f', 1),
        ('l_max_duty', 'f', 1),
        ('l_watt_max', 'f', 1),
        ('l_watt_min', 'f', 1),
        ('sl_min_erpm', 'f', 1),
        ('sl_min_erpm_cycle_int_limit', 'f', 1),
        ('sl_max_fullbreak_current_dir_change', 'f', 1),
        ('sl_cycle_int_limit', 'f', 1),
        ('sl_phase_advance_at_br', 'f', 1),
        ('sl_cycle_int_rpm_br', 'f', 1),
        ('sl_bemf_coupling_k', 'f', 1),
        ('hall_table_0', 'b', 1),
        ('hall_table_1', 'b', 1),
        ('hall_table_2', 'b', 1),
        ('hall_table_3', 'b', 1),
        ('hall_table_4', 'b', 1),
        ('hall_table_5', 'b', 1),
        ('hall_table_6', 'b', 1),
        ('hall_table_7', 'b', 1),
        ('hall_sl_erpm', 'f', 1),
        ('foc_current_kp', 'f', 1),
        ('foc_current_ki', 'f', 1),
        ('foc_f_sw', 'f', 1),
        ('foc_dt_us', 'f', 1),
        ('foc_encoder_inverted', 'B', 1),
        ('foc_encoder_offset', 'f', 1),
        ('foc_encoder_ratio', 'f', 1),
        ('foc_sensor_mode', 'B', 1),
        ('foc_pll_kp', 'f', 1),
        ('foc_pll_ki', 'f', 1),
        ('foc_motor_l', 'f', 1),
        ('foc_motor_r', 'f', 1),
        ('foc_motor_flux_linkage', 'f', 1),
        ('foc_observer_gain', 'f', 1),
        ('foc_observer_gain_slow', 'f', 1),
        ('foc_duty_dowmramp_kp', 'f', 1),
        ('foc_duty_dowmramp_ki', 'f', 1),
        ('foc_openloop_rpm', 'f', 1),
        ('foc_sl_openloop_hyst', 'f', 1),
        ('foc_sl_openloop_time', 'f', 1),
        ('foc_sl_d_current_duty', 'f', 1),
        ('foc_sl_d_current_factor', 'f', 1),
        ('foc_hall_table_0', 'B', 1),
        ('foc_hall_table_1', 'B', 1),
        ('foc_hall_table_2', 'B', 1),
        ('foc_hall_table_3', 'B', 1),
        ('foc_hall_table_4', 'B', 1),
        ('foc_hall_table_5', 'B', 1),
        ('foc_hall_table_6', 'B', 1),
        ('foc_hall_table_7', 'B', 1),
        ('foc_sl_erpm', 'f', 1),
        ('foc_sample_v0_v7', 'B', 1),
        ('foc_sample_high_current', 'B', 1),
        ('foc_sat_comp', 'f', 1),
        ('foc_temp_comp', 'B', 1),
        ('foc_temp_comp_base_temp', 'f', 1),
        ('s_pid_kp', 'f', 1),
        ('s_pid_ki', 'f', 1),
        ('s_pid_kd', 'f', 1),
        ('s_pid_min_erpm', 'f', 1),
        ('s_pid_allow_braking', 'B', 1),
        ('p_pid_kp', 'f', 1),
        ('p_pid_ki', 'f', 1),
        ('p_pid_kd', 'f', 1),
        ('p_pid_ang_div', 'f', 1),
        ('cc_startup_boost_duty', 'f', 1),
        ('cc_min_current', 'f', 1),
        ('cc_gain', 'f', 1),
        ('cc_ramp_step_max', 'f', 1),
        ('m_fault_stop_time_ms', 'i', 1),
        ('m_duty_ramp_step', 'f', 1),
        ('m_current_backoff_gain', 'f', 1),
        ('m_encoder_counts', 'I', 1),
        ('m_sensor_port_mode', 'B', 1),
        ('m_invert_direction', 'B', 1),
        ('m_drv8301_oc_mode', 'B', 1),
        ('m_drv8301_oc_adj', 'B', 1),
        ('m_bldc_f_sw_min', 'f', 1),
        ('m_bldc_f_sw_max', 'f', 1),
        ('m_dc_f_sw', 'f', 1),
        ('m_ntc_motor_beta', 'f', 1)
    ]

Send the message :

my_msg = GetConfig(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
my_msg = pyvesc.encode(my_msg)
serial.write(my_msg)

Read the answer :

if serial.in_waiting > 0:
   data = serial.read(serial.in_waiting)
   msg, consummed = pyvesc.decode(data)
   for field_name, _, _ in msg.fields:
      print(f"{field_name}: {getattr(msg, field_name)}")