Skip to content

Commit

Permalink
Calc cadence tick 4x more often
Browse files Browse the repository at this point in the history
  • Loading branch information
dzid26 committed Apr 20, 2024
1 parent a34e7ea commit 7bf913c
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 85 deletions.
18 changes: 1 addition & 17 deletions src/controller/ebike_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,7 @@ static uint16_t smooth_start_duty_cycle_target = 0;
static uint8_t ui8_brakes_engaged = 0;

// cadence sensor
uint16_t ui16_cadence_ticks_count_min_speed_adj = CADENCE_SENSOR_CALC_COUNTER_MIN;
static uint8_t ui8_pedal_cadence_RPM = 0;
uint8_t ui8_pedal_cadence_fast_stop = 0;
static uint8_t ui8_motor_deceleration = MOTOR_DECELERATION;

// torque sensor
Expand Down Expand Up @@ -508,12 +506,6 @@ void ebike_app_init(void)
(uint8_t) PWM_DUTY_CYCLE_RAMP_DOWN_INVERSE_STEP_DEFAULT,
(uint8_t) PWM_DUTY_CYCLE_RAMP_DOWN_INVERSE_STEP_MIN);

// set pedal cadence fast stop
if(ui8_motor_deceleration == 100)
ui8_pedal_cadence_fast_stop = 1;
else
ui8_pedal_cadence_fast_stop = 0;

// set pedal torque per 10_bit DC_step x100 advanced
if((ui8_torque_sensor_calibrated)&&(m_configuration_variables.ui8_torque_sensor_adv_enabled)) {
ui8_pedal_torque_per_10_bit_ADC_step_x100 = PEDAL_TORQUE_PER_10_BIT_ADC_STEP_ADV_X100;
Expand Down Expand Up @@ -1547,15 +1539,7 @@ static void calc_wheel_speed(void)
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
static void calc_cadence(void){ // Calculate cadence in RPM
ui8_pedal_cadence_RPM = (uint8_t)(CADENCE_RPM_TICK_NUM / ui16_cadence_sensor_ticks);
}

Expand Down
4 changes: 0 additions & 4 deletions src/controller/ebike_app.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ extern volatile uint8_t ui8_system_state;
extern volatile uint8_t ui8_riding_torque_mode;
extern volatile uint16_t ui16_adc_pedal_torque_offset_cal;

// cadence sensor
extern uint16_t ui16_cadence_ticks_count_min_speed_adj;
extern uint8_t ui8_pedal_cadence_fast_stop;

// Torque sensor coaster brake engaged threshold value
extern volatile uint16_t ui16_adc_coaster_brake_threshold;

Expand Down
9 changes: 4 additions & 5 deletions src/controller/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@

// cadence sensor
#define CADENCE_SENSOR_NUMBER_MAGNETS 20U
#define CADENCE_SENSOR_STATES 4U // There are two hal sensors and both can be On or Off

/*-------------------------------------------------------------------------------
NOTE: regarding the cadence sensor
Expand All @@ -50,13 +52,10 @@
transitions of the same kind it is important to adjust the calculation of
pedal cadence.
-------------------------------------------------------------------------------*/
#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_RPM_TICK_NUM (PWM_CYCLES_SECOND * (60U / CADENCE_SENSOR_NUMBER_MAGNETS))
#define CADENCE_COUNTER_RESET 1U
#define CADENCE_COUNTER_MAX (CADENCE_RPM_TICK_NUM + 1U)
#define CADENCE_TICKS_STOP CADENCE_COUNTER_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)
#define CADENCE_TICKS_STOP (CADENCE_RPM_TICK_NUM + 1U)

// Wheel speed sensor
#define MAX_PLAUSIBLE_WHEEL_SPEED_X10 800U
#define WHEEL_SPEED_COUNTER_RESET 1U
Expand Down
109 changes: 50 additions & 59 deletions src/controller/motor.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,13 +324,7 @@ static uint8_t ui8_adc_motor_phase_current;
volatile uint8_t ui8_brake_state = 0;

// cadence sensor
#define NO_PAS_REF 5
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 = CADENCE_COUNTER_MAX;
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 };

