Skip to content

Commit eb604db

Browse files
committed
Add support for all the existing MagAlpha and MagDiff sensors. MagAlpha.h now point to sensor Gen3 for the library backward compatibility.
1 parent 29ef72e commit eb604db

16 files changed

+3194
-41
lines changed

src/MagAlpha.h

+2-41
Original file line numberDiff line numberDiff line change
@@ -16,47 +16,8 @@
1616
#else
1717
#include "WProgram.h"
1818
#endif
19-
#include <SPI.h>
19+
#include "MagAlphaGen3.h"
2020

21-
//SPI Mode: MagAlpha Gen3 support SPI mode 3 and 0 [SPI_MODE3, SPI_MODE0]
22-
#define MA_SPI_MODE_0 SPI_MODE0
23-
#define MA_SPI_MODE_3 SPI_MODE3
21+
class MagAlpha: public MagAlphaGen3 {};
2422

25-
class MagAlpha {
26-
public:
27-
MagAlpha();
28-
void begin(uint8_t spiChipSelectPin);
29-
void begin(int32_t spiSclkFrequency, uint8_t spiMode, uint8_t spiChipSelectPin);
30-
void end();
31-
double readAngle();
32-
uint16_t readAngleRaw();
33-
uint16_t readAngleRaw(bool* error);
34-
uint16_t readAngleRaw16();
35-
uint8_t readAngleRaw8();
36-
uint8_t readRegister(uint8_t address);
37-
uint8_t writeRegister(uint8_t address, uint8_t value);
38-
void setSpiClockFrequency(uint32_t speedMaximum);
39-
void setSpiDataMode(uint8_t spiMode);
40-
void setSpiChipSelectPin(uint8_t spiChipSelectPin);
41-
double convertRawAngleToDegree(uint8_t rawAngleDataBitLength, uint16_t rawAngle);
42-
private:
43-
uint32_t _speedMaximum;
44-
uint8_t _spiMode;
45-
uint8_t _spiChipSelectPin;
46-
};
47-
48-
class MagAlphaSSI {
49-
public:
50-
MagAlphaSSI();
51-
void begin();
52-
void begin(int32_t ssiSsckFrequency);
53-
void end();
54-
double readAngle();
55-
uint16_t readAngleRaw();
56-
uint16_t readAngleRaw(bool* error);
57-
void setSsiClockFrequency(uint32_t speedMaximum);
58-
double convertRawAngleToDegree(uint8_t rawAngleDataBitLength, uint16_t rawAngle);
59-
private:
60-
uint32_t _speedMaximum;
61-
};
6223
#endif //MAGALPHA_H

src/MagAlphaBase.cpp

