Skip to content

Commit 1b4fe43

Browse files
committed
working on SSI sensors (not ready!)
1 parent aef01bf commit 1b4fe43

File tree

8 files changed

+402
-0
lines changed

8 files changed

+402
-0
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
2+
#include "AEAT8800Q24.h"
3+
4+
5+
AEAT8800Q24::AEAT8800Q24(int nCS, int pinNSL, SPISettings spiSettings, SPISettings ssiSettings) : nCS(nCS), pinNSL(pinNSL), spiSettings(spiSettings), ssiSettings(ssiSettings) {
6+
};
7+
AEAT8800Q24::~AEAT8800Q24(){
8+
};
9+
10+
void AEAT8800Q24::init(SPIClass* _spi){
11+
spi = _spi;
12+
spi->beginTransaction(ssiSettings);
13+
};
14+
15+
16+
float AEAT8800Q24::getCurrentAngle() {
17+
return ((float)readRawAngle())/(float)AEAT8800Q24_CPR * 2.0f * (float)PI;
18+
}; // angle in radians, return current value
19+
20+
21+
// reads angle via ssi
22+
uint16_t AEAT8800Q24::readRawAngle() {
23+
// digitalWrite(pinNSL, LOW); //TODO maybe we don't need it...
24+
// // 300ns delay
25+
// delayMicroseconds(1);
26+
uint16_t value = spi->transfer16(0x0000);
27+
uint8_t status = spi->transfer(0x00);
28+
//digitalWrite(pinNSL, HIGH);
29+
// // 200ns delay before next read...
30+
// delayMicroseconds(1);
31+
lastStatus.reg = status;
32+
return value;
33+
};
34+
35+
AEAT8800Q24_Status_t AEAT8800Q24::getLastStatus() {
36+
return lastStatus;
37+
}
38+
39+
uint16_t AEAT8800Q24::getZero(){
40+
uint8_t value = readRegister(AEAT8800Q24_REG_ZERO_MSB);
41+
return (value<<8)|readRegister(AEAT8800Q24_REG_ZERO_LSB);
42+
};
43+
void AEAT8800Q24::setZero(uint16_t value){
44+
writeRegister(AEAT8800Q24_REG_ZERO_MSB, (value>>8)&0xFF);
45+
writeRegister(AEAT8800Q24_REG_ZERO_LSB, value&0xFF);
46+
};
47+
48+
AEAT8800Q24_CONF0_t AEAT8800Q24::getConf0(){
49+
AEAT8800Q24_CONF0_t result;
50+
result.reg = readRegister(AEAT8800Q24_REG_CONF0);
51+
return result;
52+
};
53+
void AEAT8800Q24::setConf0(AEAT8800Q24_CONF0_t value){
54+
writeRegister(AEAT8800Q24_REG_CONF0, value.reg);
55+
};
56+
57+
AEAT8800Q24_CONF1_t AEAT8800Q24::getConf1(){
58+
AEAT8800Q24_CONF1_t result;
59+
result.reg = readRegister(AEAT8800Q24_REG_CONF1);
60+
return result;
61+
};
62+
void AEAT8800Q24::setConf1(AEAT8800Q24_CONF1_t value){
63+
writeRegister(AEAT8800Q24_REG_CONF1, value.reg);
64+
};
65+
66+
AEAT8800Q24_CONF2_t AEAT8800Q24::getConf2(){
67+
AEAT8800Q24_CONF2_t result;
68+
result.reg = readRegister(AEAT8800Q24_REG_CONF2);
69+
return result;
70+
};
71+
void AEAT8800Q24::setConf2(AEAT8800Q24_CONF2_t value){
72+
writeRegister(AEAT8800Q24_REG_CONF2, value.reg);
73+
};
74+
75+
76+
77+
78+
uint16_t AEAT8800Q24::transfer16SPI(uint16_t outValue) {
79+
// delay 1us between switching the CS line to SPI
80+
delayMicroseconds(1);
81+
if (nCS >= 0)
82+
digitalWrite(nCS, LOW);
83+
spi->endTransaction();
84+
spi->beginTransaction(spiSettings);
85+
uint16_t value = spi->transfer16(outValue);
86+
spi->endTransaction();
87+
if (nCS >= 0)
88+
digitalWrite(nCS, HIGH);
89+
// delay 1us between switching the CS line to SSI
90+
delayMicroseconds(1);
91+
spi->beginTransaction(ssiSettings);
92+
return value;
93+
};
94+
uint8_t AEAT8800Q24::readRegister(uint8_t reg) {
95+
uint16_t cmd = 0x8000 | ((reg&0x001F)<<8);
96+
uint16_t value = transfer16SPI(cmd);
97+
return value&0x00FF;
98+
};
99+
void AEAT8800Q24::writeRegister(uint8_t reg, uint8_t value) {
100+
uint16_t cmd = 0x4000 | ((reg&0x1F)<<8) | value;
101+
uint16_t result = transfer16SPI(cmd);
102+
};
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#ifndef __AEAT8800Q24_H__
2+
#define __AEAT8800Q24_H__
3+
4+
5+
#include "Arduino.h"
6+
#include "SPI.h"
7+
8+
#define AEAT8800Q24_CPR 65536
9+
10+
#define AEAT8800Q24_REG_CUST0 0x00
11+
#define AEAT8800Q24_REG_CUST1 0x01
12+
#define AEAT8800Q24_REG_ZERO_LSB 0x02
13+
#define AEAT8800Q24_REG_ZERO_MSB 0x03
14+
#define AEAT8800Q24_REG_CONF0 0x04
15+
#define AEAT8800Q24_REG_CONF1 0x05
16+
#define AEAT8800Q24_REG_CONF2 0x06
17+
#define AEAT8800Q24_REG_CONF_OTP 0x13
18+
#define AEAT8800Q24_REG_CAL_OTP 0x1B
19+
#define AEAT8800Q24_REG_CUST_OTP 0x11
20+
#define AEAT8800Q24_REG_CAL 0x17
21+
22+
#define AEAT8800Q24_CONF_OTP_ON 0xA3
23+
#define AEAT8800Q24_CAL_OTP_ON 0xA5
24+
#define AEAT8800Q24_CUST_OTP_ON 0xA1
25+
#define AEAT8800Q24_CAL_ON 0x02
26+
#define AEAT8800Q24_CAL_OFF 0x00
27+
28+
29+
typedef union {
30+
struct {
31+
uint8_t uvw_pwm_mode:1;
32+
uint8_t pwm:2;
33+
uint8_t iwidth:2;
34+
uint8_t uvw:3;
35+
};
36+
uint8_t reg;
37+
} AEAT8800Q24_CONF0_t;
38+
39+
40+
typedef union {
41+
struct {
42+
uint8_t cpr1:4;
43+
uint8_t hys:4;
44+
};
45+
uint8_t reg;
46+
} AEAT8800Q24_CONF1_t;
47+
48+
49+
typedef union {
50+
struct {
51+
uint8_t dir:1;
52+
uint8_t zero_latency:1;
53+
uint8_t abs_res:2;
54+
uint8_t cpr2:4;
55+
};
56+
uint8_t reg;
57+
} AEAT8800Q24_CONF2_t;
58+
59+
60+
61+
typedef union {
62+
struct {
63+
uint8_t mhi:1;
64+
uint8_t mlo:1;
65+
uint8_t ready:1;
66+
uint8_t parity:1;
67+
uint8_t :4;
68+
};
69+
uint8_t reg;
70+
} AEAT8800Q24_Status_t;
71+
72+
73+
#if defined(ESP32)
74+
#define AEAT8800Q24_BITORDER MSBFIRST
75+
#else
76+
#define AEAT8800Q24_BITORDER BitOrder::MSBFIRST
77+
#endif
78+
79+
static SPISettings AEAT8800Q24SPISettings(1000000, AEAT8800Q24_BITORDER, SPI_MODE3); // @suppress("Invalid arguments")
80+
static SPISettings AEAT8800Q24SSISettings(4000000, AEAT8800Q24_BITORDER, SPI_MODE2); // @suppress("Invalid arguments")
81+
82+
83+
class AEAT8800Q24 {
84+
public:
85+
AEAT8800Q24(int nCS, int pinNSL = MOSI, SPISettings spiSettings = AEAT8800Q24SPISettings, SPISettings ssiSettings = AEAT8800Q24SSISettings);
86+
virtual ~AEAT8800Q24();
87+
88+
virtual void init(SPIClass* _spi = &SPI);
89+
90+
float getCurrentAngle(); // angle in radians, return current value
91+
92+
uint16_t readRawAngle(); // 14bit angle value
93+
AEAT8800Q24_Status_t getLastStatus(); // get status associated with last angle read
94+
95+
uint16_t getZero();
96+
void setZero(uint16_t);
97+
98+
AEAT8800Q24_CONF0_t getConf0();
99+
void setConf0(AEAT8800Q24_CONF0_t);
100+
101+
AEAT8800Q24_CONF1_t getConf1();
102+
void setConf1(AEAT8800Q24_CONF1_t);
103+
104+
AEAT8800Q24_CONF2_t getConf2();
105+
void setConf2(AEAT8800Q24_CONF2_t);
106+
107+
private:
108+
int nCS = -1;
109+
int pinNSL = -1;
110+
SPISettings spiSettings;
111+
SPISettings ssiSettings;
112+
SPIClass* spi;
113+
AEAT8800Q24_Status_t lastStatus;
114+
115+
uint16_t transfer16SPI(uint16_t outValue);
116+
uint8_t readRegister(uint8_t reg);
117+
void writeRegister(uint8_t reg, uint8_t value);
118+
};
119+
120+
121+
#endif
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include "./MagneticSensorAEAT8800Q24.h"
2+
#include "common/foc_utils.h"
3+
#include "common/time_utils.h"
4+
5+
MagneticSensorAEAT8800Q24::MagneticSensorAEAT8800Q24(int nCS, int pinNSL, SPISettings spiSettings, SPISettings ssiSettings) : AEAT8800Q24(nCS, pinNSL, spiSettings, ssiSettings) {
6+
};
7+
8+
9+
MagneticSensorAEAT8800Q24::~MagneticSensorAEAT8800Q24(){
10+
};
11+
12+
13+
void MagneticSensorAEAT8800Q24::init(SPIClass* _spi) {
14+
this->AEAT8800Q24::init(_spi);
15+
this->Sensor::init();
16+
};
17+
18+
19+
float MagneticSensorAEAT8800Q24::getSensorAngle() {
20+
float angle_data = readRawAngle();
21+
angle_data = ( angle_data / (float)AEAT8800Q24_CPR) * _2PI;
22+
// return the shaft angle
23+
return angle_data;
24+
};
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef __MAGNETICSENSORAEAT8800Q24_H__
2+
#define __MAGNETICSENSORAEAT8800Q24_H__
3+
4+
5+
#include "common/base_classes/Sensor.h"
6+
#include "./AEAT8800Q24.h"
7+
8+
class MagneticSensorAEAT8800Q24 : public Sensor, public AEAT8800Q24 {
9+
public:
10+
MagneticSensorAEAT8800Q24(int nCS, int pinNSL = MOSI, SPISettings spiSettings = AEAT8800Q24SPISettings, SPISettings ssiSettings = AEAT8800Q24SSISettings);
11+
virtual ~MagneticSensorAEAT8800Q24();
12+
13+
virtual float getSensorAngle() override;
14+
15+
virtual void init(SPIClass* _spi = &SPI);
16+
};
17+
18+
#endif