// wheel speed sensor
volatile uint16_t ui16_wheel_speed_sensor_ticks = WHEEL_SPEED_TICKS_STOP;
Expand Down Expand Up @@ -655,11 +649,6 @@ void TIM1_CAP_COM_IRQHandler(void) __interrupt(TIM1_CAP_COM_IRQHANDLER)
// reset duty cycle ramp up counter (filter)
ui8_counter_duty_cycle_ramp_up = 0;

// motor fast stop
if(ui8_pedal_cadence_fast_stop) {
ui8_controller_duty_cycle_ramp_down_inverse_step = PWM_DUTY_CYCLE_RAMP_DOWN_INVERSE_STEP_MIN;
}

// ramp down duty cycle
if (++ui8_counter_duty_cycle_ramp_down >= ui8_controller_duty_cycle_ramp_down_inverse_step) {
ui8_counter_duty_cycle_ramp_down = 0;
Expand Down Expand Up @@ -841,62 +830,64 @@ void TIM1_CAP_COM_IRQHandler(void) __interrupt(TIM1_CAP_COM_IRQHANDLER)
* - New pedal start/stop detection Algorithm (by MSpider65) -
*
* Pedal start/stop detection uses both transitions of both PAS sensors
* ui8_pas_state stores the PAS1 and PAS2 state: bit0=PAS1, bit1=PAS2
* Pedal forward ui8_pas_state sequence is: 0x01 -> 0x00 -> 0x02 -> 0x03 -> 0x01
* ui8_cadence_hal_state stores the PAS1 and PAS2 state: bit0=PAS1, bit1=PAS2
* Pedal forward ui8_cadence_hal_state sequence is: 0x01 -> 0x00 -> 0x02 -> 0x03
* After a stop, the first forward transition is taken as reference transition
* Following forward transition sets the cadence to 1RPM for immediate startup
* Then, starting form the second reference transition, the cadence is calculated based on counter value
* All transitions resets the stop detection counter (much faster stop detection):
*/

uint8_t ui8_pas_state = (PAS1__PORT->IDR & PAS1__PIN) | ((PAS2__PORT->IDR & PAS2__PIN) >> 6);

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 = 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 != CADENCE_TICKS_STOP)) {
ui16_cadence_sensor_ticks_counter_min = ui16_cadence_sensor_ticks;
}
else {
ui16_cadence_sensor_ticks_counter_min = ui16_cadence_ticks_count_min_speed_adj;
}

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 = CADENCE_COUNTER_RESET;
} 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 = CADENCE_COUNTER_RESET;
const static uint8_t ui8_pas_next_state[CADENCE_SENSOR_STATES] = { 0x02, 0x00, 0x03, 0x01 }; //calculate next state index in forward direction
const static uint8_t ui8_pas_prev_state[CADENCE_SENSOR_STATES] = { 0x01, 0x03, 0x00, 0x02 }; //calculate previous state index in forward direction
uint8_t ui8_cadence_hal_state = (PAS1__PORT->IDR & PAS1__PIN) | ((PAS2__PORT->IDR & PAS2__PIN) >> 6U);
static uint8_t ui8_cadence_hal_state_prev = 0xffU;
static uint16_t ui16_cadence_hal_state_cnt[CADENCE_SENSOR_STATES] = {CADENCE_TICKS_STOP, CADENCE_TICKS_STOP, CADENCE_TICKS_STOP, CADENCE_TICKS_STOP};


