Is regen and centre zero throttle supported?
Just wondering how to do regen on this board when you back off on the throttle, and how to set regen rate.
Also, is centre zero throttle supported with FWD/REV on the same pot.
I havn't been able to see anything in the header files or docs to set this up. (Probably blind :) )
To help others out who are interested, I created the following app to implement centre zero throttle with deadband for a Boat application, each range (FWD/REV) has been restored after the deadband was subtracted. It works well.
// Mapping function
static float mapOneRangeToAnother(float sourceNumber, float fromA, float fromB, float toA, float toB) {
float deltaA = fromB - fromA;
float deltaB = toB - toA;
float scale = deltaB / deltaA;
float negA = -1 * fromA;
float offset = (negA * scale) + toA;
float finalNumber = (sourceNumber * scale) + offset;
return finalNumber;
}
#define DEADBAND 0.05 // +- 5%
// Boat application that implements a zero center throttle
void Boat_app(MESC_motor_typedef *_motor){
volatile float temp;
_motor->safe_start[0] = 0; // Remove deadband so we can apply our own.
// Make our pot center zero
temp = _motor->input_vars.ADC1_req - 0.5;
if(temp < DEADBAND && temp > -(DEADBAND)) {
temp = 0.0f; // Deadband
}
// Re-map to new range, upper part of pot (FWD)
if(temp > DEADBAND){
temp = mapOneRangeToAnother(temp,DEADBAND,1.0,0.0,1.0);
}
// Lower part of pot (REV)
if(temp < -(DEADBAND)){
temp = mapOneRangeToAnother(temp,-(DEADBAND),-1.0,0.0,-1.0);
}
//We just scale and sum the input current requests
_motor->FOC.Idq_prereq.q = _motor->input_vars.UART_req +
_motor->input_vars.max_request_Idq.q * (temp + _motor->input_vars.ADC2_req +
_motor->input_vars.RCPWM_req + _motor->input_vars.ADC12_diff_req +
_motor->input_vars.remote_ADC1_req + _motor->input_vars.remote_ADC2_req );
//Clamp the Q component; d component is not directly requested
_motor->FOC.Idq_prereq.q = clamp(_motor->FOC.Idq_prereq.q, _motor->input_vars.min_request_Idq.q, _motor->input_vars.max_request_Idq.q);
}
This is applied in MESCApps.c You also need to add that as a vehicle type to MESCinterface.c etc and MESCfoc.c
Hello bmentink. Have you found out if it is possible to regenerate? I'm trying to do it now
@dpeinado Yes, it all works as expected, just throttle back and/or into the REV region and it applies regen braking.
But did you code an special controller mode for regen, or you had only to change the sign of the i_d?
No, Just the sign, as per the code above, regen happens naturally, no special mode:
// Lower part of pot (REV) if(temp < -(DEADBAND)){ temp = mapOneRangeToAnother(temp,-(DEADBAND),-1.0,0.0,-1.0); }
Ok, I see. What I'm looking for is a generator behaviour. If you apply a negative current when your motor is forward moving, it is clear that it will brake. The point is that once the vehicle is stopped then a backward movement will occur. It is applying a "reverse gear". I'm looking for a mode in which the motor opposes to movement, but it does not move. It is an electric generator function. Do you think that this mode exists in MESC?
Ah, I understand. Yes MESC has a brake function, I haven't tried it .
On Mon, 20 Oct 2025, 9:44 pm Diego Peinado Martin, @.***> wrote:
dpeinado left a comment (davidmolony/MESC_Firmware#77) https://github.com/davidmolony/MESC_Firmware/issues/77#issuecomment-3421091300
Ok, I see. What I'm looking for is a generator behaviour. If you apply a negative current when your motor is forward moving, it is clear that it will brake. The point is that once the vehicle is stopped then a backward movement will occur. It is applying a "reverse gear". I'm looking for a mode in which the motor opposes to movement, but it does not move. It is an electric generator function. Do you think that this mode exists in MESC?
— Reply to this email directly, view it on GitHub https://github.com/davidmolony/MESC_Firmware/issues/77#issuecomment-3421091300, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACNHVB6EFHWUQ52QMUCJGF33YSOHBAVCNFSM6AAAAAB6OI2VF6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTIMRRGA4TCMZQGA . You are receiving this because you authored the thread.Message ID: @.***>
Specific modes like "Diego's generator" are not explicitly implemented in MESC. The architecture makes it easy for you to implement such things; I would suggest you just implement your own app which is called fom the slowloop (you will see there is a switch statement for selecting apps) which takes the input parameters _motor->FOC.eHz and only sets the idq prereq when the eHz is above a threshold; say 10.0f.
You could add a ramp and map it to the frequency, or make it gradually roll on and off with an exponential IIR... Many options, but I did not so far give thought to using MESC as a generator. It is a worthy application though.
If you get an error state, you would need to return the Iq prereq to 0 to reset the error.
There is scope for you to implement your own state machine easily within the app; you could make it so that if you press a button it moves to a starting state and generates positive torque to spin up the motor or such like...
The MESC brake function is probably not quite what you want for a generator.
Hi David, thanks for your feedback.
I've been reading a forum of other xESC :-) and also analysing the code and the solution they use, it's very curious. In the literature, it's common to find that for generating the low side MOSFETs are chopped (PWM on), and the high side are off, using the free wheeling diodes as rectificator. I thought that xESC used that scheme, but it does not. In the code I saw they use a mode in which:
- near zero velocity, a PWM is generated without any modulation (duty = 0), so there is a square wave in high side mosfets, and the complementary (with compensation time for preventing shorts) in the low side. This is equivalent to shortcut the phases (?) and then an uncontrolled generation is done.
- when the current reaches the predefined braking current, or the velocity of the rotor is not zero, then a normal PWM generation that makes a torque contrary to the movement is set up.
- as a final comment in the forum I saw some guys that used this for a generator app and they detect some instability at high rpms. Perhaps the literature cited method is better suited for generators (?)
I will try to make the same in MESC code, probably introducing a new motor_control_mode_e called MOTOR_CONTROL_MODE_BRAKE and implement the same logic in your firmware. Do you think it would be worth to merge this in your repository?
The code in vesc fw is:
// Short all phases (duty=0) the moment the direction or modulation changes sign. That will avoid
// active braking or changing direction. Keep all phases shorted (duty == 0) until the
// braking current reaches the set or maximum value, then go back to current control
// mode. Stay in duty=0 for at least 10 cycles to avoid jumping in and out of that mode rapidly
// around the threshold.
if (motor_now->m_control_mode == CONTROL_MODE_CURRENT_BRAKE) {
if ((SIGN(speed_fast_now) != SIGN(motor_now->m_br_speed_before) ||
SIGN(vq_now) != SIGN(motor_now->m_br_vq_before) ||
fabsf(motor_now->m_duty_filtered) < 0.001 || motor_now->m_br_no_duty_samples < 10) &&
motor_now->m_motor_state.i_abs_filter < fabsf(iq_set_tmp)) {
control_duty = true;
duty_set = 0.0;
motor_now->m_br_no_duty_samples = 0;
} else if (motor_now->m_br_no_duty_samples < 10) {
control_duty = true;
duty_set = 0.0;
motor_now->m_br_no_duty_samples++;
}
} else {
motor_now->m_br_no_duty_samples = 0;
}
I've made a test in your code commenting out a couple of lines in slowLoop:
case MOTOR_CONTROL_MODE_DUTY:
if(_motor->FOC.Duty_scaler > 0.01f){
}else{
// _motor->MotorState = MOTOR_STATE_TRACKING;
// MESCpwm_generateBreak(_motor);
}
break;
So I can have a PWM signal with zero duty. It works, but curiously makes some noise that does not occur when using vesc fw.
So, I will try to implement it, and if you like, make a branch and a pull request. If you think that this can have some license issues, then I will not.
Thanks again for your feedback!!
It is very unclear to me what you are trying to do. This literature you cite is probably not the best way to manage this. Using the freewheel diodes as a rectifier is unlikely to be efficient. It is unclear to me why a generator needs to generate torque at low speed. You reach a point where you cannot really get any power out of it and torque at low speed will stall an engine anyway...
There is a handbrake mode which shorts the FETs.
I do not know what xESC is. There will be no VESC code added to this firmware, ever.
If you want to run a generator with an FOC synchronous rectification, you need to think very clearly about what you really want to achieve and what your system limittions are and code that. I do not think this ever results in using body diodes or shorting the motor through the MOS... It probably involves a speed control loop around the engine's most efficient operating point, for any given power demand, and some kind of feedback to the engine governor, OR more simply the engine runs at a fixed RPM and the torque request on the ESC is adapted to regulate the bus voltage.
Thanks David. Yes you are right, this is something that must be carefully planned. I searched a little and I saw an article that. I've uploaded a screenshot for you to see, and even the link to the article https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/171/Performance_5F00_Analysis_5F00_of_5F00_Regenerative_5F00_Braking_5F00_in_5F00_Pe.pdf
Also, it helps your confirmation (I suspected it) about of integrating code coming from xESC (vesc ;-) )
Thanks!!!