-
-
Notifications
You must be signed in to change notification settings - Fork 22
/
AS5600.h
292 lines (224 loc) · 8.09 KB
/
AS5600.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
#pragma once
//
// FILE: AS5600.h
// AUTHOR: Rob Tillaart
// VERSION: 0.6.4
// PURPOSE: Arduino library for AS5600 magnetic rotation meter
// DATE: 2022-05-28
// URL: https://github.com/RobTillaart/AS5600
#include "Arduino.h"
#include "Wire.h"
#define AS5600_LIB_VERSION (F("0.6.4"))
// default addresses
const uint8_t AS5600_DEFAULT_ADDRESS = 0x36;
const uint8_t AS5600L_DEFAULT_ADDRESS = 0x40;
const uint8_t AS5600_SW_DIRECTION_PIN = 255;
// setDirection
const uint8_t AS5600_CLOCK_WISE = 0; // LOW
const uint8_t AS5600_COUNTERCLOCK_WISE = 1; // HIGH
// 0.087890625;
const float AS5600_RAW_TO_DEGREES = 360.0 / 4096;
const float AS5600_DEGREES_TO_RAW = 4096 / 360.0;
// 0.00153398078788564122971808758949;
const float AS5600_RAW_TO_RADIANS = PI * 2.0 / 4096;
// 4.06901041666666e-6
const float AS5600_RAW_TO_RPM = 60.0 / 4096;
// getAngularSpeed
const uint8_t AS5600_MODE_DEGREES = 0;
const uint8_t AS5600_MODE_RADIANS = 1;
const uint8_t AS5600_MODE_RPM = 2;
// ERROR CODES
const int AS5600_OK = 0;
const int AS5600_ERROR_I2C_READ_0 = -100;
const int AS5600_ERROR_I2C_READ_1 = -101;
const int AS5600_ERROR_I2C_READ_2 = -102;
const int AS5600_ERROR_I2C_READ_3 = -103;
const int AS5600_ERROR_I2C_WRITE_0 = -200;
const int AS5600_ERROR_I2C_WRITE_1 = -201;
// CONFIGURE CONSTANTS
// check datasheet for details
// setOutputMode
const uint8_t AS5600_OUTMODE_ANALOG_100 = 0;
const uint8_t AS5600_OUTMODE_ANALOG_90 = 1;
const uint8_t AS5600_OUTMODE_PWM = 2;
// setPowerMode
const uint8_t AS5600_POWERMODE_NOMINAL = 0;
const uint8_t AS5600_POWERMODE_LOW1 = 1;
const uint8_t AS5600_POWERMODE_LOW2 = 2;
const uint8_t AS5600_POWERMODE_LOW3 = 3;
// setPWMFrequency
const uint8_t AS5600_PWM_115 = 0;
const uint8_t AS5600_PWM_230 = 1;
const uint8_t AS5600_PWM_460 = 2;
const uint8_t AS5600_PWM_920 = 3;
// setHysteresis
const uint8_t AS5600_HYST_OFF = 0;
const uint8_t AS5600_HYST_LSB1 = 1;
const uint8_t AS5600_HYST_LSB2 = 2;
const uint8_t AS5600_HYST_LSB3 = 3;
// setSlowFilter
const uint8_t AS5600_SLOW_FILT_16X = 0;
const uint8_t AS5600_SLOW_FILT_8X = 1;
const uint8_t AS5600_SLOW_FILT_4X = 2;
const uint8_t AS5600_SLOW_FILT_2X = 3;
// setFastFilter
const uint8_t AS5600_FAST_FILT_NONE = 0;
const uint8_t AS5600_FAST_FILT_LSB6 = 1;
const uint8_t AS5600_FAST_FILT_LSB7 = 2;
const uint8_t AS5600_FAST_FILT_LSB9 = 3;
const uint8_t AS5600_FAST_FILT_LSB18 = 4;
const uint8_t AS5600_FAST_FILT_LSB21 = 5;
const uint8_t AS5600_FAST_FILT_LSB24 = 6;
const uint8_t AS5600_FAST_FILT_LSB10 = 7;
// setWatchDog
const uint8_t AS5600_WATCHDOG_OFF = 0;
const uint8_t AS5600_WATCHDOG_ON = 1;
class AS5600
{
public:
AS5600(TwoWire *wire = &Wire);
bool begin(uint8_t directionPin = AS5600_SW_DIRECTION_PIN);
// made virtual, see #66
virtual bool isConnected();
// address = fixed 0x36 for AS5600,
// = default 0x40 for AS5600L
uint8_t getAddress();
// SET CONFIGURE REGISTERS
// read datasheet first
// 0 = AS5600_CLOCK_WISE
// 1 = AS5600_COUNTERCLOCK_WISE
// all other = AS5600_COUNTERCLOCK_WISE
void setDirection(uint8_t direction = AS5600_CLOCK_WISE);
uint8_t getDirection();
uint8_t getZMCO();
// 0 .. 4095
// returns false if parameter out of range
bool setZPosition(uint16_t value);
uint16_t getZPosition();
// 0 .. 4095
// returns false if parameter out of range
bool setMPosition(uint16_t value);
uint16_t getMPosition();
// 0 .. 4095
// returns false if parameter out of range
bool setMaxAngle(uint16_t value);
uint16_t getMaxAngle();
// access the whole configuration register
// check datasheet for bit fields
// returns false if parameter out of range
bool setConfigure(uint16_t value);
uint16_t getConfigure();
// access details of the configuration register
// 0 = Normal
// 1,2,3 are low power mode - check datasheet
// returns false if parameter out of range
bool setPowerMode(uint8_t powerMode);
uint8_t getPowerMode();
// 0 = off 1 = lsb1 2 = lsb2 3 = lsb3
// returns false if parameter out of range
// suppresses noise when the magnet is not moving.
bool setHysteresis(uint8_t hysteresis);
uint8_t getHysteresis();
// 0 = analog 0-100%
// 1 = analog 10-90%
// 2 = PWM
// returns false if parameter out of range
bool setOutputMode(uint8_t outputMode);
uint8_t getOutputMode();
// 0 = 115 1 = 230 2 = 460 3 = 920 (Hz)
// returns false if parameter out of range
bool setPWMFrequency(uint8_t pwmFreq);
uint8_t getPWMFrequency();
// 0 = 16x 1 = 8x 2 = 4x 3 = 2x
// returns false if parameter out of range
bool setSlowFilter(uint8_t mask);
uint8_t getSlowFilter();
// 0 = none 1 = LSB6 2 = LSB7 3 = LSB9
// 4 = LSB18 5 = LSB21 6 = LSB24 7 = LSB10
// returns false if parameter out of range
bool setFastFilter(uint8_t mask);
uint8_t getFastFilter();
// 0 = OFF
// 1 = ON (auto low power mode)
// returns false if parameter out of range
bool setWatchDog(uint8_t mask);
uint8_t getWatchDog();
// READ OUTPUT REGISTERS
uint16_t rawAngle();
uint16_t readAngle();
// software based offset.
// degrees = -359.99 .. 359.99 (preferred)
// returns false if abs(parameter) > 36000
// => expect loss of precision
bool setOffset(float degrees); // sets an absolute offset
float getOffset();
bool increaseOffset(float degrees); // adds to existing offset.
// READ STATUS REGISTERS
uint8_t readStatus();
uint8_t readAGC();
uint16_t readMagnitude();
// access detail status register
bool detectMagnet();
bool magnetTooStrong();
bool magnetTooWeak();
// BURN COMMANDS
// DO NOT UNCOMMENT - USE AT OWN RISK - READ DATASHEET
// void burnAngle();
// void burnSetting();
// EXPERIMENTAL 0.1.2 - to be tested.
// approximation of the angular speed in rotations per second.
// mode == 1: radians /second
// mode == 0: degrees /second (default)
float getAngularSpeed(uint8_t mode = AS5600_MODE_DEGREES,
bool update = true);
// EXPERIMENTAL CUMULATIVE POSITION
// reads sensor and updates cumulative position
int32_t getCumulativePosition(bool update = true);
// converts last position to whole revolutions.
int32_t getRevolutions();
// resets position only (not the i)
// returns last position but not internal lastPosition.
int32_t resetPosition(int32_t position = 0);
// resets position and internal lastPosition
// returns last position.
int32_t resetCumulativePosition(int32_t position = 0);
// EXPERIMENTAL 0.5.2
int lastError();
protected:
// made virtual, see #66
virtual uint8_t readReg(uint8_t reg);
virtual uint16_t readReg2(uint8_t reg);
virtual uint8_t writeReg(uint8_t reg, uint8_t value);
virtual uint8_t writeReg2(uint8_t reg, uint16_t value);
uint8_t _address = AS5600_DEFAULT_ADDRESS;
uint8_t _directionPin = 255;
uint8_t _direction = AS5600_CLOCK_WISE;
int _error = AS5600_OK;
TwoWire* _wire;
// for getAngularSpeed()
uint32_t _lastMeasurement = 0;
int16_t _lastAngle = 0;
int16_t _lastReadAngle = 0;
// for readAngle() and rawAngle()
uint16_t _offset = 0;
// EXPERIMENTAL
// cumulative position counter
// works only if the sensor is read often enough.
int32_t _position = 0;
int16_t _lastPosition = 0;
};
/////////////////////////////////////////////////////////////////////////////
//
// AS5600L
//
class AS5600L : public AS5600
{
public:
AS5600L(uint8_t address = AS5600L_DEFAULT_ADDRESS, TwoWire *wire = &Wire);
bool setAddress(uint8_t address);
// UPDT = UPDATE
// are these two needed?
bool setI2CUPDT(uint8_t value);
uint8_t getI2CUPDT();
};
// -- END OF FILE --