if (ui8_cadence_hal_state != ui8_cadence_hal_state_prev) {
if (ui8_cadence_hal_state_prev == ui8_pas_prev_state[ui8_cadence_hal_state]) {//forward direction
if (ui16_cadence_hal_state_cnt[ui8_cadence_hal_state] < CADENCE_TICKS_STOP) {//normal operation - not stopped
ui16_cadence_sensor_ticks = ui16_cadence_hal_state_cnt[ui8_cadence_hal_state];
} else {//quick cadence estimation when starting after full stop
// Only provide tick estimation as cadence sensor states are not necessarily equally spaced
// Uses fractions of full tick time (CADENCE_SENSOR_STATES) to estimate the cadence
static uint8_t ui8_cadence_hal_state_start;
static uint8_t ui8_cadence_hal_transitions = CADENCE_SENSOR_STATES;
if(ui16_cadence_sensor_ticks >= CADENCE_TICKS_STOP){
ui8_cadence_hal_state_start = ui8_cadence_hal_state; //first pulse state after full stop
ui8_cadence_hal_transitions = 1U;
#define CADENCE_FIRST_PULSE_RPM 1U
ui16_cadence_sensor_ticks = CADENCE_RPM_TICK_NUM / CADENCE_FIRST_PULSE_RPM;
}else{
if(ui16_cadence_hal_state_cnt[ui8_cadence_hal_state_start] < (CADENCE_TICKS_STOP / CADENCE_SENSOR_STATES * ui8_cadence_hal_transitions)){
ui16_cadence_sensor_ticks = ui16_cadence_hal_state_cnt[ui8_cadence_hal_state_start] / ui8_cadence_hal_transitions * CADENCE_SENSOR_STATES;//the operation order is not ideal, but it avoids using 32bit or addition 1+1/3 and if statements
ui8_cadence_hal_transitions++; //after reaching CADENCE_SENSOR_STATES, we will naturally move to normal operation
} else {
ui8_cadence_hal_transitions = CADENCE_SENSOR_STATES;
}
}
}// end of quick cadence estimation
ui16_cadence_hal_state_cnt[ui8_cadence_hal_state] = CADENCE_COUNTER_RESET;
} else {
// wrong state sequence: backward rotation - assume stop
ui16_cadence_hal_state_cnt[0x00] = CADENCE_TICKS_STOP;
ui16_cadence_hal_state_cnt[0x01] = CADENCE_TICKS_STOP;
ui16_cadence_hal_state_cnt[0x02] = CADENCE_TICKS_STOP;
ui16_cadence_hal_state_cnt[0x03] = CADENCE_TICKS_STOP;
ui16_cadence_sensor_ticks = CADENCE_TICKS_STOP;
} else if (ui16_cadence_sensor_ticks == CADENCE_TICKS_STOP) {
// When first magnet passes through the two hal sensors we know we rotate forward, but can't calculate speed yet, so assume 1RPM
ui16_cadence_sensor_ticks = CADENCE_RPM_TICK_NUM; //1RPM
ui16_cadence_calc_counter = CADENCE_COUNTER_RESET;
}

skip_cadence:
// save current PAS state
ui8_pas_state_old = ui8_pas_state;
}
if (ui16_cadence_calc_counter > ui16_cadence_sensor_ticks) {
// next pulse later than previous - start decaying the speed
ui16_cadence_sensor_ticks = ui16_cadence_calc_counter;
ui8_cadence_hal_state_prev = ui8_cadence_hal_state;
}

if (ui16_cadence_calc_counter < CADENCE_COUNTER_MAX) {
// increment cadence tick counter
++ui16_cadence_calc_counter;
} else { //detect stop
ui8_cadence_calc_ref_state = NO_PAS_REF;
ui16_cadence_sensor_ticks = CADENCE_TICKS_STOP;
// increment cadence counters for each sensor state
if (ui16_cadence_hal_state_cnt[0x00] < CADENCE_TICKS_STOP) {++ui16_cadence_hal_state_cnt[0x00];}
if (ui16_cadence_hal_state_cnt[0x01] < CADENCE_TICKS_STOP) {++ui16_cadence_hal_state_cnt[0x01];}
if (ui16_cadence_hal_state_cnt[0x02] < CADENCE_TICKS_STOP) {++ui16_cadence_hal_state_cnt[0x02];}
if (ui16_cadence_hal_state_cnt[0x03] < CADENCE_TICKS_STOP) {++ui16_cadence_hal_state_cnt[0x03];}

// start decaying the speed if next pulse is arriving late
// when full stop, ui16_cadence_sensor_ticks becomes CADENCE_TICKS_STOP
if (ui16_cadence_hal_state_cnt[ui8_pas_next_state[ui8_cadence_hal_state]] > ui16_cadence_sensor_ticks) {
ui16_cadence_sensor_ticks = ui16_cadence_hal_state_cnt[ui8_pas_next_state[ui8_cadence_hal_state]];
}

/****************************************************************************/
Expand Down

0 comments on commit 7bf913c

Please sign in to comment.