Skip to content

Commit

Permalink
Merge pull request #315 from simplefoc/dev
Browse files Browse the repository at this point in the history
Release v2.3.1
  • Loading branch information
runger1101001 authored Sep 22, 2023
2 parents 05954cb + 192ab76 commit 717480b
Show file tree
Hide file tree
Showing 55 changed files with 1,039 additions and 222 deletions.
48 changes: 18 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,34 +24,20 @@ Therefore this is an attempt to:
- *Medium-power* BLDC driver (<30Amps): [Arduino <span class="simple">Simple<b>FOC</b>PowerShield</span> ](https://github.com/simplefoc/Arduino-SimpleFOC-PowerShield).
- See also [@byDagor](https://github.com/byDagor)'s *fully-integrated* ESP32 based board: [Dagor Brushless Controller](https://github.com/byDagor/Dagor-Brushless-Controller)

> NEW RELEASE 📢 : <span class="simple">Simple<span class="foc">FOC</span>library</span> v2.3.0
> - Arduino Mega 6pwm more timers supported
> - Arduino boards - frequency change support either 32kHz or 4kHz
> - Arduino Uno - synched timers in 3pwm and 6pwm mode [#71](https://github.com/simplefoc/Arduino-FOC/issues/71)
> - Teensy 3.x initial support for 6pwm
> - Teensy 4.x initial support for 6pwm
> - Example for v3.1 SimpleFOCShield
> - RP2040 compatibility for earlehillpower core [#234](https://github.com/simplefoc/Arduino-FOC/pull/234) [#236](https://github.com/simplefoc/Arduino-FOC/pull/236)
> - More flexible monitoring API
> - start, end and separator characters
> - decimal places (settable through commander)
> - Added machine readable verbose mode in `Commander` [#233](https://github.com/simplefoc/Arduino-FOC/pull/233)
> - *Simple**FOC**WebController* - Web based user interface for SimpleFOC by [@geekuillaume](https://github.com/geekuillaume) - [webcontroller.simplefoc.com](webcontroller.simplefoc.com)
> - bugfix - `MagneticSensorPWM` multiple occasions - [#258](https://github.com/simplefoc/Arduino-FOC/pull/258)
> - bugfix - current sense align - added offset exchange when exchanging pins
> - bugfix - trapezoid 150 fixed
> - bugfix - 4pwm on ESP8266 [#224](https://github.com/simplefoc/Arduino-FOC/pull/224)
> - Additional `InlineCurrentSense` and `LowsideCurrentSense` constructor using milliVolts per Amp [#253](https://github.com/simplefoc/Arduino-FOC/pull/253)
> - STM32L4xx current sense support by [@Triple6](https://github.com/Triple6) (discord) [#257](https://github.com/simplefoc/Arduino-FOC/pull/257)
> - phase disable in 6pwm mode
> - stm32 - software and hardware 6pwm
> - atmega328
> - atmega2560
> - Lag compensation using motor inductance [#246](https://github.com/simplefoc/Arduino-FOC/issues/246)
> - current control through voltage torque mode enhancement
> - extended `BLDCMotor` and `StepperMotor` constructors to receive the inductance paramerer
> - can also be set using `motor.phase_inductance` or through `Commander`
## Arduino *SimpleFOClibrary* v2.3
> NEW RELEASE 📢 : <span class="simple">Simple<span class="foc">FOC</span>library</span> v2.3.1
> - Support for Arduino UNO R4 Minima (Renesas R7FA4M1 MCU - note UNO R4 WiFi is not yet supported)
> - Support setting PWM polarity on ESP32 (thanks to [@mcells](https://github.com/mcells))
> - Expose I2C errors in MagneticSensorI2C (thanks to [@padok](https://github.com/padok))
> - Improved default trig functions (sine, cosine) - faster, smaller
> - Overridable trig functions - plug in your own optimized versions
> - Bugfix: microseconds overflow in velocity mode [#287](https://github.com/simplefoc/Arduino-FOC/issues/287)
> - Bugfix: KV initialization ([5fc3128](https://github.com/simplefoc/Arduino-FOC/commit/5fc3128d282b65c141ca486327c6235089999627))
> - And more bugfixes - see the [complete list of 2.3.1 fixes here](https://github.com/simplefoc/Arduino-FOC/issues?q=is%3Aissue+milestone%3A2.3.1_Release)
> - Change: simplify initFOC() API ([d57d32d](https://github.com/simplefoc/Arduino-FOC/commit/d57d32dd8715dbed4e476469bc3de0c052f1d531). [5231e5e](https://github.com/simplefoc/Arduino-FOC/commit/5231e5e1d044b0cc33ede67664b6ef2f9d0a8cdf), [10c5b87](https://github.com/simplefoc/Arduino-FOC/commit/10c5b872672cab72df16ddd738bbf09bcce95d28))
> - Change: check for linked driver in currentsense and exit gracefully ([5ef4d9d](https://github.com/simplefoc/Arduino-FOC/commit/5ef4d9d5a92e03da0dd5af7f624243ab30f1b688))
> - Compatibility with newest versions of Arduino framework for STM32, Renesas, ESP32, Atmel SAM, Atmel AVR, nRF52 and RP2040
## Arduino *SimpleFOClibrary* v2.3.1

<p align="">
<a href="https://youtu.be/Y5kLeqTc6Zk">
Expand All @@ -78,7 +64,7 @@ This video demonstrates the *Simple**FOC**library* basic usage, electronic conne
- **Cross-platform**:
- Seamless code transfer from one microcontroller family to another
- Supports multiple [MCU architectures](https://docs.simplefoc.com/microcontrollers):
- Arduino: UNO, MEGA, DUE, Leonardo ....
- Arduino: UNO R4, UNO, MEGA, DUE, Leonardo, Nano, Nano33 ....
- STM32
- ESP32
- Teensy
Expand Down Expand Up @@ -132,7 +118,9 @@ Please do not hesitate to leave an issue if you have problems/advices/suggestion

Pull requests are welcome, but let's first discuss them in [community forum](https://community.simplefoc.com)!

If you'd like to contribute to this porject but you are not very familiar with github, don't worry, let us know either by posting at the community forum , by posting a github issue or at our discord server.
If you'd like to contribute to this project but you are not very familiar with github, don't worry, let us know either by posting at the community forum , by posting a github issue or at our discord server.

If you are familiar, we accept pull requests to the dev branch!

## Arduino code example
This is a simple Arduino code example implementing the velocity control program of a BLDC motor with encoder.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ void setup() {
void loop() {
// open loop angle movements
// using motor.voltage_limit and motor.velocity_limit
// angles can be positive or negative, negative angles correspond to opposite motor direction
motor.move(target_position);

// user communication
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ void loop() {

// open loop velocity movement
// using motor.voltage_limit and motor.velocity_limit
// to turn the motor "backwards", just set a negative target_velocity
motor.move(target_velocity);

// user communication
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
* Simple example intended to help users find the zero offset and natural direction of the sensor.
*
* These values can further be used to avoid motor and sensor alignment procedure.
*
* motor.initFOC(zero_offset, sensor_direction);
* To use these values add them to the code:");
* motor.sensor_direction=Direction::CW; // or Direction::CCW
* motor.zero_electric_angle=1.2345; // use the real value!
*
* This will only work for abosolute value sensors - magnetic sensors.
* Bypassing the alignment procedure is not possible for the encoders and for the current implementation of the Hall sensors.
Expand Down Expand Up @@ -44,6 +45,9 @@ void setup() {
// set motion control loop to be used
motor.controller = MotionControlType::torque;

// force direction search - because default is CW
motor.sensor_direction = Direction::UNKNOWN;

// initialize motor
motor.init();
// align sensor and start FOC
Expand All @@ -54,9 +58,16 @@ void setup() {
Serial.println("Sensor zero offset is:");
Serial.println(motor.zero_electric_angle, 4);
Serial.println("Sensor natural direction is: ");
Serial.println(motor.sensor_direction == 1 ? "Direction::CW" : "Direction::CCW");
Serial.println(motor.sensor_direction == Direction::CW ? "Direction::CW" : "Direction::CCW");

Serial.println("To use these values add them to the code:");
Serial.print(" motor.sensor_direction=");
Serial.print(motor.sensor_direction == Direction::CW ? "Direction::CW" : "Direction::CCW");
Serial.println(";");
Serial.print(" motor.zero_electric_angle=");
Serial.print(motor.zero_electric_angle, 4);
Serial.println(";");

Serial.println("To use these values provide them to the: motor.initFOC(offset, direction)");
_delay(1000);
Serial.println("If motor is not moving the alignment procedure was not successfull!!");
}
Expand Down
44 changes: 22 additions & 22 deletions src/BLDCMotor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ BLDCMotor::BLDCMotor(int pp, float _R, float _KV, float _inductance)
phase_resistance = _R;
// save back emf constant KV = 1/KV
// 1/sqrt(2) - rms value
KV_rating = _KV*_SQRT2;
KV_rating = NOT_SET;
if (_isset(_KV))
KV_rating = _KV*_SQRT2;
// save phase inductance
phase_inductance = _inductance;

Expand Down Expand Up @@ -90,6 +92,13 @@ void BLDCMotor::init() {
}
P_angle.limit = velocity_limit;

// if using open loop control, set a CW as the default direction if not already set
if ((controller==MotionControlType::angle_openloop
||controller==MotionControlType::velocity_openloop)
&& (sensor_direction == Direction::UNKNOWN)) {
sensor_direction = Direction::CW;
}

_delay(500);
// enable motor
SIMPLEFOC_DEBUG("MOT: Enable driver.");
Expand Down Expand Up @@ -124,20 +133,13 @@ void BLDCMotor::enable()
FOC functions
*/
// FOC initialization function
int BLDCMotor::initFOC( float zero_electric_offset, Direction _sensor_direction) {
int BLDCMotor::initFOC() {
int exit_flag = 1;

motor_status = FOCMotorStatus::motor_calibrating;

// align motor if necessary
// alignment necessary for encoders!
if(_isset(zero_electric_offset)){
// abosolute zero offset provided - no need to align
zero_electric_angle = zero_electric_offset;
// set the sensor direction - default CW
sensor_direction = _sensor_direction;
}

// sensor and motor alignment - can be skipped
// by setting motor.sensor_direction and motor.zero_electric_angle
_delay(500);
Expand Down Expand Up @@ -165,7 +167,7 @@ int BLDCMotor::initFOC( float zero_electric_offset, Direction _sensor_direction
exit_flag *= alignCurrentSense();
}
}
else SIMPLEFOC_DEBUG("MOT: No current sense.");
else { SIMPLEFOC_DEBUG("MOT: No current sense."); }
}

if(exit_flag){
Expand Down Expand Up @@ -211,7 +213,7 @@ int BLDCMotor::alignSensor() {
if(!exit_flag) return exit_flag;

// if unknown natural direction
if(!_isset(sensor_direction)){
if(sensor_direction==Direction::UNKNOWN){

// find natural direction
// move one electrical revolution forward
Expand Down Expand Up @@ -250,10 +252,11 @@ int BLDCMotor::alignSensor() {
// check pole pair number
if( fabs(moved*pole_pairs - _2PI) > 0.5f ) { // 0.5f is arbitrary number it can be lower or higher!
SIMPLEFOC_DEBUG("MOT: PP check: fail - estimated pp: ", _2PI/moved);
} else
} else {
SIMPLEFOC_DEBUG("MOT: PP check: OK!");
}

} else SIMPLEFOC_DEBUG("MOT: Skip dir calib.");
} else { SIMPLEFOC_DEBUG("MOT: Skip dir calib."); }

// zero electric angle not known
if(!_isset(zero_electric_angle)){
Expand All @@ -274,7 +277,7 @@ int BLDCMotor::alignSensor() {
// stop everything
setPhaseVoltage(0, 0, 0);
_delay(200);
}else SIMPLEFOC_DEBUG("MOT: Skip offset calib.");
} else { SIMPLEFOC_DEBUG("MOT: Skip offset calib."); }
return exit_flag;
}

Expand Down Expand Up @@ -303,8 +306,8 @@ int BLDCMotor::absoluteZeroSearch() {
voltage_limit = limit_volt;
// check if the zero found
if(monitor_port){
if(sensor->needsSearch()) SIMPLEFOC_DEBUG("MOT: Error: Not found!");
else SIMPLEFOC_DEBUG("MOT: Success!");
if(sensor->needsSearch()) { SIMPLEFOC_DEBUG("MOT: Error: Not found!"); }
else { SIMPLEFOC_DEBUG("MOT: Success!"); }
}
return !sensor->needsSearch();
}
Expand Down Expand Up @@ -418,7 +421,8 @@ void BLDCMotor::move(float new_target) {
// angle set point
shaft_angle_sp = target;
// calculate velocity set point
shaft_velocity_sp = P_angle( shaft_angle_sp - shaft_angle );
shaft_velocity_sp = feed_forward_velocity + P_angle( shaft_angle_sp - shaft_angle );
shaft_angle_sp = _constrain(shaft_angle_sp,-velocity_limit, velocity_limit);
// calculate the torque command - sensor precision: this calculation is ok, but based on bad value from previous calculation
current_sp = PID_velocity(shaft_velocity_sp - shaft_velocity); // if voltage torque control
// if torque controlled through voltage
Expand Down Expand Up @@ -543,12 +547,8 @@ void BLDCMotor::setPhaseVoltage(float Uq, float Ud, float angle_el) {
case FOCModulationType::SinePWM :
// Sinusoidal PWM modulation
// Inverse Park + Clarke transformation
_sincos(angle_el, &_sa, &_ca);

// angle normalization in between 0 and 2pi
// only necessary if using _sin and _cos - approximation functions
angle_el = _normalizeAngle(angle_el);
_ca = _cos(angle_el);
_sa = _sin(angle_el);
// Inverse park transform
Ualpha = _ca * Ud - _sa * Uq; // -sin(angle) * Uq;
Ubeta = _sa * Ud + _ca * Uq; // cos(angle) * Uq;
Expand Down
2 changes: 1 addition & 1 deletion src/BLDCMotor.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class BLDCMotor: public FOCMotor
* Function initializing FOC algorithm
* and aligning sensor's and motors' zero position
*/
int initFOC( float zero_electric_offset = NOT_SET , Direction sensor_direction = Direction::CW) override;
int initFOC() override;
/**
* Function running FOC algorithm in real-time
* it calculates the gets motor angle and sets the appropriate voltages
Expand Down
39 changes: 20 additions & 19 deletions src/StepperMotor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ void StepperMotor::init() {
}
P_angle.limit = velocity_limit;

// if using open loop control, set a CW as the default direction if not already set
if ((controller==MotionControlType::angle_openloop
||controller==MotionControlType::velocity_openloop)
&& (sensor_direction == Direction::UNKNOWN)) {
sensor_direction = Direction::CW;
}

_delay(500);
// enable motor
SIMPLEFOC_DEBUG("MOT: Enable driver.");
Expand Down Expand Up @@ -92,20 +99,13 @@ void StepperMotor::enable()
FOC functions
*/
// FOC initialization function
int StepperMotor::initFOC( float zero_electric_offset, Direction _sensor_direction ) {
int StepperMotor::initFOC() {
int exit_flag = 1;

motor_status = FOCMotorStatus::motor_calibrating;

// align motor if necessary
// alignment necessary for encoders!
if(_isset(zero_electric_offset)){
// abosolute zero offset provided - no need to align
zero_electric_angle = zero_electric_offset;
// set the sensor direction - default CW
sensor_direction = _sensor_direction;
}

// sensor and motor alignment - can be skipped
// by setting motor.sensor_direction and motor.zero_electric_angle
_delay(500);
Expand All @@ -114,7 +114,7 @@ int StepperMotor::initFOC( float zero_electric_offset, Direction _sensor_direct
// added the shaft_angle update
sensor->update();
shaft_angle = sensor->getAngle();
}else SIMPLEFOC_DEBUG("MOT: No sensor.");
} else { SIMPLEFOC_DEBUG("MOT: No sensor."); }

if(exit_flag){
SIMPLEFOC_DEBUG("MOT: Ready.");
Expand Down Expand Up @@ -177,10 +177,13 @@ int StepperMotor::alignSensor() {
float moved = fabs(mid_angle - end_angle);
if( fabs(moved*pole_pairs - _2PI) > 0.5f ) { // 0.5f is arbitrary number it can be lower or higher!
SIMPLEFOC_DEBUG("MOT: PP check: fail - estimated pp: ", _2PI/moved);
} else
} else {
SIMPLEFOC_DEBUG("MOT: PP check: OK!");
}

}else SIMPLEFOC_DEBUG("MOT: Skip dir calib.");
} else {
SIMPLEFOC_DEBUG("MOT: Skip dir calib.");
}

// zero electric angle not known
if(!_isset(zero_electric_angle)){
Expand All @@ -200,7 +203,7 @@ int StepperMotor::alignSensor() {
// stop everything
setPhaseVoltage(0, 0, 0);
_delay(200);
}else SIMPLEFOC_DEBUG("MOT: Skip offset calib.");
} else { SIMPLEFOC_DEBUG("MOT: Skip offset calib."); }
return exit_flag;
}

Expand Down Expand Up @@ -229,7 +232,7 @@ int StepperMotor::absoluteZeroSearch() {
// check if the zero found
if(monitor_port){
if(sensor->needsSearch()) SIMPLEFOC_DEBUG("MOT: Error: Not found!");
else SIMPLEFOC_DEBUG("MOT: Success!");
else { SIMPLEFOC_DEBUG("MOT: Success!"); }
}
return !sensor->needsSearch();
}
Expand Down Expand Up @@ -307,7 +310,8 @@ void StepperMotor::move(float new_target) {
// angle set point
shaft_angle_sp = target;
// calculate velocity set point
shaft_velocity_sp = P_angle( shaft_angle_sp - shaft_angle );
shaft_velocity_sp = feed_forward_velocity + P_angle( shaft_angle_sp - shaft_angle );
shaft_angle_sp = _constrain(shaft_angle_sp, -velocity_limit, velocity_limit);
// calculate the torque command
current_sp = PID_velocity(shaft_velocity_sp - shaft_velocity); // if voltage torque control
// if torque controlled through voltage
Expand Down Expand Up @@ -357,12 +361,9 @@ void StepperMotor::move(float new_target) {
void StepperMotor::setPhaseVoltage(float Uq, float Ud, float angle_el) {
// Sinusoidal PWM modulation
// Inverse Park transformation
float _sa, _ca;
_sincos(angle_el, &_sa, &_ca);

// angle normalization in between 0 and 2pi
// only necessary if using _sin and _cos - approximation functions
angle_el = _normalizeAngle(angle_el);
float _ca = _cos(angle_el);
float _sa = _sin(angle_el);
// Inverse park transform
Ualpha = _ca * Ud - _sa * Uq; // -sin(angle) * Uq;
Ubeta = _sa * Ud + _ca * Uq; // cos(angle) * Uq;
Expand Down
6 changes: 1 addition & 5 deletions src/StepperMotor.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,8 @@ class StepperMotor: public FOCMotor
* and aligning sensor's and motors' zero position
*
* - If zero_electric_offset parameter is set the alignment procedure is skipped
*
* @param zero_electric_offset value of the sensors absolute position electrical offset in respect to motor's electrical 0 position.
* @param sensor_direction sensor natural direction - default is CW
*
*/
int initFOC( float zero_electric_offset = NOT_SET , Direction sensor_direction = Direction::CW) override;
int initFOC() override;
/**
* Function running FOC algorithm in real-time
* it calculates the gets motor angle and sets the appropriate voltages
Expand Down
Loading

0 comments on commit 717480b

Please sign in to comment.