JMotor
Loading...
Searching...
No Matches
JEncoderPWMAbsolute.h
Go to the documentation of this file.
1#ifndef J_ENCODER_ATTACH_INTERRUPT_PWM_ABSOLUTE_H
2#define J_ENCODER_ATTACH_INTERRUPT_PWM_ABSOLUTE_H
3#include "JEncoder.h"
4#include <Arduino.h>
5
10#define JEncoderPWMAbsolute_AS5048settings \
11 { \
12 4095, 4119, 16, HIGH, 800, 1100 \
13 }
14
24public:
28 struct pwmSettings {
32 uint16_t RESOLUTION;
36 uint16_t PWM_STEPS;
40 uint16_t MIN_STEPS;
48 uint16_t MIN_CYCLE;
52 uint16_t MAX_CYCLE;
53 };
54
55protected:
57
58private:
59 long turns;
60 uint16_t angle;
61 uint16_t lastAngle;
62 uint16_t zeroPos;
63 bool resetAngleOnStart;
64 bool firstAngle;
65 int8_t reverse;
66 float distPerCountFactor;
67 bool newSpeed;
68 uint16_t lastVelAngle;
69 long lastVelTurns;
70 unsigned long lastVelTimeMicros;
71 unsigned long velEnoughTime;
72 unsigned long velEnoughTicks;
73 float velocity;
74 bool justStartedVel;
75 volatile bool newAngle;
76 volatile unsigned long dataStartMicros;
77 volatile unsigned long dataEndMicros;
78 volatile unsigned long earlyDataStartMicros;
79 volatile unsigned long oldDataEndMicros;
80 bool setPosZero;
81
82 pwmSettings ps;
83
84public:
96 JEncoderPWMAbsolute(byte _encoderPin, pwmSettings _ps, bool _reverse = false, float _distPerCountFactor = 1.0, unsigned long _velEnoughTime = 0, unsigned long _velEnoughTicks = 0, bool _resetAngleOnStart = false, uint16_t _zeroPos = 0)
97 : ps(_ps)
98 {
99 firstAngle = true;
100 resetAngleOnStart = _resetAngleOnStart;
101 encoderPin = _encoderPin;
102 if (_reverse) {
103 reverse = -1;
104 } else {
105 reverse = 1;
106 }
107 setDistPerCountFactor(_distPerCountFactor);
108
109 velEnoughTime = _velEnoughTime;
110 velEnoughTicks = _velEnoughTicks;
111 zeroPos = _zeroPos % ps.RESOLUTION;
112
113 turns = 0;
114 angle = 0;
115 lastAngle = 0;
116 newSpeed = false;
117 lastVelAngle = 0;
118 lastVelTurns = 0;
119 lastVelTimeMicros = 0;
120 velocity = 0.0;
121 newAngle = false;
122 dataStartMicros = 0;
123 dataEndMicros = 0;
124 earlyDataStartMicros = 0;
125 oldDataEndMicros = 0;
126 justStartedVel = true;
127 setPosZero = false;
128 }
129
134 virtual void setUpInterrupts(void (*_isrPointer)(void));
139 virtual void turnOffInterrupts();
140
147 {
148 return angle * reverse;
149 }
150
156 long intTurns()
157 {
158 return turns * reverse;
159 }
160
162 {
163 return zeroCounter(true);
164 }
165
171 long zeroCounter(bool resetAngle)
172 {
173 long tTurns = turns;
174 turns = 0;
175 if (resetAngle) {
176 setPosZero = true;
177 }
178 justStartedVel = true;
179 return (tTurns * ps.RESOLUTION) * reverse;
180 }
181
182 float getVel()
183 {
184 return velocity;
185 }
186
188 {
189 return (turns * ps.RESOLUTION + angle) * reverse;
190 }
191
192 float getPos()
193 {
194 return (turns * ps.RESOLUTION + angle) * reverse * distPerCountFactor;
195 }
196
198 {
199 return distPerCountFactor;
200 }
201
206 void setDistPerCountFactor(float _factor)
207 {
208 distPerCountFactor = _factor / ps.RESOLUTION;
209 }
210
212 {
213 return true;
214 }
215
216 bool isVelNew()
217 {
218 return newSpeed;
219 }
220
227 bool setZeroPos(uint16_t zeroAngle)
228 {
229 if (zeroAngle % ps.RESOLUTION != zeroPos) {
230 zeroPos = zeroAngle % ps.RESOLUTION;
231 return true;
232 }
233 return false;
234 }
235
239 void run()
240 {
241 if (newAngle) {
242 noInterrupts();
243 long interval = dataEndMicros - dataStartMicros;
244 long cycle = dataEndMicros - oldDataEndMicros;
245 newAngle = false;
246 interrupts();
247 if (interval > 0 && cycle > ps.MIN_CYCLE && cycle < ps.MAX_CYCLE) { //check that interrupts didn't change one number but not the other, and that frequency is within range
248 if ((resetAngleOnStart && firstAngle) || setPosZero) {
249 zeroPos = 0;
250 }
251 angle = (constrain(interval * ps.PWM_STEPS / cycle - ps.MIN_STEPS, 0, ps.RESOLUTION - 1) + ps.RESOLUTION - zeroPos) % ps.RESOLUTION;
252 if ((resetAngleOnStart && firstAngle) || setPosZero) {
253 zeroPos = (angle) % ps.RESOLUTION;
254 firstAngle = false;
255 lastAngle = 0;
256 setPosZero = false;
257 angle = 0;
258 }
259 if (abs((int16_t)angle - (int16_t)lastAngle) >= ps.RESOLUTION / 2) { // angle jump over half of circle is assummed to be the shorter crossing of 0
260 if (angle > lastAngle) {
261 turns--;
262 } else {
263 turns++;
264 }
265 }
266 lastAngle = angle;
267 }
268 }
269 int64_t velDist = ((int16_t)angle - (int16_t)lastVelAngle) + (turns - lastVelTurns) * ps.RESOLUTION;
270 if ((micros() - lastVelTimeMicros > velEnoughTime || abs(velDist) > velEnoughTicks)) {
271 if (justStartedVel) {
272 justStartedVel = false;
273 lastVelAngle = angle;
274 velDist = 0;
275 }
276 velocity = (double)1000000.0 * velDist / (micros() - lastVelTimeMicros) * distPerCountFactor * reverse;
277 newSpeed = true;
278 lastVelTimeMicros = micros();
279 lastVelAngle = angle;
280 lastVelTurns = turns;
281 } else {
282 newSpeed = false;
283 }
284 }
286 {
287 if (digitalRead(encoderPin) == ps.dataState) {
288 earlyDataStartMicros = micros();
289 } else {
290 oldDataEndMicros = dataEndMicros;
291 dataEndMicros = micros();
292 dataStartMicros = earlyDataStartMicros;
293 newAngle = true;
294 }
295 }
296};
297#endif
defines common interface for JEncoder
Definition JEncoder.h:33
reads a PWM signal from an absolute encoder
Definition JEncoderPWMAbsolute.h:23
long zeroCounter()
reset the counter of how far the encoder has turned
Definition JEncoderPWMAbsolute.h:161
virtual void setUpInterrupts(void(*_isrPointer)(void))
set up pins and interrupts
void run()
Definition JEncoderPWMAbsolute.h:239
long zeroCounter(bool resetAngle)
reset the zero point of the encoder
Definition JEncoderPWMAbsolute.h:171
bool hasDirection()
can this encoder measure direction or just speed
Definition JEncoderPWMAbsolute.h:211
long getCounter()
returns how far the encoder has turned from the zero position
Definition JEncoderPWMAbsolute.h:187
float getPos()
returns how far the encoder has turned from the zero position converted to distance
Definition JEncoderPWMAbsolute.h:192
void encoderISR()
Definition JEncoderPWMAbsolute.h:285
byte encoderPin
Definition JEncoderPWMAbsolute.h:56
JEncoderPWMAbsolute(byte _encoderPin, pwmSettings _ps, bool _reverse=false, float _distPerCountFactor=1.0, unsigned long _velEnoughTime=0, unsigned long _velEnoughTicks=0, bool _resetAngleOnStart=false, uint16_t _zeroPos=0)
sets pins and settings for reading the encoder
Definition JEncoderPWMAbsolute.h:96
virtual void turnOffInterrupts()
disable interrupts and stop monitoring encoder
float getDistPerCountFactor()
returns a conversion factor between encoder ticks and distance that can be set for the encoder
Definition JEncoderPWMAbsolute.h:197
bool setZeroPos(uint16_t zeroAngle)
change what angle of the absolute encoder is zero
Definition JEncoderPWMAbsolute.h:227
bool isVelNew()
could be useful for only recalculating a control loop if there's new velocity data
Definition JEncoderPWMAbsolute.h:216
float getVel()
calculates velocity in distance per second where distance was set by setdistPerCountFactor()
Definition JEncoderPWMAbsolute.h:182
long intTurns()
how many full turns the encoder has made.
Definition JEncoderPWMAbsolute.h:156
int rawReading()
Definition JEncoderPWMAbsolute.h:146
void setDistPerCountFactor(float _factor)
Definition JEncoderPWMAbsolute.h:206
struct for holding parameters for reading PWM Absolute Encoders
Definition JEncoderPWMAbsolute.h:28
uint16_t MIN_STEPS
number of steps corresponding to min angle. MAX_STEPS=MIN_STEPS+RESOLUTION
Definition JEncoderPWMAbsolute.h:40
uint16_t MAX_CYCLE
longest time (microseconds) between falling edges that will be considered a valid encoder signal (hig...
Definition JEncoderPWMAbsolute.h:52
uint16_t RESOLUTION
resolution of encoder data (pwm steps)
Definition JEncoderPWMAbsolute.h:32
bool dataState
HIGH or LOW, which state when pulse length increasing=increasing angle.
Definition JEncoderPWMAbsolute.h:44
uint16_t MIN_CYCLE
shortest time (microseconds) between falling edges that will be considered a valid encoder signal (lo...
Definition JEncoderPWMAbsolute.h:48
uint16_t PWM_STEPS
number of total clock steps in pwm output
Definition JEncoderPWMAbsolute.h:36