So the BLDC motor contoller for the Escooter, that i am trying to develop is slowly getting where i want it to be. The current state of the project - open loop works great, and right now i am testing closed loop but without current sensing just yet.
So i have 2 questions that i wanted to ask before i hook up the current sensors.
- For position sensing i am using hall sensors. So far i tested the velocity controll and
torque controll - voltage mode. The code works great, but becouse of the hall sensors being located inside of the motor, they pick up quite a lot of noise. I used a Low Pass filter to filter some of the noise. After filtering, the output signals from the sensors are enough to run the
torque - voltage mode very smoothly. Unfortunately it is not enough to run the velocity loop. The velocity loop also works but the rotation is much less smooth. Obviously, when using velocity loop, a very precise reading of the velocity is needed.
Now my question is:
When i hook up the current sensors and try the FOCcurrent mode, how crucial for the proper work of the motor are the signals from the hall sensors?
I am asking this becouse i am not sure, what should i expect after using current sensing (assuming the current sensors will work well). Should i give more care to filter the signals from the hall sensors? Or becouse the signals are enough for torque - voltage mode, they will also be enough to run
torque-FOCcurrent mode. In my mind better signals should provide better feedback and better motor rotation. That’s why i am thinking about implementing an active LP filter. This will allow setting the cut-off frequency lower and the high impedance of the amplifier, should help filter more noise. But i am not sure if there is sense in doing it. Maybe it’s just not that significant when using current sensing and FOCcurrent mode.
- The second question is about the motor.disable() function.
The escooter controller is going to work with a trigger-like potentiometer. So i dont want the motor to stop and the scooter to flip, with me riding on it, when i let off the “gas” . I wanted to use the motor.disable() function. I dont have the full code yet to support this functionality, but i am using this function to disable the motor when the target_velocity that i adjust with the potentiometer, gets below a specific value.
The problem is that that the motor.disable() command gets into some conflict with rest the of the code, when used in closed loop. When i use this command in open loop, everything works the way it should. When i use it in closed loop, both, velocity and torque - voltage mode, the code works and the motor disables when at low speed, but the motor rotation gets way less smooth than without using the motor.disable() function. I am not sure if i am using it the correct way, but i am using it the very same way in open loop and it works flawlesly there.
So the second question is, how to use the motor.disable() function/command the proper way? Or maybe a different function to achieve freewheeling.
I’m using the nucleo32 G431KB
My code:
#include <SimpleFOC.h>
//#define PIN_SERIAL_RX PA3
//#define PIN_SERIAL_TX PA2
//HardwareSerial Serial1(PA3, PA2);
float target_velocity;
int analog_read_A0;
// Hall sensor instance
// HallSensor(int hallA, int hallB , int hallC , int pp)
// - hallA, hallB, hallC - HallSensor A, B and C pins
// - pp - pole pairs
BLDCMotor motor = BLDCMotor(15);
HallSensor sensor = HallSensor(PB7, PA15, PB6, 15);
BLDCDriver6PWM driver = BLDCDriver6PWM(PA9, PB0, PA10, PF0, PA8, PA7);
// Interrupt routine initialization
// channel A and B callbacks
void doA(){sensor.handleA();}
void doB(){sensor.handleB();}
void doC(){sensor.handleC();}
//Commander command = Commander(Serial);
//void onTarget(char* cmd) { command.target(&motor, cmd); }
//void onMotor(char* cmd) { command.motor(&motor, cmd); }
void setup() {
// monitoring port
//Serial1.begin(115200);
// check if you need internal pullups
sensor.pullup = Pullup::USE_EXTERN;
// initialize sensor hardware
sensor.init();
// hardware interrupt enable
sensor.enableInterrupts(doA, doB, doC);
sensor.velocity_max = 61;
motor.linkSensor(&sensor);
//Serial.println("Sensor ready");
_delay(1000);
driver.voltage_power_supply = 12.5;
driver.pwm_frequency = 25000;
driver.dead_zone = 0.01;
driver.init();
//Serial.print("Driver init ");// init driver
//if (driver.init())
//Serial.println("success!");
//else{Serial.println("failed!");
//return;}
motor.linkDriver(&driver);
motor.voltage_sensor_align = 1;
motor.velocity_limit = 1000; // [rad/s] cca 50rpm
motor.phase_resistance = 0.57; // [Ohm]
//motor.KV_rating = 87;
motor.current_limit = 10;
//motor.voltage_limit = 20;
motor.torque_controller = TorqueControlType::voltage;
// set motion control loop to be used
motor.controller = MotionControlType::torque;
//motor.controller = MotionControlType::velocity;
motor.PID_velocity.P = 0.1;
motor.PID_velocity.I = 15;
//motor.PID_velocity.D = 0.005;
motor.PID_velocity.output_ramp = 200;
//default voltage_power_supply
// velocity low pass filtering
// default 5ms - try different values to see what is the best.
// the lower the less filtered
motor.LPF_velocity.Tf = 0.18;
motor.init();
motor.initFOC();
//Serial.println("Motor ready.");
//command.add('T', onTarget, "target velocity");
//command.add('M', onMotor, "motor");
//command.motor(&motor,"E0");
_delay(1000);
}
void loop() {
sensor.update();
motor.loopFOC();
analog_read_A0 = analogRead(PA1);
target_velocity = float(map(analog_read_A0, 0, 4096, 0, 10000))/60.0;
if (target_velocity >= 1.0f)
motor.enable();
else
motor.disable();
motor.move(target_velocity);
//Serial1.println(sensor.getVelocity());
}
In the end i wanted to say, big Thank You to the SimpleFOC Crew for their work, and all the help i got so far with my project!!!