src/encoders/aeat8800q24/README.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# AEAT-8800-Q24 SimpleFOC driver
2+
3+
SPI/SSI driver for the absolute position magnetic rotary encoder. This encoder is not supported by the
4+
normal SimpleFOC drivers due to its mixed SPI/SSI mode.
5+
6+
- access to the configuration registers of the AEAT-8800-Q24, enabling you to set parameters
7+
- angles are read via SSI, with 16 bit (!) precision
8+
- currently only 16 bit resolution is supported, don't lower the resolution
9+
10+
11+
## Hardware setup
12+
13+
Connect as per normal for your SPI bus. No special hardware setup is needed to use this driver. nCS pin is
14+
required.
15+
16+
Note that due to the way SSI and SPI share pins, you can normally only run one of these sensors per SPI bus.
17+
18+
## Software setup
19+
20+
Its actually easier to use than the standard SPI sensor class, because it is less generic:
21+
22+
```c++
23+
#include "Arduino.h"
24+
#include "Wire.h"
25+
#include "SPI.h"
26+
#include "SimpleFOC.h"
27+
#include "SimpleFOCDrivers.h"
28+
#include "encoders/aeat8800q24/MagneticSensorAEAT8800Q24.h"
29+
30+
#define SENSOR1_CS 5 // some digital pin that you're using as the nCS pin
31+
MagneticSensorAEAT8800Q24 sensor1(SENSOR1_CS);
32+
33+
34+
void setup() {
35+
sensor1.init();
36+
}
37+
```
38+
39+
Set some options:
40+
41+
```c++
42+
MagneticSensorAEAT8800Q24 sensor1(SENSOR1_CS, MOSI_pin, mySPISettings, mySSISettings);
43+
```
44+
45+
Use another SPI bus:
46+
47+
```c++
48+
void setup() {
49+
sensor1.init(SPI2);
50+
}
51+
```
52+
53+
Here's how you can use it:
54+
55+
```c++
56+
// get the angle, in radians, including full rotations
57+
float a1 = sensor1.getAngle();
58+
59+
// get the velocity, in rad/s - note: you have to call getAngle() on a regular basis for it to work
60+
float v1 = sensor1.getVelocity();
61+
62+
// get the angle, in radians, no full rotations
63+
float a2 = sensor1.getCurrentAngle();
64+
65+
// get the raw 16 bit value
66+
uint16_t raw = sensor1.readRawAngle();
67+
68+
// check status
69+
float angle = sensor1.getSensorAngle();
70+
AEAT8800Q24_Status_t status = sensor1.getLastStatus();
71+
if (status.mlo)
72+
Serial.println("Sensor magnet low error");
73+
if (status.mhi)
74+
Serial.println("Sensor magnet high error");
75+
```

