SimpleFOClibrary 2.4.0
Loading...
Searching...
No Matches
MagneticSensorSPI.cpp
Go to the documentation of this file.
1
2#include "MagneticSensorSPI.h"
3
4/** Typical configuration for the 14bit AMS AS5147 magnetic sensor over SPI interface */
6 .spi_mode = SPI_MODE1,
7 .clock_speed = 1000000, // 1MHz clock (AMS should be able to accept up to 10MHz)
8 .bit_resolution = 14,
9 .angle_register = 0x3FFF,
10 .data_start_bit = 13,
11 .command_rw_bit = 14,
12 .command_parity_bit = 15
13};
14
15// AS5048 and AS5047 share the same configuration as AS5147
16// we have to explicilty assign them anyway due to compiler issues
17// Ex. https://community.simplefoc.com/t/esp32s3-qtpy-platformio-spi-problem/7444
19 .spi_mode = SPI_MODE1,
20 .clock_speed = 1000000, // 1MHz clock (AMS should be able to accept up to 10MHz)
21 .bit_resolution = 14,
22 .angle_register = 0x3FFF,
23 .data_start_bit = 13,
24 .command_rw_bit = 14,
25 .command_parity_bit = 15
26};
28 .spi_mode = SPI_MODE1,
29 .clock_speed = 1000000, // 1MHz clock (AMS should be able to accept up to 10MHz)
30 .bit_resolution = 14,
31 .angle_register = 0x3FFF,
32 .data_start_bit = 13,
33 .command_rw_bit = 14,
34 .command_parity_bit = 15
35};
36
37/** Typical configuration for the 14bit MonolithicPower MA730 magnetic sensor over SPI interface */
39 .spi_mode = SPI_MODE0,
40 .clock_speed = 1000000,
41 .bit_resolution = 14,
42 .angle_register = 0x0000,
43 .data_start_bit = 15,
44 .command_rw_bit = 0, // not required
45 .command_parity_bit = 0 // parity not implemented
46};
47
48
49// MagneticSensorSPI(int cs, float _bit_resolution, int _angle_register)
50// cs - SPI chip select pin
51// _bit_resolution sensor resolution bit number
52// _angle_register - (optional) angle read register - default 0x3FFF
53MagneticSensorSPI::MagneticSensorSPI(int cs, int _bit_resolution, int _angle_register, long _clock_speed){
54
55 chip_select_pin = cs;
56 // angle read register of the magnetic sensor
57 angle_register = _angle_register ? _angle_register : DEF_ANGLE_REGISTER;
58 // register maximum value (counts per revolution)
59 cpr = _powtwo(_bit_resolution);
60 spi_mode = SPI_MODE1;
61 clock_speed = _isset(_clock_speed) ? _clock_speed : 1000000;
62 bit_resolution = _bit_resolution;
63
64 command_parity_bit = 15; // for backwards compatibilty
65 command_rw_bit = 14; // for backwards compatibilty
66 data_start_bit = 13; // for backwards compatibilty
67}
68
70 chip_select_pin = cs;
71 // angle read register of the magnetic sensor
72 angle_register = config.angle_register ? config.angle_register : DEF_ANGLE_REGISTER;
73 // register maximum value (counts per revolution)
74 cpr = _powtwo(config.bit_resolution);
75 spi_mode = config.spi_mode;
76 // allow to override clock speed from config with the one provided as argument
77 // if the argument clock speed is not provided (i.e. is NOT_SET), use the clock speed from the config
78 clock_speed = _isset(_clock_speed) ? _clock_speed : config.clock_speed;
79 bit_resolution = config.bit_resolution;
80
81 command_parity_bit = config.command_parity_bit; // for backwards compatibilty
82 command_rw_bit = config.command_rw_bit; // for backwards compatibilty
83 data_start_bit = config.data_start_bit; // for backwards compatibilty
84}
85
86void MagneticSensorSPI::init(SPIClass* _spi){
87 spi = _spi;
88 // 1MHz clock (AMS should be able to accept up to 10MHz)
89 settings = SPISettings(clock_speed, MSBFIRST, spi_mode);
90 //setup pins
91 pinMode(chip_select_pin, OUTPUT);
92 //SPI has an internal SPI-device counter, it is possible to call "begin()" from different devices
93 spi->begin();
94 // do any architectures need to set the clock divider for SPI? Why was this in the code?
95 //spi->setClockDivider(SPI_CLOCK_DIV8);
96 digitalWrite(chip_select_pin, HIGH);
97
98 this->Sensor::init(); // call base class init
99}
100
101// Shaft angle calculation
102// angle is in radians [rad]
104 return (getRawCount() / (float)cpr) * _2PI;
105}
106
107// function reading the raw counter of the magnetic sensor
108int MagneticSensorSPI::getRawCount(){
109 return (int)MagneticSensorSPI::read(angle_register);
110}
111
112// SPI functions
113/**
114 * Utility function used to calculate even parity of word
115 */
116byte MagneticSensorSPI::spiCalcEvenParity(word value){
117 byte cnt = 0;
118 byte i;
119
120 for (i = 0; i < 16; i++)
121 {
122 if (value & 0x1) cnt++;
123 value >>= 1;
124 }
125 return cnt & 0x1;
126}
127
128 /*
129 * Read a register from the sensor
130 * Takes the address of the register as a 16 bit word
131 * Returns the value of the register
132 */
133word MagneticSensorSPI::read(word angle_register){
134
135 word command = angle_register;
136
137 if (command_rw_bit > 0) {
138 command = angle_register | (1 << command_rw_bit);
139 }
140 if (command_parity_bit > 0) {
141 //Add a parity bit on the the MSB
142 command |= ((word)spiCalcEvenParity(command) << command_parity_bit);
143 }
144
145 //SPI - begin transaction
146 spi->beginTransaction(settings);
147
148 //Send the command
149 digitalWrite(chip_select_pin, LOW);
150 spi->transfer16(command);
151 digitalWrite(chip_select_pin,HIGH);
152
153#if defined(ESP_H) && defined(ARDUINO_ARCH_ESP32) // if ESP32 board
154 delayMicroseconds(50); // why do we need to delay 50us on ESP32? In my experience no extra delays are needed, on any of the architectures I've tested...
155#else
156 delayMicroseconds(1); // delay 1us, the minimum time possible in plain arduino. 350ns is the required time for AMS sensors, 80ns for MA730, MA702
157#endif
158
159 //Now read the response
160 digitalWrite(chip_select_pin, LOW);
161 word register_value = spi->transfer16(0x00);
162 digitalWrite(chip_select_pin, HIGH);
163
164 //SPI - end transaction
165 spi->endTransaction();
166
167 register_value = register_value >> (1 + data_start_bit - bit_resolution); //this should shift data to the rightmost bits of the word
168
169 const static word data_mask = 0xFFFF >> (16 - bit_resolution);
170
171 return register_value & data_mask; // Return the data, stripping the non data (e.g parity) bits
172}
173
174/**
175 * Closes the SPI connection
176 * SPI has an internal SPI-device counter, for each init()-call the close() function must be called exactly 1 time
177 */
178void MagneticSensorSPI::close(){
179 spi->end();
180}
181
182
MagneticSensorSPIConfig_s MA730_SPI
MagneticSensorSPIConfig_s AS5047_SPI
MagneticSensorSPIConfig_s AS5048_SPI
MagneticSensorSPIConfig_s AS5147_SPI
#define DEF_ANGLE_REGISTER
float getSensorAngle() override
MagneticSensorSPI(int cs, int bit_resolution, int angle_register=0, long clock_speed=NOT_SET)
virtual void init()
Definition Sensor.cpp:59
#define _2PI
Definition foc_utils.h:29
#define _powtwo(x)
Definition foc_utils.h:15
#define _isset(a)
Definition foc_utils.h:13