Skip to content

Commit

Permalink
LinearHall improvements and move to main repository
Browse files Browse the repository at this point in the history
Changes compared to the original pull request in the drivers repository simplefoc/Arduino-FOC-drivers#12
1. Added a version of init which turns the motor one revolution to find the center values of the sensors.
2. Moved the calls to analogRead into a weakly bound function ReadLinearHalls so it can be overridden with custom ADC code on platforms with poor analogRead performance.
3. Commented out the pinMode calls in init, which makes it possible to pass in ADC channel numbers for custom ReadLinearHalls to use without having to remap them every update.
4. Changed to use the much faster _atan2 function that was added to foc_utils recently.
5. Added examples.
  • Loading branch information
dekutree64 committed Jan 14, 2024
1 parent 1bad770 commit 241e8c0
Show file tree
Hide file tree
Showing 6 changed files with 477 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/**
*
* Position/angle motion control example
* Steps:
* 1) Configure the motor and hall sensor
* 2) Run the code
* 3) Set the target angle (in radians) from serial terminal
*/
#include <SimpleFOC.h>

// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(11);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);
// Stepper motor & driver instance
//StepperMotor motor = StepperMotor(50);
//StepperDriver4PWM driver = StepperDriver4PWM(9, 5, 10, 6, 8);

// hall sensor instance
LinearHall sensor = LinearHall(A0, A1, 11);

// angle set point variable
float target_angle = 0;
// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_angle, cmd); }

void setup() {

// driver config
// power supply voltage [V]
driver.voltage_power_supply = 12;
driver.init();
// link the motor and the driver
motor.linkDriver(&driver);


// aligning voltage [V]
motor.voltage_sensor_align = 3;
// index search velocity [rad/s]
motor.velocity_index_search = 3;

// set motion control loop to be used
motor.controller = MotionControlType::angle;

// contoller configuration
// default parameters in defaults.h

// velocity PI controller parameters
motor.PID_velocity.P = 0.2f;
motor.PID_velocity.I = 2;
motor.PID_velocity.D = 0;
// default voltage_power_supply
motor.voltage_limit = 6;
// jerk control using voltage voltage ramp
// default value is 300 volts per sec ~ 0.3V per millisecond
motor.PID_velocity.output_ramp = 1000;

// velocity low pass filtering time constant
motor.LPF_velocity.Tf = 0.01f;

// angle P controller
motor.P_angle.P = 20;
// maximal velocity of the position control
motor.velocity_limit = 4;


// use monitoring with serial
Serial.begin(115200);
// comment out if not needed
motor.useMonitoring(Serial);

// initialize motor
motor.init();
// initialize sensor hardware. This moves the motor to find the min/max sensor readings and
// averages them to get the center values. The motor can't move until motor.init is called, and
// motor.initFOC can't do its calibration until the sensor is intialized, so this must be done inbetween.
// You can then take the values printed to the serial monitor and pass them to sensor.init to
// avoid having to move the motor every time. In that case it doesn't matter whether sensor.init
// is called before or after motor.init.
sensor.init(&motor);
Serial.print("LinearHall centerA: ");
Serial.print(sensor.centerA);
Serial.print(", centerB: ");
Serial.println(sensor.centerB);
// link the motor to the sensor
motor.linkSensor(&sensor);
// align sensor and start FOC
motor.initFOC();

// add target command T
command.add('T', doTarget, "target angle");

Serial.println(F("Motor ready."));
Serial.println(F("Set the target angle using serial terminal:"));
_delay(1000);
}

