JMotor
Loading...
Searching...
No Matches
JEncoderAS5600I2C.h
Go to the documentation of this file.
1#ifndef JENCODER_AS5600I2C_H
2#define JENCODER_AS5600I2C_H
3#include "JEncoder.h"
4#include <Arduino.h>
5#include <Wire.h>
12private:
13 TwoWire* wire;
14
15 byte address;
16 long turns;
17 uint16_t angle;
18 int8_t reverse;
19 float velocity;
20 float distPerCountFactor;
21 bool newSpeed;
22 uint16_t lastAngle;
23 uint16_t lastVelAngle;
24 long lastVelTurns;
25 unsigned long lastVelTimeMicros;
26 unsigned long velEnoughTime;
27 unsigned long velEnoughTicks;
28 bool recognizeOutOfRange;
29 uint16_t zeroAngle;
30
31public:
32 const byte ZMCO_REG = 0x00;
33 const byte ZPOSMSB_REG = 0x01;
34 const byte MPOSMSB_REG = 0X03;
35 const byte MANG_REG = 0x05;
36 const byte CONF_REG = 0x07;
37 const byte RAWANGLEMSB_REG = 0x0C;
38 const byte ANGLEMSB_REG = 0x0E;
39 const byte STATUS_REG = 0x0B;
40 const byte AGC_REG = 0x1A;
41 const byte MAGNITUDE_REG = 0x1B;
42 const byte BURN_REG = 0xFF;
43
44 void writeRegister8(uint8_t reg, uint8_t value)
45 {
46 wire->beginTransmission(address);
47 wire->write(reg);
48 wire->write(value);
49 wire->endTransmission();
50 }
51
52 void writeRegister12(uint8_t reg, uint16_t value)
53 {
54 // 12 bit value got from 2 8bits registers (7..0 MSB + 3..0 LSB) => 12 bits value
55 wire->beginTransmission(0x36);
56 wire->write(reg);
57 wire->write((uint8_t)((value >> 8) & 0b1111));
58 wire->write((uint8_t)(value & 0b11111111));
59 wire->endTransmission();
60 }
61
62 uint16_t readRegister12(uint8_t reg)
63 {
64 // 12 bit value got from 2 8bits registers (11..8 MSB + 7..0 LSB) => 12 bits value
65 byte readArray[2];
66
67 wire->beginTransmission(0x36);
68 wire->write(reg);
69 wire->endTransmission(false);
70
71 wire->requestFrom(0x36, 2);
72 readArray[0] = wire->read();
73 readArray[1] = wire->read();
74
75 uint16_t readValue = ((readArray[0] & 0b1111) << 8) | readArray[1];
76 return readValue;
77 }
78
79 uint8_t readRegister8(uint8_t reg)
80 {
81 uint8_t readValue;
82
83 wire->beginTransmission(address);
84 wire->write(reg);
85 wire->endTransmission(false);
86
87 wire->requestFrom(address, (uint8_t)1);
88 readValue = (uint8_t)wire->read();
89
90 return readValue;
91 }
92
93 const unsigned int STEPS_PER_TURN = 4096; // resolution of encoder
94 static const byte AS5048B_DEFAULT_ADDRESS = 0x36; // can be accessed as JEncoderAS5048bI2C::AS5048B_DEFAULT_ADDRESS
95
106 JEncoderAS5600I2C(bool _reverse = false, float _distPerCountFactor = 1.0, uint16_t _zeroAngle = 0, unsigned long _velEnoughTime = 0, unsigned long _velEnoughTicks = 0, bool _recognizeOutOfRange = true)
107 {
108 address = AS5048B_DEFAULT_ADDRESS;
109 wire = &Wire;
110 if (_reverse) {
111 reverse = -1;
112 } else {
113 reverse = 1;
114 }
115 turns = 0;
116 angle = 0;
117 velocity = 0;
118 setDistPerCountFactor(_distPerCountFactor);
119 newSpeed = false;
120 lastAngle = 0;
121 lastVelAngle = 0;
122 lastVelTurns = 0;
123 lastVelTimeMicros = 0;
124 velEnoughTime = _velEnoughTime;
125 velEnoughTicks = _velEnoughTicks;
126 recognizeOutOfRange = _recognizeOutOfRange;
127 }
128
132 uint8_t getAutoGain()
133 {
134 return readRegister8(AGC_REG);
135 }
136
140 uint16_t readAngle()
141 {
142 return (rawReading() + STEPS_PER_TURN - zeroAngle) % STEPS_PER_TURN;
143 }
144
149 void useCustomWire(TwoWire& _wire)
150 {
151 wire = &_wire;
152 }
153
158 void run()
159 {
160 if (!(recognizeOutOfRange && !isMagnetInRange())) {
161
162 angle = readAngle();
163 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
164 if (angle > lastAngle) {
165 turns--;
166 } else {
167 turns++;
168 }
169 }
170
171 long velDist = ((int16_t)angle - (int16_t)lastVelAngle) + (turns - lastVelTurns) * STEPS_PER_TURN;
172 if (micros() - lastVelTimeMicros > velEnoughTime || abs(velDist) > velEnoughTicks) {
173 velocity = (double)1000000.0 * velDist / (micros() - lastVelTimeMicros) * distPerCountFactor * reverse;
174 lastVelTimeMicros = micros();
175 newSpeed = true;
176 lastVelAngle = angle;
177 lastVelTurns = turns;
178 } else {
179 newSpeed = false;
180 }
181
182 lastAngle = angle;
183 } else {
184 velocity = 0;
185 }
186 }
187
192 void setEncoderZero(int _zeroAngle)
193 {
194 zeroAngle = constrain(_zeroAngle, 0, (long)STEPS_PER_TURN - 1);
195 }
196
202 {
204 }
205
212 {
214 }
215
223 {
224 return (readRegister8(STATUS_REG) & 0b100000) > 0;
225 }
226
232 long intTurns()
233 {
234 return turns * reverse;
235 }
236
242 {
243 return zeroCounter(true);
244 }
245
251 long zeroCounter(bool _resetAngle)
252 {
253 long tTurns = turns;
254 turns = 0;
255 if (_resetAngle) {
257 }
258 return (tTurns * STEPS_PER_TURN + angle) * reverse;
259 }
260
261 float getVel()
262 {
263 return velocity;
264 }
265
267 {
268 return (turns * STEPS_PER_TURN + angle) * reverse;
269 }
270
271 float getPos()
272 {
273 return (int32_t)((turns * STEPS_PER_TURN + angle) * reverse) * distPerCountFactor;
274 }
275
277 {
278 return distPerCountFactor;
279 }
280
285 void setDistPerCountFactor(float _factor)
286 {
287 distPerCountFactor = _factor / STEPS_PER_TURN;
288 }
289
291 {
292 return true;
293 }
294
295 bool isVelNew()
296 {
297 return newSpeed;
298 }
299 void setVelEnoughTime(unsigned long _velEnoughTime)
300 {
301 velEnoughTime = _velEnoughTime;
302 }
303 void setVelEnoughTicks(unsigned long _velEnoughTicks)
304 {
305 velEnoughTicks = _velEnoughTicks;
306 }
310 void setRecognizeOutOfRange(bool _recognizeOutOfRange)
311 {
312 recognizeOutOfRange = _recognizeOutOfRange;
313 }
314};
315#endif // JENCODER_AS5600I2C_H
reads a type of absolute encoder https://ams.com/en/as5600 (uses I2C)
Definition JEncoderAS5600I2C.h:11
float getPos()
returns how far the encoder has turned from the zero position converted to distance
Definition JEncoderAS5600I2C.h:271
uint16_t readRegister12(uint8_t reg)
Definition JEncoderAS5600I2C.h:62
long intTurns()
how many full turns the encoder has made.
Definition JEncoderAS5600I2C.h:232
void setVelEnoughTime(unsigned long _velEnoughTime)
Definition JEncoderAS5600I2C.h:299
void setRecognizeOutOfRange(bool _recognizeOutOfRange)
Definition JEncoderAS5600I2C.h:310
uint8_t readRegister8(uint8_t reg)
Definition JEncoderAS5600I2C.h:79
bool isMagnetInRange()
is the magnet in the optimal position Unlike other functions, this function does not rely on run()
Definition JEncoderAS5600I2C.h:222
uint16_t readAngle()
angle in raw units, but adjusted for custom zero
Definition JEncoderAS5600I2C.h:140
void writeRegister8(uint8_t reg, uint8_t value)
Definition JEncoderAS5600I2C.h:44
void run()
communication is done over I2C and requires constant polling instead of being able to use interrupts
Definition JEncoderAS5600I2C.h:158
const byte RAWANGLEMSB_REG
Definition JEncoderAS5600I2C.h:37
const byte BURN_REG
Definition JEncoderAS5600I2C.h:42
long zeroCounter(bool _resetAngle)
reset the counter of how far the encoder has turned
Definition JEncoderAS5600I2C.h:251
const byte MAGNITUDE_REG
Definition JEncoderAS5600I2C.h:41
float getDistPerCountFactor()
returns a conversion factor between encoder ticks and distance that can be set for the encoder
Definition JEncoderAS5600I2C.h:276
long getCounter()
returns how far the encoder has turned from the zero position
Definition JEncoderAS5600I2C.h:266
const byte MPOSMSB_REG
Definition JEncoderAS5600I2C.h:34
void writeRegister12(uint8_t reg, uint16_t value)
Definition JEncoderAS5600I2C.h:52
const byte ANGLEMSB_REG
Definition JEncoderAS5600I2C.h:38
const byte CONF_REG
Definition JEncoderAS5600I2C.h:36
const byte AGC_REG
Definition JEncoderAS5600I2C.h:40
static const byte AS5048B_DEFAULT_ADDRESS
Definition JEncoderAS5600I2C.h:94
const byte ZPOSMSB_REG
Definition JEncoderAS5600I2C.h:33
void setVelEnoughTicks(unsigned long _velEnoughTicks)
Definition JEncoderAS5600I2C.h:303
JEncoderAS5600I2C(bool _reverse=false, float _distPerCountFactor=1.0, uint16_t _zeroAngle=0, 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 JEncoderAS5600I2C.h:106
const byte STATUS_REG
Definition JEncoderAS5600I2C.h:39
void setEncoderZero()
set current angle as zero
Definition JEncoderAS5600I2C.h:201
bool hasDirection()
can this encoder measure direction or just speed
Definition JEncoderAS5600I2C.h:290
void useCustomWire(TwoWire &_wire)
Set what Wire (I2C) bus to use (for microcontrollers with more than one)
Definition JEncoderAS5600I2C.h:149
long zeroCounter()
reset the counter of how far the encoder has turned
Definition JEncoderAS5600I2C.h:241
const unsigned int STEPS_PER_TURN
Definition JEncoderAS5600I2C.h:93
float getVel()
calculates velocity in distance per second where distance was set by setdistPerCountFactor()
Definition JEncoderAS5600I2C.h:261
uint8_t getAutoGain()
Definition JEncoderAS5600I2C.h:132
void setEncoderZero(int _zeroAngle)
A custom (repeatable) angle can be set for what the sensor calls zero relative to default zero.
Definition JEncoderAS5600I2C.h:192
void setDistPerCountFactor(float _factor)
Definition JEncoderAS5600I2C.h:285
const byte MANG_REG
Definition JEncoderAS5600I2C.h:35
bool isVelNew()
could be useful for only recalculating a control loop if there's new velocity data
Definition JEncoderAS5600I2C.h:295
const byte ZMCO_REG
Definition JEncoderAS5600I2C.h:32
int rawReading()
Definition JEncoderAS5600I2C.h:211
defines common interface for JEncoder
Definition JEncoder.h:33