Skip to content

Commit 22be810

Browse files
committed
update of the PWM sensor
1 parent 08b36cc commit 22be810

File tree

8 files changed

+102
-13
lines changed

8 files changed

+102
-13
lines changed

src/comms/stm32speeddir/README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ The direction input is optional - if not provided, you can control the direction
2121

2222
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.
2323

24+
> **IMPORTANT**<br>
25+
> If the PWM frequency of the speed input is not known, provide its value in Hz to the constructor. If not provided, it will default to 1kHz (very common value). The frequency is used to make sure that the PWM period stays within one timer counter period. If this is not the case the timer counter can overflow and the input will not work correctly.
26+
27+
2428
## Usage
2529

2630
Use it like this:
@@ -31,8 +35,9 @@ Use it like this:
3135
// some example pins - the speed pin has to be on channel 1 or 2 of a timer
3236
#define PIN_SPEED PC6
3337
#define PIN_DIRECTION PB8
38+
#define PWM_FREQUENCY 1000 // 1kHz (defualt)
3439

35-
STM32SpeedDirInput speed_dir = STM32SpeedDirInput(PIN_SPEED, PIN_DIRECTION);
40+
STM32SpeedDirInput speed_dir = STM32SpeedDirInput(PIN_SPEED, PIN_DIRECTION, PWM_FREQUENCY);
3641

3742
float target = 0.0f;
3843

src/comms/stm32speeddir/STM32SpeedDirInput.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
#if defined(_STM32_DEF_)
55

