Skip to content

Commit

Permalink
Merge pull request #22 from simplefoc/dev
Browse files Browse the repository at this point in the history
1.0.4 release PR
  • Loading branch information
runger1101001 authored Jun 2, 2023
2 parents e379709 + 4ce521f commit 72c1a9e
Show file tree
Hide file tree
Showing 21 changed files with 783 additions and 234 deletions.
34 changes: 24 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,14 @@ The intent is to keep the core of SimpleFOC clean, and thus easy to maintain, un

## New Release

v1.0.3 - Released March 2023, for Simple FOC 2.3.0

What's changed since 1.0.2?
- New Sensor: MT6835
- Fixed bugs

What's changed since 1.0.1?
- Calibrated sensor by @MarethyuPrefect
- New Sensors: MT6701, MA330, MT6816
- Fixed bugs
v1.0.4 - Released June 2023, for Simple FOC 2.3.0

What's changed since 1.0.3?
- New Comms/Input: STM32SpeedDirCommander
- New Utility: STM32PWMInput
- Fixed MT6835 driver bugs
- Improved AS5047 driver, fixed bugs
- Improved AS5047U driver, fixed bugs

## What is included

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

### Communications

- [I2CCommander I2C driver](src/comms/i2c/) - I2C communications protocol and drivers for both controller and target devices.
- [STM32 SpeedDir Input](src/comms/stm32speeddir/) - Control target velocity with PWM speed and direction inputs

### Utilities

- [STM32 PWM Input driver](src/utilities/stm32pwm/) - PWM Input driver for STM32 MCUs. Accurately measure PWM inputs with zero MCU overhead.


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

