SimpleFOClibrary 2.4.0
Loading...
Searching...
No Matches
MagneticSensorI2C.cpp
Go to the documentation of this file.
1#include "MagneticSensorI2C.h"
2
3/** Typical configuration for the 12bit AMS AS5600 magnetic sensor over I2C interface */
5 .chip_address = 0x36,
6 .bit_resolution = 12,
7 .angle_register = 0x0C,
8 .msb_mask = 0x0F,
9 .msb_shift = 8,
10 .lsb_mask = 0xFF,
11 .lsb_shift = 0
12};
13
14/** Typical configuration for the 12bit AMS AS5048 magnetic sensor over I2C interface */
16 .chip_address = 0x40, // highly configurable. if A1 and A2 are held low, this is probable value
17 .bit_resolution = 14,
18 .angle_register = 0xFE,
19 .msb_mask = 0xFF,
20 .msb_shift = 6,
21 .lsb_mask = 0x3F,
22 .lsb_shift = 0
23};
24
25/** Typical configuration for the 12bit MT6701 magnetic sensor over I2C interface */
27 .chip_address = 0x06,
28 .bit_resolution = 14,
29 .angle_register = 0x03,
30 .msb_mask = 0xFF,
31 .msb_shift = 6,
32 .lsb_mask = 0xFC,
33 .lsb_shift = 2
34};
35
36
37// MagneticSensorI2C(uint8_t _chip_address, float _cpr, uint8_t _angle_register_msb)
38// @param _chip_address I2C chip address
39// @param _bit_resolution bit resolution of the sensor
40// @param _angle_register_msb angle read register
41// @param _bits_used_msb number of used bits in msb
42MagneticSensorI2C::MagneticSensorI2C(uint8_t _chip_address, int _bit_resolution, uint8_t _angle_register_msb, int _bits_used_msb, bool lsb_right_aligned){
43 _conf.chip_address = _chip_address;
44 _conf.bit_resolution = _bit_resolution;
45 _conf.angle_register = _angle_register_msb;
46 _conf.msb_mask = (uint8_t)( (1 << _bits_used_msb) - 1 );
47
48 uint8_t lsb_used = _bit_resolution - _bits_used_msb; // used bits in LSB
49 _conf.lsb_mask = (uint8_t)( (1 << (lsb_used)) - 1 );
50 if (!lsb_right_aligned)
51 _conf.lsb_shift = 8-lsb_used;
52 else
53 _conf.lsb_shift = 0;
54 _conf.msb_shift = lsb_used;
55
56 cpr = _powtwo(_bit_resolution);
57
58 wire = &Wire;
59}
60
61
62
64 _conf = config;
65 cpr = _powtwo(config.bit_resolution);
66 wire = &Wire;
67}
68
69
70
74
75
76
77void MagneticSensorI2C::init(TwoWire* _wire){
78 wire = _wire;
79 wire->begin(); // I2C communication begin
80 this->Sensor::init(); // call base class init
81}
82
83
84
85// Shaft angle calculation
86// angle is in radians [rad]
88 // (number of full rotations)*2PI + current sensor angle
89 return ( getRawCount() / (float)cpr) * _2PI ;
90}
91
92
93
94// I2C functions
95/*
96* Read an angle from the angle register of the sensor
97*/
98int MagneticSensorI2C::getRawCount() {
99 // read the angle register first MSB then LSB
100 byte readArray[2];
101 uint16_t readValue = 0;
102 // notify the device that is aboout to be read
103 wire->beginTransmission(_conf.chip_address);
104 wire->write(_conf.angle_register);
105 currWireError = wire->endTransmission(false);
106 // read the data msb and lsb
107 wire->requestFrom(_conf.chip_address, (uint8_t)2);
108 for (byte i=0; i < 2; i++) {
109 readArray[i] = wire->read();
110 }
111 readValue = (readArray[0] & _conf.msb_mask) << _conf.msb_shift;
112 readValue |= (readArray[1] & _conf.lsb_mask) >> _conf.lsb_shift;
113 return readValue;
114}
115
116/*
117* Checks whether other devices have locked the bus. Can clear SDA locks.
118* This should be called before sensor.init() on devices that suffer i2c slaves locking sda
119* e.g some stm32 boards with AS5600 chips
120* Takes the sda_pin and scl_pin
121* Returns 0 for OK, 1 for other master and 2 for unfixable sda locked LOW
122*/
123int MagneticSensorI2C::checkBus(byte sda_pin, byte scl_pin) {
124
125 pinMode(scl_pin, INPUT_PULLUP);
126 pinMode(sda_pin, INPUT_PULLUP);
127 delay(250);
128
129 if (digitalRead(scl_pin) == LOW) {
130 // Someone else has claimed master!");
131 return 1;
132 }
133
134 if(digitalRead(sda_pin) == LOW) {
135 // slave is communicating and awaiting clocks, we are blocked
136 pinMode(scl_pin, OUTPUT);
137 for (byte i = 0; i < 16; i++) {
138 // toggle clock for 2 bytes of data
139 digitalWrite(scl_pin, LOW);
140 delayMicroseconds(20);
141 digitalWrite(scl_pin, HIGH);
142 delayMicroseconds(20);
143 }
144 pinMode(sda_pin, INPUT);
145 delayMicroseconds(20);
146 if (digitalRead(sda_pin) == LOW) {
147 // SDA still blocked
148 return 2;
149 }
150 _delay(1000);
151 }
152 // SDA is clear (HIGH)
153 pinMode(sda_pin, INPUT);
154 pinMode(scl_pin, INPUT);
155
156 return 0;
157}
MagneticSensorI2CConfig_s AS5048_I2C
MagneticSensorI2CConfig_s MT6701_I2C
MagneticSensorI2CConfig_s AS5600_I2C
MagneticSensorI2CConfig_s AS5600_I2C
float getSensorAngle() override
static MagneticSensorI2C AS5600()
MagneticSensorI2C(uint8_t _chip_address, int _bit_resolution, uint8_t _angle_register_msb, int _msb_bits_used, bool lsb_right_aligned=true)
int checkBus(byte sda_pin, byte scl_pin)
virtual void init()
Definition Sensor.cpp:59
#define _2PI
Definition foc_utils.h:29
#define _powtwo(x)
Definition foc_utils.h:15
void _delay(unsigned long ms)
Definition time_utils.cpp:5