6-
STM32SpeedDirInput::STM32SpeedDirInput(int pin_speed, int pin_dir) : STM32PWMInput(pin_speed) {
6+
STM32SpeedDirInput::STM32SpeedDirInput(int pin_speed, int pin_dir, uint32_t pwm_freq) : STM32PWMInput(pin_speed, _pwm_freq) {
77
_pin_speed = pin_speed;
88
_pin_dir = pin_dir;
99
};

src/comms/stm32speeddir/STM32SpeedDirInput.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,21 @@
1010

1111
class STM32SpeedDirInput : public STM32PWMInput {
1212
public:
13-
STM32SpeedDirInput(int pin_speed, int pin_dir = NOT_SET);
13+
14+
/**
15+
* STM32SpeedDirInput constructor
16+
*
17+
* @param pin_speed - the pin number to read the speed PWM signal from
18+
* @param pin_dir - the pin number to read the direction signal from (default is NOT_SET)
19+
* @param pwm_freq - the frequency of the PWM signal (default is 1kHz)
20+
*
21+
* This class is used to read speed and direction signals from a pin using the STM32 HAL library.
22+
* IMPORTANT!
23+
* This class can only be used with the pins that are associated with some timer,
24+
* and only if they are associated to the channels 1 or 2. The timer can not be
25+
* used for other purposes, like motor control.
26+
*/
27+
STM32SpeedDirInput(int pin_speed, int pin_dir = NOT_SET, uint32_t pwm_freq = 1000);
1428
~STM32SpeedDirInput();
1529

1630
int init();

src/encoders/stm32pwmsensor/README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,18 @@ sensor.getDutyCycleTicks();
2121

2222
By rotating the motor through several full turns while printing the ticks to the screen you will be able to determine the correct values empirically.
2323

24+
25+
> **IMPORTANT**<br>
26+
> If the PWM frequency of the speed input is not known, provide its value in Hz to the constructor. If not provided, it will default to 1kHz (very common value). The frequency is used to make sure that the PWM period stays within one timer counter period. If this is not the case the timer counter can overflow and the input will not work correctly.
27+
28+
2429
## Usage
2530

2631
```
27-
STM32MagneticSensorPWM sensor = STM32MagneticSensorPWM(PB7, 412, 6917); // sample values, yours will be different
32+
33+
#define PWM_FREQ_HZ 1000 // 1kHz (default)
34+
35+
STM32MagneticSensorPWM sensor = STM32MagneticSensorPWM(PB7, 412, 6917, PWM_FREQ_HZ); // sample values, yours will be different
2836
2937
void setup() {
3038
...

src/encoders/stm32pwmsensor/STM32MagneticSensorPWM.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include "common/foc_utils.h"
77

88

9-
STM32MagneticSensorPWM::STM32MagneticSensorPWM(int pin, uint32_t _min_ticks, uint32_t _max_ticks) : STM32PWMInput(pin), max_ticks(_max_ticks), min_ticks(_min_ticks) {
9+
STM32MagneticSensorPWM::STM32MagneticSensorPWM(int pin, uint32_t _min_ticks, uint32_t _max_ticks, uint32_t _pwm_freq) : STM32PWMInput(pin), max_ticks(_max_ticks), min_ticks(_min_ticks) {
1010

1111
};
1212

src/encoders/stm32pwmsensor/STM32MagneticSensorPWM.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
class STM32MagneticSensorPWM : public Sensor, public STM32PWMInput {
1515
public:
16-
STM32MagneticSensorPWM(int pin, uint32_t _min_ticks = 0, uint32_t _max_ticks = 0x0FFF);
16+
STM32MagneticSensorPWM(int pin, uint32_t _min_ticks = 0, uint32_t _max_ticks = 0x0FFF, uint32_t _pwm_freq = 1000);
1717
~STM32MagneticSensorPWM();
1818

1919
void init() override;

src/utilities/stm32pwm/STM32PWMInput.cpp

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11

22
#include "./STM32PWMInput.h"
3+
#include <SimpleFOC.h>
4+
#include "communication/SimpleFOCDebug.h"
35

46
#if defined(_STM32_DEF_)
57

68

79

8-
STM32PWMInput::STM32PWMInput(int pin){
10+
STM32PWMInput::STM32PWMInput(int pin, uint32_t pwm_freq){
911
_pin = digitalPinToPinName(pin);
12+
_pwm_freq = pwm_freq;
1013
};
1114

1215

@@ -20,9 +23,13 @@ int STM32PWMInput::initialize(){
2023
pinmap_pinout(_pin, PinMap_TIM);
2124
uint32_t channel = STM_PIN_CHANNEL(pinmap_function(_pin, PinMap_TIM));
2225
timer.Instance = (TIM_TypeDef *)pinmap_peripheral(_pin, PinMap_TIM);
23-
timer.Init.Prescaler = 0;
2426
timer.Init.CounterMode = TIM_COUNTERMODE_UP;
25-
timer.Init.Period = 4.294967295E9; // TODO max period, depends on which timer is used - 32 bits or 16 bits
27+
// Check if timer is 16 or 32 bit and set max period accordingly
28+
if (IS_TIM_32B_COUNTER_INSTANCE(timer.Instance)) {
29+
timer.Init.Period = 0xFFFFFFFF; // 32-bit timer max
30+
} else {
31+
timer.Init.Period = 0xFFFF; // 16-bit timer max
32+
}
2633
timer.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
2734
timer.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
2835
if (channel!=1 && channel!=2) // only channels 1 & 2 supported
@@ -76,6 +83,32 @@ int STM32PWMInput::initialize(){
7683
if (HAL_TIM_IC_Start(&timer, TIM_CHANNEL_2)!=HAL_OK) {
7784
return -9;
7885
}
86+
87+
// Check if the timer period is longer than the PWM period
88+
// if it isnt set the perescaler to make it longer
89+
// Calculate timer clock frequency
90+
uint32_t timer_clk = HAL_RCC_GetPCLK1Freq();
91+
if (IS_TIM_CLOCK_DIVISION_INSTANCE(timer.Instance)) {
92+
// If APB1 prescaler > 1, timer clock is doubled
93+
if ((RCC->CFGR & RCC_CFGR_PPRE1) != RCC_CFGR_PPRE1_DIV1) {
94+
timer_clk *= 2;
95+
}
96+
}
97+
98+
// Calculate required period (in timer ticks) for one PWM period
99+
uint32_t desired_period_ticks = timer_clk / _pwm_freq;
100+
101+
// Check if timer's max period can fit the desired period
102+
uint32_t max_period = (IS_TIM_32B_COUNTER_INSTANCE(timer.Instance)) ? 0xFFFFFFFF : 0xFFFF;
103+
uint32_t prescaler = 1;
104+
if (desired_period_ticks > max_period) {
105+
prescaler = (desired_period_ticks + max_period - 1) / max_period;
106+
if (prescaler > 0xFFFF) prescaler = 0xFFFF; // limit to 16-bit prescaler
107+
}
108+
109+
// Set the prescaler to achieve the desired period
110+
LL_TIM_SetPrescaler(timer.Instance, prescaler);
111+
79112
timer.Instance->CR1 |= TIM_CR1_CEN;
80113
return 0;
81114
};

src/utilities/stm32pwm/STM32PWMInput.h

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,48 @@
77

88
class STM32PWMInput {
99
public:
10-
STM32PWMInput(int pin);
10+
/**
11+
* StM32PWMInput constructor
12+
*
13+
* @param pin - the pin number to read the PWM signal from
14+
* @param pwm_freq - the frequency of the PWM signal (default is 1kHz)
15+
*
16+
* This class is used to read PWM signals from a pin using the STM32 HAL library.
17+
* IMPORTANT!
18+
* This class can only be used with the pins that are assocaited with some timer,
19+
* and only if they are associated to the channels 1 or 2. The timer can not be
20+
* used for other purposes, like motor control.
21+
*/
22+
STM32PWMInput(int pin, uint32_t pwm_freq = 1000);
1123
~STM32PWMInput();
1224

1325
int initialize();
1426

27+
/**
28+
* Get the duty cycle of the PWM signal as a percentage.
29+
*
30+
* @return float - the duty cycle in percent
31+
*/
1532
float getDutyCyclePercent();
33+
/**
34+
* Get the duty cycle of the PWM signal in ticks.
35+
*
36+
* @return uint32_t - the duty cycle in ticks
37+
*/
1638
uint32_t getDutyCycleTicks();
39+
/**
40+
* Get the period of the PWM signal in ticks.
41+
*
42+
* @return uint32_t - the period in ticks
43+
*/
1744
uint32_t getPeriodTicks();
1845

19-
PinName _pin;
46+
PinName _pin; // the pin to read the PWM signal from
47+
uint32_t _pwm_freq; // the frequency of the PWM signal
48+
2049
protected:
21-
TIM_HandleTypeDef timer;
22-
bool useChannel2 = false;
50+
TIM_HandleTypeDef timer; // the timer handle for the PWM input
51+
bool useChannel2 = false; // whether to use channel 2 or not, default is channel 1
2352
};
2453

2554

0 commit comments

Comments
 (0)