Find out more information about the Arduino SimpleFOC project on the [docs website](https://docs.simplefoc.com/)

## Release History

What's changed since 1.0.2?
- New Sensor: MT6835
- Fixed bugs

What's changed since 1.0.1?
- Calibrated sensor by @MarethyuPrefect
- New Sensors: MT6701, MA330, MT6816
- Fixed bugs
4 changes: 3 additions & 1 deletion keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ AS5048A KEYWORD1
AS5047 KEYWORD1
AS5145 KEYWORD1
MA730 KEYWORD1
MT6835 KEYWORD1
SC60228 KEYWORD1
TLE5012B KEYWORD1
I2CCommander KEYWORD1

STM32HWEncoder KEYWORD1
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=SimpleFOCDrivers
version=1.0.3
version=1.0.4
author=Simplefoc <info@simplefoc.com>
maintainer=Simplefoc <info@simplefoc.com>
sentence=A library of supporting drivers for SimpleFOC. Motor drivers chips, encoder chips, current sensing and supporting code.
Expand Down
58 changes: 58 additions & 0 deletions src/comms/stm32speeddir/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@

# STM32SpeedDirInput

Control SimpleFOC using PWM speed and direction inputs.

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.



## Setup

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:
- Advanced control timers: TIM1, TIM8
- General purpose timers (32 bit): TIM2, TIM5
- General purpose timers (16 bit): TIM3, TIM4, TIM9, TIM12
If in doubt, check in STM32CubeIDE and see if the PWM-Input mode can be enabled (under "Combined Channels") for the timer.

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`

The direction input is optional - if not provided, you can control the direction from software using the `direction` field.

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.

## Usage

Use it like this:

```c++
#include "comms/stm32speeddir/STM32SpeedDirInput.h"

// some example pins - the speed pin has to be on channel 1 or 2 of a timer
#define PIN_SPEED PC6
#define PIN_DIRECTION PB8

STM32SpeedDirInput speed_dir = STM32SpeedDirInput(PIN_SPEED, PIN_DIRECTION);

float target = 0.0f;

void setup(){
...

speed_dir.min_speed = 10.0f; // 10rad/s min speed
speed_dir.max_speed = 100.0f; // 100rad/s max speed
speed_dir.min_pwm = 5.0f; // 5% min duty cycle
speed_dir.max_pwm = 95.0f; // 95% max duty cycle
speed_dir.init();

...
}


void loop(){
target = speed_dir.getTargetVelocity();
motor.move(target);
motor.loopFOC();
}

```
29 changes: 29 additions & 0 deletions src/comms/stm32speeddir/STM32SpeedDirInput.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

#include "./STM32SpeedDirInput.h"

#if defined(_STM32_DEF_)

STM32SpeedDirInput::STM32SpeedDirInput(int pin_speed, int pin_dir) : STM32PWMInput(pin_speed) {
_pin_speed = pin_speed;
_pin_dir = pin_dir;
};

STM32SpeedDirInput::~STM32SpeedDirInput(){};

int STM32SpeedDirInput::init(){
pinMode(_pin_dir, INPUT);
return STM32PWMInput::initialize();
};


float STM32SpeedDirInput::getTargetVelocity(){
if (_pin_dir != NOT_SET)
direction = digitalRead(_pin_dir);
float speed = getDutyCyclePercent();
speed = constrain(speed, min_pwm, max_pwm);
speed = (speed - min_pwm)/(max_pwm - min_pwm) * (max_speed - min_speed) + min_speed;
return (direction == dir_positive_high) ? speed : -speed;
};


#endif
31 changes: 31 additions & 0 deletions src/comms/stm32speeddir/STM32SpeedDirInput.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

#pragma once

#include "Arduino.h"

#if defined(_STM32_DEF_)

#include "common/foc_utils.h"
#include "utilities/stm32pwm/STM32PWMInput.h"

class STM32SpeedDirInput : public STM32PWMInput {
public:
STM32SpeedDirInput(int pin_speed, int pin_dir = NOT_SET);
~STM32SpeedDirInput();

int init();
float getTargetVelocity();

float min_speed = 0; // min speed in rad/s
float max_speed = 100; // max speed in rad/s
float min_pwm = 5.0; // min duty cycle in %
float max_pwm = 95.0; // max duty cycle in %
bool dir_positive_high = true; // true if the direction pin is high when the motor is spinning in the positive direction
bool direction = true; // direction of rotation, default positive
protected:
int _pin_speed;
int _pin_dir;
};


#endif
106 changes: 100 additions & 6 deletions src/encoders/as5047/AS5047.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,21 +85,29 @@ AS5047Settings1 AS5047::readSettings1(){

void AS5047::writeSettings1(AS5047Settings1 settings){
uint16_t command = AS5047_SETTINGS1_REG; // set r=0, result is 0x0018
/*uint16_t cmdresult =*/ spi_transfer16(command);
/*cmdresult =*/ spi_transfer16(settings.reg);
spi_transfer16(command);
spi_transfer16(calcParity(settings.reg));
}


AS5047Settings2 AS5047::readSettings2(){
uint16_t command = AS5047_SETTINGS2_REG | AS5047_RW; // set r=1, result is 0x4019
/*uint16_t cmdresult =*/ spi_transfer16(command);
spi_transfer16(command);
AS5047Settings2 result = {
.reg = nop()
};
return result;
}


void AS5047::writeSettings2(AS5047Settings2 settings){
uint16_t command = AS5047_SETTINGS2_REG | AS5047_PARITY; // set r=0, result is 0x8019
spi_transfer16(command);
spi_transfer16(calcParity(settings.reg));
}



AS5047Diagnostics AS5047::readDiagnostics(){
uint16_t command = AS5047_DIAGNOSTICS_REG | AS5047_PARITY | AS5047_RW; // set r=1, result is 0xFFFC
/*uint16_t cmdresult =*/ spi_transfer16(command);
Expand All @@ -112,21 +120,96 @@ AS5047Diagnostics AS5047::readDiagnostics(){

void AS5047::enablePWM(bool enable){
AS5047Settings1 settings = readSettings1();
if (settings.pwmon == enable) return; // no change
settings.pwmon = enable;
writeSettings1(settings);
}

void AS5047::enableABI(bool enable){
AS5047Settings1 settings = readSettings1();
settings.uvw_abi = enable?0:1;
uint8_t val = enable?0:1;
if (settings.uvw_abi == val) return; // no change
settings.uvw_abi = val;
writeSettings1(settings);
}


void AS5047::enableDEAC(bool enable){
AS5047Settings1 settings = readSettings1();
uint8_t val = enable?0:1;
if (settings.daecdis == val) return; // no change
settings.daecdis = enable?0:1;
writeSettings1(settings);
}


void AS5047::useCorrectedAngle(bool useCorrected){
AS5047Settings1 settings = readSettings1();
uint8_t val = useCorrected?0:1;
if (settings.dataselect == val) return; // no change
settings.dataselect = val;
writeSettings1(settings);
}



void AS5047::setHysteresis(uint8_t hyst){
if (hyst>3) hyst = 3;
uint8_t val = 3-hyst;
AS5047Settings2 settings = readSettings2();
if (settings.hys == val) return; // no change
settings.hys = val;
writeSettings2(settings);
}




void AS5047::setABIResolution(AS5047ABIRes res){
AS5047Settings1 settings = readSettings1();
uint8_t val = (res>>3)&0x01;
if (settings.abibin!=val || settings.uvw_abi!=0) {
settings.abibin = val;
settings.uvw_abi = 0;
writeSettings1(settings);
}
AS5047Settings2 settings2 = readSettings2();
val = (res&0x07);
if (settings2.abires!=val) {
settings2.abires = val;
writeSettings2(settings2);
}
}



uint16_t AS5047::setZero(uint16_t value){
// TODO implement me!
return 0;
uint16_t command = AS5047_ZPOSL_REG | AS5047_PARITY | AS5047_RW;
spi_transfer16(command);
AS5047ZPosL posL = {
.reg = nop()
};
command = AS5047_ZPOSM_REG | AS5047_PARITY;
spi_transfer16(command);
spi_transfer16(calcParity((value>>6)&0x00FF));
command = AS5047_ZPOSL_REG;
posL.zposl = value&0x003F;
spi_transfer16(command);
spi_transfer16(calcParity(posL.reg));

return getZero();
}


uint16_t AS5047::getZero() {
uint16_t command = AS5047_ZPOSM_REG | AS5047_RW;
spi_transfer16(command);
command = AS5047_ZPOSL_REG | AS5047_PARITY | AS5047_RW;
uint16_t result = spi_transfer16(command);
AS5047ZPosL posL = {
.reg = nop()
};
return ((result&0x00FF)<<6) | posL.zposl;
}


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


uint16_t AS5047::calcParity(uint16_t data){
data = data & 0x7FFF;
int sum = 0;
for (int i=0;i<15;i++)
if ((data>>i)&0x0001)
sum++;
return (sum&0x01)==0x01?(data|0x8000):data;
}


uint16_t AS5047::spi_transfer16(uint16_t outdata) {
if (nCS>=0)
digitalWrite(nCS, 0);
Expand Down
Loading

0 comments on commit 72c1a9e

Please sign in to comment.