+259
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
/***************************************************
2+
Arduino library for the MPS MagAlpha magnetic angle sensor
3+
----> http://www.monolithicpower.com/Products/Position-Sensors/Products-Overview
4+
Written by Mathieu Kaelin for Monolithic Power Systems.
5+
MIT license, all text above must be included in any redistribution
6+
****************************************************/
7+
8+
#include "MagAlphaBase.h"
9+
10+
MagAlphaBase::MagAlphaBase(){
11+
}
12+
13+
double MagAlphaBase::readAngle(){
14+
return readAngleRaw16()*(360.0/65536.0);
15+
}
16+
17+
uint16_t MagAlphaBase::readAngleRaw(){
18+
return readAngleRaw16();
19+
}
20+
21+
void MagAlphaBase::getPartNumber(char *partNumber){
22+
sprintf(partNumber, "Unknown Part Number");
23+
}
24+
25+
double MagAlphaBase::convertRawAngleToDegree(uint8_t rawAngleDataBitLength, uint16_t rawAngle){
26+
double angleInDegree;
27+
angleInDegree = (rawAngle*360.0)/((double)pow(2, rawAngleDataBitLength));
28+
return angleInDegree;
29+
}
30+
31+
int16_t MagAlphaBase::twosComplement(uint16_t value, uint8_t numberOfBits){
32+
int16_t signedValue = static_cast<int16_t>(value);
33+
if ((value & (1 << (numberOfBits - 1))) != 0){
34+
signedValue = value - (1 << numberOfBits);
35+
}
36+
return signedValue;
37+
}
38+
39+
uint16_t MagAlphaBase::twosComplementInverse(int16_t value, uint8_t numberOfBits){
40+
uint16_t unsignedValue = static_cast<uint16_t>(value);
41+
if (value < 0){
42+
unsignedValue = value + (1 << numberOfBits);
43+
}
44+
return unsignedValue;
45+
}
46+
47+
/*====================================================================================*/
48+
/*============================== MagAlphaSPI =========================================*/
49+
/*====================================================================================*/
50+
MagAlphaSPI::MagAlphaSPI(){
51+
}
52+
53+
void MagAlphaSPI::begin(int spiChipSelectPin, SPIClass *spi){
54+
begin(10000000, (MagAlphaSPIMode)SPI_MODE3, spiChipSelectPin, spi);
55+
}
56+
57+
void MagAlphaSPI::begin(int32_t spiSclkFrequency, MagAlphaSPIMode spiMode, uint8_t spiChipSelectPin, SPIClass *spi){
58+
_spi = spi;
59+
_clockFrequency = spiSclkFrequency;
60+
_spiMode = (uint8_t)spiMode;
61+
setSpiChipSelectPin(spiChipSelectPin);
62+
_spi->begin();
63+
_spi->beginTransaction(SPISettings(_clockFrequency, MSBFIRST, _spiMode));
64+
}
65+
66+
void MagAlphaSPI::end(){
67+
_spi->endTransaction();
68+
_spi->end();
69+
}
70+
71+
void MagAlphaSPI::setSpiClockFrequency(uint32_t clockFrequency){
72+
_clockFrequency = clockFrequency;
73+
_spi->endTransaction();
74+
_spi->beginTransaction(SPISettings(_clockFrequency, MSBFIRST, _spiMode));
75+
}
76+
77+
void MagAlphaSPI::setSpiDataMode(MagAlphaSPIMode spiMode){
78+
_spiMode = (uint8_t)spiMode;
79+
_spi->endTransaction();
80+
_spi->beginTransaction(SPISettings(_clockFrequency, MSBFIRST, _spiMode));
81+
}
82+
83+
void MagAlphaSPI::setSpiChipSelectPin(uint8_t spiChipSelectPin){
84+
_spiChipSelectPin = spiChipSelectPin;
85+
pinMode(_spiChipSelectPin, OUTPUT);
86+
digitalWrite(_spiChipSelectPin, HIGH);
87+
}
88+
89+
uint16_t MagAlphaSPI::readAngleRaw16Quick(){
90+
uint16_t angle;
91+
digitalWrite(_spiChipSelectPin, LOW);
92+
// angle = _spi->transfer16(0x0000); //Read 16-bit angle
93+
spi0_hw->dr = 0x0000;
94+
angle = spi0_hw->dr;
95+
digitalWrite(_spiChipSelectPin, HIGH);
96+
return angle;
97+
}
98+
99+
/*====================================================================================*/
100+
/*============================== MagAlphaSSI =========================================*/
101+
/*====================================================================================*/
102+
MagAlphaSSI::MagAlphaSSI(){
103+
}
104+
105+
void MagAlphaSSI::begin(SPIClass *ssi){
106+
begin(1000000, MagAlphaSSIMode::MODE_A, ssi);
107+
}
108+
109+
void MagAlphaSSI::begin(int32_t ssiSsckFrequency, SPIClass *ssi){
110+
begin(ssiSsckFrequency, MagAlphaSSIMode::MODE_A, ssi);
111+
}
112+
113+
void MagAlphaSSI::begin(int32_t ssiSsckFrequency, MagAlphaSSIMode ssiMode, SPIClass *ssi){
114+
_ssi = ssi;
115+
_clockFrequency = ssiSsckFrequency;
116+
_ssiMode = (uint8_t)ssiMode;
117+
_ssi->begin();
118+
_ssi->beginTransaction(SPISettings(_clockFrequency, MSBFIRST, _ssiMode));
119+
}
120+
121+
void MagAlphaSSI::end(){
122+
_ssi->endTransaction();
123+
_ssi->end();
124+
}
125+
126+
void MagAlphaSSI::setSsiClockFrequency(uint32_t clockFrequency){
127+
_clockFrequency = clockFrequency;
128+
_ssi->endTransaction();
129+
_ssi->beginTransaction(SPISettings(_clockFrequency, MSBFIRST, _ssiMode));
130+
}
131+
132+
void MagAlphaSSI::setSSiMode(MagAlphaSSIMode ssiMode){
133+
_ssiMode = (uint8_t)ssiMode;
134+
_ssi->endTransaction();
135+
_ssi->beginTransaction(SPISettings(_clockFrequency, MSBFIRST, _ssiMode));
136+
}
137+
138+
double MagAlphaSSI::readAngle(){
139+
uint16_t angle;
140+
double angleInDegree;
141+
angle = readAngleRaw16();
142+
angleInDegree = (angle*360.0)/65536.0;
143+
return angleInDegree;
144+
}
145+
146+
uint16_t MagAlphaSSI::readAngleRaw(){
147+
return readAngleRaw16();
148+
}
149+
150+
uint16_t MagAlphaSSI::readAngleRaw(bool* error){
151+
uint16_t data1;
152+
uint8_t data2;
153+
uint8_t highStateCount = 0;
154+
data1 = _ssi->transfer16(0);
155+
data2 = _ssi->transfer(0);
156+
data1 = (data1 << 1);
157+
data1 = data1 + (data2 >> 7);
158+
data2 = ((data2 & 0x40) >> 6);
159+
//Count the number of 1 in the angle binary value
160+
for (int i=0;i<16;++i){
161+
if (data1 & (1 << i)){
162+
highStateCount++;
163+
}
164+
}
165+
//check if parity bit is correct
166+
if ((highStateCount % 2) == 0){
167+
if (data2 == 0){
168+
*error = false;
169+
}
170+
else{
171+
*error = true;
172+
}
173+
}
174+
else{
175+
if (data2 == 1){
176+
*error = false;
177+
}
178+
else{
179+
*error = true;
180+
}
181+
}
182+
return data1;
183+
}
184+
185+
uint16_t MagAlphaSSI::readAngleRaw16(){
186+
uint16_t data1;
187+
uint8_t data2;
188+
data1 = _ssi->transfer16(0);
189+
data2 = _ssi->transfer(0);
190+
data1 = (data1 << 1);
191+
return data1 + (data2 >> 7);
192+
}
193+
194+
uint8_t MagAlphaSSI::readAngleRaw8(){
195+
uint16_t data;
196+
data = _ssi->transfer16(0);
197+
return (data & 0x7F80) >> 7;
198+
}
199+
200+
201+
/*====================================================================================*/
202+
/*============================== MagAlphaI2C =========================================*/
203+
/*====================================================================================*/
204+
MagAlphaI2C::MagAlphaI2C(){
205+
}
206+
207+
void MagAlphaI2C::begin(uint8_t deviceAddress, uint32_t clockFrequency, TwoWire *i2c){
208+
_i2c = i2c;
209+
_deviceAddress = deviceAddress;
210+
_i2c->begin();
211+
setClockFrequency(clockFrequency);
212+
}
213+
214+
void MagAlphaI2C::end(){
215+
_i2c->end();
216+
}
217+
218+
void MagAlphaI2C::setClockFrequency(uint32_t clockFrequency){
219+
_clockFrequency=clockFrequency;
220+
_i2c->setClock(_clockFrequency);
221+
//100000 = Standard-mode (Sm)
222+
//400000 = Fast-mode (Fm)
223+
//1000000 = Fast-mode Plus (Fm)
224+
//3400000 = High-Speed mode (Hs-mode)
225+
//5000000 = Ulta Fast-mode (UFm) !!! Unidirectional Bus ONLY
226+
//10000 = low speed mode => not supported by the MKRZERO apparently
227+
}
228+
229+
void MagAlphaI2C::setDeviceAddress(uint8_t deviceAddress){
230+
_deviceAddress = deviceAddress;
231+
}
232+
233+
uint8_t MagAlphaI2C::findDeviceAddress(){
234+
for(int i=0; i<128; i++){
235+
_i2c->beginTransmission(i);
236+
if (_i2c->endTransmission() == 0){
237+
setDeviceAddress(i);
238+
return i;
239+
}
240+
}
241+
return 255;
242+
}
243+
244+
uint8_t MagAlphaI2C::findAllDeviceAddresses(uint8_t detectedDeviceAddresses[], uint8_t arraySize){
245+
uint8_t numberOfDeviceDetected = 0;
246+
for(int i=0; i<128; i++){
247+
_i2c->beginTransmission(i);
248+
if (_i2c->endTransmission() == 0){
249+
if (numberOfDeviceDetected < arraySize){
250+
detectedDeviceAddresses[numberOfDeviceDetected] = i;
251+
}
252+
numberOfDeviceDetected++;
253+
}
254+
}
255+
if (numberOfDeviceDetected == 1){
256+
setDeviceAddress(detectedDeviceAddresses[0]);
257+
}
258+
return numberOfDeviceDetected;
259+
}

0 commit comments

Comments
 (0)