Skip to content

Commit b0c5275

Browse files
authored
Merge pull request #20 from owennewo/magnetic_sensor_ma730
Magnetic sensor refactoring and ma70 support
2 parents a19e812 + eae25dd commit b0c5275

File tree

6 files changed

+164
-29
lines changed

6 files changed

+164
-29
lines changed

src/Hardware.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#ifndef HARDWARE_H
2+
#define HARDWARE_H
3+
4+
5+
#include "MagneticSensorSPI.h"
6+
7+
/** Typical configuration for the 14bit AMS AS5147 magnetic sensor over SPI interface */
8+
MagneticSensorSPIConfig_s AS5147_SPI = {
9+
.spi_mode = SPI_MODE1,
10+
.clock_speed = 1000000,
11+
.bit_resolution = 14,
12+
.angle_register = 0xCFFF,
13+
.data_start_bit = 13,
14+
.command_rw_bit = 14,
15+
.command_parity_bit = 15
16+
};
17+
18+
/** Typical configuration for the 14bit MonolithicPower MA730 magnetic sensor over SPI interface */
19+
MagneticSensorSPIConfig_s MA730_SPI = {
20+
.spi_mode = SPI_MODE0,
21+
.clock_speed = 1000000,
22+
.bit_resolution = 14,
23+
.angle_register = 0x0000,
24+
.data_start_bit = 15,
25+
.command_rw_bit = 0, // not required
26+
.command_parity_bit = 0 // parity not implemented
27+
};
28+
29+
/** Typical configuration for the 12bit AMS AS5600 magnetic sensor over I2C interface */
30+
MagneticSensorI2CConfig_s AS5600_I2C = {
31+
.chip_address = 0x36,
32+
.clock_speed = 1000000,
33+
.bit_resolution = 12,
34+
.angle_register = 0x0E,
35+
.data_start_bit = 11
36+
};
37+
38+
/** Typical configuration for the 12bit AMS AS5048 magnetic sensor over I2C interface */
39+
MagneticSensorI2CConfig_s AS5048_I2C = {
40+
.chip_address = 0x40, // highly configurable. if A1 and A2 are held low, this is probable value
41+
.clock_speed = 1000000,
42+
.bit_resolution = 14,
43+
.angle_register = 0xFE,
44+
.data_start_bit = 15
45+
};
46+
47+
#endif

src/MagneticSensorI2C.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,35 @@ MagneticSensorI2C::MagneticSensorI2C(uint8_t _chip_address, int _bit_resolution,
2222
// extraction masks
2323
lsb_mask = (uint8_t)( (2 << lsb_used) - 1 );
2424
msb_mask = (uint8_t)( (2 << _bits_used_msb) - 1 );
25+
clock_speed = 400000;
26+
sda_pin = SDA;
27+
scl_pin = SCL;
28+
2529
}
2630

31+
MagneticSensorI2C::MagneticSensorI2C(MagneticSensorI2CConfig_s config){
32+
chip_address = config.chip_address;
33+
34+
// angle read register of the magnetic sensor
35+
angle_register_msb = config.angle_register;
36+
// register maximum value (counts per revolution)
37+
cpr = pow(2, config.bit_resolution);
38+
39+
int bits_used_msb = config.data_start_bit - 7;
40+
lsb_used = config.bit_resolution - bits_used_msb;
41+
// extraction masks
42+
lsb_mask = (uint8_t)( (2 << lsb_used) - 1 );
43+
msb_mask = (uint8_t)( (2 << bits_used_msb) - 1 );
44+
clock_speed = 400000;
45+
sda_pin = SDA;
46+
scl_pin = SCL;
47+
48+
}
2749

