Skip to content

Commit 8dd7fbc

Browse files
author
Richard Unger
committed
Merge branch 'dev' of github.com:simplefoc/Arduino-FOC-drivers into dev
2 parents 427933e + 9ca9040 commit 8dd7fbc

File tree

6 files changed

+246
-0
lines changed

6 files changed

+246
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ What's here? See the sections below. Each driver or function should come with it
2828
- [STM32 Hardware Encoder](src/encoders/stm32hwencoder/) - Hardware timer based encoder driver for ABI type quadrature encoders.
2929
- [SC60228 SPI driver](src/encoders/sc60228/) - SPI driver for SemiMent SC60288 magnetic encoder IC.
3030
- [MA330 SPI driver](src/encoders/ma330/) - SPI driver for the MPS MagAlpha MA330 absolute position magnetic rotary encoder IC.
31+
- [MT6816 SPI driver](src/encoders/mt6816/) - SPI driver for the MagnTek MT6816 absolute position magnetic rotary encoder IC.
3132

3233
### Communications
3334

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/**
2+
* Comprehensive BLDC motor control example using magnetic sensor MT6816
3+
*
4+
* Using serial terminal user can send motor commands and configure the motor and FOC in real-time:
5+
* - configure PID controller constants
6+
* - change motion control loops
7+
* - monitor motor variabels
8+
* - set target values
9+
* - check all the configuration values
10+
*
11+
* See more info in docs.simplefoc.com/commander_interface
12+
*/
13+
#include <SimpleFOC.h>
14+
#include <SimpleFOCDrivers.h>
15+
#include <encoders/mt6816/MagneticSensorMT6816.h>
16+
17+
// magnetic sensor instance - MT6816 SPI mode
18+
MagneticSensorMT6816 sensor = MagneticSensorMT6816(5);
19+
20+
21+
// BLDC motor & driver instance
22+
BLDCMotor motor = BLDCMotor(7);
23+
BLDCDriver3PWM driver = BLDCDriver3PWM(32, 25, 26, 33);
24+
25+
// Inline Current Sense instance
26+
InlineCurrentSense current_sense = InlineCurrentSense(0.01, 50.0, 35, 34);
27+
28+
// commander interface
29+
Commander command = Commander(Serial);
30+
void onMotor(char* cmd){ command.motor(&motor, cmd); }
31+
32+
void setup() {
33+
34+
// initialise magnetic sensor hardware
35+
sensor.init();
36+
// link the motor to the sensor
37+
motor.linkSensor(&sensor);
38+
39+
// driver config
40+
// power supply voltage [V]
41+
driver.voltage_power_supply = 12;
42+
driver.init();
43+
// link driver
44+
motor.linkDriver(&driver);
45+
46+
// choose FOC modulation
47+
motor.foc_modulation = FOCModulationType::SpaceVectorPWM;
48+
49+
// set control loop type to be used
50+
motor.controller = MotionControlType::torque;
51+
52+
// contoller configuration based on the control type
53+
motor.PID_velocity.P = 0.2f;
54+
motor.PID_velocity.I = 20;
55+
motor.PID_velocity.D = 0;
56+
// default voltage_power_supply
57+
motor.voltage_limit = 12;
58+
59+
// velocity low pass filtering time constant
60+
motor.LPF_velocity.Tf = 0.01f;
61+
62+
// angle loop velocity limit
63+
motor.velocity_limit = 50;
64+
65+
// use monitoring with serial for motor init
66+
// monitoring port
67+
Serial.begin(115200);
68+
// comment out if not needed
69+
motor.useMonitoring(Serial);
70+
71+
current_sense.linkDriver(&driver);
72+
current_sense.init();
73+
current_sense.gain_b *= -1;
74+
current_sense.skip_align = true;
75+
motor.linkCurrentSense(&current_sense);
76+
77+
// initialise motor
78+
motor.init();
79+
// align encoder and start FOC
80+
motor.initFOC();
81+
82+
// set the inital target value
83+
motor.target = 2;
84+
85+
// define the motor id
86+
command.add('A', onMotor, "motor");
87+
88+
// Run user commands to configure and the motor (find the full command list in docs.simplefoc.com)
89+
Serial.println(F("Motor commands sketch | Initial motion control > torque/voltage : target 2V."));
90+
91+
_delay(1000);
92+
}
93+
94+
95+
void loop() {
96+
// iterative setting FOC phase voltage
97+
motor.loopFOC();
98+
99+
// iterative function setting the outter loop target
100+
// velocity, position or voltage
101+
// if tatget not set in parameter uses motor.target variable
102+
motor.move();
103+
104+
// user communication
105+
command.run();
106+
}

