Skip to content

Commit

Permalink
Use high UINT16_MAX instead of 0 to express stop speed tick period - …
Browse files Browse the repository at this point in the history
…removes need for for CADENCE_TICKS_STARTUP in motor.c and div by 0 checks in ebike.c. Use more constants. Small cleanups.

WHEEL_SPEED_SENSOR_TICKS_COUNTER_MIN and MAX calculated based on the wheel size.
  • Loading branch information
dzid26 committed Nov 11, 2023
1 parent 24fe1ba commit ccdcb6b
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 72 deletions.
45 changes: 14 additions & 31 deletions src/controller/ebike_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -763,7 +763,7 @@ static void ebike_control_motor(void)
}
}

//voltage based control assumes the winding resistance is constant - this limitation is ignored for simplicity
//voltage based control assumes the winding resistance is constant for simplicity
uint32_t smooth_start_voltage_target_x100 = smooth_start_voltage_limit_x100 + smooth_start_voltage_limit_blend_x100;
smooth_start_voltage_target_x100 += (ui16_motor_bemf_voltage_x1000 / (10U + SMOOTH_START_BEMF_REDUCE_FACTOR));
if (smooth_start_voltage_target_x100 > UINT16_MAX){
Expand Down Expand Up @@ -1545,43 +1545,26 @@ static void calc_wheel_speed(void)
}


