Skip to content

Commit 5fa5893

Browse files
committed
Merge branch 'dev' into rp2040
2 parents 3fc05d2 + d8011fc commit 5fa5893

File tree

8 files changed

+127
-51
lines changed

8 files changed

+127
-51
lines changed

README.md

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,36 +20,12 @@ Therefore this is an attempt to:
2020
> - bugfixes commander
2121
> - bugfix `voltage_limit` when provided `phase_resistance`
2222
> - bugfix `hall_sensor` examples
23-
> - added examples fot the powershield
23+
> - added examples fot the PowerShield
2424
> - added initial support for `MagneticSensorPWM`
25+
> - added examples to find the raw max and min of the analog and pwm sensor
2526
> - extension of the `Commander` interface
26-
27-
28-
## Arduino *SimpleFOCShield* v2.0.3
29-
<p align="">
30-
<a href="https://youtu.be/G5pbo0C6ujE">
31-
<img src="https://docs.simplefoc.com/extras/Images/foc_shield_video.jpg" height="320px">
32-
</a>
33-
</p>
34-
35-
### Features
36-
- **Plug & play**: In combination with Arduino *Simple**FOC**library* - [github](https://github.com/simplefoc/Arduino-FOC)
37-
- **Low-cost**: Price of €15 - [Check the pricing](https://www.simplefoc.com/shop)
38-
- **In-line current sensing**: Up to 3Amps/5Amps bidirectional
39-
- configurable: 3.3Amps - 3.3V adc, 5Amps - 5V adc
40-
- **Integrated 8V regulator**:
41-
- Enable/disable by soldering pads
42-
- **Max power 120W** - max current 5A, power-supply 12-24V
43-
- Designed for Gimbal motors with the internal resistance >10 Ωs.
44-
- **Stackable**: running 2 motors in the same time
45-
- **Encoder/Hall sensors interface**: Integrated 3.3kΩ pullups (configurable)
46-
- **I2C interface**: Integrated 4.7kΩ pullups (configurable)
47-
- **Configurable pinout**: Hardware configuration - soldering connections
48-
- **Arduino headers**: Arduino UNO, Arduino MEGA, STM32 Nucleo boards...
49-
- **Open Source**: Fully available fabrication files - [how to make it yourself](https://docs.simplefoc.com/arduino_simplefoc_shield_fabrication)
50-
51-
<p align=""><img src="https://simplefoc.com/assets/img/v2.jpg" height="180px"> <img src="https://simplefoc.com/assets/img/v1.jpg" height="180px"> <img src="https://docs.simplefoc.com/extras/Images/simple_foc_shield_v13_small.gif" height="180x"></p>
52-
27+
> - improved esp32 implementation to avoid the need for mcpwm.h changes by @tschundler
28+
> - issue #62: motor.shaft_angle setting in the motor.initFOC()
5329
5430
## Arduino *SimpleFOClibrary* v2.1
5531

@@ -81,6 +57,33 @@ This video demonstrates the *Simple**FOC**library* basic usage, electronic conne
8157

8258
<p align=""> <img src="https://docs.simplefoc.com/extras/Images/uno_l6234.jpg" height="170px"> <img src="https://docs.simplefoc.com/extras/Images/hmbgc_v22.jpg" height="170px"> <img src="https://docs.simplefoc.com/extras/Images/foc_shield_v13.jpg" height="170px"></p>
8359

60+
## Arduino *SimpleFOCShield* v2.0.3
61+
<p align="">
62+
<a href="https://youtu.be/G5pbo0C6ujE">
63+
<img src="https://docs.simplefoc.com/extras/Images/foc_shield_video.jpg" height="320px">
64+
</a>
65+
</p>
66+
67+
### Features
68+
- **Plug & play**: In combination with Arduino *Simple**FOC**library* - [github](https://github.com/simplefoc/Arduino-FOC)
69+
- **Low-cost**: Price of €15 - [Check the pricing](https://www.simplefoc.com/shop)
70+
- **In-line current sensing**: Up to 3Amps/5Amps bidirectional
71+
- configurable: 3.3Amps - 3.3V adc, 5Amps - 5V adc
72+
- **Integrated 8V regulator**:
73+
- Enable/disable by soldering pads
74+
- **Max power 120W** - max current 5A, power-supply 12-24V
75+
- Designed for Gimbal motors with the internal resistance >10 Ωs.
76+
- **Stackable**: running 2 motors in the same time
77+
- **Encoder/Hall sensors interface**: Integrated 3.3kΩ pullups (configurable)
78+
- **I2C interface**: Integrated 4.7kΩ pullups (configurable)
79+
- **Configurable pinout**: Hardware configuration - soldering connections
80+
- **Arduino headers**: Arduino UNO, Arduino MEGA, STM32 Nucleo boards...
81+
- **Open Source**: Fully available fabrication files - [how to make it yourself](https://docs.simplefoc.com/arduino_simplefoc_shield_fabrication)
82+
83+
<p align=""><img src="https://simplefoc.com/assets/img/v2.jpg" height="180px"> <img src="https://simplefoc.com/assets/img/v1.jpg" height="180px"> <img src="https://docs.simplefoc.com/extras/Images/simple_foc_shield_v13_small.gif" height="180x"></p>
84+
85+
86+
8487
## Getting Started
8588
Depending on if you want to use this library as the plug and play Arduino library or you want to get insight in the algorithm and make changes there are two ways to install this code.
8689

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include <SimpleFOC.h>
2+
3+
/**
4+
* An example to find out the raw max and min count to be provided to the constructor
5+
* Spin your motor/sensor/magnet to see what is the maximum output of the sensor and what is the minimum value
6+
* And replace values 14 and 1020 with new values. Once when you replace them make sure there is no jump in the angle reading sensor.getAngle().
7+
* If there is a jump that means you can still find better values.
8+
*/
9+
10+
/**
11+
* Magnetic sensor reading analog voltage on pin A1. This voltage is proportional to rotation position.
12+
* Tested on AS5600 magnetic sensor running in 'analog mode'. Note AS5600 works better in 'i2C mode' (less noise) but only supports one sensor per i2c bus.
13+
*
14+
* MagneticSensorAnalog(uint8_t _pinAnalog, int _min, int _max)
15+
* - pinAnalog - the pin that is reading the pwm from magnetic sensor
16+
* - min_raw_count - the smallest expected reading. Whilst you might expect it to be 0 it is often ~15. Getting this wrong results in a small click once per revolution
17+
* - max_raw_count - the largest value read. whilst you might expect it to be 2^10 = 1023 it is often ~ 1020. Note ESP32 will be closer to 4096 with its 12bit ADC
18+
*/
19+
MagneticSensorAnalog sensor = MagneticSensorAnalog(A1, 14, 1020);
20+
21+
void setup() {
22+
// monitoring port
23+
Serial.begin(115200);
24+
25+
// initialise magnetic sensor hardware
26+
sensor.init();
27+
28+
Serial.println("Sensor ready");
29+
_delay(1000);
30+
}
31+
32+
int max_count = 0;
33+
int min_count = 100000;
34+
35+
void loop() {
36+
37+
// keep track of min and max
38+
if(sensor.raw_count > max_count) max_count = sensor.raw_count;
39+
else if(sensor.raw_count < min_count) min_count = sensor.raw_count;
40+
41+
// display the raw count, and max and min raw count
42+
Serial.print("angle:");
43+
Serial.print(sensor.getAngle());
44+
Serial.print("\t, raw:");
45+
Serial.print(sensor.raw_count);
46+
Serial.print("\t, min:");
47+
Serial.print(min_count);
48+
Serial.print("\t, max:");
49+
Serial.println(max_count);
50+
delay(100);
51+
}

examples/utils/sensor_test/magnetic_sensors/magnetic_sensor_analog_example/magnetic_sensor_analog_example.ino renamed to examples/utils/sensor_test/magnetic_sensors/magnetic_sensor_analog_example/magnetic_sensor_analog/magnetic_sensor_analog.ino

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <SimpleFOC.h>
22

33

4+
45
/**
56
* Magnetic sensor reading analog voltage on pin A1. This voltage is proportional to rotation position.
67
* Tested on AS5600 magnetic sensor running in 'analog mode'. Note AS5600 works better in 'i2C mode' (less noise) but only supports one sensor per i2c bus.
@@ -28,4 +29,4 @@ void loop() {
2829
Serial.print(sensor.getAngle());
2930
Serial.print("\t");
3031
Serial.println(sensor.getVelocity());
31-
}
32+
}

examples/utils/sensor_test/magnetic_sensors/magnetic_sensor_pwm_example/find_raw_min_max/find_raw_min_max.ino

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,22 @@ void setup() {
2222
_delay(1000);
2323
}
2424

25+
int max_pulse= 0;
26+
int min_pulse = 10000;
27+
2528
void loop() {
26-
// display the angle and the angular velocity to the terminal
29+
30+
// keep track of min and max
31+
if(sensor.pulse_length_us > max_pulse) max_pulse = sensor.pulse_length_us;
32+
else if(sensor.pulse_length_us < min_pulse) min_pulse = sensor.pulse_length_us;
33+
34+
// display the raw count, and max and min raw count
35+
Serial.print("angle:");
36+
Serial.print(sensor.getAngle());
37+
Serial.print("\t, raw:");
2738
Serial.print(sensor.pulse_length_us);
28-
Serial.print("\t");
29-
Serial.println(sensor.getAngle());
39+
Serial.print("\t, min:");
40+
Serial.print(min_pulse);
41+
Serial.print("\t, max:");
42+
Serial.println(max_pulse);
3043
}

src/BLDCMotor.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,11 @@ int BLDCMotor::initFOC( float zero_electric_offset, Direction _sensor_direction
9898
// sensor and motor alignment - can be skipped
9999
// by setting motor.sensor_direction and motor.zero_electric_angle
100100
_delay(500);
101-
if(sensor) exit_flag *= alignSensor();
102-
else if(monitor_port) monitor_port->println(F("MOT: No sensor."));
101+
if(sensor){
102+
exit_flag *= alignSensor();
103+
// added the shaft_angle update
104+
shaft_angle = sensor->getAngle();
105+
}else if(monitor_port) monitor_port->println(F("MOT: No sensor."));
103106

104107
// aligning the current sensor - can be skipped
105108
// checks if driver phases are the same as current sense phases
@@ -244,14 +247,13 @@ int BLDCMotor::absoluteZeroSearch() {
244247
// Iterative function looping FOC algorithm, setting Uq on the Motor
245248
// The faster it can be run the better
246249
void BLDCMotor::loopFOC() {
247-
250+
// if open-loop do nothing
251+
if( controller==MotionControlType::angle_openloop || controller==MotionControlType::velocity_openloop ) return;
248252
// shaft angle
249253
shaft_angle = shaftAngle(); // read value even if motor is disabled to keep the monitoring updated
250254

251255
// if disabled do nothing
252256
if(!enabled) return;
253-
// if open-loop do nothing
254-
if( controller==MotionControlType::angle_openloop || controller==MotionControlType::velocity_openloop ) return;
255257

256258
// electrical angle - need shaftAngle to be called first
257259
electrical_angle = electricalAngle();

src/StepperMotor.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,11 @@ int StepperMotor::initFOC( float zero_electric_offset, Direction _sensor_direct
9696
// sensor and motor alignment - can be skipped
9797
// by setting motor.sensor_direction and motor.zero_electric_angle
9898
_delay(500);
99-
if(sensor) exit_flag = alignSensor();
100-
else if(monitor_port) monitor_port->println(F("MOT: No sensor."));
99+
if(sensor){
100+
exit_flag *= alignSensor();
101+
// added the shaft_angle update
102+
shaft_angle = sensor->getAngle();
103+
}else if(monitor_port) monitor_port->println(F("MOT: No sensor."));
101104

102105
if(exit_flag){
103106
if(monitor_port) monitor_port->println(F("MOT: Ready."));
@@ -213,13 +216,14 @@ int StepperMotor::absoluteZeroSearch() {
213216
// Iterative function looping FOC algorithm, setting Uq on the Motor
214217
// The faster it can be run the better
215218
void StepperMotor::loopFOC() {
216-
// if disabled do nothing
217-
if(!enabled) return;
218219
// if open-loop do nothing
219220
if( controller==MotionControlType::angle_openloop || controller==MotionControlType::velocity_openloop ) return;
220-
221221
// shaft angle
222222
shaft_angle = shaftAngle();
223+
224+
// if disabled do nothing
225+
if(!enabled) return;
226+
223227
electrical_angle = electricalAngle();
224228

225229
// set the phase voltage - FOC heart function :)
@@ -232,15 +236,15 @@ void StepperMotor::loopFOC() {
232236
// - needs to be called iteratively it is asynchronous function
233237
// - if target is not set it uses motor.target value
234238
void StepperMotor::move(float new_target) {
239+
// get angular velocity
240+
shaft_velocity = shaftVelocity();
235241
// if disabled do nothing
236242
if(!enabled) return;
237243
// downsampling (optional)
238244
if(motion_cnt++ < motion_downsample) return;
239245
motion_cnt = 0;
240246
// set internal target variable
241247
if(_isset(new_target) ) target = new_target;
242-
// get angular velocity
243-
shaft_velocity = shaftVelocity();
244248
// choose control loop
245249
switch (controller) {
246250
case MotionControlType::torque:

src/drivers/hardware_specific/esp32_mcu.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,12 @@ void _configureTimerFrequency(long pwm_frequency, mcpwm_dev_t* mcpwm_num, mcpwm
154154
mcpwm_start(mcpwm_unit, MCPWM_TIMER_1);
155155
mcpwm_start(mcpwm_unit, MCPWM_TIMER_2);
156156
_delay(1);
157-
158-
mcpwm_sync_enable(mcpwm_unit, MCPWM_TIMER_0, MCPWM_SELECT_SYNC_INT0, 0);
159-
mcpwm_sync_enable(mcpwm_unit, MCPWM_TIMER_1, MCPWM_SELECT_SYNC_INT0, 0);
160-
mcpwm_sync_enable(mcpwm_unit, MCPWM_TIMER_2, MCPWM_SELECT_SYNC_INT0, 0);
157+
// Cast here because MCPWM_SELECT_SYNC_INT0 (1) is not defined
158+
// in the default Espressif MCPWM headers. The correct const may be used
159+
// when https://github.com/espressif/esp-idf/issues/5429 is resolved.
160+
mcpwm_sync_enable(mcpwm_unit, MCPWM_TIMER_0, (mcpwm_sync_signal_t)1, 0);
161+
mcpwm_sync_enable(mcpwm_unit, MCPWM_TIMER_1, (mcpwm_sync_signal_t)1, 0);
162+
mcpwm_sync_enable(mcpwm_unit, MCPWM_TIMER_2, (mcpwm_sync_signal_t)1, 0);
161163
_delay(1);
162164
mcpwm_num->timer[0].sync.out_sel = 1;
163165
_delay(1);
@@ -428,4 +430,4 @@ void _writeDutyCycle6PWM(float dc_a, float dc_b, float dc_c, float dead_zone, i
428430
}
429431
}
430432
}
431-
#endif
433+
#endif

src/sensors/MagneticSensorAnalog.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ class MagneticSensorAnalog: public Sensor{
3333
/** get current angular velocity (rad/s) **/
3434
float getVelocity() override;
3535

36-
37-
private:
3836
/** raw count (typically in range of 0-1023), useful for debugging resolution issues */
3937
int raw_count;
38+
39+
private:
4040
int min_raw_count;
4141
int max_raw_count;
4242
int cpr;

0 commit comments

Comments
 (0)