Skip to content

Commit 72c1a9e

Browse files
Merge pull request simplefoc#22 from simplefoc/dev
1.0.4 release PR
2 parents e379709 + 4ce521f commit 72c1a9e

21 files changed

+783
-234
lines changed

README.md

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

1111
## New Release
1212

13-
v1.0.3 - Released March 2023, for Simple FOC 2.3.0
14-
15-
What's changed since 1.0.2?
16-
- New Sensor: MT6835
17-
- Fixed bugs
18-
19-
What's changed since 1.0.1?
20-
- Calibrated sensor by @MarethyuPrefect
21-
- New Sensors: MT6701, MA330, MT6816
22-
- Fixed bugs
13+
v1.0.4 - Released June 2023, for Simple FOC 2.3.0
2314

15+
What's changed since 1.0.3?
16+
- New Comms/Input: STM32SpeedDirCommander
17+
- New Utility: STM32PWMInput
18+
- Fixed MT6835 driver bugs
19+
- Improved AS5047 driver, fixed bugs
20+
- Improved AS5047U driver, fixed bugs
2421

2522
## What is included
2623

@@ -45,10 +42,16 @@ What is here? See the sections below. Each driver or function should come with i
4542
- [MT6816 SPI driver](src/encoders/mt6816/) - SPI driver for the MagnTek MT6816 absolute position magnetic rotary encoder IC.
4643
- [MT6701 SSI driver](src/encoders/mt6701/) - SSI driver for the MagnTek MT6701 absolute position magnetic rotary encoder IC.
4744
- [MT6835 SPI driver](src/encoders/mt6835/) - SPI driver for the MagnTek MT6835 21 bit magnetic rotary encoder IC.
45+
- [STM32 PWM sensor driver](src/encoders/stm32pwmsensor/) - STM32 native timer-based driver for PWM angle sensors.
4846

4947
### Communications
5048

5149
- [I2CCommander I2C driver](src/comms/i2c/) - I2C communications protocol and drivers for both controller and target devices.
50+
- [STM32 SpeedDir Input](src/comms/stm32speeddir/) - Control target velocity with PWM speed and direction inputs
51+
52+
### Utilities
53+
54+
- [STM32 PWM Input driver](src/utilities/stm32pwm/) - PWM Input driver for STM32 MCUs. Accurately measure PWM inputs with zero MCU overhead.
5255

5356

