├── .gitignore ├── library.properties ├── examples ├── legacy │ ├── read-magalpha-angle │ │ └── read-magalpha-angle.ino │ ├── read-magalpha-angle-with-ssi │ │ └── read-magalpha-angle-with-ssi.ino │ ├── read-magalpha-angle-and-error │ │ └── read-magalpha-angle-and-error.ino │ ├── read-magalpha-angle-with-ssi-and-error │ │ └── read-magalpha-angle-with-ssi-and-error.ino │ └── edit-magalpha-config │ │ └── edit-magalpha-config.ino ├── gen3 │ └── gen3.ino ├── gen8 │ └── gen8.ino ├── gen7 │ └── gen7.ino ├── gen4 │ └── gen4.ino └── gen6 │ └── gen6.ino ├── LICENSE ├── keywords.txt ├── src ├── MagAlpha.h ├── MagAlpha.cpp ├── MagAlphaPartProperties.h ├── MagAlphaGen3.h ├── MagAlphaGen8.h ├── MagAlphaGen4.h ├── MagAlphaGen6.h ├── MagAlphaBase.h ├── MagAlphaGen7.h ├── MagAlphaBase.cpp ├── MagAlphaGen8.cpp ├── MagAlphaGen4.cpp ├── MagAlphaGen3.cpp ├── MagAlphaGen6.cpp └── MagAlphaGen7.cpp ├── .github └── workflows │ └── compile-examples.yml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE related files 2 | .vscode/ 3 | .idea/ 4 | 5 | # Build related folders 6 | build/ -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=MagAlpha Angle Sensor Library 2 | version=2.0.0 3 | author=Mathieu Kaelin, Monolithic Power Systems 4 | maintainer=Mathieu Kaelin 5 | sentence=Arduino library for the MPS MagAlpha magnetic angle sensor. 6 | paragraph=Supports MagAlpha 3, 4, 6, 7, 8 sensor generation. MagAlpha sensor detects the absolute angular position of a permanent magnet, typically a diametrically magnetized cylinder on the rotating shaft. 7 | category=Sensors 8 | url=https://github.com/monolithicpower/MagAlpha-Arduino-Library 9 | architectures=* 10 | includes=SPI.h,MagAlpha.h,MagAlphaGen3.h,MagAlphaGen4.h,MagAlphaGen6.h,MagAlphaGen7.h,MagAlphaGen8.h,MagAlphaPartProperties.h 11 | -------------------------------------------------------------------------------- /examples/legacy/read-magalpha-angle/read-magalpha-angle.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //Check https://www.arduino.cc/en/reference/SPI for SPI signals connections 4 | 5 | #define UART_BAUDRATE 115200 //UART data rate in bits per second (baud) 6 | #define SPI_SCLK_FREQUENCY 10000000 //SPI SCLK Clock frequency in Hz 7 | #define SPI_CS_PIN 0 //SPI CS pin 8 | 9 | MagAlpha magAlpha; 10 | 11 | void setup() { 12 | // put your setup code here, to run once: 13 | //Set the SPI SCLK frequency, SPI Mode and CS pin 14 | magAlpha.begin(SPI_SCLK_FREQUENCY, MA_SPI_MODE_3, SPI_CS_PIN); 15 | //Set the Serial Communication used to report the angle 16 | Serial.begin(UART_BAUDRATE); 17 | } 18 | 19 | void loop() { 20 | // put your main code here, to run repeatedly: 21 | double angle; 22 | //Read the angle 23 | angle = magAlpha.readAngle(); 24 | Serial.println(angle, 3); 25 | //Wait before the next angle measurement (not needed by the sensor, only targeted to make the output easier to read) 26 | delay(25); 27 | } 28 | -------------------------------------------------------------------------------- /examples/legacy/read-magalpha-angle-with-ssi/read-magalpha-angle-with-ssi.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //Check https://www.arduino.cc/en/reference/SPI for SPI signals connections 4 | //Connect SSI SSCK to SPI SCLK signal 5 | //Connect SSI SSD to SPI MISO signal 6 | 7 | #define UART_BAUDRATE 115200 //UART data rate in bits per second (baud) 8 | #define SSI_SSCK_FREQUENCY 1000000 //SSI SSCK Clock frequency in Hz 9 | 10 | MagAlphaSSI magAlphaSsi; 11 | 12 | void setup() { 13 | // put your setup code here, to run once: 14 | //Set the SSI SSCK frequency 15 | magAlphaSsi.begin(SSI_SSCK_FREQUENCY); 16 | //Set the Serial Communication used to report the angle 17 | Serial.begin(UART_BAUDRATE); 18 | } 19 | 20 | void loop() { 21 | // put your main code here, to run repeatedly: 22 | double angle; 23 | //Read the angle 24 | angle = magAlphaSsi.readAngle(); 25 | Serial.println(angle, 3); 26 | //Wait before the next angle measurement (not needed by the sensor, only targeted to make the output easier to read) 27 | delay(25); 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 MPS Tech Switzerland LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/legacy/read-magalpha-angle-and-error/read-magalpha-angle-and-error.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //Check https://www.arduino.cc/en/reference/SPI for SPI signals connections 4 | 5 | #define UART_BAUDRATE 115200 //UART data rate in bits per second (baud) 6 | #define SPI_SCLK_FREQUENCY 10000000 //SPI SCLK Clock frequency in Hz 7 | #define SPI_CS_PIN 0 //SPI CS pin 8 | 9 | MagAlpha magAlpha; 10 | 11 | void setup() { 12 | // put your setup code here, to run once: 13 | //Set the SPI SCLK frequency, SPI Mode and CS pin 14 | magAlpha.begin(SPI_SCLK_FREQUENCY, MA_SPI_MODE_3, SPI_CS_PIN); 15 | //Set the Serial Communication used to report the angle 16 | Serial.begin(UART_BAUDRATE); 17 | } 18 | 19 | void loop() { 20 | // put your main code here, to run repeatedly: 21 | uint16_t angleRaw16; 22 | bool crc_error; 23 | //Read the angle 24 | angleRaw16 = magAlpha.readAngleRaw(&crc_error); 25 | Serial.print(angleRaw16, DEC); 26 | if (crc_error){ 27 | Serial.print("\t => Communication Error Detected"); 28 | } 29 | else{ 30 | Serial.print("\t => Communication Succeeded"); 31 | } 32 | Serial.println(); 33 | //Wait before the next angle measurement (not needed by the sensor, only targeted to make the output easier to read) 34 | delay(25); 35 | } 36 | -------------------------------------------------------------------------------- /examples/legacy/read-magalpha-angle-with-ssi-and-error/read-magalpha-angle-with-ssi-and-error.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //Check https://www.arduino.cc/en/reference/SPI for SPI signals connections 4 | //Connect SSI SSCK to SPI SCLK signal 5 | //Connect SSI SSD to SPI MISO signal 6 | 7 | #define UART_BAUDRATE 115200 //UART data rate in bits per second (baud) 8 | #define SSI_SSCK_FREQUENCY 1000000 //SSI SSCK Clock frequency in Hz 9 | 10 | MagAlphaSSI magAlphaSsi; 11 | 12 | void setup() { 13 | // put your setup code here, to run once: 14 | //Set the SSI SSCK frequency 15 | magAlphaSsi.begin(SSI_SSCK_FREQUENCY); 16 | //Set the Serial Communication used to report the angle 17 | Serial.begin(UART_BAUDRATE); 18 | } 19 | 20 | void loop() { 21 | // put your main code here, to run repeatedly: 22 | uint16_t angleRaw16; 23 | bool crc_error; 24 | //Read the angle 25 | angleRaw16 = magAlphaSsi.readAngleRaw(&crc_error); 26 | Serial.print(angleRaw16, DEC); 27 | if (crc_error){ 28 | Serial.print("\t => Communication Error Detected"); 29 | } 30 | else{ 31 | Serial.print("\t => Communication Succeeded"); 32 | } 33 | Serial.println(); 34 | //Wait before the next angle measurement (not needed by the sensor, only targeted to make the output easier to read) 35 | delay(25); 36 | } 37 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For MagAlpha-Library 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | MagAlpha KEYWORD1 10 | MagAlphaSPI KEYWORD1 11 | MagAlphaSSI KEYWORD1 12 | MagAlphaI2C KEYWORD1 13 | MagAlphaGen3 KEYWORD1 14 | MagAlphaGen4 KEYWORD1 15 | MagAlphaGen6 KEYWORD1 16 | MagAlphaGen7 KEYWORD1 17 | MagAlphaGen8 KEYWORD1 18 | 19 | ####################################### 20 | # Methods and Functions (KEYWORD2) 21 | ####################################### 22 | 23 | begin KEYWORD2 24 | end KEYWORD2 25 | readAngle KEYWORD2 26 | readAngleRaw KEYWORD2 27 | readAngleRaw16 KEYWORD2 28 | readAngleRaw8 KEYWORD2 29 | readRegister KEYWORD2 30 | writeRegister KEYWORD2 31 | setSpiClockFrequency KEYWORD2 32 | setSpiDataMode KEYWORD2 33 | setSpiChipSelectPin KEYWORD2 34 | convertRawAngleToDegree KEYWORD2 35 | setSsiClockFrequency KEYWORD2 36 | 37 | ####################################### 38 | # Instances (KEYWORD2) 39 | ####################################### 40 | magAlpha KEYWORD2 41 | magAlphaSsi KEYWORD2 42 | 43 | ####################################### 44 | # Constants (LITERAL1) 45 | ####################################### 46 | MA_SPI_MODE_0 LITERAL1 47 | MA_SPI_MODE_3 LITERAL1 48 | -------------------------------------------------------------------------------- /src/MagAlpha.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | Arduino library for the MPS MagAlpha magnetic angle sensor 3 | Supports MagAlpha 3rd generation Sensors. MagAlpha sensor detects the 4 | absolute angular position of a permanent magnet, typically a diametrically 5 | magnetized cylinder on the rotating shaft. 6 | ----> http://www.monolithicpower.com/Products/Position-Sensors/Products-Overview 7 | Written by Mathieu Kaelin for Monolithic Power Systems. 8 | MIT license, all text above must be included in any redistribution 9 | ****************************************************/ 10 | 11 | #ifndef MAGALPHA_H 12 | #define MAGALPHA_H 13 | 14 | #if (ARDUINO >= 100) 15 | #include "Arduino.h" 16 | #else 17 | #include "WProgram.h" 18 | #endif 19 | #include 20 | #include "MagAlphaGen3.h" 21 | #include "MagAlphaPartProperties.h" 22 | //SPI Mode: MagAlpha Gen3 support SPI mode 3 and 0 [SPI_MODE3, SPI_MODE0] 23 | #define MA_SPI_MODE_0 SPI_MODE0 24 | #define MA_SPI_MODE_3 SPI_MODE3 25 | 26 | #include "MagAlphaBase.h" 27 | 28 | /*====================================================================================*/ 29 | /*========================== MagAlphaGen3 Legacy =====================================*/ 30 | /*====================================================================================*/ 31 | class MagAlpha : public MagAlphaGen3 { 32 | public: 33 | MagAlpha(); 34 | void begin(uint8_t spiChipSelectPin); 35 | void begin(int32_t spiSclkFrequency, uint8_t spiMode, uint8_t spiChipSelectPin); 36 | void setSpiDataMode(uint8_t spiMode); 37 | uint16_t readAngleRaw(); 38 | uint16_t readAngleRaw(bool* error); 39 | }; 40 | 41 | #endif //MAGALPHA_H 42 | -------------------------------------------------------------------------------- /src/MagAlpha.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | Arduino library for the MPS MagAlpha magnetic angle sensor 3 | Supports MagAlpha 3rd generation Sensors. MagAlpha sensor detects the 4 | absolute angular position of a permanent magnet, typically a diametrically 5 | magnetized cylinder on the rotating shaft. 6 | ----> http://www.monolithicpower.com/Products/Position-Sensors/Products-Overview 7 | Written by Mathieu Kaelin for Monolithic Power Systems. 8 | MIT license, all text above must be included in any redistribution 9 | ****************************************************/ 10 | 11 | #include 12 | #include "MagAlpha.h" 13 | 14 | //MagAlpha Read/Write Register Command 15 | //#define READ_REG_COMMAND (0b010 << 13) 16 | //#define WRITE_REG_COMMAND (0b100 << 13) 17 | 18 | #define SSI_MODE SPI_MODE1 19 | 20 | /*====================================================================================*/ 21 | /*========================== MagAlphaGen3 Legacy =====================================*/ 22 | /*====================================================================================*/ 23 | MagAlpha::MagAlpha(){ 24 | } 25 | 26 | void MagAlpha::begin(uint8_t spiChipSelectPin){ 27 | MagAlphaSPI::begin(10000000, MagAlphaSPIMode::MODE_3, spiChipSelectPin, &SPI); 28 | } 29 | 30 | void MagAlpha::begin(int32_t spiSclkFrequency, uint8_t spiMode, uint8_t spiChipSelectPin){ 31 | MagAlphaSPI::begin(spiSclkFrequency, (MagAlphaSPIMode)spiMode, spiChipSelectPin, &SPI); 32 | } 33 | 34 | void MagAlpha::setSpiDataMode(uint8_t spiMode){ 35 | MagAlphaSPI::setSpiDataMode((MagAlphaSPIMode)spiMode); 36 | } 37 | 38 | uint16_t MagAlpha::readAngleRaw() { 39 | return MagAlphaGen3::readAngleRaw16(); 40 | } 41 | 42 | uint16_t MagAlpha::readAngleRaw(bool* error) { 43 | return MagAlphaGen3::readAngleRaw(error); 44 | } -------------------------------------------------------------------------------- /src/MagAlphaPartProperties.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MAGALPHAPARTPROPERTIES_H 3 | #define MAGALPHAPARTPROPERTIES_H 4 | 5 | #if (ARDUINO >= 100) 6 | #include "Arduino.h" 7 | #else 8 | #include "WProgram.h" 9 | #endif 10 | #include 11 | #include 12 | 13 | typedef enum MagAlphaInterface{ 14 | UNKNOWN_INTERFACE = 0, 15 | SPI_INTERFACE = 1, 16 | I2C_INTERFACE = 2, 17 | SSI_INTERFACE = 3, 18 | ABZ_INTERFACE = 4, 19 | UVW_INTERFACE = 5, 20 | SENT_INTERFACE = 6 21 | }MagAlphaInterface; 22 | 23 | typedef enum MagAlphaGeneration{ 24 | UNKNOWN_GEN = 0, 25 | MA_GEN_1 = 1, 26 | MA_GEN_2 = 2, 27 | MA_GEN_3 = 3, 28 | MA_GEN_4 = 4, 29 | MA_GEN_5 = 5, 30 | MA_GEN_6 = 6, 31 | MA_GEN_7 = 7, 32 | MA_GEN_8 = 8 33 | }MagAlphaGeneration; 34 | 35 | typedef enum MagAlphaSPIMode{ 36 | MODE_0 = SPI_MODE0, 37 | MODE_3 = SPI_MODE3 38 | }MagAlphaSPIMode; 39 | 40 | typedef enum MagAlphaSSIMode{ 41 | MODE_A = SPI_MODE2, 42 | MODE_B = SPI_MODE1 43 | }MagAlphaSSIMode; 44 | 45 | typedef enum MagAlphaPartNumber{ 46 | UNKNOWN_PART_NUMBER = 0, 47 | MA100 = 1, //MA_GEN_1 48 | MA120 = 2, //MA_GEN_1 49 | MA300 = 3, //MA_GEN_1 50 | MA301 = 4, //MA_GEN_1 51 | MA700 = 5, //MA_GEN_1 52 | MA750 = 6, //MA_GEN_1 53 | MA700A = 7, //MA_GEN_2 54 | MA102 = 8, //MA_GEN_3 55 | MA302 = 9, //MA_GEN_3 56 | MA310 = 10, //MA_GEN_3 57 | MA330 = 11, //MA_GEN_3 58 | MA702 = 12, //MA_GEN_3 59 | MA704 = 13, //MA_GEN_3 60 | MA710 = 14, //MA_GEN_3 61 | MA730 = 15, //MA_GEN_3 62 | MA731 = 16, //MA_GEN_3 63 | MA732 = 17, //MA_GEN_3 64 | MA800 = 18, //MA_GEN_3 65 | MA820 = 19, //MA_GEN_3 66 | MA850 = 20, //MA_GEN_3 67 | MAQ430 = 21, //MA_GEN_3 68 | MAQ470 = 22, //MA_GEN_3 69 | MAQ473 = 23, //MA_GEN_3 70 | MAP790 = 24, //MA_GEN_3 71 | MAP791 = 25, //MA_GEN_3 72 | MA780 = 26, //MA_GEN_4 73 | MA781 = 27, //MA_GEN_4 74 | MA734 = 28, //MA_GEN_4 75 | MA760 = 29, //MA_GEN_5 76 | MA600 = 30, //MA_GEN_6 77 | MA900 = 31, //MA_GEN_7 78 | MAQ79010FS = 32,//MA_GEN_7 79 | MA980 = 33, //MA_GEN_8 80 | MA981 = 34, //MA_GEN_8 81 | 82 | }MagAlphaPartNumber; 83 | 84 | #endif //MAGALPHAPARTPROPERTIES_H -------------------------------------------------------------------------------- /src/MagAlphaGen3.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | Arduino library for the MPS MagAlpha magnetic angle sensor 3 | Supports MagAlpha 3rd generation Sensors. 4 | Support Part Number includes: MA102, MA302, MA310, MA330, 5 | MA702, MA704, MA710, MA730, MA731, MA732, MA800, MA820, MA850, MAQ430, 6 | MAQ470, MAQ473, MAP790-xxxx, MAP791-xxxx 7 | MagAlpha sensor detects the 8 | absolute angular position of a permanent magnet, typically a diametrically 9 | magnetized cylinder on the rotating shaft. 10 | ----> http://www.monolithicpower.com/Products/Position-Sensors/Products-Overview 11 | Written by Mathieu Kaelin for Monolithic Power Systems. 12 | MIT license, all text above must be included in any redistribution 13 | ****************************************************/ 14 | 15 | #ifndef MAGALPHAGEN3_H 16 | #define MAGALPHAGEN3_H 17 | 18 | #if (ARDUINO >= 100) 19 | #include "Arduino.h" 20 | #else 21 | #include "WProgram.h" 22 | #endif 23 | #include "MagAlphaBase.h" 24 | 25 | class MagAlphaGen3: public MagAlphaSPI { 26 | public: 27 | MagAlphaGen3(); 28 | uint16_t readAngleRaw(bool* error) override; 29 | uint16_t readAngleRaw16() override; 30 | uint8_t readAngleRaw8() override; 31 | uint8_t readRegister(uint8_t address) override; 32 | uint8_t writeRegister(uint8_t address, uint8_t value) override; 33 | void readRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister) override; 34 | void writeRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister) override; 35 | 36 | //Detect the sensor generation 37 | //uint16_t detectSensorGeneration() override; 38 | 39 | //Set Key Parameters 40 | uint16_t getZero() override; 41 | void setZero(uint16_t zero) override; 42 | uint16_t setCurrentAngleAsZero() override; 43 | uint16_t getBct() override; 44 | void setBct(uint16_t bct) override; 45 | 46 | //Part Information 47 | uint16_t getNumberOfRegisters() override; 48 | void getLockedRegisters(uint8_t unlockedRegisters[]) override; 49 | void getPartNumber(char *partNumber) override; 50 | uint8_t getSiliconId() override; 51 | uint8_t getSiliconRevision() override; 52 | uint8_t getRegisterMapRevision() override; 53 | }; 54 | 55 | class MagAlphaSSIGen3: public MagAlphaSSI {}; 56 | 57 | #endif //MAGALPHAGEN3_H 58 | -------------------------------------------------------------------------------- /src/MagAlphaGen8.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | Arduino library for the MPS MagAlpha magnetic angle sensor 3 | Supports MagDiff 8th generation Sensors. 4 | Support Part Number includes: MA980, MA981 5 | MagDiff sensor detects the 6 | absolute angular position of a permanent magnet, typically a diametrically 7 | magnetized cylinder on the rotating shaft. 8 | ----> http://www.monolithicpower.com/Products/Position-Sensors/Products-Overview 9 | Written by Mathieu Kaelin for Monolithic Power Systems. 10 | MIT license, all text above must be included in any redistribution 11 | ****************************************************/ 12 | 13 | #ifndef MAGALPHAGEN8_H 14 | #define MAGALPHAGEN8_H 15 | 16 | #if (ARDUINO >= 100) 17 | #include "Arduino.h" 18 | #else 19 | #include "WProgram.h" 20 | #endif 21 | #include "MagAlphaBase.h" 22 | 23 | class MagAlphaGen8: public MagAlphaSPI { 24 | public: 25 | MagAlphaGen8(); 26 | uint16_t readAngleRaw(bool* error) override; 27 | uint16_t readAngleRaw16() override; 28 | uint8_t readAngleRaw8() override; 29 | uint8_t readRegister(uint8_t address) override; 30 | uint8_t writeRegister(uint8_t address, uint8_t value) override; 31 | void readRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister) override; 32 | void writeRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister) override; 33 | 34 | //Detect the sensor generation 35 | //uint16_t detectSensorGeneration() override; 36 | 37 | //Set Key Parameters 38 | uint16_t getZero() override; 39 | void setZero(uint16_t zero) override; 40 | uint16_t setCurrentAngleAsZero() override; 41 | 42 | //Memory management 43 | void restoreAllRegisters() override; 44 | void storeAllRegisters() override; 45 | void storeRegister(uint8_t address) override; 46 | 47 | //Advanced features 48 | void clearErrorFlags() override; 49 | 50 | //Part Information 51 | uint16_t getNumberOfRegisters() override; 52 | void getLockedRegisters(uint8_t unlockedRegisters[]) override; 53 | void getPartNumber(char *partNumber) override; 54 | uint8_t getSiliconId() override; 55 | uint8_t getSiliconRevision() override; 56 | uint8_t getRegisterMapRevision() override; 57 | 58 | }; 59 | 60 | class MagAlphaSSIGen8: public MagAlphaSSI {}; 61 | 62 | #endif //MAGALPHAGEN8_H 63 | -------------------------------------------------------------------------------- /src/MagAlphaGen4.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | Arduino library for the MPS MagAlpha magnetic angle sensor 3 | Supports MagAlpha 4th generation Sensors. 4 | Support Part Number includes: MA780, MA782, MA734 5 | MagAlpha sensor detects the 6 | absolute angular position of a permanent magnet, typically a diametrically 7 | magnetized cylinder on the rotating shaft. 8 | ----> http://www.monolithicpower.com/Products/Position-Sensors/Products-Overview 9 | Written by Mathieu Kaelin for Monolithic Power Systems. 10 | MIT license, all text above must be included in any redistribution 11 | ****************************************************/ 12 | 13 | #ifndef MAGALPHAGEN4_H 14 | #define MAGALPHAGEN4_H 15 | 16 | #if (ARDUINO >= 100) 17 | #include "Arduino.h" 18 | #else 19 | #include "WProgram.h" 20 | #endif 21 | #include "MagAlphaBase.h" 22 | 23 | class MagAlphaGen4: public MagAlphaSPI { 24 | public: 25 | MagAlphaGen4(); 26 | uint16_t readAngleRaw(bool* error) override; 27 | uint16_t readAngleRaw16() override; 28 | uint8_t readAngleRaw8() override; 29 | uint8_t readRegister(uint8_t address) override; 30 | uint8_t writeRegister(uint8_t address, uint8_t value) override; 31 | void readRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister) override; 32 | void writeRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister) override; 33 | 34 | //Detect the sensor generation 35 | //uint16_t detectSensorGeneration() override; 36 | 37 | //Set Key Parameters 38 | uint16_t getZero() override; 39 | void setZero(uint16_t zero) override; 40 | uint16_t setCurrentAngleAsZero() override; 41 | uint16_t getBct() override; 42 | void setBct(uint16_t bct) override; 43 | 44 | //Memory management 45 | void restoreAllRegisters() override; 46 | void storeAllRegisters() override; 47 | void storeRegister(uint8_t address) override; 48 | 49 | //Advanced features 50 | void clearErrorFlags() override; 51 | 52 | //Part Information 53 | uint16_t getNumberOfRegisters() override; 54 | void getLockedRegisters(uint8_t unlockedRegisters[]) override; 55 | void getPartNumber(char *partNumber) override; 56 | uint8_t getSiliconId() override; 57 | uint8_t getSiliconRevision() override; 58 | uint8_t getRegisterMapRevision() override; 59 | }; 60 | 61 | class MagAlphaSSIGen4: public MagAlphaSSI {}; 62 | 63 | #endif //MAGALPHAGEN4_H 64 | -------------------------------------------------------------------------------- /examples/gen3/gen3.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #define SPI_CS_PIN (7) 7 | #define SPI_SCLK_FREQUENCY (1000000) 8 | 9 | MagAlphaGen3 magalpha; 10 | 11 | double angle_real; 12 | uint16_t zero, bct, angle_raw; 13 | uint8_t register_value[2]; 14 | bool crc_error; 15 | 16 | void setup() { 17 | 18 | magalpha.begin(SPI_SCLK_FREQUENCY, MagAlphaSPIMode::MODE_0, SPI_CS_PIN, &SPI); 19 | // Other ways of use of begin() that will set default settings to the SPI peripheral 20 | // magalpha.begin(SPI_CS_PIN, &SPI); 21 | 22 | //magalpha.setSpiClockFrequency(SPI_SCLK_FREQUENCY); 23 | //magalpha.setSpiDataMode(MagAlphaSPIMode::MODE0); 24 | //magalpha.setSpiChipSelectPin(SPI_CS_PIN); 25 | Serial.begin(115200); 26 | while(!Serial); 27 | } 28 | 29 | void loop() { 30 | 31 | // Read & Write registers 32 | register_value[0] = magalpha.writeRegister(0, 0xAA); 33 | Serial.println(register_value[0], HEX); 34 | register_value[0] = magalpha.readRegister(0); 35 | Serial.println(register_value[0], HEX); 36 | register_value[0] = magalpha.writeRegister(0, 0x00); 37 | 38 | // Read & Write registers in burst mode 39 | register_value[0] = 0xAA; 40 | register_value[1] = 0x55; 41 | magalpha.writeRegisterBurst(0, register_value, 2); 42 | magalpha.readRegisterBurst(0, register_value, 2); 43 | for(uint8_t i = 0; i < sizeof(register_value); i++) { 44 | Serial.print("Register "); 45 | Serial.print(i); 46 | Serial.print(" = "); 47 | Serial.println(register_value[i], HEX); 48 | } 49 | register_value[0] = 0x00; 50 | register_value[1] = 0x00; 51 | magalpha.writeRegisterBurst(0, register_value, 2); 52 | 53 | // Set & Get zero setting 54 | zero = magalpha.setCurrentAngleAsZero(); 55 | Serial.print("Zero setting = "); 56 | Serial.println(zero, HEX); 57 | magalpha.setZero(0x0000); 58 | zero = magalpha.getZero(); 59 | Serial.print("Zero setting = "); 60 | Serial.println(zero, HEX); 61 | 62 | // Set & Get BCT setting 63 | magalpha.setBct(0xAA55); 64 | bct = magalpha.getBct(); 65 | Serial.print("BCT = "); 66 | Serial.println(bct, HEX); 67 | magalpha.setBct(0x00); 68 | 69 | // Read angle 70 | angle_raw = magalpha.readAngleRaw8(); 71 | Serial.print("Angle raw (8 bits) = "); 72 | Serial.println(angle_raw, HEX); 73 | angle_raw = magalpha.readAngleRaw16(); 74 | Serial.print("Angle raw (16 bits) = "); 75 | Serial.println(angle_raw, HEX); 76 | angle_raw = magalpha.readAngleRaw(&crc_error); 77 | if(crc_error) { 78 | Serial.println("An error occured during readAngleRaw"); 79 | } else { 80 | Serial.print("readAngleRaw succeded, Angle raw (16 bits) = "); 81 | Serial.println(angle_raw, HEX); 82 | } 83 | 84 | angle_real = magalpha.readAngle(); 85 | Serial.print("Angle in degree = "); 86 | Serial.println(angle_real, DEC); 87 | 88 | // This delay has been added only for visual purpose of the terminal 89 | delay(25); 90 | } -------------------------------------------------------------------------------- /src/MagAlphaGen6.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | Arduino library for the MPS MagAlpha magnetic angle sensor 3 | Supports MagAlpha 6th generation Sensors. 4 | Support Part Number includes: MA600 5 | MagAlpha sensor detects the 6 | absolute angular position of a permanent magnet, typically a diametrically 7 | magnetized cylinder on the rotating shaft. 8 | ----> http://www.monolithicpower.com/Products/Position-Sensors/Products-Overview 9 | Written by Mathieu Kaelin for Monolithic Power Systems. 10 | MIT license, all text above must be included in any redistribution 11 | ****************************************************/ 12 | 13 | #ifndef MAGALPHAGEN6_H 14 | #define MAGALPHAGEN6_H 15 | 16 | #if (ARDUINO >= 100) 17 | #include "Arduino.h" 18 | #else 19 | #include "WProgram.h" 20 | #endif 21 | #include "MagAlphaBase.h" 22 | 23 | class MagAlphaGen6: public MagAlphaSPI { 24 | public: 25 | MagAlphaGen6(); 26 | uint16_t readAngleRaw(bool *error) override; 27 | uint16_t readAngleRaw16() override; 28 | uint8_t readAngleRaw8() override; 29 | uint8_t readRegister(uint8_t address) override; 30 | uint8_t writeRegister(uint8_t address, uint8_t value) override; 31 | void readRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister) override; 32 | void writeRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister) override; 33 | 34 | //Detect the sensor generation 35 | //uint16_t detectSensorGeneration() override; 36 | 37 | //Set Key Parameters 38 | uint16_t getZero() override; 39 | void setZero(uint16_t zero) override; 40 | uint16_t setCurrentAngleAsZero() override; 41 | uint16_t getBct() override; 42 | void setBct(uint16_t bct) override; 43 | 44 | //Memory management 45 | void restoreAllRegisters() override; 46 | void storeAllRegisters() override; 47 | /** 48 | * @brief Store register block 49 | * @param block Register block to store. if block=0, it stores register 0 to 31 50 | * (registers containing the configuration). 51 | * if block=1 it stores register 31 to 63 52 | * (registers containing the correction table). 53 | */ 54 | void storeRegisterBlock(uint8_t block) override; 55 | 56 | //Advanced features 57 | void clearErrorFlags() override; 58 | double readSpeed() override; 59 | int16_t readTurn() override; 60 | /** 61 | * @brief set a multiturn offset by configuring the MTOFFSET field 62 | * in the configuration register. 63 | * MTOFFSET is set to 0 at the system power up. 64 | * @attention MTOFFSET setting can’t be stored into NVM, 65 | * so user needs to set MTOFFSET after every power up if offset is needed. 66 | * 67 | * 68 | */ 69 | void writeTurn(int16_t turn) override; 70 | void readAngleAndMultiturnOrSpeedRaw(uint16_t *angle, uint16_t *multiturnOrSpeed); 71 | 72 | //Part Information 73 | uint16_t getNumberOfRegisters() override; 74 | void getLockedRegisters(uint8_t unlockedRegisters[]) override; 75 | void getPartNumber(char *partNumber) override; 76 | uint8_t getSiliconId() override; 77 | uint8_t getSiliconRevision() override; 78 | uint8_t getRegisterMapRevision() override; 79 | 80 | }; 81 | 82 | class MagAlphaSSIGen6: public MagAlphaSSI {}; 83 | 84 | #endif //MAGALPHAGEN6_H 85 | -------------------------------------------------------------------------------- /examples/gen8/gen8.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #define SPI_CS_PIN (7) 7 | #define SPI_SCLK_FREQUENCY (1000000) 8 | 9 | MagAlphaGen8 magalpha; 10 | 11 | double angle_real, speed; 12 | uint16_t zero, angle_raw, turn; 13 | uint8_t register_value[2]; 14 | bool crc_error; 15 | 16 | void setup() { 17 | 18 | magalpha.begin(SPI_SCLK_FREQUENCY, MagAlphaSPIMode::MODE_0, SPI_CS_PIN, &SPI); 19 | // Other ways of use of begin() that will set default settings to the SPI peripheral 20 | // magalpha.begin(SPI_CS_PIN, &SPI); 21 | 22 | //magalpha.setSpiClockFrequency(SPI_SCLK_FREQUENCY); 23 | //magalpha.setSpiDataMode(MagAlphaSPIMode::MODE0); 24 | //magalpha.setSpiChipSelectPin(SPI_CS_PIN); 25 | Serial.begin(115200); 26 | while(!Serial); 27 | } 28 | 29 | void loop() { 30 | 31 | // Read & Write registers 32 | register_value[0] = magalpha.writeRegister(0, 0xAA); 33 | Serial.println(register_value[0], HEX); 34 | register_value[0] = magalpha.readRegister(0); 35 | Serial.println(register_value[0], HEX); 36 | register_value[0] = magalpha.writeRegister(0, 0x00); 37 | 38 | // Read & Write registers in burst mode 39 | register_value[0] = 0xAA; 40 | register_value[1] = 0x55; 41 | magalpha.writeRegisterBurst(0, register_value, 2); 42 | magalpha.readRegisterBurst(0, register_value, 2); 43 | for(uint8_t i = 0; i < sizeof(register_value); i++) { 44 | Serial.print("Register "); 45 | Serial.print(i); 46 | Serial.print(" = "); 47 | Serial.println(register_value[i], HEX); 48 | } 49 | register_value[0] = 0x00; 50 | register_value[1] = 0x00; 51 | magalpha.writeRegisterBurst(0, register_value, 2); 52 | 53 | // Set & Get zero setting 54 | zero = magalpha.setCurrentAngleAsZero(); 55 | Serial.print("Zero setting = "); 56 | Serial.println(zero, HEX); 57 | magalpha.setZero(0x0000); 58 | zero = magalpha.getZero(); 59 | Serial.print("Zero setting = "); 60 | Serial.println(zero, HEX); 61 | 62 | // Memory management 63 | magalpha.writeRegister(0, 0xAA); 64 | magalpha.storeRegister(0); 65 | magalpha.writeRegister(0, 0x00); 66 | magalpha.restoreAllRegisters(); 67 | if(magalpha.readRegister(0) != 0xAA) { 68 | Serial.println("An error occured during restoreAllRegisters"); 69 | } 70 | magalpha.writeRegister(0, 0x00); 71 | magalpha.storeAllRegisters(); 72 | magalpha.restoreAllRegisters(); 73 | if(magalpha.readRegister(0) != 0x00) { 74 | Serial.println("An error occured during storeAllRegisters"); 75 | } 76 | 77 | // Clear error flags 78 | magalpha.clearErrorFlags(); 79 | 80 | // Read angle 81 | angle_raw = magalpha.readAngleRaw8(); 82 | Serial.print("Angle raw (8 bits) = "); 83 | Serial.println(angle_raw, HEX); 84 | angle_raw = magalpha.readAngleRaw16(); 85 | Serial.print("Angle raw (16 bits) = "); 86 | Serial.println(angle_raw, HEX); 87 | angle_raw = magalpha.readAngleRaw(&crc_error); 88 | if(crc_error) { 89 | Serial.println("An error occured during readAngleRaw"); 90 | } else { 91 | Serial.print("readAngleRaw succeded, Angle raw (16 bits) = "); 92 | Serial.println(angle_raw, HEX); 93 | } 94 | 95 | angle_real = magalpha.readAngle(); 96 | Serial.print("Angle in degree = "); 97 | Serial.println(angle_real, DEC); 98 | 99 | // This delay has been added only for visual purpose of the terminal 100 | delay(25); 101 | } 102 | -------------------------------------------------------------------------------- /.github/workflows/compile-examples.yml: -------------------------------------------------------------------------------- 1 | name: Compile Examples 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - ".github/workflows/compile-examples.yml" 7 | - "examples/**" 8 | - "src/**" 9 | push: 10 | paths: 11 | - ".github/workflows/compile-examples.yml" 12 | - "examples/**" 13 | - "src/**" 14 | 15 | jobs: 16 | build: 17 | runs-on: ubuntu-latest 18 | 19 | env: 20 | SKETCHES_REPORTS_PATH: sketches-reports 21 | 22 | strategy: 23 | fail-fast: false 24 | 25 | matrix: 26 | board: 27 | - fqbn: arduino:avr:uno 28 | platforms: | 29 | - name: arduino:avr 30 | - fqbn: arduino:samd:mkr1000 31 | platforms: | 32 | - name: arduino:samd 33 | - fqbn: arduino:samd:mkrzero 34 | platforms: | 35 | - name: arduino:samd 36 | - fqbn: arduino:samd:mkrwifi1010 37 | platforms: | 38 | - name: arduino:samd 39 | - fqbn: arduino:samd:mkrfox1200 40 | platforms: | 41 | - name: arduino:samd 42 | - fqbn: arduino:samd:mkrwan1300 43 | platforms: | 44 | - name: arduino:samd 45 | - fqbn: arduino:samd:mkrwan1310 46 | platforms: | 47 | - name: arduino:samd 48 | - fqbn: arduino:samd:mkrgsm1400 49 | platforms: | 50 | - name: arduino:samd 51 | - fqbn: arduino:samd:mkrnb1500 52 | platforms: | 53 | - name: arduino:samd 54 | - fqbn: arduino:samd:mkrvidor4000 55 | platforms: | 56 | - name: arduino:samd 57 | - fqbn: arduino:mbed_rp2040:pico 58 | platforms: | 59 | - name: arduino:mbed_rp2040 60 | - fqbn: arduino:mbed_nano:nano33ble 61 | platforms: | 62 | - name: arduino:mbed_nano 63 | - fqbn: arduino:mbed_nano:nanorp2040connect 64 | platforms: | 65 | - name: arduino:mbed_nano 66 | - fqbn: arduino:mbed_edge:edge_control 67 | platforms: | 68 | - name: arduino:mbed_edge 69 | - fqbn: esp32:esp32:esp32 70 | platforms: | 71 | - name: esp32:esp32 72 | source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json 73 | - fqbn: rp2040:rp2040:rpipico 74 | platforms: | 75 | - name: rp2040:rp2040 76 | source-url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json 77 | 78 | steps: 79 | - name: Checkout 80 | uses: actions/checkout@v4 81 | 82 | - name: Install ESP32 platform dependencies 83 | if: startsWith(matrix.board.fqbn, 'esp32:esp32') 84 | run: pip3 install pyserial 85 | 86 | - name: Compile examples 87 | uses: arduino/compile-sketches@v1 88 | with: 89 | fqbn: ${{ matrix.board.fqbn }} 90 | platforms: ${{ matrix.board.platforms }} 91 | enable-deltas-report: true 92 | sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }} 93 | github-token: ${{ secrets.GITHUB_TOKEN }} 94 | 95 | - name: Save memory usage change report as artifact 96 | if: github.event_name == 'pull_request' 97 | uses: actions/upload-artifact@v4 98 | with: 99 | name: ${{ env.SKETCHES_REPORTS_PATH }} 100 | path: ${{ env.SKETCHES_REPORTS_PATH }} 101 | -------------------------------------------------------------------------------- /examples/gen7/gen7.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #define SPI_CS_PIN (7) 7 | #define SPI_SCLK_FREQUENCY (1000000) 8 | 9 | MagAlphaGen7 magalpha; 10 | 11 | double angle_real, speed; 12 | uint16_t zero, angle_raw, turn; 13 | uint8_t register_value[2]; 14 | bool crc_error; 15 | 16 | void setup() { 17 | 18 | magalpha.begin(SPI_SCLK_FREQUENCY, MagAlphaSPIMode::MODE_0, SPI_CS_PIN, &SPI); 19 | // Other ways of use of begin() that will set default settings to the SPI peripheral 20 | // magalpha.begin(SPI_CS_PIN, &SPI); 21 | 22 | //magalpha.setSpiClockFrequency(SPI_SCLK_FREQUENCY); 23 | //magalpha.setSpiDataMode(MagAlphaSPIMode::MODE0); 24 | //magalpha.setSpiChipSelectPin(SPI_CS_PIN); 25 | Serial.begin(115200); 26 | while(!Serial); 27 | } 28 | 29 | void loop() { 30 | 31 | // Read & Write registers 32 | register_value[0] = magalpha.writeRegister(0, 0xAA); 33 | Serial.print("Register 0 = "); 34 | Serial.println(register_value[0], HEX); 35 | register_value[0] = magalpha.readRegister(0); 36 | register_value[0] = magalpha.writeRegister(0, 0x00); 37 | 38 | // Read & Write registers in burst mode 39 | register_value[0] = 0x55; 40 | register_value[1] = 0xAA; 41 | magalpha.writeRegisterBurst(0, register_value, 2); 42 | magalpha.readRegisterBurst(0, register_value, 2); 43 | for(uint8_t i = 0; i < sizeof(register_value); i++) { 44 | Serial.print("Register "); 45 | Serial.print(i); 46 | Serial.print(" = "); 47 | Serial.println(register_value[i], HEX); 48 | } 49 | register_value[0] = 0x00; 50 | register_value[1] = 0x00; 51 | magalpha.writeRegisterBurst(0, register_value, 2); 52 | 53 | // Set & Get zero setting 54 | zero = magalpha.setCurrentAngleAsZero(); 55 | Serial.print("Zero setting = "); 56 | Serial.println(zero, HEX); 57 | magalpha.setZero(0x0000); 58 | zero = magalpha.getZero(); 59 | Serial.print("Zero setting = "); 60 | Serial.println(zero, HEX); 61 | 62 | // Memory management 63 | magalpha.writeRegister(0, 0xAA); 64 | magalpha.storeRegisterBlock(1); 65 | magalpha.writeRegister(0, 0x00); 66 | magalpha.restoreAllRegisters(); 67 | if(magalpha.readRegister(0) != 0xAA) { 68 | Serial.println("An error occured during restoreAllRegisters"); 69 | } 70 | magalpha.writeRegister(0, 0x00); 71 | magalpha.storeAllRegisters(); 72 | magalpha.restoreAllRegisters(); 73 | if(magalpha.readRegister(0) != 0x00) { 74 | Serial.println("An error occured during storeAllRegisters"); 75 | } 76 | 77 | // Clear error flags 78 | magalpha.clearErrorFlags(); 79 | 80 | speed = magalpha.readSpeed(); 81 | Serial.println(speed); 82 | turn = magalpha.readTurn(); 83 | Serial.println(turn); 84 | 85 | // Read angle 86 | angle_raw = magalpha.readAngleRaw8(); 87 | Serial.print("Angle raw (8 bits) = "); 88 | Serial.println(angle_raw, HEX); 89 | angle_raw = magalpha.readAngleRaw16(); 90 | Serial.print("Angle raw (16 bits) = "); 91 | Serial.println(angle_raw, HEX); 92 | angle_raw = magalpha.readAngleRaw(&crc_error); 93 | if(crc_error) { 94 | Serial.println("An error occured during readAngleRaw"); 95 | } else { 96 | Serial.print("readAngleRaw succeded, Angle raw (16 bits) = "); 97 | Serial.println(angle_raw, HEX); 98 | } 99 | 100 | angle_real = magalpha.readAngle(); 101 | Serial.print("Angle in degree = "); 102 | Serial.println(angle_real, DEC); 103 | 104 | // This delay has been added only for visual purpose of the terminal 105 | delay(1000); 106 | } 107 | -------------------------------------------------------------------------------- /examples/gen4/gen4.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #define SPI_CS_PIN (7) 7 | #define SPI_SCLK_FREQUENCY (1000000) 8 | 9 | MagAlphaGen4 magalpha; 10 | 11 | double angle_real; 12 | uint16_t zero, bct, angle_raw; 13 | uint8_t register_value[2]; 14 | bool crc_error; 15 | 16 | void setup() { 17 | 18 | magalpha.begin(SPI_SCLK_FREQUENCY, MagAlphaSPIMode::MODE_0, SPI_CS_PIN, &SPI); 19 | // Other ways of use of begin() that will set default settings to the SPI peripheral 20 | // magalpha.begin(SPI_CS_PIN, &SPI); 21 | 22 | //magalpha.setSpiClockFrequency(SPI_SCLK_FREQUENCY); 23 | //magalpha.setSpiDataMode(MagAlphaSPIMode::MODE0); 24 | //magalpha.setSpiChipSelectPin(SPI_CS_PIN); 25 | Serial.begin(115200); 26 | while(!Serial); 27 | } 28 | 29 | void loop() { 30 | 31 | // Read & Write registers 32 | register_value[0] = magalpha.writeRegister(0, 0xAA); 33 | Serial.println(register_value[0], HEX); 34 | register_value[0] = magalpha.readRegister(0); 35 | Serial.println(register_value[0], HEX); 36 | register_value[0] = magalpha.writeRegister(0, 0x00); 37 | 38 | // Read & Write registers in burst mode 39 | register_value[0] = 0xAA; 40 | register_value[1] = 0x55; 41 | magalpha.writeRegisterBurst(0, register_value, 2); 42 | magalpha.readRegisterBurst(0, register_value, 2); 43 | for(uint8_t i = 0; i < sizeof(register_value); i++) { 44 | Serial.print("Register "); 45 | Serial.print(i); 46 | Serial.print(" = "); 47 | Serial.println(register_value[i], HEX); 48 | } 49 | register_value[0] = 0x00; 50 | register_value[1] = 0x00; 51 | magalpha.writeRegisterBurst(0, register_value, 2); 52 | 53 | // Set & Get zero setting 54 | zero = magalpha.setCurrentAngleAsZero(); 55 | Serial.print("Zero setting = "); 56 | Serial.println(zero, HEX); 57 | magalpha.setZero(0x0000); 58 | zero = magalpha.getZero(); 59 | Serial.print("Zero setting = "); 60 | Serial.println(zero, HEX); 61 | 62 | // Set & Get BCT setting 63 | magalpha.setBct(0xAA55); 64 | bct = magalpha.getBct(); 65 | Serial.print("BCT = "); 66 | Serial.println(bct, HEX); 67 | magalpha.setBct(0x00); 68 | 69 | // Memory management 70 | magalpha.writeRegister(0, 0xAA); 71 | magalpha.storeRegister(0); 72 | magalpha.writeRegister(0, 0x00); 73 | magalpha.restoreAllRegisters(); 74 | if(magalpha.readRegister(0) != 0xAA) { 75 | Serial.println("An error occured during restoreAllRegisters"); 76 | } 77 | magalpha.writeRegister(0, 0x00); 78 | magalpha.storeAllRegisters(); 79 | magalpha.restoreAllRegisters(); 80 | if(magalpha.readRegister(0) != 0x00) { 81 | Serial.println("An error occured during storeAllRegisters"); 82 | } 83 | 84 | // Clear error flags 85 | magalpha.clearErrorFlags(); 86 | 87 | // Read angle 88 | angle_raw = magalpha.readAngleRaw8(); 89 | Serial.print("Angle raw (8 bits) = "); 90 | Serial.println(angle_raw, HEX); 91 | angle_raw = magalpha.readAngleRaw16(); 92 | Serial.print("Angle raw (16 bits) = "); 93 | Serial.println(angle_raw, HEX); 94 | angle_raw = magalpha.readAngleRaw(&crc_error); 95 | if(crc_error) { 96 | Serial.println("An error occured during readAngleRaw"); 97 | } else { 98 | Serial.print("readAngleRaw succeded, Angle raw (16 bits) = "); 99 | Serial.println(angle_raw, HEX); 100 | } 101 | 102 | angle_real = magalpha.readAngle(); 103 | Serial.print("Angle in degree = "); 104 | Serial.println(angle_real, DEC); 105 | 106 | // This delay has been added only for visual purpose of the terminal 107 | delay(25); 108 | } 109 | -------------------------------------------------------------------------------- /examples/gen6/gen6.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #define SPI_CS_PIN (7) 7 | #define SPI_SCLK_FREQUENCY (1000000) 8 | 9 | MagAlphaGen6 magalpha; 10 | 11 | double angle_real, speed; 12 | uint16_t zero, bct, angle_raw, turn; 13 | uint8_t register_value[2]; 14 | bool crc_error; 15 | 16 | void setup() { 17 | 18 | magalpha.begin(SPI_SCLK_FREQUENCY, MagAlphaSPIMode::MODE_0, SPI_CS_PIN, &SPI); 19 | // Other ways of use of begin() that will set default settings to the SPI peripheral 20 | // magalpha.begin(SPI_CS_PIN, &SPI); 21 | 22 | //magalpha.setSpiClockFrequency(SPI_SCLK_FREQUENCY); 23 | //magalpha.setSpiDataMode(MagAlphaSPIMode::MODE0); 24 | //magalpha.setSpiChipSelectPin(SPI_CS_PIN); 25 | Serial.begin(115200); 26 | while(!Serial); 27 | } 28 | 29 | void loop() { 30 | 31 | // Read & Write registers 32 | register_value[0] = magalpha.writeRegister(0, 0xAA); 33 | Serial.println(register_value[0], HEX); 34 | register_value[0] = magalpha.readRegister(0); 35 | Serial.println(register_value[0], HEX); 36 | register_value[0] = magalpha.writeRegister(0, 0x00); 37 | 38 | // Read & Write registers in burst mode 39 | register_value[0] = 0xAA; 40 | register_value[1] = 0x55; 41 | magalpha.writeRegisterBurst(0, register_value, 2); 42 | magalpha.readRegisterBurst(0, register_value, 2); 43 | for(uint8_t i = 0; i < sizeof(register_value); i++) { 44 | Serial.print("Register "); 45 | Serial.print(i); 46 | Serial.print(" = "); 47 | Serial.println(register_value[i], HEX); 48 | } 49 | register_value[0] = 0x00; 50 | register_value[1] = 0x00; 51 | magalpha.writeRegisterBurst(0, register_value, 2); 52 | 53 | // Set & Get zero setting 54 | zero = magalpha.setCurrentAngleAsZero(); 55 | Serial.print("Zero setting = "); 56 | Serial.println(zero, HEX); 57 | magalpha.setZero(0x0000); 58 | zero = magalpha.getZero(); 59 | Serial.print("Zero setting = "); 60 | Serial.println(zero, HEX); 61 | 62 | // Set & Get BCT setting 63 | magalpha.setBct(0xAA55); 64 | bct = magalpha.getBct(); 65 | Serial.print("BCT = "); 66 | Serial.println(bct, HEX); 67 | magalpha.setBct(0x00); 68 | 69 | // Memory management 70 | magalpha.writeRegister(0, 0xAA); 71 | magalpha.storeRegisterBlock(0); 72 | magalpha.writeRegister(0, 0x00); 73 | magalpha.restoreAllRegisters(); 74 | if(magalpha.readRegister(0) != 0xAA) { 75 | Serial.println("An error occured during restoreAllRegisters"); 76 | } 77 | magalpha.writeRegister(0, 0x00); 78 | magalpha.storeAllRegisters(); 79 | magalpha.restoreAllRegisters(); 80 | if(magalpha.readRegister(0) != 0x00) { 81 | Serial.println("An error occured during storeAllRegisters"); 82 | } 83 | 84 | // Clear error flags 85 | magalpha.clearErrorFlags(); 86 | 87 | speed = magalpha.readSpeed(); 88 | Serial.println(speed); 89 | turn = magalpha.readTurn(); 90 | Serial.println(turn); 91 | 92 | // Read angle 93 | angle_raw = magalpha.readAngleRaw8(); 94 | Serial.print("Angle raw (8 bits) = "); 95 | Serial.println(angle_raw, HEX); 96 | angle_raw = magalpha.readAngleRaw16(); 97 | Serial.print("Angle raw (16 bits) = "); 98 | Serial.println(angle_raw, HEX); 99 | angle_raw = magalpha.readAngleRaw(&crc_error); 100 | if(crc_error) { 101 | Serial.println("An error occured during readAngleRaw"); 102 | } else { 103 | Serial.print("readAngleRaw succeded, Angle raw (16 bits) = "); 104 | Serial.println(angle_raw, HEX); 105 | } 106 | 107 | angle_real = magalpha.readAngle(); 108 | Serial.print("Angle in degree = "); 109 | Serial.println(angle_real, DEC); 110 | 111 | // This delay has been added only for visual purpose of the terminal 112 | delay(25); 113 | } 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MagAlpha library 2 | [![Compile Examples](https://github.com/monolithicpower/MagAlpha-Arduino-Library/actions/workflows/compile-examples.yml/badge.svg)](https://github.com/monolithicpower/MagAlpha-Arduino-Library/actions/workflows/compile-examples.yml) 3 | 4 | Arduino library for the MPS MagAlpha magnetic angle sensor. 5 | 6 | ## About 7 | MagAlpha sensor detects the absolute angular position of a permanent magnet, typically a diametrically magnetized cylinder on the rotating shaft. 8 | 9 | For more information on the MagAlpha sensor family: 10 | * [MagAlpha Product Overview](http://www.monolithicpower.com/Products/Position-Sensors/Products-Overview) 11 | * [MagAlpha Support Materials](http://www.monolithicpower.com/Design-Support/Position-Sensors-Design-Support) 12 | 13 | ## Supported sensors 14 | Supports all 3rd, 4th, 6th, 7th, 8th generation MagAlpha magnetic angle sensors from [Monolithic Power Systems](https://www.monolithicpower.com/). 15 | 16 | | Applications | Part Numbers | 17 | | ------------| ------------ | 18 | | Turning knob applications (potentiometer replacement) | MA800, MA820, MA850 | 19 | | Rotary encoders (optical encoder replacement, Servo motors, ...) | MA702, MA704, MA710, MA730 | 20 | | Position controlled motor drivers (FOC, ...) | MA302, MA310, MA600 | 21 | | Motor commutation (hall switches replacement) | MA102 | 22 | 23 | 24 | ## License 25 | Written by Mathieu Kaelin for Monolithic Power Systems. 26 | MIT license, all text above must be included in any redistribution. 27 | 28 | 29 | ## Connections 30 | ### Power supply 31 | | Arduino | MagAlpha | 32 | | -------- | -------- | 33 | | GND | GND | 34 | | **+3.3V** (Not 5V)| VDD | 35 | 36 | | Warning | 37 | | :-------: | 38 | | Unlike most Arduino & Genuino boards, the **MagAlpha runs at 3.3V**. Even if the I/O can tolerate 5V, check that the voltage applied to VDD is at 3.3V. **Applying a voltages higher than 3.3V to the VDD pin could damage the sensor**.| 39 | 40 | ### Serial communication 41 | All MagAlpha have a SPI communication interface. Some sensors like the MA702 also have an additional SSI (2-wire) interface. 42 | MagAlpha gen8 possess an I2C interface. 43 | 44 | #### SPI (4-wire interface) 45 | | Arduino | MagAlpha | 46 | | -------- | -------- | 47 | | MOSI | MOSI | 48 | | MISO | MISO | 49 | | SCK | SCLK | 50 | | any available digital pin (default: pin 0) | CS | 51 | 52 | #### SSI (2-wire interface) 53 | | Arduino | MagAlpha | 54 | | -------- | -------- | 55 | | MISO | SSD | 56 | | SCK | SSCK | 57 | 58 | ### I2C (2-wire interface) 59 | | Arduino | MagAlpha | 60 | | -------- | -------- | 61 | | SCL | SCL | 62 | | SDA | SDA | 63 | 64 | #### Arduino SPI pin mapping 65 | | Arduino / Genuino Board | MOSI | MISO | SCK | CS | Voltage Level | 66 | | ----------------------- | ---- | ---- | ---- | :---: | ------------- | 67 | | Zero | ICSP-4 | ICSP-1 | ICSP-3 | defined by the user, any digital pin (default: pin 0) | +3.3V | 68 | | MKRZero | 8 | 10 | 9 | defined by the user, any digital pin (default: pin 0) | +3.3V | 69 | | MKR1000 | 8 | 10 | 9 | defined by the user, any digital pin (default: pin 0) | +3.3V | 70 | | 101 | 11 or ICSP-4 | 12 or ICSP-1 | 13 or ICSP-3 | defined by the user, any digital pin (default: pin 0) | +3.3V | 71 | | Due | ICSP-4 | ICSP-1 | ICSP-3 | defined by the user, any digital pin (default: pin 0) | +3.3V | 72 | | Uno or Duemilanove | 11 or ICSP-4 | 12 or ICSP-1 | 13 or ICSP-3 | defined by the user, any digital pin. **Default pin must be changed because pin 0 is also used by the Serial port**. (use pin 7 for example) | +5V | 73 | | Mega1280 or Mega2560 | 51 or ICSP-4 | 50 or ICSP-1 | 52 or ICSP-3 | defined by the user, any digital pin (default: pin 0) | +5V | 74 | | Leonardo | ICSP-4 | ICSP-1 | ICSP-3 | defined by the user, any digital pin (default: pin 0) | +5V | 75 | 76 | Check [Arduino SPI library reference page](https://www.arduino.cc/en/Reference/SPI) for more information on the SPI signal connections. 77 | 78 | ## Setup 79 | Install the library directly from within the Arduino IDE by using the Library Manager (Sketch => Include Library => Manage Libraries...). 80 | 81 | It is also possible to import the library Zip file (check release tab) from the Arduino IDE (Sketch => Include Library => Add .ZIP Library...). 82 | 83 | The library can also be manually installed by copying the MagAlpha library folder in your arduinosketchfolder/libraries/ folder. You may need to create the libraries subfolder if its your first library. Restart the IDE to see the library. 84 | 85 | Check this tutorial on Arduino library installation for more information: 86 | * [All About Arduino Libraries](http://learn.adafruit.com/adafruit-all-about-arduino-libraries-install-use) 87 | -------------------------------------------------------------------------------- /examples/legacy/edit-magalpha-config/edit-magalpha-config.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //Check https://www.arduino.cc/en/reference/SPI for SPI signals connections 4 | 5 | #define UART_BAUDRATE 115200 //UART data rate in bits per second (baud) 6 | #define SPI_SCLK_FREQUENCY 10000000 //SPI SCLK Clock frequency in Hz 7 | #define SPI_CS_PIN 0 //SPI CS pin 8 | 9 | MagAlpha magAlpha; 10 | 11 | void setup() { 12 | // put your setup code here, to run once: 13 | //Set the SPI SCLK frequency, SPI Mode and CS pin 14 | magAlpha.begin(SPI_SCLK_FREQUENCY, MA_SPI_MODE_3, SPI_CS_PIN); 15 | //Set the Serial Communication used to report the angle 16 | Serial.begin(UART_BAUDRATE); 17 | } 18 | 19 | void loop() { 20 | // put your main code here, to run repeatedly: 21 | //======================================================================== 22 | //Read the angle using different methods 23 | //======================================================================== 24 | double angle; 25 | uint16_t angleRaw16; 26 | uint8_t angleRaw8; 27 | 28 | Serial.println("Read Angle using different methods:"); 29 | 30 | //Read the angle in degree (Read 16-bit raw angle value and then convert it to the 0-360 degree range) 31 | angle = magAlpha.readAngle(); 32 | Serial.print(" magAlpha.readAngle() = "); 33 | Serial.println(angle, 3); 34 | 35 | //Read the angle (16-bit raw angle value) 36 | angleRaw16 = magAlpha.readAngleRaw(); 37 | Serial.print(" magAlpha.readAngleRaw() = "); 38 | Serial.println(angleRaw16, DEC); 39 | 40 | //Read the angle (16-bit raw angle value), equivalent to magAlpha.readAngleRaw() function 41 | angleRaw16 = magAlpha.readAngleRaw16(); 42 | Serial.print(" magAlpha.readAngleRaw16() = "); 43 | Serial.println(angleRaw16, DEC); 44 | 45 | //Read the angle (8-bit raw angle value) 46 | angleRaw8 = magAlpha.readAngleRaw8(); 47 | Serial.print(" magAlpha.readAngleRaw8() = "); 48 | Serial.println(angleRaw8, DEC); 49 | 50 | //Read the angle (16-bit raw angle value) and check the parity bit to detect possible communication error 51 | bool crc_error; 52 | angleRaw16 = magAlpha.readAngleRaw(&crc_error); 53 | Serial.print(" magAlpha.readAngleRaw16(&error) = "); 54 | Serial.print(angleRaw16, DEC); 55 | if (crc_error){ 56 | Serial.print("\t => Communication error detected"); 57 | } 58 | else{ 59 | Serial.print("\t => Operation Succeed"); 60 | } 61 | Serial.println(); 62 | 63 | 64 | 65 | //======================================================================== 66 | //Read the zero settings in register 0 and 1 67 | //======================================================================== 68 | uint8_t readbackRegister0Value, readbackRegister1Value; 69 | //Read MagAlpha Gen3 Zero Settings (Registers 0 and 1 70 | readbackRegister0Value = magAlpha.readRegister(0); 71 | readbackRegister1Value = magAlpha.readRegister(1); 72 | Serial.println("Read Zero Setting:"); 73 | Serial.print(" Read Register[0] = 0x"); 74 | Serial.println(readbackRegister0Value, HEX); 75 | Serial.print(" Read Register[1] = 0x"); 76 | Serial.println(readbackRegister1Value, HEX); 77 | 78 | //======================================================================== 79 | //Write MagAlpha Gen3 Zero Settings with value 0x7FFF (Registers 0 and 1) 80 | //======================================================================== 81 | readbackRegister0Value = magAlpha.writeRegister(0, 0xFF); 82 | readbackRegister1Value = magAlpha.writeRegister(1, 0x7F); 83 | Serial.println("Write Zero Setting:"); 84 | Serial.print(" Write Register[0] = 0x"); 85 | Serial.println(readbackRegister0Value, HEX); 86 | Serial.print(" Write Register[1] = 0x"); 87 | Serial.println(readbackRegister1Value, HEX); 88 | if ((readbackRegister0Value == 0xFF) && (readbackRegister1Value == 0x7F)) 89 | { 90 | Serial.println(" Write Process Succeed"); 91 | } 92 | else 93 | { 94 | Serial.println(" Write Process Fail"); 95 | } 96 | 97 | //======================================================================== 98 | //Change MagAlpha Gen3 Rotation Direction (Register 9, bit 7) 99 | //======================================================================== 100 | uint8_t readbackRegister9Value; 101 | //Read register 9 and toggle RD state 102 | readbackRegister9Value = magAlpha.readRegister(9); 103 | if ((readbackRegister9Value & 0x80) == 0){ 104 | //Set RD to 1 105 | magAlpha.writeRegister(9, 0x80); 106 | } 107 | else{ 108 | //Set RD to 0 109 | magAlpha.writeRegister(9, 0x00); 110 | } 111 | Serial.println("Write Rotation Direction Setting:"); 112 | Serial.print(" Write Register[9] = 0x"); 113 | Serial.println(readbackRegister9Value, HEX); 114 | } 115 | -------------------------------------------------------------------------------- /src/MagAlphaBase.h: -------------------------------------------------------------------------------- 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 | #ifndef MAGALPHABASE_H 9 | #define MAGALPHABASE_H 10 | 11 | #if (ARDUINO >= 100) 12 | #include "Arduino.h" 13 | #else 14 | #include "WProgram.h" 15 | #endif 16 | #include 17 | #include 18 | #include 19 | #include "MagAlphaPartProperties.h" 20 | 21 | 22 | class MagAlphaBase { 23 | public: 24 | MagAlphaBase(); 25 | 26 | double readAngle(); 27 | uint16_t readAngleRaw(); 28 | 29 | virtual uint16_t readAngleRaw(bool* error){return 0;} 30 | virtual uint16_t readAngleRaw16(){return 0;} 31 | virtual uint8_t readAngleRaw8(){return 0;} 32 | virtual uint8_t readRegister(uint8_t address){return 0;} 33 | virtual uint8_t writeRegister(uint8_t address, uint8_t value){return 0;} 34 | virtual void readRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister){} 35 | virtual void writeRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister){} 36 | 37 | //Detect the sensor generation 38 | virtual uint16_t detectSensorGeneration(){return 0;} 39 | 40 | //Set Key Parameters 41 | virtual uint16_t getZero(){return 0;} 42 | virtual void setZero(uint16_t zero){} 43 | virtual uint16_t setCurrentAngleAsZero(){return 0;} 44 | virtual uint16_t getBct(){return 0;} 45 | virtual void setBct(uint16_t bct){} 46 | 47 | //Memory management 48 | virtual void restoreAllRegisters(){} 49 | virtual void storeAllRegisters(){} 50 | virtual void storeRegisterBlock(uint8_t block){} 51 | virtual void storeRegister(uint8_t address){} 52 | 53 | //Advanced features 54 | virtual void clearErrorFlags(){} 55 | virtual double readSpeed(){return 0;} 56 | virtual int16_t readTurn(){return 0;} 57 | virtual void writeTurn(int16_t turn){} 58 | virtual double readTemperature(){return 0.0;} 59 | virtual uint16_t readAcquisitionCounter(){return 0;} 60 | 61 | //Part Information 62 | virtual uint16_t getNumberOfRegisters(){return 0;} 63 | virtual void getLockedRegisters(uint8_t unlockedRegisters[]){} 64 | virtual void getPartNumber(char *partNumber); 65 | virtual uint8_t getSiliconId(){return 0;} 66 | virtual uint8_t getSiliconRevision(){return 0;} 67 | virtual uint8_t getRegisterMapRevision(){return 0;} 68 | 69 | //Utility functions 70 | double convertRawAngleToDegree(uint8_t rawAngleDataBitLength, uint16_t rawAngle); 71 | int16_t twosComplement(uint16_t value, uint8_t numberOfBits); 72 | uint16_t twosComplementInverse(int16_t value, uint8_t numberOfBits); 73 | protected: 74 | // bool _featureSuppored; 75 | }; 76 | 77 | /*====================================================================================*/ 78 | /*============================== MagAlphaSPI =========================================*/ 79 | /*====================================================================================*/ 80 | class MagAlphaSPI : public MagAlphaBase { 81 | public: 82 | MagAlphaSPI(); 83 | void begin(int spiChipSelectPin, SPIClass *spi = &SPI); 84 | void begin(int32_t spiSclkFrequency, MagAlphaSPIMode spiMode, uint8_t spiChipSelectPin, SPIClass *spi = &SPI); 85 | void end(); 86 | void setSpiClockFrequency(uint32_t clockFrequency); 87 | void setSpiDataMode(MagAlphaSPIMode spiMode); 88 | void setSpiChipSelectPin(uint8_t spiChipSelectPin); 89 | virtual uint16_t readAngleRaw16Quick(); 90 | protected: 91 | uint8_t _spiChipSelectPin; 92 | uint32_t _clockFrequency; 93 | uint8_t _spiMode; 94 | SPIClass *_spi; 95 | }; 96 | 97 | /*====================================================================================*/ 98 | /*============================== MagAlphaSSI =========================================*/ 99 | /*====================================================================================*/ 100 | class MagAlphaSSI : public MagAlphaBase { 101 | public: 102 | MagAlphaSSI(); 103 | void begin(); 104 | //void begin(int32_t ssiClkFrequency); 105 | void begin(SPIClass *ssi); 106 | void begin(int32_t ssiSsckFrequency, SPIClass *ssi = &SPI); 107 | void begin(int32_t ssiSsckFrequency, MagAlphaSSIMode ssiMode, SPIClass *ssi = &SPI); 108 | void end(); 109 | void setSsiClockFrequency(uint32_t clockFrequency); 110 | void setSSiMode(MagAlphaSSIMode ssiMode); 111 | double readAngle(); 112 | uint16_t readAngleRaw(); 113 | virtual uint16_t readAngleRaw(bool* error); 114 | virtual uint16_t readAngleRaw16(); 115 | virtual uint8_t readAngleRaw8(); 116 | protected: 117 | uint32_t _clockFrequency; 118 | uint8_t _ssiMode; 119 | SPIClass *_ssi; 120 | }; 121 | 122 | /*====================================================================================*/ 123 | /*============================== MagAlphaI2C =========================================*/ 124 | /*====================================================================================*/ 125 | class MagAlphaI2C : public MagAlphaBase { 126 | public: 127 | MagAlphaI2C(); 128 | void begin(uint8_t deviceAddress, uint32_t clockFrequency=400000, TwoWire *i2c = &Wire); 129 | void end(); 130 | void setClockFrequency(uint32_t clockFrequency); 131 | void setDeviceAddress(uint8_t deviceAddress); 132 | uint8_t findDeviceAddress(); 133 | uint8_t findAllDeviceAddresses(uint8_t detectedDeviceAddresses[], uint8_t arraySize); 134 | protected: 135 | uint8_t _deviceAddress; 136 | uint32_t _clockFrequency; 137 | TwoWire *_i2c; 138 | }; 139 | 140 | #endif //MAGALPHABASE_H 141 | -------------------------------------------------------------------------------- /src/MagAlphaGen7.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | Arduino library for the MPS MagAlpha magnetic angle sensor 3 | Supports MagAlpha 7th generation Sensors. 4 | Support Part Number includes: MA900 5 | MagAlpha sensor detects the 6 | absolute angular position of a permanent magnet, typically a diametrically 7 | magnetized cylinder on the rotating shaft. 8 | ----> http://www.monolithicpower.com/Products/Position-Sensors/Products-Overview 9 | Written by Mathieu Kaelin for Monolithic Power Systems. 10 | MIT license, all text above must be included in any redistribution 11 | ****************************************************/ 12 | 13 | #ifndef MAGALPHAGEN7_H 14 | #define MAGALPHAGEN7_H 15 | 16 | #if (ARDUINO >= 100) 17 | #include "Arduino.h" 18 | #else 19 | #include "WProgram.h" 20 | #endif 21 | #include "MagAlphaBase.h" 22 | 23 | class MagAlphaGen7: public MagAlphaSPI { 24 | public: 25 | MagAlphaGen7(); 26 | 27 | uint16_t readAngleRaw(bool *error) override; 28 | uint16_t readAngleRaw16() override; 29 | uint8_t readAngleRaw8() override; 30 | uint8_t readRegister(uint8_t address) override; 31 | uint8_t writeRegister(uint8_t address, uint8_t value) override; 32 | void readRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister) override; 33 | void writeRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister) override; 34 | 35 | //Detect the sensor generation 36 | //uint16_t detectSensorGeneration() override; 37 | 38 | //Set Key Parameters 39 | uint16_t getZero() override; 40 | void setZero(uint16_t zero) override; 41 | uint16_t setCurrentAngleAsZero() override; 42 | 43 | //Memory management 44 | void restoreAllRegisters() override; 45 | void storeAllRegisters() override; 46 | /** 47 | * @brief Store register block 48 | * @param block Register block to store. 49 | * block=0, Do not store anything (Do not use) 50 | * block=1, Store Page 0 51 | * block=2, Store Page 1 52 | * block=3, Store Page 0 and Page 1 53 | */ 54 | void storeRegisterBlock(uint8_t block) override; 55 | 56 | //Advanced features 57 | void clearErrorFlags() override; 58 | double readSpeed() override; 59 | int16_t readTurn() override; 60 | void writeTurn(int16_t turn) override; 61 | double readTemperature() override; 62 | uint16_t readAcquisitionCounter() override; 63 | 64 | //Part Information 65 | uint16_t getNumberOfRegisters() override; 66 | void getLockedRegisters(uint8_t unlockedRegisters[]) override; 67 | void getPartNumber(char *partNumber) override; 68 | uint8_t getSiliconId() override; 69 | uint8_t getSiliconRevision() override; 70 | 71 | uint16_t readAngleRaw16(bool *error, bool *inversion, bool isShortRead=false); 72 | uint16_t readAngleCounter(uint16_t *angle, bool *error, bool *inversion); 73 | uint16_t readAngleSpeed(uint16_t *angle, bool *error, bool *inversion); 74 | uint16_t readAngleMultiturn(uint16_t *angle, bool *error, bool *inversion); 75 | uint16_t readAngleTemperature(uint16_t *angle, bool *error, bool *inversion); 76 | uint8_t readRegister(uint8_t address, bool *error, bool *inversion); 77 | uint16_t readRegisterBurst(uint8_t address, uint8_t readbackValueArray[], uint16_t numberOfRegister, bool *error, bool *inversion); 78 | uint8_t writeRegister(uint8_t address, uint8_t value, bool *error, bool *inversion, bool *wrongHandshaking); 79 | void writeRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister, bool *error, bool *inversion, bool *wrongHandshaking); 80 | void setCrcCheckSetting(bool enable); 81 | uint16_t appendCrc4(uint16_t data); 82 | void checkCrc4(uint16_t readData, uint16_t *computedCrc, bool *errorDetected, bool *inversionDetected); 83 | 84 | private: 85 | bool _crcCheckEnabled; 86 | uint8_t _crcInitValue; 87 | }; 88 | 89 | class MagAlphaSSIGen7: public MagAlphaSSI {}; 90 | 91 | class MagAlphaI2CGen7: public MagAlphaI2C { 92 | public: 93 | MagAlphaI2CGen7(); 94 | 95 | uint16_t readAngleRaw(bool *error) override; 96 | uint16_t readAngleRaw16() override; 97 | uint8_t readAngleRaw8() override; 98 | uint8_t readRegister(uint8_t address) override; 99 | uint8_t writeRegister(uint8_t address, uint8_t value) override; 100 | void readRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister) override; 101 | void writeRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister) override; 102 | 103 | //Detect the sensor generation 104 | uint16_t detectSensorGeneration() override; 105 | 106 | //Set Key Parameters 107 | uint16_t getZero() override; 108 | void setZero(uint16_t zero) override; 109 | uint16_t setCurrentAngleAsZero() override; 110 | 111 | //Memory management 112 | void restoreAllRegisters() override; 113 | void storeAllRegisters() override; 114 | /** 115 | * @brief Store register block 116 | * @param block Register block to store. 117 | * block=0, Do not store anything (Do not use) 118 | * block=1, Store Page 0 119 | * block=2, Store Page 1 120 | * block=3, Store Page 0 and Page 1 121 | */ 122 | void storeRegisterBlock(uint8_t block) override; 123 | 124 | //Advanced features 125 | void clearErrorFlags() override; 126 | double readSpeed() override; 127 | int16_t readTurn() override; 128 | void writeTurn(int16_t turn) override; 129 | double readTemperature() override; 130 | uint16_t readAcquisitionCounter() override; 131 | 132 | uint16_t getNumberOfRegisters() override; 133 | void getLockedRegisters(uint8_t unlockedRegisters[]) override; 134 | void getPartNumber(char *partNumber) override; 135 | uint8_t getSiliconId() override; 136 | uint8_t getSiliconRevision() override; 137 | 138 | uint8_t readRegister(uint8_t address, bool *error); 139 | uint16_t readRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister, bool *error); 140 | uint16_t readRegisterQuickRead(uint8_t valueArray[], uint16_t numberOfRegister, bool *error); 141 | void setCrcCheckSetting(bool enable); 142 | 143 | uint8_t crc8(uint8_t crc, uint8_t data); 144 | void checkCrc8(uint8_t &readData, uint8_t &computedCrc, bool *errorDetected); 145 | 146 | private: 147 | bool _crcCheckEnabled; 148 | uint8_t _crcInitValue; 149 | }; 150 | 151 | #endif //MAGALPHAGEN7_H -------------------------------------------------------------------------------- /src/MagAlphaBase.cpp: -------------------------------------------------------------------------------- 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(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(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(){ 106 | _ssi = &SPI; 107 | _clockFrequency = 1000000; 108 | _ssi->begin(); 109 | _ssi->beginTransaction(SPISettings(_clockFrequency, MSBFIRST, MagAlphaSSIMode::MODE_B)); 110 | } 111 | 112 | /* 113 | void MagAlphaSSI::begin(int32_t ssiSsckFrequency){ 114 | _ssi = &SPI; 115 | _clockFrequency = ssiSsckFrequency; 116 | _ssi->begin(); 117 | _ssi->beginTransaction(SPISettings(_clockFrequency, MSBFIRST, MagAlphaSSIMode::MODE_B)); 118 | } 119 | */ 120 | 121 | void MagAlphaSSI::begin(SPIClass *ssi){ 122 | begin(1000000, MagAlphaSSIMode::MODE_A, ssi); 123 | } 124 | 125 | void MagAlphaSSI::begin(int32_t ssiSsckFrequency, SPIClass *ssi){ 126 | begin(ssiSsckFrequency, MagAlphaSSIMode::MODE_A, ssi); 127 | } 128 | 129 | void MagAlphaSSI::begin(int32_t ssiSsckFrequency, MagAlphaSSIMode ssiMode, SPIClass *ssi){ 130 | _ssi = ssi; 131 | _clockFrequency = ssiSsckFrequency; 132 | _ssiMode = (uint8_t)ssiMode; 133 | _ssi->begin(); 134 | _ssi->beginTransaction(SPISettings(_clockFrequency, MSBFIRST, _ssiMode)); 135 | } 136 | 137 | void MagAlphaSSI::end(){ 138 | _ssi->endTransaction(); 139 | _ssi->end(); 140 | } 141 | 142 | void MagAlphaSSI::setSsiClockFrequency(uint32_t clockFrequency){ 143 | _clockFrequency = clockFrequency; 144 | _ssi->endTransaction(); 145 | _ssi->beginTransaction(SPISettings(_clockFrequency, MSBFIRST, _ssiMode)); 146 | } 147 | 148 | void MagAlphaSSI::setSSiMode(MagAlphaSSIMode ssiMode){ 149 | _ssiMode = (uint8_t)ssiMode; 150 | _ssi->endTransaction(); 151 | _ssi->beginTransaction(SPISettings(_clockFrequency, MSBFIRST, _ssiMode)); 152 | } 153 | 154 | double MagAlphaSSI::readAngle(){ 155 | uint16_t angle; 156 | double angleInDegree; 157 | angle = readAngleRaw16(); 158 | angleInDegree = (angle*360.0)/65536.0; 159 | return angleInDegree; 160 | } 161 | 162 | uint16_t MagAlphaSSI::readAngleRaw(){ 163 | return readAngleRaw16(); 164 | } 165 | 166 | uint16_t MagAlphaSSI::readAngleRaw(bool* error){ 167 | uint16_t data1; 168 | uint8_t data2; 169 | uint8_t highStateCount = 0; 170 | data1 = _ssi->transfer16(0); 171 | data2 = _ssi->transfer(0); 172 | data1 = (data1 << 1); 173 | data1 = data1 + (data2 >> 7); 174 | data2 = ((data2 & 0x40) >> 6); 175 | //Count the number of 1 in the angle binary value 176 | for (int i=0;i<16;++i){ 177 | if (data1 & (1 << i)){ 178 | highStateCount++; 179 | } 180 | } 181 | //check if parity bit is correct 182 | if ((highStateCount % 2) == 0){ 183 | if (data2 == 0){ 184 | *error = false; 185 | } 186 | else{ 187 | *error = true; 188 | } 189 | } 190 | else{ 191 | if (data2 == 1){ 192 | *error = false; 193 | } 194 | else{ 195 | *error = true; 196 | } 197 | } 198 | return data1; 199 | } 200 | 201 | uint16_t MagAlphaSSI::readAngleRaw16(){ 202 | uint16_t data1; 203 | uint8_t data2; 204 | data1 = _ssi->transfer16(0); 205 | data2 = _ssi->transfer(0); 206 | data1 = (data1 << 1); 207 | return data1 + (data2 >> 7); 208 | } 209 | 210 | uint8_t MagAlphaSSI::readAngleRaw8(){ 211 | uint16_t data; 212 | data = _ssi->transfer16(0); 213 | return (data & 0x7F80) >> 7; 214 | } 215 | 216 | /*====================================================================================*/ 217 | /*============================== MagAlphaI2C =========================================*/ 218 | /*====================================================================================*/ 219 | MagAlphaI2C::MagAlphaI2C(){ 220 | } 221 | 222 | void MagAlphaI2C::begin(uint8_t deviceAddress, uint32_t clockFrequency, TwoWire *i2c){ 223 | _i2c = i2c; 224 | _deviceAddress = deviceAddress; 225 | _i2c->begin(); 226 | setClockFrequency(clockFrequency); 227 | } 228 | 229 | void MagAlphaI2C::end(){ 230 | _i2c->end(); 231 | } 232 | 233 | void MagAlphaI2C::setClockFrequency(uint32_t clockFrequency){ 234 | _clockFrequency=clockFrequency; 235 | _i2c->setClock(_clockFrequency); 236 | //100000 = Standard-mode (Sm) 237 | //400000 = Fast-mode (Fm) 238 | //1000000 = Fast-mode Plus (Fm) 239 | //3400000 = High-Speed mode (Hs-mode) 240 | //5000000 = Ulta Fast-mode (UFm) !!! Unidirectional Bus ONLY 241 | //10000 = low speed mode => not supported by the MKRZERO apparently 242 | } 243 | 244 | void MagAlphaI2C::setDeviceAddress(uint8_t deviceAddress){ 245 | _deviceAddress = deviceAddress; 246 | } 247 | 248 | uint8_t MagAlphaI2C::findDeviceAddress(){ 249 | for(int i=0; i<128; i++){ 250 | _i2c->beginTransmission(i); 251 | if (_i2c->endTransmission() == 0){ 252 | setDeviceAddress(i); 253 | return i; 254 | } 255 | } 256 | return 255; 257 | } 258 | 259 | uint8_t MagAlphaI2C::findAllDeviceAddresses(uint8_t detectedDeviceAddresses[], uint8_t arraySize){ 260 | uint8_t numberOfDeviceDetected = 0; 261 | for(int i=0; i<128; i++){ 262 | _i2c->beginTransmission(i); 263 | if (_i2c->endTransmission() == 0){ 264 | if (numberOfDeviceDetected < arraySize){ 265 | detectedDeviceAddresses[numberOfDeviceDetected] = i; 266 | } 267 | numberOfDeviceDetected++; 268 | } 269 | } 270 | if (numberOfDeviceDetected == 1){ 271 | setDeviceAddress(detectedDeviceAddresses[0]); 272 | } 273 | return numberOfDeviceDetected; 274 | } 275 | -------------------------------------------------------------------------------- /src/MagAlphaGen8.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | Arduino library for the MPS MagAlpha magnetic angle sensor 3 | Supports MagDiff 8th generation Sensors. 4 | Support Part Number includes: MA980, MA981 5 | MagDiff sensor detects the 6 | absolute angular position of a permanent magnet, typically a diametrically 7 | magnetized cylinder on the rotating shaft. 8 | ----> http://www.monolithicpower.com/Products/Position-Sensors/Products-Overview 9 | Written by Mathieu Kaelin for Monolithic Power Systems. 10 | MIT license, all text above must be included in any redistribution 11 | ****************************************************/ 12 | 13 | #include "MagAlphaGen8.h" 14 | 15 | //MagAlpha Read/Write Register Command 16 | #define READ_REG_COMMAND (0b010 << 13) 17 | #define WRITE_REG_COMMAND (0b100 << 13) 18 | #define STORE_SINGLE_REGISTER_COMMAND (0b111 << 13) 19 | #define STORE_ALL_REGISTERS_COMMAND (0b110 << 13) 20 | #define RESTORE_ALL_REGISTERS_COMMAND (0b101 << 13) 21 | #define CLEAR_ERROR_FLAGS_COMMAND (0b001 << 13) 22 | 23 | #define REG_REGMAPID 23 24 | #define REG_SID 24 25 | #define REG_PID 25 26 | #define REG_LOCK0 28 27 | #define REG_LOCK1 29 28 | #define REG_LOCK2 30 29 | #define REG_LOCK3 31 30 | 31 | MagAlphaGen8::MagAlphaGen8(){ 32 | } 33 | 34 | uint16_t MagAlphaGen8::readAngleRaw16(){ 35 | uint16_t angle; 36 | digitalWrite(_spiChipSelectPin, LOW); 37 | angle = _spi->transfer16(0x0000); //Read 16-bit angle 38 | digitalWrite(_spiChipSelectPin, HIGH); 39 | return angle; 40 | } 41 | 42 | uint8_t MagAlphaGen8::readAngleRaw8(){ 43 | uint8_t angle; 44 | digitalWrite(_spiChipSelectPin, LOW); 45 | angle = _spi->transfer(0x00); //Read 8-bit angle 46 | digitalWrite(_spiChipSelectPin, HIGH); 47 | return angle; 48 | } 49 | 50 | uint16_t MagAlphaGen8::readAngleRaw(bool* error){ 51 | uint16_t angle; 52 | uint8_t parity; 53 | uint8_t highStateCount = 0; 54 | digitalWrite(_spiChipSelectPin, LOW); 55 | angle = _spi->transfer16(0x0000); 56 | parity = _spi->transfer(0x00); 57 | digitalWrite(_spiChipSelectPin, HIGH); 58 | parity = ((parity & 0x80) >> 7); 59 | //Count the number of 1 in the angle binary value 60 | for (int i=0;i<16;++i){ 61 | if ((angle & (1 << i)) != 0){ 62 | highStateCount++; 63 | } 64 | } 65 | //check if parity bit is correct 66 | if ((highStateCount % 2) == 0){ 67 | if (parity == 0){ 68 | *error = false; 69 | } 70 | else{ 71 | *error = true; 72 | } 73 | } 74 | else{ 75 | if (parity == 1){ 76 | *error = false; 77 | } 78 | else{ 79 | *error = true; 80 | } 81 | } 82 | return angle; 83 | } 84 | 85 | uint8_t MagAlphaGen8::readRegister(uint8_t address){ 86 | uint8_t readbackRegisterValue; 87 | digitalWrite(_spiChipSelectPin, LOW); 88 | _spi->transfer16(READ_REG_COMMAND | ((address & 0x1F) << 8) | 0x00); 89 | digitalWrite(_spiChipSelectPin, HIGH); 90 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout 91 | digitalWrite(_spiChipSelectPin, LOW); 92 | readbackRegisterValue = (_spi->transfer16(0x0000) & 0x00FF); 93 | digitalWrite(_spiChipSelectPin, HIGH); 94 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 95 | return readbackRegisterValue; 96 | } 97 | 98 | uint8_t MagAlphaGen8::writeRegister(uint8_t address, uint8_t value){ 99 | uint8_t readbackRegisterValue; 100 | digitalWrite(_spiChipSelectPin, LOW); 101 | _spi->transfer16(WRITE_REG_COMMAND | ((address & 0x1F) << 8) | value); 102 | digitalWrite(_spiChipSelectPin, HIGH); 103 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout 104 | digitalWrite(_spiChipSelectPin, LOW); 105 | readbackRegisterValue = (_spi->transfer16(0x0000) & 0x00FF); 106 | digitalWrite(_spiChipSelectPin, HIGH); 107 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 108 | return readbackRegisterValue; 109 | } 110 | 111 | void MagAlphaGen8::readRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister){ 112 | uint8_t readbackRegisterValue; 113 | digitalWrite(_spiChipSelectPin, LOW); 114 | _spi->transfer16(READ_REG_COMMAND | (((address) & 0x1F) << 8) | 0x00); 115 | digitalWrite(_spiChipSelectPin, HIGH); 116 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout 117 | for (uint8_t i=0;itransfer16(READ_REG_COMMAND | (((address+i+1) & 0x1F) << 8) | 0x00) & 0x00FF); 120 | digitalWrite(_spiChipSelectPin, HIGH); 121 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout 122 | } 123 | digitalWrite(_spiChipSelectPin, LOW); 124 | valueArray[numberOfRegister-1] = (_spi->transfer16(0x0000) & 0x00FF); 125 | digitalWrite(_spiChipSelectPin, HIGH); 126 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 127 | } 128 | 129 | void MagAlphaGen8::writeRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister){ 130 | for (uint8_t i=0;itransfer16(WRITE_REG_COMMAND | (((address+i) & 0x1F) << 8) | valueArray[i]); 133 | digitalWrite(_spiChipSelectPin, HIGH); 134 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 135 | } 136 | digitalWrite(_spiChipSelectPin, LOW); 137 | _spi->transfer16(0x0000); 138 | digitalWrite(_spiChipSelectPin, HIGH); 139 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 140 | } 141 | 142 | /* 143 | uint16_t MagAlphaGen8::detectSensorGeneration(){ 144 | uint16_t chipId; 145 | digitalWrite(_spiChipSelectPin, LOW); 146 | _spi->transfer16(0x6000); 147 | digitalWrite(_spiChipSelectPin, HIGH); 148 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout 149 | digitalWrite(_spiChipSelectPin, LOW); 150 | chipId = _spi->transfer16(0x0000) & 0x00FF; 151 | digitalWrite(_spiChipSelectPin, HIGH); 152 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 153 | return chipId; 154 | } 155 | */ 156 | 157 | uint16_t MagAlphaGen8::getZero() 158 | { 159 | return (readRegister(1)<<8) + readRegister(0); 160 | } 161 | 162 | void MagAlphaGen8::setZero(uint16_t zero){ 163 | writeRegister(0, zero&0xFF); 164 | writeRegister(1, zero>>8); 165 | } 166 | 167 | uint16_t MagAlphaGen8::setCurrentAngleAsZero(){ 168 | uint16_t zero; 169 | setZero(0); 170 | zero=readAngleRaw16(); 171 | setZero(zero); 172 | return zero; 173 | } 174 | 175 | void MagAlphaGen8::restoreAllRegisters(){ 176 | digitalWrite(_spiChipSelectPin, LOW); 177 | _spi->transfer16(RESTORE_ALL_REGISTERS_COMMAND); 178 | digitalWrite(_spiChipSelectPin, HIGH); 179 | delayMicroseconds(240); //Wait for 240us 180 | digitalWrite(_spiChipSelectPin, LOW); 181 | _spi->transfer16(0x0000); 182 | digitalWrite(_spiChipSelectPin, HIGH); 183 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 184 | } 185 | 186 | void MagAlphaGen8::storeAllRegisters(){ 187 | digitalWrite(_spiChipSelectPin, LOW); 188 | _spi->transfer16(STORE_ALL_REGISTERS_COMMAND); 189 | digitalWrite(_spiChipSelectPin, HIGH); 190 | delay(704); //Wait for 704ms 191 | digitalWrite(_spiChipSelectPin, LOW); 192 | _spi->transfer16(0x0000); 193 | digitalWrite(_spiChipSelectPin, HIGH); 194 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 195 | } 196 | 197 | void MagAlphaGen8::storeRegister(uint8_t address){ 198 | digitalWrite(_spiChipSelectPin, LOW); 199 | _spi->transfer16(STORE_SINGLE_REGISTER_COMMAND | ((address & 0x1F) << 8) | 0x00); 200 | digitalWrite(_spiChipSelectPin, HIGH); 201 | delay(23); //Wait for 23ms 202 | digitalWrite(_spiChipSelectPin, LOW); 203 | _spi->transfer16(0x0000); 204 | digitalWrite(_spiChipSelectPin, HIGH); 205 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 206 | } 207 | 208 | void MagAlphaGen8::clearErrorFlags(){ 209 | digitalWrite(_spiChipSelectPin, LOW); 210 | _spi->transfer16(CLEAR_ERROR_FLAGS_COMMAND); 211 | digitalWrite(_spiChipSelectPin, HIGH); 212 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tClearFault of 40ns before register readout 213 | digitalWrite(_spiChipSelectPin, LOW); 214 | _spi->transfer16(0x0000); 215 | digitalWrite(_spiChipSelectPin, HIGH); 216 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 217 | } 218 | 219 | uint16_t MagAlphaGen8::getNumberOfRegisters(){ 220 | return 32; 221 | } 222 | 223 | void MagAlphaGen8::getLockedRegisters(uint8_t unlockedRegisters[]){ 224 | uint8_t registerArray[4] = {0}; 225 | readRegisterBurst(REG_LOCK0, registerArray, 4); 226 | for(uint8_t i=0; i<4; i++){ 227 | for(uint8_t j=0; j<8; j++){ 228 | unlockedRegisters[i*8+j] = ((registerArray[i]>>j)&0x01) ? 0xFF : 0x00; 229 | } 230 | } 231 | } 232 | 233 | void MagAlphaGen8::getPartNumber(char *partNumber){ 234 | uint8_t partId = readRegister(REG_PID); 235 | switch(partId) { 236 | case 1: 237 | sprintf(partNumber, "MA980"); 238 | break; 239 | case 2: 240 | sprintf(partNumber, "MA981"); 241 | break; 242 | default: 243 | sprintf(partNumber, "Gen8 [%u] Unknown Part Number", partId); 244 | } 245 | } 246 | 247 | uint8_t MagAlphaGen8::getSiliconId(){ 248 | return (readRegister(REG_SID) & 0xF0) >> 4; 249 | } 250 | 251 | uint8_t MagAlphaGen8::getSiliconRevision(){ 252 | return readRegister(REG_SID) & 0x0F; 253 | } 254 | 255 | uint8_t MagAlphaGen8::getRegisterMapRevision(){ 256 | return readRegister(REG_REGMAPID); 257 | } 258 | -------------------------------------------------------------------------------- /src/MagAlphaGen4.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | Arduino library for the MPS MagAlpha magnetic angle sensor 3 | Supports MagAlpha 4th generation Sensors. 4 | Support Part Number includes: MA780, MA782, MA734 5 | MagAlpha sensor detects the 6 | absolute angular position of a permanent magnet, typically a diametrically 7 | magnetized cylinder on the rotating shaft. 8 | ----> http://www.monolithicpower.com/Products/Position-Sensors/Products-Overview 9 | Written by Mathieu Kaelin for Monolithic Power Systems. 10 | MIT license, all text above must be included in any redistribution 11 | ****************************************************/ 12 | 13 | #include "MagAlphaGen4.h" 14 | 15 | //MagAlpha Read/Write Register Command 16 | #define READ_REG_COMMAND (0b010 << 13) 17 | #define WRITE_REG_COMMAND (0b100 << 13) 18 | #define STORE_SINGLE_REGISTER_COMMAND (0b111 << 13) 19 | #define STORE_ALL_REGISTERS_COMMAND (0b110 << 13) 20 | #define RESTORE_ALL_REGISTERS_COMMAND (0b101 << 13) 21 | #define CLEAR_ERROR_FLAGS_COMMAND (0b001 << 13) 22 | 23 | #define REG_REGMAPID 23 24 | #define REG_SID 24 25 | #define REG_PID 25 26 | #define REG_LOCK0 28 27 | #define REG_LOCK1 29 28 | #define REG_LOCK2 30 29 | #define REG_LOCK3 31 30 | 31 | MagAlphaGen4::MagAlphaGen4(){ 32 | } 33 | 34 | uint16_t MagAlphaGen4::readAngleRaw16(){ 35 | uint16_t angle; 36 | digitalWrite(_spiChipSelectPin, LOW); 37 | angle = _spi->transfer16(0x0000); //Read 16-bit angle 38 | digitalWrite(_spiChipSelectPin, HIGH); 39 | return angle; 40 | } 41 | 42 | uint8_t MagAlphaGen4::readAngleRaw8(){ 43 | uint8_t angle; 44 | digitalWrite(_spiChipSelectPin, LOW); 45 | angle = _spi->transfer(0x00); //Read 8-bit angle 46 | digitalWrite(_spiChipSelectPin, HIGH); 47 | return angle; 48 | } 49 | 50 | uint16_t MagAlphaGen4::readAngleRaw(bool* error){ 51 | uint16_t angle; 52 | uint8_t parity; 53 | uint8_t highStateCount = 0; 54 | digitalWrite(_spiChipSelectPin, LOW); 55 | angle = _spi->transfer16(0x0000); 56 | parity = _spi->transfer(0x00); 57 | digitalWrite(_spiChipSelectPin, HIGH); 58 | parity = ((parity & 0x80) >> 7); 59 | //Count the number of 1 in the angle binary value 60 | for (int i=0;i<16;++i){ 61 | if ((angle & (1 << i)) != 0){ 62 | highStateCount++; 63 | } 64 | } 65 | //check if parity bit is correct 66 | if ((highStateCount % 2) == 0){ 67 | if (parity == 0){ 68 | *error = false; 69 | } 70 | else{ 71 | *error = true; 72 | } 73 | } 74 | else{ 75 | if (parity == 1){ 76 | *error = false; 77 | } 78 | else{ 79 | *error = true; 80 | } 81 | } 82 | return angle; 83 | } 84 | 85 | uint8_t MagAlphaGen4::readRegister(uint8_t address){ 86 | uint8_t readbackRegisterValue; 87 | digitalWrite(_spiChipSelectPin, LOW); 88 | _spi->transfer16(READ_REG_COMMAND | ((address & 0x1F) << 8) | 0x00); 89 | digitalWrite(_spiChipSelectPin, HIGH); 90 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout 91 | digitalWrite(_spiChipSelectPin, LOW); 92 | readbackRegisterValue = (_spi->transfer16(0x0000) & 0x00FF); 93 | digitalWrite(_spiChipSelectPin, HIGH); 94 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 95 | return readbackRegisterValue; 96 | } 97 | 98 | uint8_t MagAlphaGen4::writeRegister(uint8_t address, uint8_t value){ 99 | uint8_t readbackRegisterValue; 100 | digitalWrite(_spiChipSelectPin, LOW); 101 | _spi->transfer16(WRITE_REG_COMMAND | ((address & 0x1F) << 8) | value); 102 | digitalWrite(_spiChipSelectPin, HIGH); 103 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout 104 | digitalWrite(_spiChipSelectPin, LOW); 105 | readbackRegisterValue = (_spi->transfer16(0x0000) & 0x00FF); 106 | digitalWrite(_spiChipSelectPin, HIGH); 107 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 108 | return readbackRegisterValue; 109 | } 110 | 111 | void MagAlphaGen4::readRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister){ 112 | uint8_t readbackRegisterValue; 113 | digitalWrite(_spiChipSelectPin, LOW); 114 | _spi->transfer16(READ_REG_COMMAND | (((address) & 0x1F) << 8) | 0x00); 115 | digitalWrite(_spiChipSelectPin, HIGH); 116 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout 117 | for (uint8_t i=0;itransfer16(READ_REG_COMMAND | (((address+i+1) & 0x1F) << 8) | 0x00) & 0x00FF); 120 | digitalWrite(_spiChipSelectPin, HIGH); 121 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout 122 | } 123 | digitalWrite(_spiChipSelectPin, LOW); 124 | valueArray[numberOfRegister-1] = (_spi->transfer16(0x0000) & 0x00FF); 125 | digitalWrite(_spiChipSelectPin, HIGH); 126 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 127 | } 128 | 129 | void MagAlphaGen4::writeRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister){ 130 | for (uint8_t i=0;itransfer16(WRITE_REG_COMMAND | (((address+i) & 0x1F) << 8) | valueArray[i]); 133 | digitalWrite(_spiChipSelectPin, HIGH); 134 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 135 | } 136 | digitalWrite(_spiChipSelectPin, LOW); 137 | _spi->transfer16(0x0000); 138 | digitalWrite(_spiChipSelectPin, HIGH); 139 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 140 | } 141 | 142 | /* 143 | uint16_t MagAlphaGen4::detectSensorGeneration(){ 144 | uint16_t chipId; 145 | digitalWrite(_spiChipSelectPin, LOW); 146 | _spi->transfer16(0x6000); 147 | digitalWrite(_spiChipSelectPin, HIGH); 148 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout 149 | digitalWrite(_spiChipSelectPin, LOW); 150 | chipId = _spi->transfer16(0x0000) & 0x00FF; 151 | digitalWrite(_spiChipSelectPin, HIGH); 152 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 153 | return chipId; 154 | } 155 | */ 156 | 157 | uint16_t MagAlphaGen4::getZero() 158 | { 159 | return (readRegister(1)<<8) + readRegister(0); 160 | } 161 | 162 | void MagAlphaGen4::setZero(uint16_t zero){ 163 | writeRegister(0, zero&0xFF); 164 | writeRegister(1, zero>>8); 165 | } 166 | 167 | uint16_t MagAlphaGen4::setCurrentAngleAsZero(){ 168 | uint16_t zero; 169 | setZero(0); 170 | zero=readAngleRaw16(); 171 | setZero(zero); 172 | return zero; 173 | } 174 | 175 | uint16_t MagAlphaGen4::getBct(){ 176 | return readRegister(2); 177 | } 178 | 179 | void MagAlphaGen4::setBct(uint16_t bct){ 180 | writeRegister(2, bct&0xFF); 181 | } 182 | 183 | void MagAlphaGen4::restoreAllRegisters(){ 184 | digitalWrite(_spiChipSelectPin, LOW); 185 | _spi->transfer16(RESTORE_ALL_REGISTERS_COMMAND); 186 | digitalWrite(_spiChipSelectPin, HIGH); 187 | delayMicroseconds(240); //Wait for 240us 188 | digitalWrite(_spiChipSelectPin, LOW); 189 | _spi->transfer16(0x0000); 190 | digitalWrite(_spiChipSelectPin, HIGH); 191 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 192 | } 193 | 194 | void MagAlphaGen4::storeAllRegisters(){ 195 | digitalWrite(_spiChipSelectPin, LOW); 196 | _spi->transfer16(STORE_ALL_REGISTERS_COMMAND); 197 | digitalWrite(_spiChipSelectPin, HIGH); 198 | delay(704); //Wait for 704ms 199 | digitalWrite(_spiChipSelectPin, LOW); 200 | _spi->transfer16(0x0000); 201 | digitalWrite(_spiChipSelectPin, HIGH); 202 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 203 | } 204 | 205 | void MagAlphaGen4::storeRegister(uint8_t address){ 206 | digitalWrite(_spiChipSelectPin, LOW); 207 | _spi->transfer16(STORE_SINGLE_REGISTER_COMMAND | ((address & 0x1F) << 8) | 0x00); 208 | digitalWrite(_spiChipSelectPin, HIGH); 209 | delay(23); //Wait for 23ms 210 | digitalWrite(_spiChipSelectPin, LOW); 211 | _spi->transfer16(0x0000); 212 | digitalWrite(_spiChipSelectPin, HIGH); 213 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 214 | } 215 | 216 | void MagAlphaGen4::clearErrorFlags(){ 217 | digitalWrite(_spiChipSelectPin, LOW); 218 | _spi->transfer16(CLEAR_ERROR_FLAGS_COMMAND); 219 | digitalWrite(_spiChipSelectPin, HIGH); 220 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tClearFault of 40ns before register readout 221 | digitalWrite(_spiChipSelectPin, LOW); 222 | _spi->transfer16(0x0000); 223 | digitalWrite(_spiChipSelectPin, HIGH); 224 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 225 | } 226 | 227 | uint16_t MagAlphaGen4::getNumberOfRegisters(){ 228 | return 32; 229 | } 230 | 231 | void MagAlphaGen4::getLockedRegisters(uint8_t unlockedRegisters[]){ 232 | uint8_t registerArray[4] = {0}; 233 | readRegisterBurst(REG_LOCK0, registerArray, 4); 234 | for(uint8_t i=0; i<4; i++){ 235 | for(uint8_t j=0; j<8; j++){ 236 | unlockedRegisters[i*8+j] = ((registerArray[i]>>j)&0x01) ? 0xFF : 0x00; 237 | } 238 | } 239 | } 240 | 241 | void MagAlphaGen4::getPartNumber(char *partNumber){ 242 | uint8_t partId = readRegister(REG_PID); 243 | switch(partId) { 244 | case 1: 245 | sprintf(partNumber, "MA780"); 246 | break; 247 | case 2: 248 | sprintf(partNumber, "MA781"); 249 | break; 250 | case 3: 251 | sprintf(partNumber, "MA782"); 252 | break; 253 | case 248: 254 | sprintf(partNumber, "MA736"); 255 | break; 256 | case 249: 257 | sprintf(partNumber, "MA734"); 258 | break; 259 | case 250: 260 | sprintf(partNumber, "MA734"); 261 | break; 262 | default: 263 | sprintf(partNumber, "Gen4 [%u] Unknown Part Number", partId); 264 | } 265 | } 266 | 267 | uint8_t MagAlphaGen4::getSiliconId(){ 268 | return (readRegister(REG_SID) & 0xF0) >> 4; 269 | } 270 | 271 | uint8_t MagAlphaGen4::getSiliconRevision(){ 272 | return readRegister(REG_SID) & 0x0F; 273 | } 274 | 275 | uint8_t MagAlphaGen4::getRegisterMapRevision(){ 276 | return readRegister(REG_REGMAPID); 277 | } 278 | -------------------------------------------------------------------------------- /src/MagAlphaGen3.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | Arduino library for the MPS MagAlpha magnetic angle sensor 3 | Supports MagAlpha 3rd generation Sensors. 4 | Support Part Number includes: MA102, MA302, MA310, MA330, 5 | MA702, MA704, MA710, MA730, MA731, MA732, MA800, MA820, MA850, MAQ430, 6 | MAQ470, MAQ473, MAP790-xxxx, MAP791-xxxx 7 | MagAlpha sensor detects the 8 | absolute angular position of a permanent magnet, typically a diametrically 9 | magnetized cylinder on the rotating shaft. 10 | ----> http://www.monolithicpower.com/Products/Position-Sensors/Products-Overview 11 | Written by Mathieu Kaelin for Monolithic Power Systems. 12 | MIT license, all text above must be included in any redistribution 13 | ****************************************************/ 14 | 15 | #include "MagAlphaGen3.h" 16 | 17 | //MagAlpha Read/Write Register Command 18 | #define READ_REG_COMMAND (0b010 << 13) 19 | #define WRITE_REG_COMMAND (0b100 << 13) 20 | 21 | #define REG_REGMAPID 23 22 | #define REG_SID 24 23 | #define REG_PID 25 24 | #define REG_LOCK0 28 25 | #define REG_LOCK1 29 26 | #define REG_LOCK2 30 27 | #define REG_LOCK3 31 28 | 29 | MagAlphaGen3::MagAlphaGen3(){ 30 | } 31 | 32 | uint16_t MagAlphaGen3::readAngleRaw16(){ 33 | uint16_t angle; 34 | digitalWrite(_spiChipSelectPin, LOW); 35 | angle = _spi->transfer16(0x0000); //Read 16-bit angle 36 | digitalWrite(_spiChipSelectPin, HIGH); 37 | return angle; 38 | } 39 | 40 | uint8_t MagAlphaGen3::readAngleRaw8(){ 41 | uint8_t angle; 42 | digitalWrite(_spiChipSelectPin, LOW); 43 | angle = _spi->transfer(0x00); //Read 8-bit angle 44 | digitalWrite(_spiChipSelectPin, HIGH); 45 | return angle; 46 | } 47 | 48 | uint16_t MagAlphaGen3::readAngleRaw(bool* error){ 49 | uint16_t angle; 50 | uint8_t parity; 51 | uint8_t highStateCount = 0; 52 | digitalWrite(_spiChipSelectPin, LOW); 53 | angle = _spi->transfer16(0x0000); 54 | parity = _spi->transfer(0x00); 55 | digitalWrite(_spiChipSelectPin, HIGH); 56 | parity = ((parity & 0x80) >> 7); 57 | //Count the number of 1 in the angle binary value 58 | for (int i=0;i<16;++i){ 59 | if ((angle & (1 << i)) != 0){ 60 | highStateCount++; 61 | } 62 | } 63 | //check if parity bit is correct 64 | if ((highStateCount % 2) == 0){ 65 | if (parity == 0){ 66 | *error = false; 67 | } 68 | else{ 69 | *error = true; 70 | } 71 | } 72 | else{ 73 | if (parity == 1){ 74 | *error = false; 75 | } 76 | else{ 77 | *error = true; 78 | } 79 | } 80 | return angle; 81 | } 82 | 83 | uint8_t MagAlphaGen3::readRegister(uint8_t address){ 84 | uint8_t readbackRegisterValue; 85 | digitalWrite(_spiChipSelectPin, LOW); 86 | _spi->transfer16(READ_REG_COMMAND | ((address & 0x1F) << 8) | 0x00); 87 | digitalWrite(_spiChipSelectPin, HIGH); 88 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 750ns before register readout 89 | digitalWrite(_spiChipSelectPin, LOW); 90 | readbackRegisterValue = ((_spi->transfer16(0x0000) & 0xFF00) >> 8); 91 | digitalWrite(_spiChipSelectPin, HIGH); 92 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 750ns after register readout 93 | return readbackRegisterValue; 94 | } 95 | 96 | uint8_t MagAlphaGen3::writeRegister(uint8_t address, uint8_t value){ 97 | uint8_t readbackRegisterValue; 98 | digitalWrite(_spiChipSelectPin, LOW); 99 | _spi->transfer16(WRITE_REG_COMMAND | ((address & 0x1F) << 8) | value); 100 | digitalWrite(_spiChipSelectPin, HIGH); 101 | delay(20); //Wait for 20ms 102 | digitalWrite(_spiChipSelectPin, LOW); 103 | readbackRegisterValue = ((_spi->transfer16(0x0000) & 0xFF00) >> 8); 104 | digitalWrite(_spiChipSelectPin, HIGH); 105 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 750ns after register readout 106 | return readbackRegisterValue; 107 | } 108 | 109 | void MagAlphaGen3::readRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister){ 110 | digitalWrite(_spiChipSelectPin, LOW); 111 | _spi->transfer16(READ_REG_COMMAND | (((address) & 0x1F) << 8) | 0x00); 112 | digitalWrite(_spiChipSelectPin, HIGH); 113 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 750ns before register readout 114 | for (uint8_t i=0;itransfer16(READ_REG_COMMAND | (((address+i+1) & 0x1F) << 8) | 0x00) >> 8); 117 | digitalWrite(_spiChipSelectPin, HIGH); 118 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 750ns before register readout 119 | } 120 | digitalWrite(_spiChipSelectPin, LOW); 121 | valueArray[numberOfRegister-1] = (_spi->transfer16(0x0000) >> 8); 122 | digitalWrite(_spiChipSelectPin, HIGH); 123 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 750ns after register readout 124 | } 125 | 126 | void MagAlphaGen3::writeRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister){ 127 | for (uint8_t i=0;itransfer16(WRITE_REG_COMMAND | (((address+i) & 0x1F) << 8) | valueArray[i]); 130 | digitalWrite(_spiChipSelectPin, HIGH); 131 | delay(20); //Wait for 20ms 132 | } 133 | digitalWrite(_spiChipSelectPin, LOW); 134 | _spi->transfer16(0x0000); 135 | digitalWrite(_spiChipSelectPin, HIGH); 136 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 137 | } 138 | 139 | /* 140 | uint16_t MagAlphaGen3::detectSensorGeneration(){ 141 | uint16_t chipId; 142 | digitalWrite(_spiChipSelectPin, LOW); 143 | _spi->transfer16(0xFF00); 144 | digitalWrite(_spiChipSelectPin, HIGH); 145 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 750ns before register readout 146 | digitalWrite(_spiChipSelectPin, LOW); 147 | chipId = _spi->transfer16(0x0000); 148 | digitalWrite(_spiChipSelectPin, HIGH); 149 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 750ns after register readout 150 | return chipId; 151 | } 152 | */ 153 | 154 | uint16_t MagAlphaGen3::getZero() 155 | { 156 | return (readRegister(1)<<8) + readRegister(0); 157 | } 158 | void MagAlphaGen3::setZero(uint16_t zero){ 159 | writeRegister(0, zero&0xFF); 160 | writeRegister(1, zero>>8); 161 | } 162 | 163 | uint16_t MagAlphaGen3::setCurrentAngleAsZero(){ 164 | uint16_t angle, zero; 165 | setZero(0); 166 | angle=readAngleRaw16(); 167 | zero=65536-angle; 168 | setZero(zero); 169 | return zero; 170 | } 171 | 172 | uint16_t MagAlphaGen3::getBct(){ 173 | return readRegister(2); 174 | } 175 | 176 | void MagAlphaGen3::setBct(uint16_t bct){ 177 | writeRegister(2, bct&0xFF); 178 | } 179 | 180 | uint16_t MagAlphaGen3::getNumberOfRegisters(){ 181 | return 32; 182 | } 183 | 184 | void MagAlphaGen3::getLockedRegisters(uint8_t unlockedRegisters[]){ 185 | uint8_t registerArray[4] = {0}; 186 | readRegisterBurst(REG_LOCK0, registerArray, 4); 187 | for(uint8_t i=0; i<4; i++){ 188 | for(uint8_t j=0; j<8; j++){ 189 | unlockedRegisters[i*8+j] = ((registerArray[i]>>j)&0x01) ? 0xFF : 0x00; 190 | } 191 | } 192 | } 193 | 194 | void MagAlphaGen3::getPartNumber(char *partNumber){ 195 | uint8_t partId = readRegister(REG_PID); 196 | switch(partId) { 197 | case 1: 198 | sprintf(partNumber, "MA102"); 199 | break; 200 | case 2: 201 | sprintf(partNumber, "MA302"); 202 | break; 203 | case 21: 204 | sprintf(partNumber, "MA302GQ-E"); 205 | break; 206 | case 3: 207 | sprintf(partNumber, "MA310"); 208 | break; 209 | case 4: 210 | sprintf(partNumber, "MA702"); 211 | break; 212 | case 5: 213 | sprintf(partNumber, "MA704"); 214 | break; 215 | case 6: 216 | sprintf(partNumber, "MA710"); 217 | break; 218 | case 7: 219 | sprintf(partNumber, "MA730"); 220 | break; 221 | case 8: 222 | sprintf(partNumber, "MA800"); 223 | break; 224 | case 9: 225 | sprintf(partNumber, "MA820"); 226 | break; 227 | case 10: 228 | sprintf(partNumber, "MA850"); 229 | break; 230 | case 12: 231 | sprintf(partNumber, "MAQ430"); 232 | break; 233 | case 14: 234 | sprintf(partNumber, "MAQ470"); 235 | break; 236 | case 16: 237 | sprintf(partNumber, "MA330"); 238 | break; 239 | case 17: 240 | sprintf(partNumber, "MA731"); 241 | break; 242 | case 18: 243 | sprintf(partNumber, "MA732"); 244 | break; 245 | case 20: 246 | sprintf(partNumber, "MP9961"); 247 | break; 248 | case 22: 249 | sprintf(partNumber, "MAQ473"); 250 | break; 251 | case 23: 252 | sprintf(partNumber, "MA735"); 253 | break; 254 | case 24: 255 | sprintf(partNumber, "MAQ800"); 256 | break; 257 | case 25: 258 | sprintf(partNumber, "MAQ820"); 259 | break; 260 | case 26: 261 | sprintf(partNumber, "MAQ850"); 262 | break; 263 | case 128: 264 | sprintf(partNumber, "MAP790-0000"); 265 | break; 266 | case 129: 267 | sprintf(partNumber, "MAP790-0001"); 268 | break; 269 | case 132: 270 | sprintf(partNumber, "MAP790-0004"); 271 | break; 272 | case 250: 273 | sprintf(partNumber, "MAP790-0010"); 274 | break; 275 | case 251: 276 | sprintf(partNumber, "MAP790-0002"); 277 | break; 278 | case 252: 279 | sprintf(partNumber, "MAP791-0004"); 280 | break; 281 | default: 282 | sprintf(partNumber, "Gen3 [%u] Unknown Part Number", partId); 283 | } 284 | } 285 | 286 | uint8_t MagAlphaGen3::getSiliconId(){ 287 | return (readRegister(REG_SID) & 0xF0) >> 4; 288 | } 289 | 290 | uint8_t MagAlphaGen3::getSiliconRevision(){ 291 | return readRegister(REG_SID) & 0x0F; 292 | } 293 | 294 | uint8_t MagAlphaGen3::getRegisterMapRevision(){ 295 | return readRegister(REG_REGMAPID); 296 | } 297 | 298 | // void MagAlphaGen3::setSpiClockFrequency(uint32_t speedMaximum){ 299 | // _speedMaximum = speedMaximum; 300 | // SPI.beginTransaction(SPISettings(_speedMaximum, MSBFIRST, _spiMode)); 301 | // } 302 | 303 | // void MagAlphaGen3::setSpiDataMode(uint8_t spiMode){ 304 | // _spiMode = spiMode; 305 | // SPI.beginTransaction(SPISettings(_speedMaximum, MSBFIRST, _spiMode)); 306 | // } 307 | 308 | // void MagAlphaGen3::setSpiChipSelectPin(uint8_t spiChipSelectPin){ 309 | // _spiChipSelectPin = spiChipSelectPin; 310 | // pinMode(_spiChipSelectPin, OUTPUT); 311 | // digitalWrite(_spiChipSelectPin, HIGH); 312 | // } 313 | 314 | // double MagAlphaGen3::convertRawAngleToDegree(uint8_t rawAngleDataBitLength, uint16_t rawAngle){ 315 | // double angleInDegree; 316 | // angleInDegree = (rawAngle*360.0)/((double)pow(2, rawAngleDataBitLength)); 317 | // return angleInDegree; 318 | // } 319 | 320 | // MagAlphaSSI::MagAlphaSSI(){ 321 | // } 322 | // void MagAlphaSSI::begin(){ 323 | // _speedMaximum = 1000000; 324 | // SPI.begin(); 325 | // SPI.beginTransaction(SPISettings(_speedMaximum, MSBFIRST, SSI_MODE)); 326 | // } 327 | 328 | // void MagAlphaSSI::begin(int32_t ssiSsckFrequency){ 329 | // _speedMaximum = ssiSsckFrequency; 330 | // SPI.begin(); 331 | // SPI.beginTransaction(SPISettings(_speedMaximum, MSBFIRST, SSI_MODE)); 332 | // } 333 | 334 | // void MagAlphaSSI::end(){ 335 | // SPI.end(); 336 | // } 337 | 338 | // double MagAlphaSSI::readAngle(){ 339 | // uint16_t angle; 340 | // double angleInDegree; 341 | // angle = readAngleRaw(); 342 | // angleInDegree = (angle*360.0)/65536.0; 343 | // return angleInDegree; 344 | // } 345 | 346 | // uint16_t MagAlphaSSI::readAngleRaw(){ 347 | // uint16_t angle; 348 | // uint8_t angle0; 349 | // uint8_t angle1; 350 | // uint8_t angle2; 351 | 352 | // angle0 = SPI.transfer(0x00); 353 | // angle1 = SPI.transfer(0x00); 354 | // angle2 = SPI.transfer(0x00); 355 | 356 | // angle = ((angle0 & 0x7F) << 9) | (angle1 << 1) | ((angle2 & 0x80) >> 7); 357 | // return angle; 358 | // } 359 | 360 | // uint16_t MagAlphaSSI::readAngleRaw(bool* error){ 361 | // uint16_t angle; 362 | // uint8_t parity; 363 | // uint8_t highStateCount = 0; 364 | // uint8_t angle0; 365 | // uint8_t angle1; 366 | // uint8_t angle2; 367 | 368 | // angle0 = SPI.transfer(0x00); 369 | // angle1 = SPI.transfer(0x00); 370 | // angle2 = SPI.transfer(0x00); 371 | 372 | // angle = ((angle0 & 0x7F) << 9) | (angle1 << 1) | ((angle2 & 0x80) >> 7); 373 | // parity = ((angle2 & 0x40) >> 6); 374 | // //Count the number of 1 in the angle binary value 375 | // for (int i=0;i<16;++i){ 376 | // if ((angle & (1 << i)) != 0){ 377 | // highStateCount++; 378 | // } 379 | // } 380 | // //check if parity bit is correct 381 | // if ((highStateCount % 2) == 0){ 382 | // if (parity == 0){ 383 | // *error = false; 384 | // } 385 | // else{ 386 | // *error = true; 387 | // } 388 | // } 389 | // else{ 390 | // if (parity == 1){ 391 | // *error = false; 392 | // } 393 | // else{ 394 | // *error = true; 395 | // } 396 | // } 397 | // return angle; 398 | // } 399 | 400 | // void MagAlphaSSI::setSsiClockFrequency(uint32_t speedMaximum){ 401 | // _speedMaximum = speedMaximum; 402 | // SPI.beginTransaction(SPISettings(_speedMaximum, MSBFIRST, SSI_MODE)); 403 | // } 404 | 405 | // double MagAlphaSSI::convertRawAngleToDegree(uint8_t rawAngleDataBitLength, uint16_t rawAngle){ 406 | // double angleInDegree; 407 | // angleInDegree = (rawAngle*360.0)/((double)pow(2, rawAngleDataBitLength)); 408 | // return angleInDegree; 409 | // } 410 | -------------------------------------------------------------------------------- /src/MagAlphaGen6.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | Arduino library for the MPS MagAlpha magnetic angle sensor 3 | Supports MagAlpha 6th generation Sensors. 4 | Support Part Number includes: MA600 5 | MagAlpha sensor detects the 6 | absolute angular position of a permanent magnet, typically a diametrically 7 | magnetized cylinder on the rotating shaft. 8 | ----> http://www.monolithicpower.com/Products/Position-Sensors/Products-Overview 9 | Written by Mathieu Kaelin for Monolithic Power Systems. 10 | MIT license, all text above must be included in any redistribution 11 | ****************************************************/ 12 | 13 | #include "MagAlphaGen6.h" 14 | 15 | //MagAlpha Read/Write Register Command 16 | #define READ_REG_COMMAND (0b11010010 << 8) 17 | #define WRITE_REG_COMMAND (0b1110101001010100) 18 | 19 | #define REG_REGMAPID 30 20 | #define REG_PID 31 21 | #define REG_LOCK0 156 22 | #define REG_LOCK1 157 23 | #define REG_LOCK2 158 24 | #define REG_LOCK3 159 25 | 26 | MagAlphaGen6::MagAlphaGen6(){ 27 | } 28 | 29 | uint16_t MagAlphaGen6::readAngleRaw16(){ 30 | uint16_t angle; 31 | digitalWrite(_spiChipSelectPin, LOW); 32 | angle = _spi->transfer16(0x0000); //Read 16-bit angle 33 | digitalWrite(_spiChipSelectPin, HIGH); 34 | return angle; 35 | } 36 | 37 | uint8_t MagAlphaGen6::readAngleRaw8(){ 38 | uint8_t angle; 39 | digitalWrite(_spiChipSelectPin, LOW); 40 | angle = _spi->transfer(0x00); //Read 8-bit angle 41 | digitalWrite(_spiChipSelectPin, HIGH); 42 | return angle; 43 | } 44 | 45 | uint16_t MagAlphaGen6::readAngleRaw(bool* error){ 46 | uint16_t angle; 47 | uint8_t parity; 48 | uint8_t highStateCount = 0; 49 | digitalWrite(_spiChipSelectPin, LOW); 50 | angle = _spi->transfer16(0x0000); 51 | parity = _spi->transfer(0x00); 52 | digitalWrite(_spiChipSelectPin, HIGH); 53 | parity = ((parity & 0x80) >> 7); 54 | //Count the number of 1 in the angle binary value 55 | for (int i=0;i<16;++i){ 56 | if ((angle & (1 << i)) != 0){ 57 | highStateCount++; 58 | } 59 | } 60 | //check if parity bit is correct 61 | if ((highStateCount % 2) == 0){ 62 | if (parity == 0){ 63 | *error = false; 64 | } 65 | else{ 66 | *error = true; 67 | } 68 | } 69 | else{ 70 | if (parity == 1){ 71 | *error = false; 72 | } 73 | else{ 74 | *error = true; 75 | } 76 | } 77 | return angle; 78 | } 79 | 80 | uint8_t MagAlphaGen6::readRegister(uint8_t address){ 81 | uint8_t readbackRegisterValue; 82 | digitalWrite(_spiChipSelectPin, LOW); 83 | _spi->transfer16(READ_REG_COMMAND | address); 84 | digitalWrite(_spiChipSelectPin, HIGH); 85 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout 86 | digitalWrite(_spiChipSelectPin, LOW); 87 | readbackRegisterValue = _spi->transfer16(0x0000) & 0x00FF; 88 | digitalWrite(_spiChipSelectPin, HIGH); 89 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 90 | return readbackRegisterValue; 91 | } 92 | 93 | uint8_t MagAlphaGen6::writeRegister(uint8_t address, uint8_t value){ 94 | uint8_t readbackRegisterValue; 95 | digitalWrite(_spiChipSelectPin, LOW); 96 | _spi->transfer16(WRITE_REG_COMMAND); 97 | digitalWrite(_spiChipSelectPin, HIGH); 98 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout 99 | digitalWrite(_spiChipSelectPin, LOW); 100 | _spi->transfer16((address << 8) | value); 101 | digitalWrite(_spiChipSelectPin, HIGH); 102 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout 103 | digitalWrite(_spiChipSelectPin, LOW); 104 | readbackRegisterValue = (_spi->transfer16(0x0000) & 0x00FF); 105 | digitalWrite(_spiChipSelectPin, HIGH); 106 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 107 | return readbackRegisterValue; 108 | } 109 | 110 | void MagAlphaGen6::readRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister){ 111 | uint8_t readbackRegisterValue; 112 | digitalWrite(_spiChipSelectPin, LOW); 113 | _spi->transfer16(READ_REG_COMMAND | address); 114 | digitalWrite(_spiChipSelectPin, HIGH); 115 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout 116 | for (uint8_t i=0;itransfer16(READ_REG_COMMAND | (address+i+1)) & 0x00FF; 119 | digitalWrite(_spiChipSelectPin, HIGH); 120 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout 121 | } 122 | digitalWrite(_spiChipSelectPin, LOW); 123 | valueArray[numberOfRegister-1] = _spi->transfer16(0x0000) & 0x00FF; 124 | digitalWrite(_spiChipSelectPin, HIGH); 125 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 126 | } 127 | 128 | void MagAlphaGen6::writeRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister){ 129 | for (uint8_t i=0;itransfer16(WRITE_REG_COMMAND); 132 | digitalWrite(_spiChipSelectPin, HIGH); 133 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 134 | digitalWrite(_spiChipSelectPin, LOW); 135 | _spi->transfer16(((address+i) << 8) | valueArray[i]); 136 | digitalWrite(_spiChipSelectPin, HIGH); 137 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 138 | } 139 | digitalWrite(_spiChipSelectPin, LOW); 140 | _spi->transfer16(0x0000); 141 | digitalWrite(_spiChipSelectPin, HIGH); 142 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 143 | } 144 | 145 | /* 146 | uint16_t MagAlphaGen6::detectSensorGeneration(){ 147 | uint16_t chipId; 148 | digitalWrite(_spiChipSelectPin, LOW); 149 | _spi->transfer16(0xD300); 150 | digitalWrite(_spiChipSelectPin, HIGH); 151 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 152 | digitalWrite(_spiChipSelectPin, LOW); 153 | chipId = _spi->transfer16(0x0000)&0xFF; 154 | digitalWrite(_spiChipSelectPin, HIGH); 155 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 156 | return chipId; 157 | } 158 | */ 159 | 160 | uint16_t MagAlphaGen6::getZero() 161 | { 162 | return (readRegister(1)<<8) + readRegister(0); 163 | } 164 | void MagAlphaGen6::setZero(uint16_t zero){ 165 | writeRegister(0, zero&0xFF); 166 | writeRegister(1, zero>>8); 167 | } 168 | 169 | uint16_t MagAlphaGen6::setCurrentAngleAsZero(){ 170 | uint16_t zero; 171 | setZero(0); 172 | zero=readAngleRaw16(); 173 | setZero(zero); 174 | return zero; 175 | } 176 | 177 | uint16_t MagAlphaGen6::getBct(){ 178 | return readRegister(2); 179 | } 180 | 181 | void MagAlphaGen6::setBct(uint16_t bct){ 182 | writeRegister(2, bct&0xFF); 183 | } 184 | 185 | void MagAlphaGen6::restoreAllRegisters(){ 186 | digitalWrite(_spiChipSelectPin, LOW); 187 | _spi->transfer16(0b1110101001010110); 188 | digitalWrite(_spiChipSelectPin, HIGH); 189 | delayMicroseconds(240); //Wait for 240us 190 | digitalWrite(_spiChipSelectPin, LOW); 191 | _spi->transfer16(0x0000); 192 | digitalWrite(_spiChipSelectPin, HIGH); 193 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 194 | } 195 | 196 | void MagAlphaGen6::storeAllRegisters(){ 197 | storeRegisterBlock(0); 198 | storeRegisterBlock(1); 199 | } 200 | 201 | void MagAlphaGen6::storeRegisterBlock(uint8_t block){ 202 | digitalWrite(_spiChipSelectPin, LOW); 203 | _spi->transfer16(0b1110101001010101); 204 | digitalWrite(_spiChipSelectPin, HIGH); 205 | delayMicroseconds(1); 206 | digitalWrite(_spiChipSelectPin, LOW); 207 | _spi->transfer16(0b1110101000000000 | (block & 0x1)); 208 | digitalWrite(_spiChipSelectPin, HIGH); 209 | delay(600); //Wait for 600ms 210 | digitalWrite(_spiChipSelectPin, LOW); 211 | _spi->transfer16(0x0000); 212 | digitalWrite(_spiChipSelectPin, HIGH); 213 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 214 | } 215 | 216 | void MagAlphaGen6::clearErrorFlags(){ 217 | digitalWrite(_spiChipSelectPin, LOW); 218 | _spi->transfer16(0b1101011100000000); 219 | digitalWrite(_spiChipSelectPin, HIGH); 220 | delayMicroseconds(1); 221 | digitalWrite(_spiChipSelectPin, LOW); 222 | _spi->transfer16(0x0000); 223 | digitalWrite(_spiChipSelectPin, HIGH); 224 | delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout 225 | } 226 | 227 | double MagAlphaGen6::readSpeed(){ 228 | uint16_t angle; 229 | uint16_t multiturnOrSpeed; 230 | //The choice between multiturn and speed is done by settings MTSP 231 | //for multiturn MTSP=0, for speed MTSP=1. This is a volatile settings 232 | //MTSP = 1, PRT = 0, PRTS = 0, APRT=0, FTA(1:0)=0, FTM=0 233 | writeRegister(28, 0x80); 234 | readAngleAndMultiturnOrSpeedRaw(&angle, &multiturnOrSpeed); 235 | return twosComplement(multiturnOrSpeed, 16) * 5.722; 236 | } 237 | 238 | int16_t MagAlphaGen6::readTurn(){ 239 | uint16_t angle; 240 | uint16_t multiturnOrSpeed; 241 | //The choice between multiturn and speed is done by settings MTSP 242 | //for multiturn MTSP=0, for speed MTSP=1. This is a volatile settings 243 | //MTSP = 0, PRT = 0, PRTS = 0, APRT=0, FTA(1:0)=0, FTM=0 244 | writeRegister(28, 0x00); 245 | readAngleAndMultiturnOrSpeedRaw(&angle, &multiturnOrSpeed); 246 | return twosComplement(multiturnOrSpeed, 16); 247 | } 248 | 249 | void MagAlphaGen6::readAngleAndMultiturnOrSpeedRaw(uint16_t *angle, uint16_t *multiturnOrSpeed){ 250 | digitalWrite(_spiChipSelectPin, LOW); 251 | *angle = _spi->transfer16(0x0000); //Read 16-bit angle 252 | *multiturnOrSpeed = _spi->transfer16(0x0000); //Read 16-bit angle 253 | digitalWrite(_spiChipSelectPin, HIGH); 254 | } 255 | 256 | void MagAlphaGen6::writeTurn(int16_t turn){ 257 | uint16_t mtoffset = twosComplementInverse(turn, 16); 258 | writeRegister(18, mtoffset&0xFF); 259 | writeRegister(19, mtoffset>>8); 260 | } 261 | 262 | uint16_t MagAlphaGen6::getNumberOfRegisters(){ 263 | return 160; 264 | } 265 | 266 | void MagAlphaGen6::getLockedRegisters(uint8_t unlockedRegisters[]){ 267 | uint8_t i, j; 268 | uint8_t registerArray[4] = {0}; 269 | readRegisterBurst(REG_LOCK0, registerArray, 4); 270 | for(i=0; i<3; i++){ 271 | for(j=0; j<8; j++){ 272 | unlockedRegisters[i*8+j] = ((registerArray[i]>>j)&0x01) ? 0xFF : 0x00; 273 | } 274 | } 275 | i = 3; 276 | for(j=0; j<2; j++){ 277 | unlockedRegisters[i*8+j] = ((registerArray[i]>>j)&0x01) ? 0xFF : 0x00; 278 | } 279 | for (j=32; j<64; j++){ 280 | unlockedRegisters[j] = ((registerArray[3]>>2)&0x01) ? 0xFF : 0x00; 281 | } 282 | } 283 | 284 | void MagAlphaGen6::getPartNumber(char *partNumber){ 285 | sprintf(partNumber, "MA600"); 286 | } 287 | 288 | uint8_t MagAlphaGen6::getSiliconId(){ 289 | return readRegister(REG_PID) & 0x3F; 290 | } 291 | 292 | uint8_t MagAlphaGen6::getSiliconRevision(){ 293 | return readRegister(REG_PID) & 0x3F; 294 | } 295 | 296 | uint8_t MagAlphaGen6::getRegisterMapRevision(){ 297 | return readRegister(REG_REGMAPID) & 0x7F; 298 | } 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | // void MagAlphaGen6::setSpiClockFrequency(uint32_t speedMaximum){ 307 | // _speedMaximum = speedMaximum; 308 | // SPI.beginTransaction(SPISettings(_speedMaximum, MSBFIRST, _spiMode)); 309 | // } 310 | 311 | // void MagAlphaGen6::setSpiDataMode(uint8_t spiMode){ 312 | // _spiMode = spiMode; 313 | // SPI.beginTransaction(SPISettings(_speedMaximum, MSBFIRST, _spiMode)); 314 | // } 315 | 316 | // void MagAlphaGen6::setSpiChipSelectPin(uint8_t spiChipSelectPin){ 317 | // _spiChipSelectPin = spiChipSelectPin; 318 | // pinMode(_spiChipSelectPin, OUTPUT); 319 | // digitalWrite(_spiChipSelectPin, HIGH); 320 | // } 321 | 322 | // double MagAlphaGen6::convertRawAngleToDegree(uint8_t rawAngleDataBitLength, uint16_t rawAngle){ 323 | // double angleInDegree; 324 | // angleInDegree = (rawAngle*360.0)/((double)pow(2, rawAngleDataBitLength)); 325 | // return angleInDegree; 326 | // } 327 | 328 | 329 | // MagAlphaSSIGen6::MagAlphaSSIGen6(){ 330 | // } 331 | // void MagAlphaSSIGen6::begin(){ 332 | // _speedMaximum = 1000000; 333 | // SPI.begin(); 334 | // SPI.beginTransaction(SPISettings(_speedMaximum, MSBFIRST, SSI_MODE)); 335 | // } 336 | 337 | // void MagAlphaSSIGen6::begin(int32_t ssiSsckFrequency){ 338 | // _speedMaximum = ssiSsckFrequency; 339 | // SPI.begin(); 340 | // SPI.beginTransaction(SPISettings(_speedMaximum, MSBFIRST, SSI_MODE)); 341 | // } 342 | 343 | // void MagAlphaSSIGen6::end(){ 344 | // SPI.end(); 345 | // } 346 | 347 | // double MagAlphaSSIGen6::readAngle(){ 348 | // uint16_t angle; 349 | // double angleInDegree; 350 | // angle = readAngleRaw(); 351 | // angleInDegree = (angle*360.0)/65536.0; 352 | // return angleInDegree; 353 | // } 354 | 355 | // uint16_t MagAlphaSSIGen6::readAngleRaw(){ 356 | // uint16_t angle; 357 | // uint8_t angle0; 358 | // uint8_t angle1; 359 | // uint8_t angle2; 360 | 361 | // angle0 = SPI.transfer(0x00); 362 | // angle1 = SPI.transfer(0x00); 363 | // angle2 = SPI.transfer(0x00); 364 | 365 | // angle = ((angle0 & 0x7F) << 9) | (angle1 << 1) | ((angle2 & 0x80) >> 7); 366 | // return angle; 367 | // } 368 | 369 | // uint16_t MagAlphaSSIGen6::readAngleRaw(bool* error){ 370 | // uint16_t angle; 371 | // uint8_t parity; 372 | // uint8_t highStateCount = 0; 373 | // uint8_t angle0; 374 | // uint8_t angle1; 375 | // uint8_t angle2; 376 | 377 | // angle0 = SPI.transfer(0x00); 378 | // angle1 = SPI.transfer(0x00); 379 | // angle2 = SPI.transfer(0x00); 380 | 381 | // angle = ((angle0 & 0x7F) << 9) | (angle1 << 1) | ((angle2 & 0x80) >> 7); 382 | // parity = ((angle2 & 0x40) >> 6); 383 | // //Count the number of 1 in the angle binary value 384 | // for (int i=0;i<16;++i){ 385 | // if ((angle & (1 << i)) != 0){ 386 | // highStateCount++; 387 | // } 388 | // } 389 | // //check if parity bit is correct 390 | // if ((highStateCount % 2) == 0){ 391 | // if (parity == 0){ 392 | // *error = false; 393 | // } 394 | // else{ 395 | // *error = true; 396 | // } 397 | // } 398 | // else{ 399 | // if (parity == 1){ 400 | // *error = false; 401 | // } 402 | // else{ 403 | // *error = true; 404 | // } 405 | // } 406 | // return angle; 407 | // } 408 | 409 | // void MagAlphaSSIGen6::setSsiClockFrequency(uint32_t speedMaximum){ 410 | // _speedMaximum = speedMaximum; 411 | // SPI.beginTransaction(SPISettings(_speedMaximum, MSBFIRST, SSI_MODE)); 412 | // } 413 | 414 | // double MagAlphaSSIGen6::convertRawAngleToDegree(uint8_t rawAngleDataBitLength, uint16_t rawAngle){ 415 | // double angleInDegree; 416 | // angleInDegree = (rawAngle*360.0)/((double)pow(2, rawAngleDataBitLength)); 417 | // return angleInDegree; 418 | // } 419 | -------------------------------------------------------------------------------- /src/MagAlphaGen7.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | Arduino library for the MPS MagAlpha magnetic angle sensor 3 | Supports MagAlpha 7th generation Sensors. 4 | Support Part Number includes: MA900 5 | MagAlpha sensor detects the 6 | absolute angular position of a permanent magnet, typically a diametrically 7 | magnetized cylinder on the rotating shaft. 8 | ----> http://www.monolithicpower.com/Products/Position-Sensors/Products-Overview 9 | Written by Mathieu Kaelin for Monolithic Power Systems. 10 | MIT license, all text above must be included in any redistribution 11 | ****************************************************/ 12 | 13 | #include "MagAlphaGen7.h" 14 | 15 | //CRC table for poly = x^4 + x^3 + x^2 + 1 (0x1d or 0b11101 or 29) 16 | const uint8_t crc4LookupTable[16] = {0, 13, 7, 10, 14, 3, 9, 4, 1, 12, 6, 11, 15, 2, 8, 5}; 17 | 18 | const uint8_t poly_table[256] = {0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, 19 | 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, 20 | 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, 21 | 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, 22 | 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, 23 | 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, 24 | 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, 25 | 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, 26 | 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, 27 | 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, 28 | 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, 29 | 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, 30 | 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, 31 | 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, 32 | 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, 33 | 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3}; 34 | 35 | #define REG_ZERO0 0 36 | #define REG_ZERO1 1 37 | #define REG_SENT0 8 38 | #define REG_SENT1 9 39 | #define REG_SENT2 10 40 | #define REG_INTF 15 41 | #define REG_FILT 17 42 | #define REG_SPEEDFILT 18 43 | #define REG_IOMC 20 44 | #define REG_ID0 27 45 | #define REG_ID1 28 46 | #define REG_ID2 29 47 | #define REG_ID3 30 48 | #define REG_PID 31 49 | #define REG_TS1 39 50 | #define REG_LOCK0 52 51 | #define REG_LOCK1 53 52 | #define REG_LOCK2 54 53 | #define REG_LOCK3 55 54 | #define REG_SECRET 79 55 | #define REG_ANGLE 96 56 | #define REG_SPEED0 98 57 | #define REG_MTV0 100 58 | #define REG_TEMP0 102 59 | #define REG_READC 107 60 | #define REG_STATUS 108 61 | #define REG_MTP 120 62 | #define REG_FAULT 125 63 | #define REG_LOCKST 126 64 | #define REG_LOCK 127 65 | 66 | #define SENT_FORMAT_H1 0 67 | #define SENT_FORMAT_H2 1 68 | #define SENT_FORMAT_H3 2 69 | #define SENT_FORMAT_H4 3 70 | #define SENT_FORMAT_H5 4 71 | #define SENT_FORMAT_H6 5 72 | #define SENT_FORMAT_H7 6 73 | 74 | #define IOMC_PULL_DOWN 0 75 | #define IOMC_ABZ_UVW_PWM 1 76 | #define IOMC_ABZ_PWM 2 77 | #define IOMC_ABZ_SSI_PWM 3 78 | #define IOMC_SSI_UVW 4 79 | #define IOMC_UVW_DIFF 5 80 | #define IOMC_ABZ_PBI 6 81 | #define IOMC_UVW 7 82 | #define IOMC_MGL_UVW 8 83 | #define IOMC_SENT 9 84 | #define IOMC_ABZ_MGL 10 85 | #define IOMC_PWM_PBI 11 86 | #define IOMC_MGL_SSI 12 87 | #define IOMC_TRIG 13 88 | #define IOMC_GPIO_MODE 15 89 | 90 | /*====================================================================================*/ 91 | /*====================================== SPI =========================================*/ 92 | /*====================================================================================*/ 93 | 94 | MagAlphaGen7::MagAlphaGen7(){ 95 | _crcCheckEnabled = true; 96 | _crcInitValue = 10; 97 | } 98 | 99 | uint16_t MagAlphaGen7::readAngleRaw(bool* error){ 100 | bool inversion = false; 101 | return readAngleRaw16(error, &inversion, false); 102 | } 103 | 104 | uint16_t MagAlphaGen7::readAngleRaw16(){ 105 | bool error = false; 106 | bool inversion = false; 107 | return readAngleRaw16(&error, &inversion, false); 108 | } 109 | 110 | uint16_t MagAlphaGen7::readAngleRaw16(bool *error, bool *inversion, bool isShortRead){ 111 | uint16_t readbackValue, valueToWrite, computedCrc, angle; 112 | bool errorDetected; 113 | bool inversionDetected; 114 | *error = false; 115 | *inversion = false; 116 | valueToWrite = 0x0300 | REG_READC; 117 | valueToWrite = appendCrc4(valueToWrite); 118 | digitalWrite(_spiChipSelectPin, LOW); 119 | readbackValue = _spi->transfer16(valueToWrite); 120 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 121 | *error = errorDetected?true:*error; 122 | *inversion = inversionDetected?true:*inversion; 123 | angle = readbackValue & 0xFFF0; 124 | 125 | if(!isShortRead){ 126 | valueToWrite=readbackValue; 127 | readbackValue = _spi->transfer16(valueToWrite); 128 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 129 | *error=errorDetected?true:*error; 130 | *inversion=inversionDetected?true:*inversion; 131 | angle |= (readbackValue>>12)&0x000F; 132 | } 133 | digitalWrite(_spiChipSelectPin, HIGH); 134 | return angle; 135 | } 136 | 137 | uint8_t MagAlphaGen7::readAngleRaw8(){ 138 | bool error = false; 139 | bool inversion = false; 140 | return (readAngleRaw16(&error, &inversion, true) >> 8); 141 | } 142 | 143 | uint8_t MagAlphaGen7::readRegister(uint8_t address){ 144 | bool error, inversion; 145 | return readRegister(address, &error, &inversion); 146 | } 147 | 148 | uint8_t MagAlphaGen7::writeRegister(uint8_t address, uint8_t value){ 149 | bool error, inversion, wrongHandshaking; 150 | return writeRegister(address, value, &error, &inversion, &wrongHandshaking); 151 | } 152 | 153 | void MagAlphaGen7::readRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister){ 154 | bool error, inversion; 155 | readRegisterBurst(address, valueArray, numberOfRegister, &error, &inversion); 156 | } 157 | 158 | void MagAlphaGen7::writeRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister){ 159 | bool error, inversion, wrongHandshaking; 160 | writeRegisterBurst(address, valueArray, numberOfRegister, &error, &inversion, &wrongHandshaking); 161 | } 162 | 163 | /* 164 | uint16_t MagAlphaGen7::detectSensorGeneration(){ 165 | bool error, inversion; 166 | return readRegister(REG_PID, &error, &inversion) >> 4; 167 | } 168 | */ 169 | 170 | uint16_t MagAlphaGen7::getZero(){ 171 | bool error, inversion; 172 | return (readRegister(REG_ZERO1, &error, &inversion) << 8) | readRegister(REG_ZERO0, &error, &inversion); 173 | } 174 | 175 | void MagAlphaGen7::setZero(uint16_t zero){ 176 | bool error, inversion, wrongHandshaking; 177 | writeRegister(REG_ZERO0, zero&0x00FF, &error, &inversion, &wrongHandshaking); 178 | writeRegister(REG_ZERO1, zero>>8, &error, &inversion, &wrongHandshaking); 179 | } 180 | 181 | uint16_t MagAlphaGen7::setCurrentAngleAsZero(){ 182 | uint16_t zero; 183 | setZero(0); 184 | delay(10); 185 | zero = readAngleRaw16(); 186 | setZero(zero); 187 | return zero; 188 | } 189 | 190 | void MagAlphaGen7::restoreAllRegisters(){ 191 | bool error, inversion, wrongHandshaking; 192 | uint8_t tempReg; 193 | tempReg = readRegister(REG_MTP, &error, &inversion); 194 | tempReg |= 0x10; 195 | writeRegister(REG_MTP, tempReg, &error, &inversion, &wrongHandshaking); 196 | //wait for MTP DONE Flag to be set to 1 (indicate MTP Store/Restore operation is finished) 197 | tempReg=0; 198 | while((tempReg & 0x80) == 0){ 199 | tempReg = readRegister(REG_MTP, &error, &inversion); 200 | } 201 | } 202 | 203 | void MagAlphaGen7::storeAllRegisters(){ 204 | //Store Page 0 and Page 1 205 | storeRegisterBlock(3); 206 | } 207 | 208 | void MagAlphaGen7::storeRegisterBlock(uint8_t block){ 209 | bool error, inversion, wrongHandshaking; 210 | uint8_t tempReg = 0; 211 | tempReg = readRegister(REG_MTP, &error, &inversion); 212 | if(block <= 3){ 213 | tempReg &= 0xFC; 214 | tempReg |= 0x20 | block; 215 | writeRegister(REG_MTP, tempReg, &error, &inversion, &wrongHandshaking); 216 | } 217 | //wait for MTP DONE Flag to be set to 1 (indicate MTP Store/Restore operation is finished) 218 | tempReg=0; 219 | while((tempReg & 0x80) == 0){ 220 | tempReg = readRegister(REG_MTP, &error, &inversion); 221 | } 222 | } 223 | 224 | void MagAlphaGen7::clearErrorFlags(){ 225 | bool error, inversion, wrongHandshaking; 226 | writeRegister(REG_STATUS, 0X07, &error, &inversion, &wrongHandshaking); 227 | } 228 | 229 | double MagAlphaGen7::readSpeed(){ 230 | uint16_t angle; 231 | bool error, inversion; 232 | return twosComplement(readAngleSpeed(&angle, &error, &inversion), 16) * 3.57; 233 | } 234 | 235 | int16_t MagAlphaGen7::readTurn(){ 236 | uint16_t angle; 237 | bool error, inversion; 238 | return twosComplement(readAngleMultiturn(&angle, &error, &inversion), 16); 239 | } 240 | 241 | void MagAlphaGen7::writeTurn(int16_t turn){ 242 | bool error, inversion, wrongHandshaking; 243 | uint16_t multiturn = twosComplementInverse(turn, 16); 244 | writeRegister(REG_MTV0, multiturn&0x00FF, &error, &inversion, &wrongHandshaking); 245 | writeRegister(REG_MTV0+1, multiturn>>8, &error, &inversion, &wrongHandshaking); 246 | } 247 | 248 | double MagAlphaGen7::readTemperature(){ 249 | uint16_t angle; 250 | bool error, inversion; 251 | return twosComplement(readAngleTemperature(&angle, &error, &inversion), 16) * 0.125; 252 | } 253 | 254 | uint16_t MagAlphaGen7::readAcquisitionCounter(){ 255 | uint16_t angle; 256 | bool error, inversion; 257 | return readAngleCounter(&angle, &error, &inversion); 258 | } 259 | 260 | uint16_t MagAlphaGen7::readAngleCounter(uint16_t *angle, bool *error, bool *inversion) { 261 | uint16_t readbackValue, valueToWrite, computedCrc, counter; 262 | bool errorDetected; 263 | bool inversionDetected; 264 | *error=false; 265 | *inversion=false; 266 | valueToWrite=(0x0300)|REG_READC; 267 | valueToWrite=appendCrc4(valueToWrite); 268 | digitalWrite(_spiChipSelectPin, LOW); 269 | readbackValue = _spi->transfer16(valueToWrite); 270 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 271 | *error=errorDetected?true:*error; 272 | *inversion=inversionDetected?true:*inversion; 273 | *angle=readbackValue&0xFFF0; 274 | 275 | valueToWrite=readbackValue; 276 | readbackValue = _spi->transfer16(valueToWrite); 277 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 278 | *error=errorDetected?true:*error; 279 | *inversion=inversionDetected?true:*inversion; 280 | *angle |= (readbackValue>>12)&0x000F; 281 | counter = (readbackValue>>4)&0x00FF; 282 | digitalWrite(_spiChipSelectPin, HIGH); 283 | return counter; 284 | } 285 | 286 | uint16_t MagAlphaGen7::readAngleSpeed(uint16_t *angle, bool *error, bool *inversion) { 287 | uint16_t readbackValue, valueToWrite, computedCrc, speed; 288 | bool errorDetected; 289 | bool inversionDetected; 290 | *error=false; 291 | *inversion=false; 292 | valueToWrite=(0x0300)|REG_SPEED0; 293 | valueToWrite=appendCrc4(valueToWrite); 294 | digitalWrite(_spiChipSelectPin, LOW); 295 | readbackValue = _spi->transfer16(valueToWrite); 296 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 297 | *error=errorDetected?true:*error; 298 | *inversion=inversionDetected?true:*inversion; 299 | *angle=readbackValue&0xFFF0; 300 | 301 | valueToWrite=readbackValue; 302 | readbackValue = _spi->transfer16(valueToWrite); 303 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 304 | *error=errorDetected?true:*error; 305 | *inversion=inversionDetected?true:*inversion; 306 | *angle |= (readbackValue>>12)&0x000F; 307 | speed = (readbackValue>>4)&0x00FF; 308 | 309 | valueToWrite=readbackValue; 310 | readbackValue = _spi->transfer16(valueToWrite); 311 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 312 | *error=errorDetected?true:*error; 313 | *inversion=inversionDetected?true:*inversion; 314 | speed |= (readbackValue<<4)&0xFF00; 315 | digitalWrite(_spiChipSelectPin, HIGH); 316 | return speed; 317 | } 318 | 319 | uint16_t MagAlphaGen7::readAngleMultiturn(uint16_t *angle, bool *error, bool *inversion) { 320 | uint16_t readbackValue, valueToWrite, computedCrc, multiturn; 321 | bool errorDetected; 322 | bool inversionDetected; 323 | *error=false; 324 | *inversion=false; 325 | valueToWrite=(0x0300)|REG_MTV0; 326 | valueToWrite=appendCrc4(valueToWrite); 327 | digitalWrite(_spiChipSelectPin, LOW); 328 | readbackValue = _spi->transfer16(valueToWrite); 329 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 330 | *error=errorDetected?true:*error; 331 | *inversion=inversionDetected?true:*inversion; 332 | *angle=readbackValue&0xFFF0; 333 | 334 | valueToWrite=readbackValue; 335 | readbackValue = _spi->transfer16(valueToWrite); 336 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 337 | *error=errorDetected?true:*error; 338 | *inversion=inversionDetected?true:*inversion; 339 | *angle |= (readbackValue>>12)&0x000F; 340 | multiturn = (readbackValue>>4)&0x00FF; 341 | 342 | valueToWrite=readbackValue; 343 | readbackValue = _spi->transfer16(valueToWrite); 344 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 345 | *error=errorDetected?true:*error; 346 | *inversion=inversionDetected?true:*inversion; 347 | multiturn |= (readbackValue<<4)&0xFF00; 348 | digitalWrite(_spiChipSelectPin, HIGH); 349 | return multiturn; 350 | } 351 | 352 | uint16_t MagAlphaGen7::readAngleTemperature(uint16_t *angle, bool *error, bool *inversion){ 353 | uint16_t readbackValue, valueToWrite, computedCrc, temperature; 354 | bool errorDetected; 355 | bool inversionDetected; 356 | *error=false; 357 | *inversion=false; 358 | valueToWrite=(0x0300)|REG_TEMP0; 359 | valueToWrite=appendCrc4(valueToWrite); 360 | digitalWrite(_spiChipSelectPin, LOW); 361 | readbackValue = _spi->transfer16(valueToWrite); 362 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 363 | *error=errorDetected?true:*error; 364 | *inversion=inversionDetected?true:*inversion; 365 | *angle=readbackValue&0xFFF0; 366 | 367 | valueToWrite=readbackValue; 368 | readbackValue = _spi->transfer16(valueToWrite); 369 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 370 | *error=errorDetected?true:*error; 371 | *inversion=inversionDetected?true:*inversion; 372 | *angle |= (readbackValue>>12)&0x000F; 373 | temperature = (readbackValue>>4)&0x00FF; 374 | 375 | valueToWrite=readbackValue; 376 | readbackValue = _spi->transfer16(valueToWrite); 377 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 378 | *error=errorDetected?true:*error; 379 | *inversion=inversionDetected?true:*inversion; 380 | temperature |= (readbackValue<<4)&0xFF00; 381 | digitalWrite(_spiChipSelectPin, HIGH); 382 | return temperature; 383 | } 384 | 385 | uint8_t MagAlphaGen7::readRegister(uint8_t address, bool *error, bool *inversion) { 386 | uint16_t readbackValue, valueToWrite, computedCrc; 387 | bool errorDetected; 388 | bool inversionDetected; 389 | *error=false; 390 | *inversion=false; 391 | valueToWrite=(0x0300)|(address); 392 | valueToWrite=appendCrc4(valueToWrite); 393 | digitalWrite(_spiChipSelectPin, LOW); 394 | readbackValue = _spi->transfer16(valueToWrite); 395 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 396 | *error=errorDetected?true:*error; 397 | *inversion=inversionDetected?true:*inversion; 398 | 399 | //The previously received 16-bit data on CIPO (12-bit AngleMSB + 4-bit CRC4) is returned by the controller on COPI (handshaking protocol). 400 | //We do not compute the CRC of the previously received data we just send the exact same data+CRC back to the peripheral. 401 | valueToWrite=readbackValue; 402 | readbackValue = _spi->transfer16(valueToWrite); 403 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 404 | *error=errorDetected?true:*error; 405 | *inversion=inversionDetected?true:*inversion; 406 | digitalWrite(_spiChipSelectPin, HIGH); 407 | return ((readbackValue>>4)&0x00FF); 408 | } 409 | 410 | uint16_t MagAlphaGen7::readRegisterBurst(uint8_t address, uint8_t readbackValueArray[], uint16_t numberOfRegister, bool *error, bool *inversion) { 411 | uint16_t readbackValue, valueToWrite, computedCrc, angle; 412 | bool errorDetected; 413 | bool inversionDetected; 414 | *error=false; 415 | *inversion=false; 416 | valueToWrite=(0x0300)|(address); 417 | valueToWrite=appendCrc4(valueToWrite); 418 | digitalWrite(_spiChipSelectPin, LOW); 419 | readbackValue = _spi->transfer16(valueToWrite); 420 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 421 | *error=errorDetected?true:*error; 422 | *inversion=inversionDetected?true:*inversion; 423 | angle=readbackValue&0xFFF0; 424 | 425 | for (uint8_t i=0;itransfer16(valueToWrite); 428 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 429 | *error=errorDetected?true:*error; 430 | *inversion=inversionDetected?true:*inversion; 431 | readbackValueArray[i]=(readbackValue>>4)&0xFF; 432 | if (i==0) { 433 | angle=angle | ((readbackValue>>12)&0x000F); 434 | } 435 | } 436 | digitalWrite(_spiChipSelectPin, HIGH); 437 | return angle; 438 | } 439 | 440 | uint8_t MagAlphaGen7::writeRegister(uint8_t address, uint8_t value, bool *error, bool *inversion, bool *wrongHandshaking) { 441 | uint16_t readbackValue, valueToWrite, writtenValue, computedCrc; 442 | bool errorDetected, inversionDetected; 443 | 444 | *error=false; 445 | *inversion=false; 446 | *wrongHandshaking = false; 447 | 448 | valueToWrite=(0x0C00)|(address); 449 | valueToWrite=appendCrc4(valueToWrite); 450 | digitalWrite(_spiChipSelectPin, LOW); 451 | readbackValue = _spi->transfer16(valueToWrite); 452 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 453 | *error=errorDetected?true:*error; 454 | *inversion=inversionDetected?true:*inversion; 455 | writtenValue = valueToWrite; 456 | 457 | valueToWrite=(0x0000)|(value); 458 | valueToWrite=appendCrc4(valueToWrite); 459 | readbackValue = _spi->transfer16(valueToWrite); 460 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 461 | *wrongHandshaking = ((readbackValue&0x0FF0) != (writtenValue&0x0FF0))?true:*wrongHandshaking; //in this readback we get the angle LSBs instead of OpCode 462 | *error=errorDetected?true:*error; 463 | *inversion=inversionDetected?true:*inversion; 464 | writtenValue = valueToWrite; 465 | 466 | valueToWrite=0x0F00; 467 | valueToWrite=appendCrc4(valueToWrite); 468 | readbackValue = _spi->transfer16(valueToWrite); 469 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 470 | *wrongHandshaking = (readbackValue != writtenValue)?true:*wrongHandshaking; 471 | 472 | *error=errorDetected?true:*error; 473 | *inversion=inversionDetected?true:*inversion; 474 | digitalWrite(_spiChipSelectPin, HIGH); 475 | return (readbackValue & 0x0FF0) >> 4; 476 | } 477 | 478 | void MagAlphaGen7::writeRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister, bool *error, bool *inversion, bool *wrongHandshaking) { 479 | uint16_t readbackValue, valueToWrite, writtenValue, computedCrc; 480 | bool errorDetected, inversionDetected; 481 | 482 | *error=false; 483 | *inversion=false; 484 | *wrongHandshaking = false; 485 | 486 | valueToWrite=(0x0C00)|(address); 487 | valueToWrite=appendCrc4(valueToWrite); 488 | digitalWrite(_spiChipSelectPin, LOW); 489 | readbackValue = _spi->transfer16(valueToWrite); 490 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 491 | *error=errorDetected?true:*error; 492 | *inversion=inversionDetected?true:*inversion; 493 | writtenValue = valueToWrite; 494 | 495 | for (uint8_t i=0;itransfer16(valueToWrite); 499 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 500 | if(i == 0){ 501 | *wrongHandshaking = ((readbackValue&0x0FF0) != (writtenValue&0x0FF0))?true:*wrongHandshaking; //in this readback I get the angle LSBs instead of OpCode 502 | } 503 | else{ 504 | *wrongHandshaking = (readbackValue != writtenValue)?true:*wrongHandshaking; 505 | } 506 | *error=errorDetected?true:*error; 507 | *inversion=inversionDetected?true:*inversion; 508 | writtenValue = valueToWrite; 509 | } 510 | 511 | valueToWrite=0x0F00; 512 | valueToWrite=appendCrc4(valueToWrite); 513 | readbackValue = _spi->transfer16(valueToWrite); 514 | checkCrc4(readbackValue, &computedCrc, &errorDetected, &inversionDetected); 515 | *error=errorDetected?true:*error; 516 | *inversion=inversionDetected?true:*inversion; 517 | *wrongHandshaking = (readbackValue != writtenValue)?true:*wrongHandshaking; 518 | digitalWrite(_spiChipSelectPin, HIGH); 519 | } 520 | 521 | void MagAlphaGen7::setCrcCheckSetting(bool enable){ 522 | bool error, inversion, wrongHandshaking; 523 | uint8_t tempReg; 524 | tempReg = readRegister(REG_INTF, &error, &inversion); 525 | if(enable){ 526 | writeRegister(REG_INTF, tempReg|0x01, &error, &inversion, &wrongHandshaking); 527 | _crcCheckEnabled = true; 528 | } 529 | else{ 530 | writeRegister(REG_INTF, tempReg&0xFE, &error, &inversion, &wrongHandshaking); 531 | _crcCheckEnabled = false; 532 | } 533 | } 534 | 535 | uint16_t MagAlphaGen7::appendCrc4(uint16_t data){ 536 | uint8_t crc4; // 4-bit CRC (0-15) 537 | // Compute CRC4 538 | crc4 = _crcInitValue; // Initial Value for CRC4 (Seed) 539 | crc4 = (data>>8 & 0xF) ^ crc4LookupTable[crc4]; // 4 MSB first 540 | crc4 = (data>>4 & 0xF) ^ crc4LookupTable[crc4]; // 541 | crc4 = (data>>0 & 0xF) ^ crc4LookupTable[crc4]; // 4 LSB 542 | // Concatenate 12-bit data with CRC4 543 | return (data<<4) | crc4; // 16-bit word to send <12-bit data><4-bit crc> 544 | } 545 | 546 | void MagAlphaGen7::checkCrc4(uint16_t readData, uint16_t *computedCrc, bool *errorDetected, bool *inversionDetected){ 547 | *computedCrc=appendCrc4(readData>>4); 548 | //compare the data + CRC received VS the expected data + CRC 549 | if (readData==*computedCrc){ 550 | *errorDetected=false; 551 | *inversionDetected = false; 552 | } 553 | else{ 554 | *errorDetected=true; 555 | if(((~readData) & 0xF) == (*computedCrc & 0xF)){ 556 | *inversionDetected = true; //if the CRC is not the same, check if it was inverted 557 | } 558 | else{ 559 | *inversionDetected = false; 560 | } 561 | } 562 | } 563 | 564 | uint16_t MagAlphaGen7::getNumberOfRegisters(){ 565 | return 128; 566 | } 567 | 568 | void MagAlphaGen7::getLockedRegisters(uint8_t unlockedRegisters[]){ 569 | uint8_t registerArray[4] = {0}; 570 | readRegisterBurst(REG_LOCK0, registerArray, 4); 571 | for(uint8_t i=0; i<4; i++){ 572 | for(uint8_t j=0; j<8; j++){ 573 | unlockedRegisters[i*8+j] = ((registerArray[i]>>j)&0x01) ? 0xFF : 0x00; 574 | } 575 | } 576 | } 577 | 578 | void MagAlphaGen7::getPartNumber(char *partNumber){ 579 | sprintf(partNumber, "MA900"); 580 | } 581 | 582 | uint8_t MagAlphaGen7::getSiliconId(){ 583 | return readRegister(REG_PID); 584 | } 585 | 586 | uint8_t MagAlphaGen7::getSiliconRevision(){ 587 | uint8_t siliconRevision0, siliconRevision1, siliconRevision2, siliconRevision3; 588 | siliconRevision0 = readRegister(REG_ID0); 589 | siliconRevision1 = readRegister(REG_ID1); 590 | siliconRevision2 = readRegister(REG_ID2); 591 | siliconRevision3 = readRegister(REG_ID3); 592 | return siliconRevision0; 593 | } 594 | 595 | /*====================================================================================*/ 596 | /*====================================== I2C =========================================*/ 597 | /*====================================================================================*/ 598 | 599 | MagAlphaI2CGen7::MagAlphaI2CGen7(){ 600 | _crcInitValue = 0; 601 | _crcCheckEnabled = true; 602 | _deviceAddress = 0x14; 603 | } 604 | 605 | uint16_t MagAlphaI2CGen7::readAngleRaw(bool* error){ 606 | uint16_t angle; 607 | uint8_t readRegisters[2] = {0}; 608 | readRegisterQuickRead(readRegisters, 2, error); 609 | return (readRegisters[1]<<8) | readRegisters[0]; 610 | } 611 | 612 | uint16_t MagAlphaI2CGen7::readAngleRaw16(){ 613 | bool error; 614 | return readAngleRaw(&error); 615 | } 616 | 617 | uint8_t MagAlphaI2CGen7::readAngleRaw8(){ 618 | return readAngleRaw16()>>8; 619 | } 620 | 621 | uint8_t MagAlphaI2CGen7::readRegister(uint8_t address){ 622 | bool error; 623 | return readRegister(address, &error); 624 | } 625 | 626 | uint8_t MagAlphaI2CGen7::writeRegister(uint8_t address, uint8_t value){ 627 | uint8_t crc = _crcInitValue; 628 | _i2c->beginTransmission(_deviceAddress); 629 | crc = crc8(crc, (_deviceAddress<<1)+0); 630 | _i2c->write(byte(address)); 631 | crc = crc8(crc, address); 632 | _i2c->write(byte(value)); 633 | crc = crc8(crc, value); 634 | if(_crcCheckEnabled){ 635 | _i2c->write(byte(crc)); 636 | } 637 | _i2c->endTransmission(); 638 | return value; 639 | } 640 | 641 | void MagAlphaI2CGen7::readRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister){ 642 | bool error; 643 | readRegisterBurst(address, valueArray, numberOfRegister, &error); 644 | } 645 | 646 | void MagAlphaI2CGen7::writeRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister){ 647 | uint8_t crc; 648 | _i2c->beginTransmission(_deviceAddress); 649 | _i2c->write(byte(address)); 650 | for (uint8_t cnt = 0; cnt < numberOfRegister; cnt++){ 651 | _i2c->write(byte(valueArray[cnt])); 652 | if (_crcCheckEnabled){ 653 | crc = _crcInitValue; 654 | crc = crc8(crc, _deviceAddress<<1); 655 | crc = crc8(crc, (address + cnt)); 656 | crc = crc8(crc, valueArray[cnt]); 657 | _i2c->write(byte(crc)); 658 | } 659 | } 660 | _i2c->endTransmission(); 661 | } 662 | 663 | uint16_t MagAlphaI2CGen7::detectSensorGeneration(){ 664 | uint16_t chipId; 665 | chipId = readRegister(REG_PID); 666 | return (chipId>>4)&0xF; 667 | } 668 | 669 | uint16_t MagAlphaI2CGen7::getZero(){ 670 | uint8_t readRegisters[2] = {0}; 671 | readRegisterBurst(0, readRegisters, 2); 672 | return (readRegisters[1]<<8) | readRegisters[0]; 673 | } 674 | 675 | void MagAlphaI2CGen7::setZero(uint16_t zero){ 676 | uint8_t readRegisters[2] = {static_cast(zero & 0xFF), static_cast(zero >> 8)}; 677 | writeRegisterBurst(0, readRegisters, 2); 678 | } 679 | 680 | uint16_t MagAlphaI2CGen7::setCurrentAngleAsZero(){ 681 | uint16_t zero; 682 | setZero(0); 683 | delay(10); 684 | zero = readAngleRaw16(); 685 | setZero(zero); 686 | return zero; 687 | } 688 | 689 | void MagAlphaI2CGen7::restoreAllRegisters(){ 690 | uint8_t tempReg; 691 | tempReg = readRegister(REG_MTP); 692 | tempReg |= 0x10; 693 | writeRegister(REG_MTP, tempReg); 694 | //wait for MTP DONE Flag to be set to 1 (indicate MTP Store/Restore operation is finished) 695 | tempReg=0; 696 | while((tempReg & 0x80) == 0){ 697 | tempReg = readRegister(REG_MTP); 698 | } 699 | } 700 | 701 | void MagAlphaI2CGen7::storeAllRegisters(){ 702 | //Store Page 0 and Page 1 703 | storeRegisterBlock(3); 704 | } 705 | 706 | void MagAlphaI2CGen7::storeRegisterBlock(uint8_t block){ 707 | uint8_t tempReg = 0; 708 | tempReg = readRegister(REG_MTP); 709 | if(block <= 3){ 710 | tempReg &= 0xFC; 711 | tempReg |= 0x20 | block; 712 | writeRegister(REG_MTP, tempReg); 713 | } 714 | //wait for MTP DONE Flag to be set to 1 (indicate MTP Store/Restore operation is finished) 715 | tempReg=0; 716 | while((tempReg & 0x80) == 0){ 717 | tempReg = readRegister(REG_MTP); 718 | } 719 | } 720 | 721 | void MagAlphaI2CGen7::clearErrorFlags(){ 722 | writeRegister(REG_STATUS, 0X07); 723 | } 724 | 725 | double MagAlphaI2CGen7::readSpeed(){ 726 | uint16_t speed; 727 | uint8_t readRegisters[2] = {0}; 728 | readRegisterBurst(REG_SPEED0, readRegisters, 2); 729 | speed = (readRegisters[1]<<8) | readRegisters[0]; 730 | return twosComplement(speed, 16) * 3.57; 731 | } 732 | 733 | int16_t MagAlphaI2CGen7::readTurn(){ 734 | uint16_t turn; 735 | uint8_t readRegisters[2] = {0}; 736 | readRegisterBurst(REG_MTV0, readRegisters, 2); 737 | turn = (readRegisters[1]<<8) | readRegisters[0]; 738 | return twosComplement(turn, 16); 739 | } 740 | 741 | void MagAlphaI2CGen7::writeTurn(int16_t turn){ 742 | uint16_t multiturn = twosComplementInverse(turn, 16); 743 | uint8_t readRegisters[2] = {static_cast(multiturn & 0xFF), static_cast(multiturn >> 8)}; 744 | writeRegisterBurst(REG_MTV0, readRegisters, 2); 745 | } 746 | 747 | double MagAlphaI2CGen7::readTemperature(){ 748 | uint16_t temperature; 749 | uint8_t readRegisters[2] = {0}; 750 | readRegisterBurst(REG_TEMP0, readRegisters, 2); 751 | temperature = (readRegisters[1]<<8) | readRegisters[0]; 752 | return twosComplement(temperature, 16) * 0.125; 753 | } 754 | 755 | uint16_t MagAlphaI2CGen7::readAcquisitionCounter(){ 756 | return readRegister(REG_READC); 757 | } 758 | 759 | uint8_t MagAlphaI2CGen7::readRegister(uint8_t address, bool *error){ 760 | uint8_t crc = _crcInitValue; 761 | uint8_t readbackValue, crcReceived; 762 | uint8_t requestBytes; 763 | requestBytes=_crcCheckEnabled?2:1; //if crc is enabled, read 2 bytes from sensor 764 | _i2c->beginTransmission(_deviceAddress); 765 | crc = crc8(crc, (_deviceAddress<<1)+0); 766 | _i2c->write(byte(address)); 767 | crc = crc8(crc, address); 768 | _i2c->endTransmission(false); 769 | _i2c->requestFrom(_deviceAddress, requestBytes, true); 770 | crc = crc8(crc, (_deviceAddress<<1)+1); 771 | readbackValue = _i2c->read(); 772 | crc = crc8(crc, readbackValue); 773 | if(_crcCheckEnabled){ 774 | crcReceived = _i2c->read(); 775 | checkCrc8(crcReceived, crc, error); 776 | } 777 | return readbackValue; 778 | } 779 | 780 | uint16_t MagAlphaI2CGen7::readRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister, bool *error){ 781 | uint8_t byteCount = 0; 782 | uint8_t crcReceived; 783 | uint8_t crc; 784 | *error=false; 785 | _i2c->beginTransmission(_deviceAddress); 786 | _i2c->write(byte(address)); 787 | _i2c->endTransmission(false); 788 | if(_crcCheckEnabled){ 789 | numberOfRegister*=2; 790 | } 791 | _i2c->requestFrom(_deviceAddress, numberOfRegister); 792 | while(_i2c->available()){ 793 | valueArray[byteCount] = _i2c->read(); 794 | if (_crcCheckEnabled){ 795 | crc = _crcInitValue; 796 | crc = crc8(crc, _deviceAddress<<1); 797 | crc = crc8(crc, address + byteCount); 798 | crc = crc8(crc, (_deviceAddress<<1)+1); 799 | crc = crc8(crc, valueArray[byteCount]); 800 | crcReceived = _i2c->read(); 801 | *error = (crc != crcReceived) ? true : *error; 802 | } 803 | byteCount++; 804 | } 805 | return byteCount; 806 | } 807 | 808 | uint16_t MagAlphaI2CGen7::readRegisterQuickRead(uint8_t valueArray[], uint16_t numberOfRegister, bool *error){ 809 | uint8_t crc; 810 | uint8_t crcReceived; 811 | uint8_t byteCount = 0; 812 | uint8_t firstReg = 96; 813 | *error=false; 814 | if(_crcCheckEnabled){ 815 | numberOfRegister*=2; 816 | } 817 | _i2c->requestFrom(_deviceAddress, numberOfRegister); 818 | while(_i2c->available()) { 819 | valueArray[byteCount] = _i2c->read(); 820 | if (_crcCheckEnabled){ 821 | crc = _crcInitValue; 822 | crc = crc8(crc, (_deviceAddress<<1)+1); 823 | crc = crc8(crc, (firstReg + byteCount)); 824 | crc = crc8(crc, valueArray[byteCount]); 825 | crcReceived = _i2c->read(); 826 | *error = (crc != crcReceived) ? true : *error; 827 | } 828 | byteCount++; 829 | } 830 | return byteCount; 831 | } 832 | 833 | void MagAlphaI2CGen7::setCrcCheckSetting(bool enable){ 834 | bool error; 835 | uint8_t tempReg; 836 | tempReg = readRegister(REG_INTF, &error); 837 | if(enable){ 838 | writeRegister(REG_INTF, tempReg|0x01); 839 | _crcCheckEnabled = true; 840 | } 841 | else{ 842 | writeRegister(REG_INTF, tempReg&0xFE); 843 | _crcCheckEnabled = false; 844 | } 845 | } 846 | 847 | uint8_t MagAlphaI2CGen7::crc8(uint8_t crc, uint8_t data){ 848 | return poly_table[crc^data]; 849 | } 850 | 851 | void MagAlphaI2CGen7::checkCrc8(uint8_t &readData, uint8_t &computedCrc, bool *errorDetected){ 852 | //compare the data + CRC received VS the expected data + CRC 853 | if (readData==computedCrc){ 854 | *errorDetected=false; 855 | } 856 | else{ 857 | *errorDetected=true; 858 | } 859 | } 860 | 861 | uint16_t MagAlphaI2CGen7::getNumberOfRegisters(){ 862 | return 128; 863 | } 864 | 865 | void MagAlphaI2CGen7::getLockedRegisters(uint8_t unlockedRegisters[]){ 866 | uint8_t registerArray[4] = {0}; 867 | readRegisterBurst(REG_LOCK0, registerArray, 4); 868 | for(uint8_t i=0; i<4; i++){ 869 | for(uint8_t j=0; j<8; j++){ 870 | unlockedRegisters[i*8+j] = ((registerArray[i]>>j)&0x01) ? 0xFF : 0x00; 871 | } 872 | } 873 | } 874 | 875 | void MagAlphaI2CGen7::getPartNumber(char *partNumber){ 876 | sprintf(partNumber, "MA900"); 877 | } 878 | 879 | uint8_t MagAlphaI2CGen7::getSiliconId(){ 880 | return readRegister(REG_PID); 881 | } 882 | 883 | uint8_t MagAlphaI2CGen7::getSiliconRevision(){ 884 | uint8_t siliconRevision0, siliconRevision1, siliconRevision2, siliconRevision3; 885 | siliconRevision0 = readRegister(REG_ID0); 886 | siliconRevision1 = readRegister(REG_ID1); 887 | siliconRevision2 = readRegister(REG_ID2); 888 | siliconRevision3 = readRegister(REG_ID3); 889 | return siliconRevision0; 890 | } 891 | --------------------------------------------------------------------------------