Skip to content

Commit 0cf2fde

Browse files
committed
Merge remote-tracking branch 'origin/dev' into feat_hybridstepper_to_main
2 parents 6eba4b0 + 6d96569 commit 0cf2fde

File tree

11 files changed

+219
-18
lines changed

11 files changed

+219
-18
lines changed

README.md

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,12 @@ The intent is to keep the core of SimpleFOC clean, and thus easy to maintain, un
1010

1111
## New Release
1212

13-
v1.0.8 - Released July 2024, for Simple FOC 2.3.4 or later
13+
v1.0.9 - Released xxx 2024, for Simple FOC 2.3.x or later
1414

1515

16-
What's changed since 1.0.7?
17-
- MA735 driver thanks to [@techyrobot](https://github.com/techy-robot)
18-
- ESP32HWEncoder driver thanks to [@mcells](https://github.com/mcells)
19-
- Bugfixes [included](https://github.com/simplefoc/Arduino-FOC-drivers/issues?q=milestone%3A1.0.8+)
16+
What's changed since 1.0.8?
17+
- AS5600 driver bugfix thanks to [@zbas](https://github.com/zbas)
18+
- Bugfixes [included](https://github.com/simplefoc/Arduino-FOC-drivers/issues?q=milestone%3A1.0.9)
2019

2120

2221
## What is included
@@ -116,6 +115,11 @@ Find out more information about the Arduino SimpleFOC project on the [docs websi
116115

117116
## Release History
118117

118+
What's changed since 1.0.7?
119+
- MA735 driver thanks to [@techyrobot](https://github.com/techy-robot)
120+
- ESP32HWEncoder driver thanks to [@mcells](https://github.com/mcells)
121+
- Bugfixes [included](https://github.com/simplefoc/Arduino-FOC-drivers/issues?q=milestone%3A1.0.8)
122+
119123
What's changed since 1.0.6?
120124
- Improvements to LinearHall driver, thanks to dekutree
121125
- Fix for ESP32 compiler warning, thanks to Yannik Stradmann
@@ -126,14 +130,14 @@ What's changed since 1.0.6?
126130
- Refactored settings storage code
127131
- Refactored I2CCommander
128132
- New utility class for simple trapezoidal motion profiles
129-
- Bugfixes [included](https://github.com/simplefoc/Arduino-FOC-drivers/issues?q=milestone%3A1.0.7+)
133+
- Bugfixes [included](https://github.com/simplefoc/Arduino-FOC-drivers/issues?q=milestone%3A1.0.7)
130134

131135
What's changed since 1.0.5?
132136
- Added STSPIN32G4 driver
133137
- Added STM32G4 CORDIC code, for greatly accellerated trig functions on supported MCUs
134138
- Added STM32FlashSettingsStorage driver, supporting STM32G4 MCUs
135139
- Improvements in the MT6835 sensor driver
136-
- Bugfixes [included](https://github.com/simplefoc/Arduino-FOC-drivers/issues?q=is%3Aissue+milestone%3A1.0.6+)
140+
- Bugfixes [included](https://github.com/simplefoc/Arduino-FOC-drivers/issues?q=is%3Aissue+milestone%3A1.0.6)
137141

138142
What's changed since 1.0.4?
139143
- Added smoothing sensor by [@dekutree64](https://github.com/dekutree64)
@@ -143,7 +147,7 @@ What's changed since 1.0.4?
143147
- New Settings driver: SAMDNVMSettingsStorage
144148
- SimpleFOCRegisters abstraction, mapping SimpleFOC parameters to virtual "Registers"
145149
- Updated I2CCommander to use the new registers abstraction
146-
- Bugfixes [included](https://github.com/simplefoc/Arduino-FOC-drivers/issues?q=is%3Aissue+milestone%3A1.0.5+)
150+
- Bugfixes [included](https://github.com/simplefoc/Arduino-FOC-drivers/issues?q=is%3Aissue+milestone%3A1.0.5)
147151

148152
What's changed since 1.0.3?
149153
- New Comms/Input: STM32SpeedDirCommander

examples/encoders/smoothing/smoothing.ino

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
/**
22
*
3-
* Hall sensor velocity motion control example, modified to demonstrate usage of SmoothingSensor
3+
* Hall sensor velocity motion control example, modified to demonstrate usage of SmoothingSensor.
4+
* The only changes are the declaration of the SmoothingSensor, passing it to motor.linkSensor
5+
* instead of the HallSensor instance, and the added Commander code to switch between the two.
6+
*
47
* Steps:
58
* 1) Configure the motor and sensor
69
* 2) Run the code
@@ -63,8 +66,6 @@ void setup() {
6366
sensor.enableInterrupts(doA, doB); //, doC);
6467
// software interrupts
6568
PciManager.registerListener(&listenerIndex);
66-
// set SmoothingSensor phase correction for hall sensors
67-
smooth.phase_correction = -_PI_6;
6869
// link the SmoothingSensor to the motor
6970
motor.linkSensor(&smooth);
7071

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=SimpleFOCDrivers
2-
version=1.0.8
2+
version=1.0.9
33
author=Simplefoc <[email protected]>
44
maintainer=Simplefoc <[email protected]>
55
sentence=A library of supporting drivers for SimpleFOC. Motor drivers chips, encoder chips, current sensing and supporting code.
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#include "MXLEMMINGObserverSensor.h"
2+
#include "common/foc_utils.h"
3+
#include "common/time_utils.h"
4+
5+
6+
MXLEMMINGObserverSensor::MXLEMMINGObserverSensor(const FOCMotor& m) : _motor(m)
7+
{
8+
// Derive Flux linkage from KV_rating and pole_pairs
9+
if (_isset(_motor.pole_pairs) && _isset(_motor.KV_rating)){
10+
flux_linkage = 60 / ( _SQRT3 * _PI * _motor.KV_rating * _motor.pole_pairs * 2);
11+
}
12+
}
13+
14+
15+
void MXLEMMINGObserverSensor::update() {
16+
// Current sense is required for the observer
17+
if (!_motor.current_sense) return;
18+
19+
// Exit if one of the parameter needed for the flux observer is 0
20+
if ((_motor.phase_inductance == 0) ||
21+
(_motor.phase_resistance == 0) ||
22+
(flux_linkage == 0)) return;
23+
24+
// Update sensor, with optional downsampling of update rate
25+
if (sensor_cnt++ < sensor_downsample) return;
26+
27+
sensor_cnt = 0;
28+
29+
// read current phase currents
30+
PhaseCurrent_s current = _motor.current_sense->getPhaseCurrents();
31+
32+
// calculate clarke transform
33+
ABCurrent_s ABcurrent = _motor.current_sense->getABCurrents(current);
34+
35+
// get current timestamp
36+
long now_us = _micros();
37+
// calculate the sample time from last call
38+
float dt = (now_us - angle_prev_ts) * 1e-6f;
39+
// quick fix for strange cases (micros overflow + timestamp not defined)
40+
if(dt <= 0 || dt > 0.5f) dt = 1e-3f;
41+
42+
// This work deviates slightly from the BSD 3 clause licence.
43+
// The work here is entirely original to the MESC FOC project, and not based
44+
// on any appnotes, or borrowed from another project. This work is free to
45+
// use, as granted in BSD 3 clause, with the exception that this note must
46+
// be included in where this code is implemented/modified to use your
47+
// variable names, structures containing variables or other minor
48+
// rearrangements in place of the original names I have chosen, and credit
49+
// to David Molony as the original author must be noted.
50+
51+
// MXLEMMING Flux Observer
52+
float resistive_term_a = _motor.phase_resistance * ABcurrent.alpha;
53+
float resistive_term_b = _motor.phase_resistance * ABcurrent.beta;
54+
float inductive_term_a = _motor.phase_inductance * (ABcurrent.alpha - i_alpha_prev);
55+
float inductive_term_b = _motor.phase_inductance * (ABcurrent.beta - i_beta_prev);
56+
57+
flux_alpha = _constrain( flux_alpha + (_motor.Ualpha - resistive_term_a) * dt - inductive_term_a ,-flux_linkage, flux_linkage);
58+
flux_beta = _constrain( flux_beta + (_motor.Ubeta - resistive_term_b) * dt - inductive_term_b ,-flux_linkage, flux_linkage);
59+
60+
// Calculate electrical angle
61+
electrical_angle = _normalizeAngle(_atan2(flux_beta,flux_alpha));
62+
63+
// Electrical angle difference
64+
float d_electrical_angle = electrical_angle - electrical_angle_prev;
65+
if(abs(d_electrical_angle) > _2PI * 0.8 ){ //change the factor based on sample rate can also just use _PI for simplicity
66+
if (d_electrical_angle > 0){
67+
d_electrical_angle -= _2PI;
68+
}else{
69+
d_electrical_angle += _2PI;
70+
}
71+
}
72+
angle_track += d_electrical_angle;
73+
74+
// Mechanical angle and full_rotations
75+
float full_rotation = _2PI * _motor.pole_pairs;
76+
if(abs(angle_track) > full_rotation){
77+
if (angle_track>0){
78+
full_rotations += 1;
79+
angle_track -= full_rotation;
80+
}else{
81+
full_rotations -= 1;
82+
angle_track += full_rotation;
83+
}
84+
}
85+
angle_prev = angle_track /_motor.pole_pairs;
86+
87+
// Store Previous values
88+
i_alpha_prev = ABcurrent.alpha;
89+
i_beta_prev = ABcurrent.beta;
90+
angle_prev_ts = now_us;
91+
electrical_angle_prev = electrical_angle;
92+
93+
}
94+
95+
void MXLEMMINGObserverSensor::init(){
96+
this->Sensor::init(); // call base class
97+
}
98+
99+
/*
100+
Shaft angle calculation
101+
*/
102+
float MXLEMMINGObserverSensor::getSensorAngle(){
103+
return 0;
104+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#ifndef MXLEMMING_OBSERVER_SENSOR_H
2+
#define MXLEMMING_OBSERVER_SENSOR_H
3+
4+
#include "Arduino.h"
5+
#include "common/base_classes/FOCMotor.h"
6+
#include "common/base_classes/Sensor.h"
7+
8+
/**
9+
10+
*/
11+
12+
class MXLEMMINGObserverSensor : public Sensor
13+
{
14+
public:
15+
/**
16+
MXLEMMINGObserverSensor class constructor
17+
@param m Motor that the MXLEMMINGObserverSensor will be linked to
18+
*/
19+
MXLEMMINGObserverSensor(const FOCMotor& m);
20+
void update() override;
21+
22+
void init() override;
23+
24+
// Abstract functions of the Sensor class implementation
25+
/** get current angle (rad) */
26+
float getSensorAngle() override;
27+
28+
29+
// For sensors with slow communication, use these to poll less often
30+
unsigned int sensor_downsample = 0; // parameter defining the ratio of downsampling for sensor update
31+
unsigned int sensor_cnt = 0; // counting variable for downsampling
32+
float flux_alpha = 0; // Flux Alpha
33+
float flux_beta = 0; // Flux Beta
34+
float flux_linkage = 0; // Flux linkage, calculated based on KV and pole number
35+
float i_alpha_prev = 0; // Previous Alpha current
36+
float i_beta_prev = 0; // Previous Beta current
37+
float electrical_angle = 0; // Electrical angle
38+
float electrical_angle_prev = 0; // Previous electrical angle
39+
float angle_track = 0; // Total Electrical angle
40+
41+
protected:
42+
const FOCMotor& _motor;
43+
44+
};
45+
46+
#endif
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# MXLEMMING Observer Sensor
2+
3+
The MXLEMMING Obserser has been ported from the MESC Firmware, it's also the default Flux observer in Vesc firmware.
4+
The [MESC book](https://davidmolony.github.io/MESC_Firmware/operation/CONTROL.html#the-sensorless-observer) explains the math behind this flux observer.
5+
6+
It's a simple solution for sensorless motor control only using phase currents and motor parameters, if tracking the position at low speed and when not driving the motor is not relevant.
7+
8+
### Motor Parameters:
9+
The MXLEMMING Observer needs the following motor parameters to be set:
10+
- phase resistance
11+
- KV rating
12+
- phase inductance
13+
- pole pairs
14+
15+
It will not track the position if any of those parameters are missing.
16+
17+
The KV rating and pole pairs parameters are used to derive the motor flux linkage which is key for the flux observer to run well.
18+
```
19+
#include <encoders/MXLEMMING_observer/MXLEMMINGObserverSensor.h>
20+
21+
BLDCMotor motor = BLDCMotor(15, 0.1664, 17.0, 0.00036858); // Hoverboard Motor
22+
MXLEMMINGObserverSensor sensor = MXLEMMINGObserverSensor(motor);
23+
```
24+
flux_linkage parameter can be adjusted from the code.
25+
26+
### Current Sense
27+
The current sense is required as this flux observer only relies on phase currents.
28+
29+
### Sensor Alignment
30+
The flux observer sensor doesn't need sensor alignment.
31+
```
32+
motor.sensor_direction= Direction::CW;
33+
motor.zero_electric_angle = 0;
34+
```
35+
36+
### To do:
37+
- The Clarke transform is running both in the loopFOC and in the sensor update now, it can be remove from the sensor when the Alpha and Beta currents will be persisted as a BLDCMotor member
38+
- The flux observer is calculating the electrical angle directly, but SimpleFOC needs to derive the electrical angle from the sensor angle for the FOC calculation
39+

src/encoders/as5600/AS5600.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,13 @@ void AS5600::setZPos(uint16_t value) {
124124
void AS5600::setI2CAddr(uint8_t value) {
125125
uint8_t val = (uint8_t)readRegister(AS5600_REG_I2CADDR, 1);
126126
val = (value<<1) | (val&0x01);
127-
writeRegister(AS5600_REG_I2CADDR, val);
127+
writeRegister(AS5600_REG_I2CADDR, val, 1);
128128
};
129129

130130
void AS5600::setI2CUpdt(uint8_t value) {
131131
uint8_t val = (uint8_t)readRegister(AS5600_REG_I2CUPDT, 1);
132132
val = (value<<1) | (val&0x01);
133-
writeRegister(AS5600_REG_I2CUPDT, val);
133+
writeRegister(AS5600_REG_I2CUPDT, val, 1);
134134
};
135135

136136

src/encoders/as5600/MagneticSensorAS5600.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ void MagneticSensorAS5600::init(TwoWire* wire) {
1313

1414

1515
float MagneticSensorAS5600::getSensorAngle() {
16-
uint16_t raw = readRawAngle();
16+
uint16_t raw = angle();
1717
return raw / AS5600_CPR * _2PI;
1818
};

src/encoders/linearhall/LinearHall.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ LinearHall::LinearHall(int _hallA, int _hallB, int _pp){
1313
pinA = _hallA;
1414
pinB = _hallB;
1515
pp = _pp;
16+
electrical_rev = 0;
17+
prev_reading = 0;
1618
}
1719

1820
float LinearHall::getSensorAngle() {
@@ -84,7 +86,7 @@ void LinearHall::init(FOCMotor *motor) {
8486
// move one mechanical revolution forward
8587
for (int i = 0; i <= 2000; i++)
8688
{
87-
float angle = _3PI_2 + _2PI * i * pp / 2000.0f;
89+
float angle = _3PI_2 + _2PI * i * motor->pole_pairs / pp / 2000.0f;
8890
motor->setPhaseVoltage(motor->voltage_sensor_align, 0, angle);
8991

9092
ReadLinearHalls(pinA, pinB, &lastA, &lastB);

src/encoders/smoothing/SmoothingSensor.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
#include "SmoothingSensor.h"
22
#include "common/foc_utils.h"
33
#include "common/time_utils.h"
4+
#include "sensors/HallSensor.h"
45

56

67
SmoothingSensor::SmoothingSensor(Sensor& s, const FOCMotor& m) : _wrapped(s), _motor(m)
78
{
89
}
910

11+
SmoothingSensor::SmoothingSensor(HallSensor& s, const FOCMotor& m) : _wrapped(s), _motor(m) {
12+
phase_correction = -_PI_6;
13+
}
1014

1115
void SmoothingSensor::update() {
1216
// Update sensor, with optional downsampling of update rate
@@ -27,8 +31,8 @@ void SmoothingSensor::update() {
2731

2832
// Apply phase correction if needed
2933
if (phase_correction != 0) {
30-
if (_motor.shaft_velocity < -0) angle_prev -= _motor.sensor_direction * phase_correction / _motor.pole_pairs;
31-
else if (_motor.shaft_velocity > 0) angle_prev += _motor.sensor_direction * phase_correction / _motor.pole_pairs;
34+
if (_motor.shaft_velocity < -0.001) angle_prev -= _motor.sensor_direction * phase_correction / _motor.pole_pairs;
35+
else if (_motor.shaft_velocity > 0.001) angle_prev += _motor.sensor_direction * phase_correction / _motor.pole_pairs;
3236
}
3337

3438
// Handle wraparound of the projected angle

0 commit comments

Comments
 (0)