src/encoders/ma730/MA730.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ enum FieldStrength {
3232
#endif
3333

3434
static SPISettings MA730SPISettings(8000000, MA730_BITORDER, SPI_MODE3); // @suppress("Invalid arguments")
35+
static SPISettings MA730SSISettings(8000000, MA730_BITORDER, SPI_MODE1); // @suppress("Invalid arguments")
3536

3637

3738
class MA730 {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include "./MagneticSensorMA730SSI.h"
2+
#include "common/foc_utils.h"
3+
#include "common/time_utils.h"
4+
5+
MagneticSensorMA730SSI::MagneticSensorMA730SSI(SPISettings settings) : settings(settings) {
6+
7+
}
8+
9+
10+
MagneticSensorMA730SSI::~MagneticSensorMA730SSI(){
11+
12+
}
13+
14+
15+
void MagneticSensorMA730SSI::init(SPIClass* _spi) {
16+
this->spi=_spi;
17+
this->Sensor::init();
18+
}
19+
20+
// check 40us delay between each read?
21+
float MagneticSensorMA730SSI::getSensorAngle() {
22+
float angle_data = readRawAngle();
23+
angle_data = ( angle_data / (float)MA730_CPR) * _2PI;
24+
// return the shaft angle
25+
return angle_data;
26+
}
27+
28+
29+
30+
uint16_t MagneticSensorMA730SSI::readRawAngle() {
31+
spi->beginTransaction(settings);
32+
uint16_t value = spi->transfer16(0x0000);
33+
uint8_t parity = spi->transfer(0x00);
34+
// TODO: check parity
35+
spi->endTransaction();
36+
return value>>2;
37+
}; // 14bit angle value

0 commit comments

Comments
 (0)