try to fix submodule
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
# SimpleFOC Driver for STM32 hardware encoder
|
||||
|
||||
This encoder driver uses the STM32 timer hardware to track the A/B impulses, which is much more efficient (and will support higher speeds) than the generic interrupt-based solution used by the standard encoder driver.
|
||||
|
||||
Big thank you to @conroy-cheers for originally contributing this code in pull request #114 to the simplefoc repository. Due its hardware-specific nature we moved the code to this drivers repository.
|
||||
|
||||
## Warning
|
||||
|
||||
This code has not been tested much! Use at your own risk, your milage may vary.
|
||||
I have tested on: STM32F401CC/TIM4-PB6,PB7
|
||||
|
||||
## Hardware setup
|
||||
|
||||
The ABI signals of your encoder will have to be connected to the STM32 MCU in such a way that all signals are connected to the same timer. Consult your STM32 chip's datasheet for more information on which pins connect to which timer.
|
||||
|
||||
Not all of the timers support the encoder mode, so check the datasheet which timers can be used.
|
||||
|
||||
An excellent option can be to use the STM32CubeIDE software's pin assignment view to quickly check which pins connect to which timer.
|
||||
|
||||
Note that the index (I) pin is currently not used.
|
||||
|
||||
|
||||
## Software setup
|
||||
|
||||
There is no need for interrupt functions or their configuration with this encoder class, so usage is quite simple:
|
||||
|
||||
```c++
|
||||
#include "Arduino.h"
|
||||
#include "Wire.h"
|
||||
#include "SPI.h"
|
||||
#include "SimpleFOC.h"
|
||||
#include "SimpleFOCDrivers.h"
|
||||
#include "encoders/stm32hwencoder/STM32HWEncoder.h"
|
||||
|
||||
|
||||
#define ENCODER_PPR 500
|
||||
#define ENCODER_PIN_A PB6
|
||||
#define ENCODER_PIN_B PB7
|
||||
#define ENCODER_PIN_I PC13
|
||||
|
||||
|
||||
STM32HWEncoder encoder = STM32HWEncoder(ENCODER_PPR, ENCODER_PIN_A, ENCODER_PIN_B, ENCODER_PIN_I);
|
||||
|
||||
|
||||
void setup() {
|
||||
encoder.init();
|
||||
}
|
||||
|
||||
```
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "STM32HWEncoder.h"
|
||||
|
||||
#if defined(_STM32_DEF_)
|
||||
|
||||
/*
|
||||
HardwareEncoder(int cpr)
|
||||
*/
|
||||
STM32HWEncoder::STM32HWEncoder(unsigned int _ppr, int8_t pinA, int8_t pinB, int8_t pinI) {
|
||||
cpr = _ppr * 4; // 4x for quadrature
|
||||
_pinA = digitalPinToPinName(pinA);
|
||||
_pinB = digitalPinToPinName(pinB);
|
||||
_pinI = digitalPinToPinName(pinI);
|
||||
}
|
||||
|
||||
/*
|
||||
Shaft angle calculation
|
||||
*/
|
||||
float STM32HWEncoder::getSensorAngle() {
|
||||
return _2PI * encoder_handle.Instance->CNT / static_cast<float>(cpr);
|
||||
}
|
||||
|
||||
// getter for index pin
|
||||
int STM32HWEncoder::needsSearch() { return false; }
|
||||
|
||||
// private function used to determine if encoder has index
|
||||
int STM32HWEncoder::hasIndex() { return 0; }
|
||||
|
||||
// encoder initialisation of the hardware pins
|
||||
void STM32HWEncoder::init() {
|
||||
// GPIO configuration
|
||||
TIM_TypeDef *InstanceA = (TIM_TypeDef *)pinmap_peripheral(_pinA, PinMap_TIM);
|
||||
TIM_TypeDef *InstanceB = (TIM_TypeDef *)pinmap_peripheral(_pinB, PinMap_TIM);
|
||||
if (InstanceA != InstanceB) {
|
||||
initialized = false;
|
||||
return;
|
||||
}
|
||||
pinmap_pinout(_pinA, PinMap_TIM);
|
||||
pinmap_pinout(_pinB, PinMap_TIM);
|
||||
|
||||
// set up timer for encoder
|
||||
encoder_handle.Init.Period = cpr - 1;
|
||||
encoder_handle.Init.Prescaler = 0;
|
||||
encoder_handle.Init.ClockDivision = 0;
|
||||
encoder_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
encoder_handle.Init.RepetitionCounter = 0;
|
||||
encoder_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||
|
||||
TIM_Encoder_InitTypeDef encoder_config;
|
||||
|
||||
encoder_config.EncoderMode = TIM_ENCODERMODE_TI12;
|
||||
|
||||
encoder_config.IC1Polarity = TIM_ICPOLARITY_RISING;
|
||||
encoder_config.IC1Selection = TIM_ICSELECTION_DIRECTTI;
|
||||
encoder_config.IC1Prescaler = TIM_ICPSC_DIV1;
|
||||
encoder_config.IC1Filter = 0;
|
||||
|
||||
encoder_config.IC2Polarity = TIM_ICPOLARITY_RISING;
|
||||
encoder_config.IC2Selection = TIM_ICSELECTION_DIRECTTI;
|
||||
encoder_config.IC2Prescaler = TIM_ICPSC_DIV1;
|
||||
encoder_config.IC2Filter = 0;
|
||||
|
||||
encoder_handle.Instance = InstanceA; // e.g. TIM4;
|
||||
enableTimerClock(&encoder_handle);
|
||||
|
||||
if (HAL_TIM_Encoder_Init(&encoder_handle, &encoder_config) != HAL_OK) {
|
||||
initialized = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (HAL_TIM_Encoder_Start(&encoder_handle, TIM_CHANNEL_1) != HAL_OK) {
|
||||
initialized = false;
|
||||
return;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
|
||||
#if defined(_STM32_DEF_)
|
||||
|
||||
#include <HardwareTimer.h>
|
||||
#include "common/base_classes/Sensor.h"
|
||||
#include "common/foc_utils.h"
|
||||
|
||||
class STM32HWEncoder : public Sensor {
|
||||
public:
|
||||
/**
|
||||
Encoder class constructor
|
||||
@param ppr impulses per rotation (cpr=ppr*4)
|
||||
*/
|
||||
explicit STM32HWEncoder(unsigned int ppr, int8_t pinA, int8_t pinB, int8_t pinI=-1);
|
||||
|
||||
void init() override;
|
||||
int needsSearch() override;
|
||||
int hasIndex(); // !< function returning 1 if encoder has index pin and 0 if not.
|
||||
|
||||
bool initialized = false;
|
||||
uint32_t cpr; //!< encoder cpr number
|
||||
PinName _pinA, _pinB, _pinI;
|
||||
|
||||
protected:
|
||||
float getSensorAngle() override;
|
||||
|
||||
TIM_HandleTypeDef encoder_handle;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user