- For TORQUE mode, by enabling `ELECTRIC_BRAKE_ENABLE` in `config.h`, the freewheeling amount can be adjusted using the `ELECTRIC_BRAKE_MAX` parameter.
- For VOLTAGE and TORQUE mode, the standstill hold functionality can be forced by enabling `STANDSTILL_HOLD_ENABLE` in `config.h`.
Known (minor) issue: There is a small "tick" noise when Stanstill is engaged/disengaged, due to the switching to SPEED mode. To be solved by an improved mode switching strategy in the future.
#define COM_CTRL 0 // [-] Commutation Control Type
#define SIN_CTRL 1 // [-] Sinusoidal Control Type
#define FOC_CTRL 2 // [-] Field Oriented Control (FOC) Type
#define OPEN_MODE 0 // [-] OPEN mode
#define VLT_MODE 1 // [-] VOLTAGE mode
#define SPD_MODE 2 // [-] SPEED mode
#define TRQ_MODE 3 // [-] TORQUE mode
// Enable/Disable Motor
// Enable/Disable Motor
#define MOTOR_LEFT_ENA // [-] Enable LEFT motor. Comment-out if this motor is not needed to be operational
#define MOTOR_LEFT_ENA // [-] Enable LEFT motor. Comment-out if this motor is not needed to be operational
#define MOTOR_RIGHT_ENA // [-] Enable RIGHT motor. Comment-out if this motor is not needed to be operational
#define MOTOR_RIGHT_ENA // [-] Enable RIGHT motor. Comment-out if this motor is not needed to be operational
// Control selections
// Control selections
#define CTRL_TYP_SEL 2 // [-] Control type selection: 0 = Commutation , 1 = Sinusoidal, 2 = FOC Field Oriented Control (default)
#define CTRL_TYP_SEL FOC_CTRL // [-] Control type selection: COM_CTRL, SIN_CTRL, FOC_CTRL (default)
#define CTRL_MOD_REQ 1 // [-] Control mode request: 0 = Open mode, 1 = VOLTAGE mode (default), 2 = SPEED mode, 3 = TORQUE mode. Note: SPEED and TORQUE modes are only available for FOC!
#define CTRL_MOD_REQ VLT_MODE // [-] Control mode request: OPEN_MODE, VLT_MODE (default), SPD_MODE, TRQ_MODE. Note: SPD_MODE and TRQ_MODE are only available for CTRL_FOC!
#define PHASE_ADV_MAX 25 // [deg] Maximum Phase Advance angle (only for SIN). Higher angle results in higher maximum speed.
#define PHASE_ADV_MAX 25 // [deg] Maximum Phase Advance angle (only for SIN). Higher angle results in higher maximum speed.
#define FIELD_WEAK_HI 1500 // [-] Input target High threshold for reaching maximum Field Weakening / Phase Advance. Do NOT set this higher than 1500.
#define FIELD_WEAK_HI 1500 // [-] Input target High threshold for reaching maximum Field Weakening / Phase Advance. Do NOT set this higher than 1500.
#define FIELD_WEAK_LO 1000 // [-] Input target Low threshold for starting Field Weakening / Phase Advance. Do NOT set this higher than 1000.
#define FIELD_WEAK_LO 1000 // [-] Input target Low threshold for starting Field Weakening / Phase Advance. Do NOT set this higher than 1000.
// Extra functionality
// #define STANDSTILL_HOLD_ENABLE // [-] Flag to hold the position when standtill is reached. Only available and makes sense for VOLTAGE or TORQUE mode.
// #define ELECTRIC_BRAKE_ENABLE // [-] Flag to enable electric brake and replace the motor "freewheel" with a constant braking when the input torque request is 0. Only available and makes sense for TORQUE mode.
// #define ELECTRIC_BRAKE_MAX 100 // (0, 500) Maximum electric brake to be applied when input torque request is 0 (pedal fully released).
// #define ELECTRIC_BRAKE_THRES 120 // (0, 500) Threshold below at which the electric brake starts engaging.
// ########################### END OF MOTOR CONTROL ########################
// ########################### END OF MOTOR CONTROL ########################
#define CTRL_MOD_REQ 3 // HOVERCAR works best in TORQUE Mode
#define CTRL_MOD_REQ TRQ_MODE// HOVERCAR works best in TORQUE Mode
#define CONTROL_ADC // use ADC as input. disable CONTROL_SERIAL_USART2, FEEDBACK_SERIAL_USART2, DEBUG_SERIAL_USART2!
#define CONTROL_ADC // use ADC as input. disable CONTROL_SERIAL_USART2, FEEDBACK_SERIAL_USART2, DEBUG_SERIAL_USART2!
#define ADC_PROTECT_ENA // ADC Protection Enable flag. Use this flag to make sure the ADC is protected when GND or Vcc wire is disconnected
#define ADC_PROTECT_ENA // ADC Protection Enable flag. Use this flag to make sure the ADC is protected when GND or Vcc wire is disconnected
#define ADC_PROTECT_TIMEOUT 100 // ADC Protection: number of wrong / missing input commands before safety state is taken
#define ADC_PROTECT_TIMEOUT 100 // ADC Protection: number of wrong / missing input commands before safety state is taken
@ -369,6 +384,12 @@
#define SIDEBOARD_SERIAL_USART3
#define SIDEBOARD_SERIAL_USART3
#define FEEDBACK_SERIAL_USART3 // right sensor board cable, disable if I2C (nunchuk or lcd) is used!
#define FEEDBACK_SERIAL_USART3 // right sensor board cable, disable if I2C (nunchuk or lcd) is used!
// #define DEBUG_SERIAL_USART3 // right sensor board cable, disable if I2C (nunchuk or lcd) is used!
// #define DEBUG_SERIAL_USART3 // right sensor board cable, disable if I2C (nunchuk or lcd) is used!
// Extra functionality
// #define STANDSTILL_HOLD_ENABLE // [-] Flag to hold the position when standtill is reached. Only available and makes sense for VOLTAGE or TORQUE mode.
// #define ELECTRIC_BRAKE_ENABLE // [-] Flag to enable electric brake and replace the motor "freewheel" with a constant braking when the input torque request is 0. Only available and makes sense for TORQUE mode.
// #define ELECTRIC_BRAKE_MAX 100 // (0, 500) Maximum electric brake to be applied when input torque request is 0 (pedal fully released).
// #define ELECTRIC_BRAKE_THRES 120 // (0, 500) Threshold below at which the electric brake starts engaging.
#endif
#endif
// Multiple tap detection: default DOUBLE Tap on Brake pedal (4 pulses)
// Multiple tap detection: default DOUBLE Tap on Brake pedal (4 pulses)
@ -46,9 +46,23 @@ In this firmware 3 control types are available:
- Commutation
- Commutation
- SIN (Sinusoidal)
- SIN (Sinusoidal)
- FOC (Field Oriented Control) with the following 3 control modes:
- FOC (Field Oriented Control) with the following 3 control modes:
- **VOLTAGE MODE**: in this mode the controller applies a constant Voltage to the motors
- **VOLTAGE MODE**: in this mode the controller applies a constant Voltage to the motors. Recommended for robotics applications or applications where a fast motor response is required.
- **SPEED MODE**: in this mode a closed-loop controller realizes the input speed target by rejecting any of the disturbance (resistive load) applied to the motor
- **SPEED MODE**: in this mode a closed-loop controller realizes the input speed target by rejecting any of the disturbance (resistive load) applied to the motor. Recommended for robotics applications or constant speed applications.
- **TORQUE MODE**: in this mode the input torque target is realized. This mode enables motor "freewheeling" when the torque target is `0`. Recommended for most applications with a sitting human driver. If motor braking is desired instead of "freewheel" when torque target is `0`, then a torque target below `0` should be set when `speedAvgAbs > 0`.
- **TORQUE MODE**: in this mode the input torque target is realized. This mode enables motor "freewheeling" when the torque target is `0`. Recommended for most applications with a sitting human driver.
#### Comparison between different control methods
|Control method| Complexity | Efficiency | Smoothness | Field Weakening | Freewheeling | Standstill hold |
// Calculate speed Blend, a number between [0, 1] in fixdt(0,16,15)
uint16_tspeedBlend;// Calculate speed Blend, a number between [0, 1] in fixdt(0,16,15)
uint16_tspeedBlend;
speedBlend=(uint16_t)(((CLAMP(speedAvgAbs,10,60)-10)<<15)/50);// speedBlend [0,1] is within [10 rpm, 60rpm]
speedBlend=(uint16_t)(((CLAMP(speedAvgAbs,10,60)-10)<<15)/50);// speedBlend [0,1] is within [10 rpm, 60rpm]
#endif
// Check if Hovercar is physically close to standstill to enable Double tap detection on Brake pedal for Reverse functionality
#ifdef VARIANT_HOVERCAR
if(speedAvgAbs<60){
if(speedAvgAbs<60){// Check if Hovercar is physically close to standstill to enable Double tap detection on Brake pedal for Reverse functionality
multipleTapDet(cmd1,HAL_GetTick(),&MultipleTapBreak);// Break pedal in this case is "cmd1" variable
multipleTapDet(cmd1,HAL_GetTick(),&MultipleTapBrake);// Brake pedal in this case is "cmd1" variable
}
}
// If Brake pedal (cmd1) is pressed, bring to 0 also the Throttle pedal (cmd2) to avoid "Double pedal" driving
if(cmd1>30){// If Brake pedal (cmd1) is pressed, bring to 0 also the Throttle pedal (cmd2) to avoid "Double pedal" driving
if(cmd1>20){
cmd2=(int16_t)((cmd2*speedBlend)>>15);
cmd2=(int16_t)((cmd2*speedBlend)>>15);
}
}
#endif
#ifdef ELECTRIC_BRAKE_ENABLE
electricBrake(speedBlend,MultipleTapBrake.b_multipleTap);// Apply Electric Brake. Only available and makes sense for TORQUE Mode
#endif
// Make sure the Brake pedal is opposite to the direction of motion AND it goes to 0 as we reach standstill (to avoid Reverse driving by Brake pedal)
#ifdef VARIANT_HOVERCAR
if(speedAvg>0){
if(speedAvg>0){// Make sure the Brake pedal is opposite to the direction of motion AND it goes to 0 as we reach standstill (to avoid Reverse driving by Brake pedal)
cmd1=(int16_t)((-cmd1*speedBlend)>>15);
cmd1=(int16_t)((-cmd1*speedBlend)>>15);
}else{
}else{
cmd1=(int16_t)((cmd1*speedBlend)>>15);
cmd1=(int16_t)((cmd1*speedBlend)>>15);
}
}
#endif
#endif
// ####### GENERAL TIMEOUT #######
if(timeoutCnt>TIMEOUT){// Bring the system to a Safe State
cmd1=0;
cmd2=0;
}
// ####### LOW-PASS FILTER #######
// ####### LOW-PASS FILTER #######
rateLimiter16(cmd1,RATE,&steerRateFixdt);
rateLimiter16(cmd1,RATE,&steerRateFixdt);
rateLimiter16(cmd2,RATE,&speedRateFixdt);
rateLimiter16(cmd2,RATE,&speedRateFixdt);
@ -250,12 +248,16 @@ int main(void) {
steer=(int16_t)(steerFixdt>>16);// convert fixed-point to integer
steer=(int16_t)(steerFixdt>>16);// convert fixed-point to integer
speed=(int16_t)(speedFixdt>>16);// convert fixed-point to integer
speed=(int16_t)(speedFixdt>>16);// convert fixed-point to integer
#ifdef STANDSTILL_HOLD_ENABLE
standstillHold(&speed);// Apply Standstill Hold functionality. Only available and makes sense for VOLTAGE or TORQUE Mode
#endif
// ####### VARIANT_HOVERCAR #######
// ####### VARIANT_HOVERCAR #######
#ifdef VARIANT_HOVERCAR
#ifdef VARIANT_HOVERCAR
if(!MultipleTapBreak.b_multipleTap){// Check driving direction
if(!MultipleTapBrake.b_multipleTap){// Check driving direction
speed=steer+speed;// Forward driving
speed=steer+speed;// Forward driving: in this case steer = Brake, speed = Throttle
}else{
}else{
speed=steer-speed;// Reverse driving
speed=steer-speed;// Reverse driving: in this case steer = Brake, speed = Throttle
}
}
#endif
#endif
@ -470,7 +472,7 @@ int main(void) {
}elseif(BAT_LVL2_ENABLE&&batVoltage<BAT_LVL2){// low bat 2: slow beep
}elseif(BAT_LVL2_ENABLE&&batVoltage<BAT_LVL2){// low bat 2: slow beep