src/encoders/mt6816/MT6816.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
2+
#include "MT6816.h"
3+
4+
MT6816::MT6816(SPISettings settings, int nCS) : settings(settings), nCS(nCS) {
5+
};
6+
7+
MT6816::~MT6816() {
8+
};
9+
10+
void MT6816::init(SPIClass* _spi) {
11+
spi = _spi;
12+
if (nCS >= 0) {
13+
pinMode(nCS, OUTPUT);
14+
digitalWrite(nCS, HIGH);
15+
spi->begin();
16+
}
17+
};
18+
19+
uint16_t MT6816::readRawAngle() {
20+
uint16_t angle_data = 0;
21+
angle_data = spi_transfer16(MT6816_READ_REG_03) << 8;
22+
angle_data |= spi_transfer16(MT6816_READ_REG_04);
23+
24+
if ((angle_data & MT6816_NO_MAGNET_WARNING_BIT) == MT6816_NO_MAGNET_WARNING_BIT) {
25+
this->no_magnetic_reading = true;
26+
} else {
27+
this->no_magnetic_reading = false;
28+
}
29+
30+
if (!this->parityCheck(angle_data)) {
31+
return 0;
32+
}
33+
34+
return (angle_data >> 2);
35+
}
36+
37+
bool MT6816::parityCheck(uint16_t data) {
38+
data ^= data >> 8;
39+
data ^= data >> 4;
40+
data ^= data >> 2;
41+
data ^= data >> 1;
42+
43+
return (~data) & 1;
44+
}
45+
46+
uint16_t MT6816::spi_transfer16(uint16_t outdata) {
47+
if (nCS>=0)
48+
digitalWrite(nCS, 0);
49+
spi->beginTransaction(settings);
50+
uint16_t result = spi->transfer16(outdata);
51+
spi->endTransaction();
52+
if (nCS>=0)
53+
digitalWrite(nCS, 1);
54+
55+
return result;
56+
}

src/encoders/mt6816/MT6816.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
2+
#ifndef MT6816_H
3+
#define MT6816_H
4+
5+
#include "Arduino.h"
6+
#include "SPI.h"
7+
8+
#define _2PI 6.28318530718f
9+
#define MT6816_CPR 16384.0f
10+
11+
#define MT6816_READ_REG_03 0x8300
12+
#define MT6816_READ_REG_04 0x8400
13+
14+
#define MT6816_NO_MAGNET_WARNING_BIT 0x0002
15+
#define MT6816_BITORDER MSBFIRST
16+
17+
18+
static SPISettings MT6816SPISettings(1000000, MT6816_BITORDER, SPI_MODE3);
19+
20+
class MT6816 {
21+
public:
22+
MT6816(SPISettings settings = MT6816SPISettings, int nCS = -1);
23+
virtual ~MT6816();
24+
25+
virtual void init(SPIClass* _spi = &SPI);
26+
uint16_t readRawAngle();
27+
bool isNoMagneticReading() {
28+
return no_magnetic_reading;
29+
}
30+
31+
private:
32+
bool parityCheck(uint16_t data);
33+
uint16_t spi_transfer16(uint16_t outdata);
34+
SPIClass* spi;
35+
SPISettings settings;
36+
bool no_magnetic_reading = false;
37+
int nCS = -1;
38+
};
39+
40+
#endif /* MT6816_H */
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
#include "common/foc_utils.h"
3+
#include "common/time_utils.h"
4+
#include "MagneticSensorMT6816.h"
5+
6+
7+
MagneticSensorMT6816::MagneticSensorMT6816(int nCS, SPISettings settings) : MT6816(settings, nCS) {
8+
}
9+
10+
MagneticSensorMT6816::~MagneticSensorMT6816(){
11+
}
12+
13+
void MagneticSensorMT6816::init(SPIClass* _spi) {
14+
this->MT6816::init(_spi);
15+
this->Sensor::init();
16+
}
17+
18+
float MagneticSensorMT6816::getSensorAngle() {
19+
uint16_t raw_angle_data = readRawAngle();
20+
21+
if (this->MT6816::isNoMagneticReading()) {
22+
return 0;
23+
}
24+
25+
return static_cast<float>(raw_angle_data) / MT6816_CPR * _2PI;
26+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
#ifndef MAGNETICSENSOR_MT6816_H
3+
#define MAGNETICSENSOR_MT6816_H
4+
5+
#include "common/base_classes/Sensor.h"
6+
#include "MT6816.h"
7+
8+
class MagneticSensorMT6816 : public Sensor, public MT6816 {
9+
public:
10+
MagneticSensorMT6816(int nCS = -1, SPISettings settings = MT6816SPISettings);
11+
virtual ~MagneticSensorMT6816();
12+
13+
virtual float getSensorAngle() override;
14+
virtual void init(SPIClass* _spi = &SPI);
15+
};
16+
17+
#endif /* MAGNETICSENSOR_MT6816_H */

0 commit comments

Comments
 (0)