JMotor
Loading...
Searching...
No Matches
JEncoderAS5048bI2C.h
Go to the documentation of this file.
1#ifndef J_ENCODER_AS5048B_I2C_H
2#define J_ENCODER_AS5048B_I2C_H
3#include "JEncoder.h"
4#include <Arduino.h>
5#include <Wire.h>
13private:
14 TwoWire* wire;
15
16 byte address;
17 long turns;
18 uint16_t angle;
19 int8_t reverse;
20 float velocity;
21 float distPerCountFactor;
22 bool newSpeed;
23 uint16_t lastAngle;
24 uint16_t lastVelAngle;
25 long lastVelTurns;
26 unsigned long lastVelTimeMicros;
27 unsigned long velEnoughTime;
28 unsigned long velEnoughTicks;
29 bool recognizeOutOfRange;
30
31 const byte AS5048B_ZEROMSB_REG = 0x16;
32 const byte AS5048B_ZEROLSB_REG = 0x17;
33 const byte AS5048B_ANGLMSB_REG = 0xFE;
34 const byte AS5048B_GAIN_REG = 0xFA;
35
36 void writeRegister8(uint8_t reg, uint8_t value)
37 {
38 wire->beginTransmission(address);
39 wire->write(reg);
40 wire->write(value);
41 wire->endTransmission();
42 }
43
44 uint16_t readRegister14(uint8_t reg)
45 {
46 // 16 bit value got from 2 8bits registers (7..0 MSB + 5..0 LSB) => 14 bits value
47 uint16_t readValue = 0;
48 byte readArray[2];
49
50 wire->beginTransmission(address);
51 wire->write(reg);
52 wire->endTransmission(false);
53
54 wire->requestFrom(address, (uint8_t)2);
55 readArray[0] = wire->read();
56 readArray[1] = wire->read();
57
58 readValue = (((uint16_t)readArray[0]) << 6);
59 readValue += (readArray[1] & 0b111111);
60 return readValue;
61 }
62
63 uint8_t readRegister8(uint8_t reg)
64 {
65 uint8_t readValue;
66
67 wire->beginTransmission(address);
68 wire->write(reg);
69 wire->endTransmission(false);
70
71 wire->requestFrom(address, (uint8_t)1);
72 readValue = (uint8_t)wire->read();
73
74 return readValue;
75 }
76
77 void writeToZeroRegister(uint16_t val)
78 {
79 writeRegister8(AS5048B_ZEROMSB_REG, (uint8_t)(val >> 6));
80 writeRegister8(AS5048B_ZEROLSB_REG, (uint8_t)(val & 0b00111111));
81 }
82
83 uint16_t readAngle()
84 {
85 return readRegister14(AS5048B_ANGLMSB_REG);
86 }
87
88public:
89 const unsigned int STEPS_PER_TURN = 16384; // resolution of encoder
90 static const byte AS5048B_DEFAULT_ADDRESS = 0x40; // can be accessed as JEncoderAS5048bI2C::AS5048B_DEFAULT_ADDRESS
91
102 JEncoderAS5048bI2C(bool _reverse = false, float _distPerCountFactor = 1.0, uint8_t _address = 0x40, unsigned long _velEnoughTime = 0, unsigned long _velEnoughTicks = 0, bool _recognizeOutOfRange = true)
103 : address(_address)
104 {
105 wire = &Wire;
106 if (_reverse) {
107 reverse = -1;
108 } else {
109 reverse = 1;
110 }
111 turns = 0;
112 angle = 0;
113 velocity = 0;
114 setDistPerCountFactor(_distPerCountFactor);
115 newSpeed = false;
116 lastAngle = 0;
117 lastVelAngle = 0;
118 lastVelTurns = 0;
119 lastVelTimeMicros = 0;
120 velEnoughTime = _velEnoughTime;
121 velEnoughTicks = _velEnoughTicks;
122 recognizeOutOfRange = _recognizeOutOfRange;
123 }
124
129 uint8_t getAutoGain()
130 {
131 return readRegister8(AS5048B_GAIN_REG);
132 }
133
138 void useCustomWire(TwoWire& _wire)
139 {
140 wire = &_wire;
141 }
142
147 void run()
148 {
149 if (!(recognizeOutOfRange && !isMagnetInRange())) {
150
151 angle = readAngle();
152 if (abs((int16_t)angle - (int16_t)lastAngle) > STEPS_PER_TURN / 2) { // angle jump over half of circle is assumed to be the shorter crossing of 0
153 if (angle > lastAngle) {
154 turns--;
155 } else {
156 turns++;
157 }
158 }
159
160 long velDist = ((int16_t)angle - (int16_t)lastVelAngle) + (turns - lastVelTurns) * STEPS_PER_TURN;
161 if (micros() - lastVelTimeMicros > velEnoughTime || abs(velDist) > velEnoughTicks) {
162 velocity = (double)1000000.0 * velDist / (micros() - lastVelTimeMicros) * distPerCountFactor * reverse;
163 lastVelTimeMicros = micros();
164 newSpeed = true;
165 lastVelAngle = angle;
166 lastVelTurns = turns;
167 } else {
168 newSpeed = false;
169 }
170
171 lastAngle = angle;
172 } else {
173 velocity = 0;
174 }
175 }
176
181 {
182 writeToZeroRegister(0);
183 uint16_t newZero = readRegister14(AS5048B_ANGLMSB_REG);
184 writeToZeroRegister(newZero);
185 }
190 void setEncoderZero(int zeroAngle)
191 {
192 zeroAngle = constrain(zeroAngle, 0, (long)STEPS_PER_TURN - 1);
193 writeToZeroRegister(zeroAngle);
194 }
195
202 {
203 return angle * reverse;
204 }
205
213 {
214 uint8_t gain = getAutoGain();
215 return (gain != 0) && (gain != 255);
216 }
217
223 long intTurns()
224 {
225 return turns * reverse;
226 }
227
229 {
230 return zeroCounter(true);
231 }
232
238 long zeroCounter(bool _resetAngle)
239 {
240 long tTurns = turns;
241 turns = 0;
242 if (_resetAngle) {
244 }
245 return (tTurns * STEPS_PER_TURN + angle) * reverse;
246 }
247
248 float getVel()
249 {
250 return velocity;
251 }
252
254 {
255 return (turns * STEPS_PER_TURN + angle) * reverse;
256 }
257
258 float getPos()
259 {
260 return (int32_t)((turns * STEPS_PER_TURN + angle) * reverse) * distPerCountFactor;
261 }
262
264 {
265 return distPerCountFactor;
266 }
267
272 void setDistPerCountFactor(float _factor)
273 {
274 distPerCountFactor = _factor / STEPS_PER_TURN;
275 }
276
278 {
279 return true;
280 }
281
282 bool isVelNew()
283 {
284 return newSpeed;
285 }
286 void setVelEnoughTime(unsigned long _velEnoughTime)
287 {
288 velEnoughTime = _velEnoughTime;
289 }
290 void setVelEnoughTicks(unsigned long _velEnoughTicks)
291 {
292 velEnoughTicks = _velEnoughTicks;
293 }
297 void setRecognizeOutOfRange(bool _recognizeOutOfRange)
298 {
299 recognizeOutOfRange = _recognizeOutOfRange;
300 }
301};
302#endif
reads a type of absolute encoder https://ams.com/as0548b (uses I2C)
Definition JEncoderAS5048bI2C.h:12
const unsigned int STEPS_PER_TURN
Definition JEncoderAS5048bI2C.h:89
long getCounter()
returns how far the encoder has turned from the zero position
Definition JEncoderAS5048bI2C.h:253
float getPos()
returns how far the encoder has turned from the zero position converted to distance
Definition JEncoderAS5048bI2C.h:258
static const byte AS5048B_DEFAULT_ADDRESS
Definition JEncoderAS5048bI2C.h:90
long zeroCounter()
reset the counter of how far the encoder has turned
Definition JEncoderAS5048bI2C.h:228
JEncoderAS5048bI2C(bool _reverse=false, float _distPerCountFactor=1.0, uint8_t _address=0x40, unsigned long _velEnoughTime=0, unsigned long _velEnoughTicks=0, bool _recognizeOutOfRange=true)
sets pins and settings for reading the encoder, remember to use Wire.begin()
Definition JEncoderAS5048bI2C.h:102
void setEncoderZero()
The current angle of the sensor is read and set to zero.
Definition JEncoderAS5048bI2C.h:180
int rawReading()
Definition JEncoderAS5048bI2C.h:201
void setEncoderZero(int zeroAngle)
A custom (repeatable) angle can be set for what the sensor calls zero relative to default zero.
Definition JEncoderAS5048bI2C.h:190
void run()
communication is done over I2C and requires constant polling instead of being able to use interrupts
Definition JEncoderAS5048bI2C.h:147
float getDistPerCountFactor()
returns a conversion factor between encoder ticks and distance that can be set for the encoder
Definition JEncoderAS5048bI2C.h:263
long intTurns()
how many full turns the encoder has made.
Definition JEncoderAS5048bI2C.h:223
bool isVelNew()
could be useful for only recalculating a control loop if there's new velocity data
Definition JEncoderAS5048bI2C.h:282
void setVelEnoughTicks(unsigned long _velEnoughTicks)
Definition JEncoderAS5048bI2C.h:290
uint8_t getAutoGain()
read the gain setting of the sensor
Definition JEncoderAS5048bI2C.h:129
void setVelEnoughTime(unsigned long _velEnoughTime)
Definition JEncoderAS5048bI2C.h:286
void setDistPerCountFactor(float _factor)
Definition JEncoderAS5048bI2C.h:272
long zeroCounter(bool _resetAngle)
reset the counter of how far the encoder has turned
Definition JEncoderAS5048bI2C.h:238
bool isMagnetInRange()
is the magnet in the optimal position Unlike other functions, this function does not rely on run()
Definition JEncoderAS5048bI2C.h:212
void setRecognizeOutOfRange(bool _recognizeOutOfRange)
Definition JEncoderAS5048bI2C.h:297
void useCustomWire(TwoWire &_wire)
Set what Wire (I2C) bus to use (for microcontrollers with more than one)
Definition JEncoderAS5048bI2C.h:138
bool hasDirection()
can this encoder measure direction or just speed
Definition JEncoderAS5048bI2C.h:277
float getVel()
calculates velocity in distance per second where distance was set by setdistPerCountFactor()
Definition JEncoderAS5048bI2C.h:248
defines common interface for JEncoder
Definition JEncoder.h:33