void loop() {
// main FOC algorithm function
// the faster you run this function the better
// Arduino UNO loop ~1kHz
// Bluepill loop ~10kHz
motor.loopFOC();

// Motion control function
// velocity, position or voltage (defined in motor.controller)
// this function can be run at much lower frequency than loopFOC() function
// You can also use motor.move() and set the motor.target in the code
motor.move(target_angle);

// function intended to be used with serial plotter to monitor motor variables
// significantly slowing the execution down!!!!
// motor.monitor();

// user communication
command.run();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/**
*
* Torque control example using voltage control loop.
*
* Most of the low-end BLDC driver boards doesn't have current measurement therefore SimpleFOC offers
* you a way to control motor torque by setting the voltage to the motor instead of the current.
*
* This makes the BLDC motor effectively a DC motor, and you can use it in a same way.
*/
#include <SimpleFOC.h>


// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(11);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);
// Stepper motor & driver instance
//StepperMotor motor = StepperMotor(50);
//StepperDriver4PWM driver = StepperDriver4PWM(9, 5, 10, 6, 8);

// hall sensor instance
LinearHall sensor = LinearHall(A0, A1, 11);


// voltage set point variable
float target_voltage = 2;
// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_voltage, cmd); }

void setup() {

// driver config
// power supply voltage [V]
driver.voltage_power_supply = 12;
driver.init();
// link driver
motor.linkDriver(&driver);

// aligning voltage
motor.voltage_sensor_align = 3;

// choose FOC modulation (optional)
motor.foc_modulation = FOCModulationType::SpaceVectorPWM;

// set motion control loop to be used
motor.controller = MotionControlType::torque;

// use monitoring with serial
Serial.begin(115200);
// comment out if not needed
motor.useMonitoring(Serial);

// initialize motor
motor.init();
// initialize sensor hardware. This moves the motor to find the min/max sensor readings and
// averages them to get the center values. The motor can't move until motor.init is called, and
// motor.initFOC can't do its calibration until the sensor is intialized, so this must be done inbetween.
// You can then take the values printed to the serial monitor and pass them to sensor.init to
// avoid having to move the motor every time. In that case it doesn't matter whether sensor.init
// is called before or after motor.init.
sensor.init(&motor);
Serial.print("LinearHall centerA: ");
Serial.print(sensor.centerA);
Serial.print(", centerB: ");
Serial.println(sensor.centerB);
// link the motor to the sensor
motor.linkSensor(&sensor);
// align sensor and start FOC
motor.initFOC();

// add target command T
command.add('T', doTarget, "target voltage");

Serial.println(F("Motor ready."));
Serial.println(F("Set the target voltage using serial terminal:"));
_delay(1000);
}


void loop() {

// main FOC algorithm function
// the faster you run this function the better
// Arduino UNO loop ~1kHz
// Bluepill loop ~10kHz
motor.loopFOC();

// Motion control function
// velocity, position or voltage (defined in motor.controller)
// this function can be run at much lower frequency than loopFOC() function
// You can also use motor.move() and set the motor.target in the code
motor.move(target_voltage);

// user communication
command.run();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/**
*
* Velocity motion control example
* Steps:
* 1) Configure the motor and sensor
* 2) Run the code
* 3) Set the target velocity (in radians per second) from serial terminal
*/
#include <SimpleFOC.h>

// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(11);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);
// Stepper motor & driver instance
//StepperMotor motor = StepperMotor(50);
//StepperDriver4PWM driver = StepperDriver4PWM(9, 5, 10, 6, 8);

// hall sensor instance
LinearHall sensor = LinearHall(A0, A1, 11);

// velocity set point variable
float target_velocity = 0;
// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_velocity, cmd); }

void setup() {

// driver config
// power supply voltage [V]
driver.voltage_power_supply = 12;
driver.init();
// link the motor and the driver
motor.linkDriver(&driver);

// aligning voltage [V]
motor.voltage_sensor_align = 3;

// set motion control loop to be used
motor.controller = MotionControlType::velocity;

// contoller configuration
// default parameters in defaults.h

// velocity PI controller parameters
motor.PID_velocity.P = 0.2f;
motor.PID_velocity.I = 2;
motor.PID_velocity.D = 0;
// default voltage_power_supply
motor.voltage_limit = 6;
// jerk control using voltage voltage ramp
// default value is 300 volts per sec ~ 0.3V per millisecond
motor.PID_velocity.output_ramp = 1000;

// velocity low pass filtering time constant
motor.LPF_velocity.Tf = 0.01f;

// use monitoring with serial
Serial.begin(115200);
// comment out if not needed
motor.useMonitoring(Serial);

// initialize motor
motor.init();
// initialize sensor hardware. This moves the motor to find the min/max sensor readings and
// averages them to get the center values. The motor can't move until motor.init is called, and
// motor.initFOC can't do its calibration until the sensor is intialized, so this must be done inbetween.
// You can then take the values printed to the serial monitor and pass them to sensor.init to
// avoid having to move the motor every time. In that case it doesn't matter whether sensor.init
// is called before or after motor.init.
sensor.init(&motor);
Serial.print("LinearHall centerA: ");
Serial.print(sensor.centerA);
Serial.print(", centerB: ");
Serial.println(sensor.centerB);
// link the motor to the sensor
motor.linkSensor(&sensor);
// align sensor and start FOC
motor.initFOC();

// add target command T
command.add('T', doTarget, "target voltage");

Serial.println(F("Motor ready."));
Serial.println(F("Set the target velocity using serial terminal:"));
_delay(1000);
}


void loop() {
// main FOC algorithm function
// the faster you run this function the better
// Arduino UNO loop ~1kHz
// Bluepill loop ~10kHz
motor.loopFOC();

// Motion control function
// velocity, position or voltage (defined in motor.controller)
// this function can be run at much lower frequency than loopFOC() function
// You can also use motor.move() and set the motor.target in the code
motor.move(target_velocity);

// function intended to be used with serial plotter to monitor motor variables
// significantly slowing the execution down!!!!
// motor.monitor();

// user communication
command.run();
}
1 change: 1 addition & 0 deletions src/SimpleFOC.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ void loop() {
#include "sensors/MagneticSensorAnalog.h"
#include "sensors/MagneticSensorPWM.h"
#include "sensors/HallSensor.h"
#include "sensors/LinearHall.h"
#include "sensors/GenericSensor.h"
#include "drivers/BLDCDriver3PWM.h"
#include "drivers/BLDCDriver6PWM.h"
Expand Down
Loading

0 comments on commit 241e8c0

Please sign in to comment.