2850
void MagneticSensorI2C::init(){
2951

3052
//I2C communication begin
31-
Wire.begin();
53+
Wire.begin(sda_pin, scl_pin, clock_speed);
3254

3355
// velocity calculation init
3456
angle_prev = 0;

src/MagneticSensorI2C.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66
#include "FOCutils.h"
77
#include "Sensor.h"
88

9+
struct MagneticSensorI2CConfig_s {
10+
int chip_address;
11+
long clock_speed;
12+
int bit_resolution;
13+
int angle_register;
14+
int data_start_bit;
15+
};
916

1017
class MagneticSensorI2C: public Sensor{
1118
public:
@@ -17,8 +24,15 @@ class MagneticSensorI2C: public Sensor{
1724
* @param _bits_used_msb number of used bits in msb
1825
*/
1926
MagneticSensorI2C(uint8_t _chip_address, int _bit_resolution, uint8_t _angle_register_msb, int _msb_bits_used);
20-
2127

28+
/**
29+
* MagneticSensorI2C class constructor
30+
* @param config I2C config
31+
*/
32+
MagneticSensorI2C(MagneticSensorI2CConfig_s config);
33+
34+
static MagneticSensorI2C AS5600();
35+
2236
/** sensor initialise pins */
2337
void init();
2438

@@ -40,8 +54,17 @@ class MagneticSensorI2C: public Sensor{
4054
/** returns 1 because it is the absolute sensor */
4155
int hasAbsoluteZero() override;
4256
/** returns 0 maning it doesn't need search for absolute zero */
57+
4358
int needsAbsoluteZeroSearch() override;
59+
60+
/* the speed of the i2c clock signal */
61+
long clock_speed;
62+
63+
/* the pin used for i2c data */
64+
int sda_pin;
4465

66+
/* the pin used for i2c clock */
67+
int scl_pin;
4568

4669
private:
4770
float cpr; //!< Maximum range of the magnetic sensor

src/MagneticSensorSPI.cpp

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,49 @@
55
// _bit_resolution sensor resolution bit number
66
// _angle_register - (optional) angle read register - default 0x3FFF
77
MagneticSensorSPI::MagneticSensorSPI(int cs, float _bit_resolution, int _angle_register){
8-
// chip select pin
8+
99
chip_select_pin = cs;
1010
// angle read register of the magnetic sensor
1111
angle_register = _angle_register ? _angle_register : DEF_ANGLE_REGISTAR;
1212
// register maximum value (counts per revolution)
1313
cpr = pow(2,_bit_resolution);
14-
14+
spi_mode = SPI_MODE1;
15+
clock_speed = 1000000;
16+
bit_resolution = _bit_resolution;
17+
18+
command_parity_bit = 15; // for backwards compatibilty
19+
command_rw_bit = 14; // for backwards compatibilty
20+
data_start_bit = 13; // for backwards compatibilty
21+
1522
}
1623

24+
MagneticSensorSPI::MagneticSensorSPI(MagneticSensorSPIConfig_s config, int cs){
25+
chip_select_pin = cs;
26+
// angle read register of the magnetic sensor
27+
angle_register = config.angle_register ? config.angle_register : DEF_ANGLE_REGISTAR;
28+
// register maximum value (counts per revolution)
29+
cpr = pow(2, config.bit_resolution);
30+
spi_mode = config.spi_mode;
31+
clock_speed = config.clock_speed;
32+
bit_resolution = config.bit_resolution;
33+
34+
command_parity_bit = config.command_parity_bit; // for backwards compatibilty
35+
command_rw_bit = config.command_rw_bit; // for backwards compatibilty
36+
data_start_bit = config.data_start_bit; // for backwards compatibilty
37+
}
1738

1839
void MagneticSensorSPI::init(){
1940
// 1MHz clock (AMS should be able to accept up to 10MHz)
20-
settings = SPISettings(1000000, MSBFIRST, SPI_MODE1);
41+
settings = SPISettings(clock_speed, MSBFIRST, spi_mode);
2142

2243
//setup pins
2344
pinMode(chip_select_pin, OUTPUT);
24-
2545

2646
//SPI has an internal SPI-device counter, it is possible to call "begin()" from different devices
2747
SPI.begin();
2848
#ifndef ESP_H // if not ESP32 board
2949
SPI.setBitOrder(MSBFIRST); // Set the SPI_1 bit order
30-
SPI.setDataMode(SPI_MODE1) ;
50+
SPI.setDataMode(spi_mode) ;
3151
SPI.setClockDivider(SPI_CLOCK_DIV8);
3252
#endif
3353

@@ -77,7 +97,7 @@ float MagneticSensorSPI::getVelocity(){
7797
float angle_c = getAngle();
7898
// velocity calculation
7999
float vel = (angle_c - angle_prev)/Ts;
80-
100+
81101
// save variables for future pass
82102
angle_prev = angle_c;
83103
velocity_calc_timestamp = now_us;
@@ -147,35 +167,28 @@ byte MagneticSensorSPI::spiCalcEvenParity(word value){
147167
* Returns the value of the register
148168
*/
149169
word MagneticSensorSPI::read(word angle_register){
150-
word command = 0b0100000000000000; // PAR=0 R/W=R
151-
command = command | angle_register;
152-
153-
//Add a parity bit on the the MSB
154-
command |= ((word)spiCalcEvenParity(command)<<15);
155170

156-
//Split the command into two bytes
157-
byte right_byte = command & 0xFF;
158-
byte left_byte = ( command >> 8 ) & 0xFF;
171+
word command = angle_register;
159172

173+
if (command_rw_bit > 0) {
174+
command = angle_register | (1 << command_rw_bit);
175+
}
176+
if (command_parity_bit > 0) {
177+
//Add a parity bit on the the MSB
178+
command |= ((word)spiCalcEvenParity(command) << command_parity_bit);
179+
}
160180

161181
#if !defined(_STM32_DEF_) // if not stm chips
162182
//SPI - begin transaction
163183
SPI.beginTransaction(settings);
164184
#endif
165-
//SPI - begin transaction
166-
//SPI.beginTransaction(settings);
167185

168186
//Send the command
169187
digitalWrite(chip_select_pin, LOW);
170-
#ifndef ESP_H // if not ESP32 board
171188
digitalWrite(chip_select_pin, LOW);
172-
#endif
173-
SPI.transfer(left_byte);
174-
SPI.transfer(right_byte);
189+
SPI.transfer16(command);
175190
digitalWrite(chip_select_pin,HIGH);
176-
#ifndef ESP_H // if not ESP32 board
177191
digitalWrite(chip_select_pin,HIGH);
178-
#endif
179192

180193
#if defined( ESP_H ) // if ESP32 board
181194
delayMicroseconds(50);
@@ -186,18 +199,20 @@ word MagneticSensorSPI::read(word angle_register){
186199
//Now read the response
187200
digitalWrite(chip_select_pin, LOW);
188201
digitalWrite(chip_select_pin, LOW);
189-
left_byte = SPI.transfer(0x00);
190-
right_byte = SPI.transfer(0x00);
202+
word register_value = SPI.transfer16(0x00);
191203
digitalWrite(chip_select_pin, HIGH);
192204
digitalWrite(chip_select_pin,HIGH);
193205

194206
#if !defined(_STM32_DEF_) // if not stm chips
195207
//SPI - end transaction
196208
SPI.endTransaction();
197209
#endif
210+
211+
register_value = register_value >> (1 + data_start_bit - bit_resolution); //this should shift data to the rightmost bits of the word
212+
213+
const static word data_mask = ~(0 >> (16 - bit_resolution));
198214

199-
// Return the data, stripping the parity and error bits
200-
return (( ( left_byte & 0xFF ) << 8 ) | ( right_byte & 0xFF )) & ~0xC000;
215+
return register_value & data_mask; // Return the data, stripping the non data (e.g parity) bits
201216
}
202217

203218
/**

src/MagneticSensorSPI.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@
88

99
#define DEF_ANGLE_REGISTAR 0x3FFF
1010

11+
struct MagneticSensorSPIConfig_s {
12+
int spi_mode;
13+
long clock_speed;
14+
int bit_resolution;
15+
int angle_register;
16+
int data_start_bit;
17+
int command_rw_bit;
18+
int command_parity_bit;
19+
};
20+
1121
class MagneticSensorSPI: public Sensor{
1222
public:
1323
/**
@@ -17,7 +27,12 @@ class MagneticSensorSPI: public Sensor{
1727
* @param angle_register (optional) angle read register - default 0x3FFF
1828
*/
1929
MagneticSensorSPI(int cs, float bit_resolution, int angle_register = 0);
20-
30+
/**
31+
* MagneticSensorSPI class constructor
32+
* @param config SPI config
33+
* @param cs SPI chip select pin
34+
*/
35+
MagneticSensorSPI(MagneticSensorSPIConfig_s config, int cs);
2136

2237
/** sensor initialise pins */
2338
void init();
@@ -40,7 +55,14 @@ class MagneticSensorSPI: public Sensor{
4055
/** returns 1 because it is the absolute sensor */
4156
int hasAbsoluteZero() override;
4257
/** returns 0 maning it doesn't need search for absolute zero */
58+
4359
int needsAbsoluteZeroSearch() override;
60+
61+
// returns the spi mode (phase/polarity of read/writes) i.e one of SPI_MODE0 | SPI_MODE1 | SPI_MODE2 | SPI_MODE3
62+
int spi_mode;
63+
64+
/* returns the speed of the SPI clock signal */
65+
long clock_speed;
4466

4567

4668
private:
@@ -72,6 +94,11 @@ class MagneticSensorSPI: public Sensor{
7294
// velocity calculation variables
7395
float angle_prev; //!< angle in previous velocity calculation step
7496
long velocity_calc_timestamp; //!< last velocity calculation timestamp
97+
98+
int bit_resolution; //!< the number of bites of angle data
99+
int command_parity_bit; //!< the bit where parity flag is stored in command
100+
int command_rw_bit; //!< the bit where read/write flag is stored in command
101+
int data_start_bit; //!< the the position of first bit
75102

76103
};
77104

src/SimpleFOC.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,6 @@ void loop() {
9494
#include "MagneticSensorAnalog.h"
9595
#include "HallSensor.h"
9696
#include "BLDCMotor.h"
97+
#include "Hardware.h"
9798

9899
#endif

0 commit comments

Comments
 (0)