static void calc_cadence(void)
{
// get the cadence sensor ticks
uint16_t ui16_cadence_sensor_ticks_temp = ui16_cadence_sensor_ticks;

// adjust cadence sensor ticks counter min depending on wheel speed
/*-------------------------------------------------------------------------------------------------
NOTE: regarding the cadence calculation
Cadence is calculated by counting how many ticks there are between two LOW to HIGH transitions.
Formula for calculating the cadence in RPM:
(1) Cadence in RPM = (60 * PWM_CYCLES_SECOND) / CADENCE_SENSOR_NUMBER_MAGNETS) / ticks
-------------------------------------------------------------------------------------------------*/
static void calc_cadence(void){
// adjust cadence sensor ticks counter min depending on wheel speed - read in motor.c
ui16_cadence_ticks_count_min_speed_adj = map_ui16(ui16_wheel_speed_x10,
40,
400,
CADENCE_SENSOR_CALC_COUNTER_MIN,
CADENCE_SENSOR_TICKS_COUNTER_MIN_AT_SPEED);

// calculate cadence in RPM and avoid zero division
// !!!warning if PWM_CYCLES_SECOND > 21845
if (ui16_cadence_sensor_ticks_temp) {
ui8_pedal_cadence_RPM = (uint8_t)((PWM_CYCLES_SECOND * 3U) / ui16_cadence_sensor_ticks_temp);

if(ui8_pedal_cadence_RPM > 120) {ui8_pedal_cadence_RPM = 120;}
// calculate cadence in RPM
ui8_pedal_cadence_RPM = (uint8_t)(CADENCE_RPM_TICK_NUM / ui16_cadence_sensor_ticks);
if(ui8_pedal_cadence_RPM > CADENCE_MAX_RPM) {
ui8_pedal_cadence_RPM = CADENCE_MAX_RPM;
}
else {
ui8_pedal_cadence_RPM = 0;
}

/*-------------------------------------------------------------------------------------------------
NOTE: regarding the cadence calculation
Cadence is calculated by counting how many ticks there are between two LOW to HIGH transitions.
Formula for calculating the cadence in RPM:
(1) Cadence in RPM = (60 * PWM_CYCLES_SECOND) / CADENCE_SENSOR_NUMBER_MAGNETS) / ticks
(2) Cadence in RPM = (PWM_CYCLES_SECOND * 3) / ticks
-------------------------------------------------------------------------------------------------*/
}
}


static void get_battery_voltage_filtered(void)
Expand Down
52 changes: 28 additions & 24 deletions src/controller/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

// PWM related values
// motor
#define PWM_CYCLES_SECOND 19047U // 52us (PWM period)
#define PWM_CYCLES_SECOND 19047U // 52us (PWM period) - !! has to be less than 21845
#define PWM_CYCLES_COUNTER_MAX 3800U // 5 erps minimum speed -> 1/5 = 200 ms; 200 ms / 50 us = 4000 (3125 at 15.625KHz)
#define DOUBLE_PWM_CYCLES_SECOND 38094 // 25us (2 irq x PWM period)
#define DOUBLE_PWM_CYCLES_SECOND 38094U // 25us (2 irq x PWM period)
// ramp up/down PWM cycles count
#define PWM_DUTY_CYCLE_RAMP_UP_INVERSE_STEP_CADENCE_OFFSET 60 // PWM_DUTY_CYCLE_RAMP_UP_INVERSE_STEP offset for cadence assist mode
//#define PWM_DUTY_CYCLE_RAMP_UP_INVERSE_STEP_DEFAULT 195 // 160 -> 160 * 64 us for every duty cycle increment at 15.625KHz
Expand All @@ -34,16 +34,34 @@
#define THROTTLE_DUTY_CYCLE_RAMP_UP_INVERSE_STEP_MIN 49 // 40 at 15.625KHz

#define MOTOR_SPEED_FIELD_WEAKEANING_MIN 300 // ERPS
// cadence sensor
#define CADENCE_SENSOR_NUMBER_MAGNETS 20U

// cadence
#define CADENCE_SENSOR_CALC_COUNTER_MIN 4266 // 3500 at 15.625KHz
#define CADENCE_SENSOR_TICKS_COUNTER_MIN_AT_SPEED 341 // 280 at 15.625KHz
#define CADENCE_TICKS_STARTUP 7618 // ui16_cadence_sensor_ticks value for startup. About 7-8 RPM (6250 at 15.625KHz)
#define CADENCE_SENSOR_STANDARD_MODE_SCHMITT_TRIGGER_THRESHOLD 0 // software based Schmitt trigger to stop motor jitter when at resolution limits (350 at 15.625KHz)
// Wheel speed sensor
#define WHEEL_SPEED_SENSOR_TICKS_COUNTER_MAX 165 // (135 at 15,625KHz) something like 200 m/h with a 6'' wheel
#define WHEEL_SPEED_SENSOR_TICKS_COUNTER_MIN 39976 // could be a bigger number but will make for a slow detection of stopped wheel speed
/*-------------------------------------------------------------------------------
NOTE: regarding the cadence sensor
CADENCE_SENSOR_NUMBER_MAGNETS = 20, this is the number of magnets used for
the cadence sensor. Was validated on August 2018 by Casainho and jbalat
Cadence is calculated by counting how much time passes between two
transitions. Depending on if all transitions are measured or simply
transitions of the same kind it is important to adjust the calculation of
pedal cadence.
-------------------------------------------------------------------------------*/
#define CADENCE_SENSOR_MIN_RPM 7U //next minimum value other than 0
#define CADENCE_MAX_RPM 120U
#define CADENCE_SENSOR_CALC_COUNTER_MIN 4266U // 3500 at 15.625KHz
#define CADENCE_SENSOR_TICKS_COUNTER_MIN_AT_SPEED 341U // 280 at 15.625KHz
#define CADENCE_COUNTER_RESET 0U
#define CADENCE_COUNTER_MAX UINT16_MAX
#define CADENCE_RPM_TICK_NUM (PWM_CYCLES_SECOND * (60U / CADENCE_SENSOR_NUMBER_MAGNETS))
#define CADENCE_TICKS_STOP UINT16_MAX
#define CADENCE_SENSOR_STANDARD_MODE_SCHMITT_TRIGGER_THRESHOLD 0U // software based Schmitt trigger to stop motor jitter when at resolution limits (350 at 15.625KHz)
// Wheel speed sensor
#define MAX_PLAUSIBLE_WHEEL_SPEED 80U
#define MIN_PLAUSIBLE_WHEEL_SPEED 4U
#define WHEEL_SPEED_SENSOR_TICKS_COUNTER_MAX ((uint16_t)((uint32_t)WHEEL_PERIMETER * (HSE_VALUE / 420 /2) / MAX_PLAUSIBLE_WHEEL_SPEED * 60 / 1000 * 60 / 1000))
#define WHEEL_SPEED_SENSOR_TICKS_COUNTER_MIN ((uint16_t)((uint32_t)WHEEL_PERIMETER * (HSE_VALUE / 420 /2) / MIN_PLAUSIBLE_WHEEL_SPEED * 60 / 1000 * 60 / 1000))

#define PWM_DUTY_CYCLE_MAX 255U
#define PWM_DUTY_CYCLE_BITS 8
Expand Down Expand Up @@ -170,20 +188,6 @@
---------------------------------------------------------*/

// cadence sensor
#define CADENCE_SENSOR_NUMBER_MAGNETS 20U

/*-------------------------------------------------------------------------------
NOTE: regarding the cadence sensor
CADENCE_SENSOR_NUMBER_MAGNETS = 20, this is the number of magnets used for
the cadence sensor. Was validated on August 2018 by Casainho and jbalat
Cadence is calculated by counting how much time passes between two
transitions. Depending on if all transitions are measured or simply
transitions of the same kind it is important to adjust the calculation of
pedal cadence.
-------------------------------------------------------------------------------*/


// default values
Expand Down
33 changes: 16 additions & 17 deletions src/controller/motor.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ volatile uint8_t ui8_fw_angle = 0;
volatile uint8_t ui8_fw_angle_max;
volatile uint8_t ui8_controller_duty_cycle_target = 0;
volatile uint8_t ui8_g_foc_angle = 0;
volatile uint8_t ui8_g_assist_level = 0;
volatile uint8_t ui8_g_assist_level = OFF;
static uint8_t ui8_counter_duty_cycle_ramp_up = 0;
static uint8_t ui8_counter_duty_cycle_ramp_down = 0;

Expand All @@ -326,11 +326,11 @@ volatile uint8_t ui8_brake_state = 0;

// cadence sensor
#define NO_PAS_REF 5
volatile uint16_t ui16_cadence_sensor_ticks = 0;
//volatile uint32_t ui32_crank_revolutions_x20 = 0;
volatile uint16_t ui16_cadence_sensor_ticks = CADENCE_TICKS_STOP;
static uint16_t ui16_cadence_sensor_ticks_counter_min = CADENCE_SENSOR_CALC_COUNTER_MIN;
static uint8_t ui8_pas_state_old = 4;
static uint16_t ui16_cadence_calc_counter, ui16_cadence_stop_counter;
static uint16_t ui16_cadence_calc_counter = CADENCE_COUNTER_RESET;
static uint16_t ui16_cadence_stop_counter = 0;
static uint8_t ui8_cadence_calc_ref_state = NO_PAS_REF;
const static uint8_t ui8_pas_old_valid_state[4] = { 0x01, 0x03, 0x00, 0x02 };

Expand Down Expand Up @@ -358,7 +358,7 @@ void calc_foc_angle(void);
uint8_t asin_table(uint8_t ui8_inverted_angle_x128);

void motor_controller(void) {
ui16_motor_speed_erps = ((uint16_t) DOUBLE_PWM_CYCLES_SECOND) / (ui16_PWM_cycles_counter_total);
ui16_motor_speed_erps = DOUBLE_PWM_CYCLES_SECOND / ui16_PWM_cycles_counter_total;
read_battery_voltage();
calc_foc_angle();
}
Expand Down Expand Up @@ -613,8 +613,8 @@ void TIM1_CAP_COM_IRQHandler(void) __interrupt(TIM1_CAP_COM_IRQHANDLER)
ui16_adc_torque_sensor_check = UI16_ADC_10_BIT_TORQUE_SENSOR;

if((ui16_adc_torque_sensor_check < ui16_adc_pedal_torque_offset_cal)||(!ui8_adc_battery_current_target)) {
if((ui16_motor_speed_erps)
&&(!ui16_cadence_sensor_ticks)
if((ui16_motor_speed_erps > 0)
&&(ui16_cadence_sensor_ticks == CADENCE_TICKS_STOP)
#if OPTIONAL_ADC_FUNCTION == THROTTLE_CONTROL
&&(UI8_ADC_THROTTLE < ADC_THROTTLE_MIN_VALUE)
#endif
Expand Down Expand Up @@ -651,7 +651,7 @@ void TIM1_CAP_COM_IRQHandler(void) __interrupt(TIM1_CAP_COM_IRQHANDLER)
|| (UI8_ADC_BATTERY_VOLTAGE < ui8_adc_battery_voltage_cut_off)
|| (ui8_fw_angle > ui8_fw_angle_max)
|| (ui8_brake_state)
|| (!ui8_g_assist_level)) {
|| (ui8_g_assist_level == OFF)){

// reset duty cycle ramp up counter (filter)
ui8_counter_duty_cycle_ramp_up = 0;
Expand Down Expand Up @@ -855,13 +855,13 @@ void TIM1_CAP_COM_IRQHandler(void) __interrupt(TIM1_CAP_COM_IRQHANDLER)
if (ui8_pas_state != ui8_pas_state_old) {
if (ui8_pas_state_old != ui8_pas_old_valid_state[ui8_pas_state]) {
// wrong state sequence: backward rotation
ui16_cadence_sensor_ticks = 0;
ui16_cadence_sensor_ticks = CADENCE_TICKS_STOP;
ui8_cadence_calc_ref_state = NO_PAS_REF;
goto skip_cadence;
}

// motor fast stop
if(ui8_pedal_cadence_fast_stop && ui16_cadence_sensor_ticks) {
if(ui8_pedal_cadence_fast_stop && (ui16_cadence_sensor_ticks != CADENCE_TICKS_STOP)) {
ui16_cadence_sensor_ticks_counter_min = ui16_cadence_sensor_ticks - (CADENCE_SENSOR_STANDARD_MODE_SCHMITT_TRIGGER_THRESHOLD >> 1);
}
else {
Expand All @@ -875,16 +875,14 @@ void TIM1_CAP_COM_IRQHandler(void) __interrupt(TIM1_CAP_COM_IRQHANDLER)
if (ui8_pas_state == ui8_cadence_calc_ref_state) {
// ui16_cadence_calc_counter is valid for cadence calculation
ui16_cadence_sensor_ticks = ui16_cadence_calc_counter;
ui16_cadence_calc_counter = 0;
ui16_cadence_calc_counter = CADENCE_COUNTER_RESET;
// software based Schmitt trigger to stop motor jitter when at resolution limits
ui16_cadence_sensor_ticks_counter_min += CADENCE_SENSOR_STANDARD_MODE_SCHMITT_TRIGGER_THRESHOLD;
} else if (ui8_cadence_calc_ref_state == NO_PAS_REF) {
// this is the new reference state for cadence calculation
ui8_cadence_calc_ref_state = ui8_pas_state;
ui16_cadence_calc_counter = 0;
} else if (ui16_cadence_sensor_ticks == 0) {
// Waiting the second reference transition: set the cadence to 7 RPM for immediate start
ui16_cadence_sensor_ticks = CADENCE_TICKS_STARTUP;
ui16_cadence_calc_counter = CADENCE_COUNTER_RESET;
ui16_cadence_sensor_ticks = CADENCE_TICKS_STOP;
}

skip_cadence:
Expand All @@ -900,10 +898,10 @@ void TIM1_CAP_COM_IRQHandler(void) __interrupt(TIM1_CAP_COM_IRQHANDLER)

if (++ui16_cadence_stop_counter > ui16_cadence_sensor_ticks_counter_min) {
// pedals stop detected
ui16_cadence_sensor_ticks = 0;
ui16_cadence_sensor_ticks = CADENCE_TICKS_STOP;
ui16_cadence_stop_counter = 0;
ui8_cadence_calc_ref_state = NO_PAS_REF;
} else if (ui8_cadence_calc_ref_state != NO_PAS_REF) {
} else if ((ui8_cadence_calc_ref_state != NO_PAS_REF) && (ui16_cadence_calc_counter < CADENCE_COUNTER_MAX)) {
// increment cadence tick counter
++ui16_cadence_calc_counter;
}
Expand Down Expand Up @@ -941,6 +939,7 @@ void TIM1_CAP_COM_IRQHandler(void) __interrupt(TIM1_CAP_COM_IRQHANDLER)
ui16_wheel_speed_sensor_ticks_counter = 0;
ui8_wheel_speed_sensor_ticks_counter_started = 0;
} else {
//update latest tick and reset the counter
ui16_wheel_speed_sensor_ticks = ui16_wheel_speed_sensor_ticks_counter;
ui16_wheel_speed_sensor_ticks_counter = 0;
++ui32_wheel_speed_sensor_ticks_total;
Expand Down

0 comments on commit ccdcb6b

Please sign in to comment.