5457
## How to use
@@ -74,3 +77,14 @@ If you do so, please be sure to adhere to and include the [LICENSE](https://gith
7477
## Further Documentation
7578

7679
Find out more information about the Arduino SimpleFOC project on the [docs website](https://docs.simplefoc.com/)
80+
81+
## Release History
82+
83+
What's changed since 1.0.2?
84+
- New Sensor: MT6835
85+
- Fixed bugs
86+
87+
What's changed since 1.0.1?
88+
- Calibrated sensor by @MarethyuPrefect
89+
- New Sensors: MT6701, MA330, MT6816
90+
- Fixed bugs

keywords.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ AS5048A KEYWORD1
44
AS5047 KEYWORD1
55
AS5145 KEYWORD1
66
MA730 KEYWORD1
7+
MT6835 KEYWORD1
8+
SC60228 KEYWORD1
79
TLE5012B KEYWORD1
810
I2CCommander KEYWORD1
9-
11+
STM32HWEncoder KEYWORD1

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.3
2+
version=1.0.4
33
author=Simplefoc <info@simplefoc.com>
44
maintainer=Simplefoc <info@simplefoc.com>
55
sentence=A library of supporting drivers for SimpleFOC. Motor drivers chips, encoder chips, current sensing and supporting code.

src/comms/stm32speeddir/README.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
2+
# STM32SpeedDirInput
3+
4+
Control SimpleFOC using PWM speed and direction inputs.
5+
6+
Based on STM32 timer PWM-Input capabilities, which means this can only be used on STM32 MCUs. It can cover a wide range of PWM frequencies, and runs without MCU overhead in the timer hardware.
7+
8+
9+
10+
## Setup
11+
12+
The PWM speed input should be connected to either channel 1 or channel 2 of a general purpose or advanced control timer on your STM32 MCU. Suitable timers are:
13+
- Advanced control timers: TIM1, TIM8
14+
- General purpose timers (32 bit): TIM2, TIM5
15+
- General purpose timers (16 bit): TIM3, TIM4, TIM9, TIM12
16+
If in doubt, check in STM32CubeIDE and see if the PWM-Input mode can be enabled (under "Combined Channels") for the timer.
17+
18+
The optional direction input can be connected to any GPIO pin. By default a high level direction input is associated with a positive velocity value, while a low level direction input results in a negative velocity value. To reverse this, set the option `dir_positive_high = false`
19+
20+
The direction input is optional - if not provided, you can control the direction from software using the `direction` field.
21+
22+
The velocity values returned are in the range `min_speed` to `max_speed`, while the input PWM duty cycle should lie within the range `min_pwm` to `max_pwm`. Actual input values smaller than `min_pwm` will be treated as `min_pwm`, values larger than `max_pwm` will be treated as `max_pwm`. The behaviour for 100% or 0% duty cycles is undefined, and they should be avoided.
23+
24+
## Usage
25+
26+
Use it like this:
27+
28+
```c++
29+
#include "comms/stm32speeddir/STM32SpeedDirInput.h"
30+
31+
// some example pins - the speed pin has to be on channel 1 or 2 of a timer
32+
#define PIN_SPEED PC6
33+
#define PIN_DIRECTION PB8
34+
35+
STM32SpeedDirInput speed_dir = STM32SpeedDirInput(PIN_SPEED, PIN_DIRECTION);
36+
37+
float target = 0.0f;
38+
39+
void setup(){
40+
...
41+
42+
speed_dir.min_speed = 10.0f; // 10rad/s min speed
43+
speed_dir.max_speed = 100.0f; // 100rad/s max speed
44+
speed_dir.min_pwm = 5.0f; // 5% min duty cycle
45+
speed_dir.max_pwm = 95.0f; // 95% max duty cycle
46+
speed_dir.init();
47+
48+
...
49+
}
50+
51+
52+
void loop(){
53+
target = speed_dir.getTargetVelocity();
54+
motor.move(target);
55+
motor.loopFOC();
56+
}
57+
58+
```
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
#include "./STM32SpeedDirInput.h"
3+
4+
#if defined(_STM32_DEF_)
5+
6+
STM32SpeedDirInput::STM32SpeedDirInput(int pin_speed, int pin_dir) : STM32PWMInput(pin_speed) {
7+
_pin_speed = pin_speed;
8+
_pin_dir = pin_dir;
9+
};
10+
11+
STM32SpeedDirInput::~STM32SpeedDirInput(){};
12+
13+
int STM32SpeedDirInput::init(){
14+
pinMode(_pin_dir, INPUT);
15+
return STM32PWMInput::initialize();
16+
};
17+
18+
19+
float STM32SpeedDirInput::getTargetVelocity(){
20+
if (_pin_dir != NOT_SET)
21+
direction = digitalRead(_pin_dir);
22+
float speed = getDutyCyclePercent();
23+
speed = constrain(speed, min_pwm, max_pwm);
24+
speed = (speed - min_pwm)/(max_pwm - min_pwm) * (max_speed - min_speed) + min_speed;
25+
return (direction == dir_positive_high) ? speed : -speed;
26+
};
27+
28+
29+
#endif
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
#pragma once
3+
4+
#include "Arduino.h"
5+
6+
#if defined(_STM32_DEF_)
7+
8+
#include "common/foc_utils.h"
9+
#include "utilities/stm32pwm/STM32PWMInput.h"
10+
11+
class STM32SpeedDirInput : public STM32PWMInput {
12+
public:
13+
STM32SpeedDirInput(int pin_speed, int pin_dir = NOT_SET);
14+
~STM32SpeedDirInput();
15+
16+
int init();
17+
float getTargetVelocity();
18+
19+
float min_speed = 0; // min speed in rad/s
20+
float max_speed = 100; // max speed in rad/s
21+
float min_pwm = 5.0; // min duty cycle in %
22+
float max_pwm = 95.0; // max duty cycle in %
23+
bool dir_positive_high = true; // true if the direction pin is high when the motor is spinning in the positive direction
24+
bool direction = true; // direction of rotation, default positive
25+
protected:
26+
int _pin_speed;
27+
int _pin_dir;
28+
};
29+
30+
31+
#endif

src/encoders/as5047/AS5047.cpp

Lines changed: 100 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,21 +85,29 @@ AS5047Settings1 AS5047::readSettings1(){
8585

8686
void AS5047::writeSettings1(AS5047Settings1 settings){
8787
uint16_t command = AS5047_SETTINGS1_REG; // set r=0, result is 0x0018
88-
/*uint16_t cmdresult =*/ spi_transfer16(command);
89-
/*cmdresult =*/ spi_transfer16(settings.reg);
88+
spi_transfer16(command);
89+
spi_transfer16(calcParity(settings.reg));
9090
}
9191

9292

9393
AS5047Settings2 AS5047::readSettings2(){
9494
uint16_t command = AS5047_SETTINGS2_REG | AS5047_RW; // set r=1, result is 0x4019
95-
/*uint16_t cmdresult =*/ spi_transfer16(command);
95+
spi_transfer16(command);
9696
AS5047Settings2 result = {
9797
.reg = nop()
9898
};
9999
return result;
100100
}
101101

102102

103+
void AS5047::writeSettings2(AS5047Settings2 settings){
104+
uint16_t command = AS5047_SETTINGS2_REG | AS5047_PARITY; // set r=0, result is 0x8019
105+
spi_transfer16(command);
106+
spi_transfer16(calcParity(settings.reg));
107+
}
108+
109+
110+
103111
AS5047Diagnostics AS5047::readDiagnostics(){
104112
uint16_t command = AS5047_DIAGNOSTICS_REG | AS5047_PARITY | AS5047_RW; // set r=1, result is 0xFFFC
105113
/*uint16_t cmdresult =*/ spi_transfer16(command);
@@ -112,21 +120,96 @@ AS5047Diagnostics AS5047::readDiagnostics(){
112120

113121
void AS5047::enablePWM(bool enable){
114122
AS5047Settings1 settings = readSettings1();
123+
if (settings.pwmon == enable) return; // no change
115124
settings.pwmon = enable;
116125
writeSettings1(settings);
117126
}
118127

119128
void AS5047::enableABI(bool enable){
120129
AS5047Settings1 settings = readSettings1();
121-
settings.uvw_abi = enable?0:1;
130+
uint8_t val = enable?0:1;
131+
if (settings.uvw_abi == val) return; // no change
132+
settings.uvw_abi = val;
122133
writeSettings1(settings);
123134
}
124135

125136

137+
void AS5047::enableDEAC(bool enable){
138+
AS5047Settings1 settings = readSettings1();
139+
uint8_t val = enable?0:1;
140+
if (settings.daecdis == val) return; // no change
141+
settings.daecdis = enable?0:1;
142+
writeSettings1(settings);
143+
}
144+
145+
146+
void AS5047::useCorrectedAngle(bool useCorrected){
147+
AS5047Settings1 settings = readSettings1();
148+
uint8_t val = useCorrected?0:1;
149+
if (settings.dataselect == val) return; // no change
150+
settings.dataselect = val;
151+
writeSettings1(settings);
152+
}
153+
154+
155+
156+
void AS5047::setHysteresis(uint8_t hyst){
157+
if (hyst>3) hyst = 3;
158+
uint8_t val = 3-hyst;
159+
AS5047Settings2 settings = readSettings2();
160+
if (settings.hys == val) return; // no change
161+
settings.hys = val;
162+
writeSettings2(settings);
163+
}
164+
165+
166+
167+
168+
void AS5047::setABIResolution(AS5047ABIRes res){
169+
AS5047Settings1 settings = readSettings1();
170+
uint8_t val = (res>>3)&0x01;
171+
if (settings.abibin!=val || settings.uvw_abi!=0) {
172+
settings.abibin = val;
173+
settings.uvw_abi = 0;
174+
writeSettings1(settings);
175+
}
176+
AS5047Settings2 settings2 = readSettings2();
177+
val = (res&0x07);
178+
if (settings2.abires!=val) {
179+
settings2.abires = val;
180+
writeSettings2(settings2);
181+
}
182+
}
183+
184+
126185

127186
uint16_t AS5047::setZero(uint16_t value){
128-
// TODO implement me!
129-
return 0;
187+
uint16_t command = AS5047_ZPOSL_REG | AS5047_PARITY | AS5047_RW;
188+
spi_transfer16(command);
189+
AS5047ZPosL posL = {
190+
.reg = nop()
191+
};
192+
command = AS5047_ZPOSM_REG | AS5047_PARITY;
193+
spi_transfer16(command);
194+
spi_transfer16(calcParity((value>>6)&0x00FF));
195+
command = AS5047_ZPOSL_REG;
196+
posL.zposl = value&0x003F;
197+
spi_transfer16(command);
198+
spi_transfer16(calcParity(posL.reg));
199+
200+
return getZero();
201+
}
202+
203+
204+
uint16_t AS5047::getZero() {
205+
uint16_t command = AS5047_ZPOSM_REG | AS5047_RW;
206+
spi_transfer16(command);
207+
command = AS5047_ZPOSL_REG | AS5047_PARITY | AS5047_RW;
208+
uint16_t result = spi_transfer16(command);
209+
AS5047ZPosL posL = {
210+
.reg = nop()
211+
};
212+
return ((result&0x00FF)<<6) | posL.zposl;
130213
}
131214

132215

@@ -135,6 +218,17 @@ uint16_t AS5047::nop(){
135218
return result&AS5047_RESULT_MASK;
136219
}
137220

221+
222+
uint16_t AS5047::calcParity(uint16_t data){
223+
data = data & 0x7FFF;
224+
int sum = 0;
225+
for (int i=0;i<15;i++)
226+
if ((data>>i)&0x0001)
227+
sum++;
228+
return (sum&0x01)==0x01?(data|0x8000):data;
229+
}
230+
231+
138232
uint16_t AS5047::spi_transfer16(uint16_t outdata) {
139233
if (nCS>=0)
140234
digitalWrite(nCS, 0);

0 commit comments

Comments
 (0)