Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dfasd #6

Open
wants to merge 34 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
63d1b79
Added speed functionality to the library
QuentinTorg Nov 28, 2015
6cde550
Uploaded outdated code on last commit
QuentinTorg Nov 28, 2015
a5464e4
Fix compilation errors
Nov 28, 2015
407c290
Merge pull request #1 from ryanpitt/master
QuentinTorg Nov 28, 2015
9119011
Minor Updates
QuentinTorg Nov 30, 2015
f9958c4
Fixed accuracy of velocity functions
QuentinTorg Dec 1, 2015
50c85de
One last semicolon
QuentinTorg Dec 1, 2015
e487c07
Corrected mistakes in calculation
QuentinTorg Dec 1, 2015
95fea81
Update and rename Encoder.h to EncoderMod.h
QuentinTorg Dec 4, 2015
cc47eb4
Update and rename Encoder.cpp to EncoderMod.cpp
QuentinTorg Dec 4, 2015
cdc9542
Update library.json
QuentinTorg Dec 4, 2015
5f69851
Updated examples
QuentinTorg Dec 5, 2015
cab71ef
Added extrapolation
QuentinTorg Dec 5, 2015
9669203
Improved step rate function
QuentinTorg Dec 5, 2015
9c98feb
Improved velocity function
QuentinTorg Dec 6, 2015
7c837d2
Fixed direction change rate timer issue
QuentinTorg Dec 6, 2015
7fa643e
Merge pull request #7 from QuentinTorg/Velocity-Extrapolated-Position
QuentinTorg Dec 6, 2015
a798aba
Fixed Compilation Issue
QuentinTorg Dec 6, 2015
388a619
Added acceleration based position extrapolation
QuentinTorg Dec 6, 2015
7109b17
Fix a compilation error, rename the library to EncoderMod
Dec 17, 2015
9377546
Merge pull request #9 from ryanpitt/master
QuentinTorg Dec 18, 2015
42d4a25
Added a lot of comments
QuentinTorg Dec 18, 2015
e096389
Merge branch 'master' into Acceleration-Extrapolated-Position
QuentinTorg Dec 25, 2015
5795535
Merge pull request #10 from QuentinTorg/Acceleration-Extrapolated-Pos…
QuentinTorg Dec 25, 2015
912cf9c
Implemented proper SREG handling
amiller27 Jan 8, 2016
9ec47e2
Initial setup, much to do
aftersomemath Mar 30, 2016
f6e682e
Got it working! Filter time is easily set, it is not as optimized as it
aftersomemath Apr 1, 2016
9b5ef20
Cleaned up the code, added extrapolate
aftersomemath Apr 1, 2016
f2644e1
Fix SREG handling
aftersomemath Apr 1, 2016
4a9730d
Remove unused variables
aftersomemath Apr 1, 2016
163204e
Merge pull request #12 from aftersomemath/velocity-optimized
amiller27 Apr 1, 2016
43af12a
Add automatically sized buffer for filter
aftersomemath Apr 2, 2016
b9dea0a
Merge pull request #13 from aftersomemath/velocity-optimized
QuentinTorg Apr 2, 2016
a0df79c
Update EncoderMod.h
aftersomemath Apr 2, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Encoder.cpp → EncoderMod.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

#include "Encoder.h"
#include "EncoderMod.h"

// Yes, all the code is in the header file, to provide the user
// configure options with #define (before they include it), and
Expand Down
219 changes: 209 additions & 10 deletions Encoder.h → EncoderMod.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
*/


#ifndef Encoder_h_
#define Encoder_h_
#ifndef EncoderMod_h_
#define EncoderMod_h_

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
Expand All @@ -51,6 +51,10 @@
#define ENCODER_ARGLIST_SIZE 0
#endif

#define FILTER_TIME_LIMIT 10000 //uS at 100/255 pwm we get about 1/0.004 = 250uS/tick so this averages about 4 ticks
#define US_INTERVAL 50 //This must be lower than time difference between ticks will ever be.
#define FILTER_INTERVALS (FILTER_TIME_LIMIT/US_INTERVAL)
#define MAX_BUFFER_SIZE ((int)(FILTER_TIME_LIMIT / 166.66)) //For 10:1 micro metal gear motors. 1sec/(3000rpm at shaft * 10:1 * 12enc/rev) = 166uS/tick


// All the data needed by interrupts is consolidated into this ugly struct
Expand All @@ -64,11 +68,18 @@ typedef struct {
IO_REG_TYPE pin2_bitmask;
uint8_t state;
int32_t position;
unsigned long stepTime1;
unsigned long stepTime2;
signed int uSBuffer[MAX_BUFFER_SIZE];
int32_t bufferIndex;
int32_t newTicks;
unsigned long timeOfLastTick;
} Encoder_internal_state_t;

class Encoder
{
public:

Encoder(uint8_t pin1, uint8_t pin2) {
#ifdef INPUT_PULLUP
pinMode(pin1, INPUT_PULLUP);
Expand All @@ -89,6 +100,12 @@ class Encoder
// the initial state
delayMicroseconds(2000);
uint8_t s = 0;
encoder.stepTime1 = micros();
encoder.stepTime2 = encoder.stepTime1;
memset(encoder.uSBuffer, 0, MAX_BUFFER_SIZE*sizeof(int));
encoder.bufferIndex = 0;
encoder.newTicks = 0;
encoder.timeOfLastTick = micros();
if (DIRECT_PIN_READ(encoder.pin1_register, encoder.pin1_bitmask)) s |= 1;
if (DIRECT_PIN_READ(encoder.pin2_register, encoder.pin2_bitmask)) s |= 2;
encoder.state = s;
Expand All @@ -102,21 +119,101 @@ class Encoder

#ifdef ENCODER_USE_INTERRUPTS
inline int32_t read() {
uint8_t old_SREG = SREG;
if (interrupts_in_use < 2) {
noInterrupts();
update(&encoder);
} else {
noInterrupts();
}
int32_t ret = encoder.position;
interrupts();
SREG = old_SREG;
return ret;
}
inline void write(int32_t p) {
uint8_t old_SREG = SREG;
noInterrupts();
encoder.position = p;
interrupts();
SREG = old_SREG;
}

inline float stepRate() {
int8_t old_SREG = SREG;
if (interrupts_in_use < 2) {
noInterrupts();
update(&encoder);
}
else {
noInterrupts();
}

float velocitySum = 0;
int index = encoder.bufferIndex - 1;
if(index < 0){
index += MAX_BUFFER_SIZE;
}
unsigned long timeSinceLastTick = micros() - encoder.timeOfLastTick;

SREG = old_SREG;

if(encoder.uSBuffer[index] == 0){
//The buffer is not initialized in the first position so just stop with what we have now. there has never been a tick
return 0.0;
}
//int sumIntervals = timeSinceLastTick/US_INTERVAL;
int sumIntervals = 0;
if(timeSinceLastTick > FILTER_TIME_LIMIT){
return 0.0;
}

while(1){
//Get how many discrete intervals
if(encoder.uSBuffer[index] == 0){
//The buffer is not initialized so just stop with what we have now.
break;
}
int intervals = abs(encoder.uSBuffer[index])/US_INTERVAL;
sumIntervals += intervals;
if(sumIntervals <= FILTER_INTERVALS){
velocitySum += intervals * (2.0/(float)encoder.uSBuffer[index]);
} else {
velocitySum += (intervals - (sumIntervals - FILTER_INTERVALS)) * (2.0/(float)encoder.uSBuffer[index]);
break;
}
index--;
if(index < 0 ){
index += MAX_BUFFER_SIZE;
}
}
float velocity = velocitySum / (float)FILTER_INTERVALS;
return velocity;
}

inline float extrapolate() {
uint8_t old_SREG = SREG;
if (interrupts_in_use < 2) {
noInterrupts();
update(&encoder);
}
else {
noInterrupts();
}
float lastRate = stepRate();
int32_t lastPosition = encoder.position;
unsigned long timeSinceLastTick = micros() - encoder.timeOfLastTick;
SREG = old_SREG;

float extrapolatedPosition = lastRate * timeSinceLastTick;
if (extrapolatedPosition > 1) {
return (lastPosition + 1);
}
else if (extrapolatedPosition < -1) {
return (lastPosition - 1);
}
else {
return (extrapolatedPosition + lastPosition);
}
}
#else
inline int32_t read() {
update(&encoder);
Expand All @@ -125,9 +222,35 @@ class Encoder
inline void write(int32_t p) {
encoder.position = p;
}
inline float stepRate() {
float extrapolatedPosition = encoder.rate * encoder.stepTime + 0.5 * encoder.accel * encoder.stepTime * encoder.stepTime;

if (extrapolatedPosition > 1) {
return (1 / encoder.stepTime);
}
else if (extrapolatedPosition < -1) {
return (-1 / encoder.stepTime);
}
else {
return (encoder.rate + encoder.accel * encoder.stepTime)
}

}
inline float extrapolate() {
float extrapolatedPosition = encoder.rate * encoder.stepTime + 0.5 * encoder.accel * encoder.stepTime * encoder.stepTime;
if (extrapolatedPosition > 1) {
return (encoder.position + 1);
}
else if (extrapolatedPosition < -1) {
return (encoder.position - 1);
}
else {
return (extrapolatedPosition + encoder.position);
}
}
#endif
private:
Encoder_internal_state_t encoder;
Encoder_internal_state_t encoder;
#ifdef ENCODER_USE_INTERRUPTS
uint8_t interrupts_in_use;
#endif
Expand Down Expand Up @@ -274,19 +397,95 @@ class Encoder
if (p1val) state |= 4;
if (p2val) state |= 8;
arg->state = (state >> 2);
// _______ _______
// Pin1 ______| |_______| |______ Pin1
// negative <--- _______ _______ __ --> positive
// Pin2 __| |_______| |_______| Pin2
// new new old old
// pin2 pin1 pin2 pin1 Result
// ---- ---- ---- ---- ------
//0 0 0 0 0 no movement
//1 0 0 0 1 +1 pin1 edge
//2 0 0 1 0 -1 pin2 edge
//3 0 0 1 1 +2 (assume pin1 edges only)
//4 0 1 0 0 -1 pin1 edge
//5 0 1 0 1 no movement
//6 0 1 1 0 -2 (assume pin1 edges only)
//7 0 1 1 1 +1 pin2 edge
//8 1 0 0 0 +1 pin2 edge
//9 1 0 0 1 -2 (assume pin1 edges only)
//10 1 0 1 0 no movement
//11 1 0 1 1 -1 pin1 edge
//12 1 1 0 0 +2 (assume pin1 edges only)
//13 1 1 0 1 -1 pin2 edge
//14 1 1 1 0 +1 pin1 edge
//15 1 1 1 1 no movement
unsigned long microsTemp = micros();
arg->timeOfLastTick = microsTemp;
switch (state) {
case 1: case 7: case 8: case 14:
case 1: case 14: //+1 pin1 edge
arg->uSBuffer[arg->bufferIndex] = microsTemp - arg->stepTime1;
arg->bufferIndex++;
arg->stepTime1 = microsTemp;
if(arg->bufferIndex >= MAX_BUFFER_SIZE){
arg->bufferIndex = 0;
}
//arg->newTicks++;
arg->position++;
return;
case 2: case 4: case 11: case 13:

case 7: case 8: //+1 pin2 edge
arg->uSBuffer[arg->bufferIndex] = microsTemp - arg->stepTime2;
arg->bufferIndex++;
arg->stepTime2 = microsTemp;
if(arg->bufferIndex >= MAX_BUFFER_SIZE){
arg->bufferIndex = 0;
}
//arg->newTicks++;
arg->position++;
return;

case 2: case 13: //-1 pin2 edge
arg->uSBuffer[arg->bufferIndex] = -(microsTemp - arg->stepTime2);
arg->bufferIndex++;
arg->stepTime2 = microsTemp;
if(arg->bufferIndex >= MAX_BUFFER_SIZE){
arg->bufferIndex = 0;
}
//arg->newTicks++;
arg->position--;
return;
case 3: case 12:
arg->position += 2;

case 4: case 11: //-1 pin1 edge
arg->uSBuffer[arg->bufferIndex] = -(microsTemp - arg->stepTime1);
arg->bufferIndex++;
arg->stepTime1 = microsTemp;
if(arg->bufferIndex >= MAX_BUFFER_SIZE){
arg->bufferIndex = 0;
}
//arg->newTicks++;
arg->position--;
return;

//+2's -2's to come later
//Because you can't know which direction you were going
//You will have to infer it from the last time in the buffer
//Meaning finding out if its less than or more than 0.
//Based on that result you will place the non corrupted timer in
//The timebuffer 3 times.
//One for the edge you measured correctly. One for the corrupted timer. One for the next corrupted timer which could never be correct.
//You don't need to put it in 3 times, just multiply it by three by shifting over one bit and adding itself.
//Set a flag for the next update of the corrupted timer so it knows not to add itself and to reset itself.
/*
case 3: case 12: //+2
arg->position += 2;
return;
case 6: case 9:
arg->position -= 2;

arg->position -= 2;
return;
*/

}
#endif
}
Expand Down
2 changes: 1 addition & 1 deletion examples/Basic/Basic.pde
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This example code is in the public domain.
*/

#include <Encoder.h>
#include <EncoderMod.h>

// Change these two numbers to the pins connected to your encoder.
// Best Performance: both pins have interrupt capability
Expand Down
2 changes: 1 addition & 1 deletion examples/NoInterrupts/NoInterrupts.pde
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// your program must call the read() function rapidly, or risk
// missing changes in position.
#define ENCODER_DO_NOT_USE_INTERRUPTS
#include <Encoder.h>
#include <EncoderMod.h>

// Beware of Serial.print() speed. Without interrupts, if you
// transmit too much data with Serial.print() it can slow your
Expand Down
2 changes: 1 addition & 1 deletion examples/SpeedTest/SpeedTest.pde
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
// It must be defined before Encoder.h is included.
//#define ENCODER_OPTIMIZE_INTERRUPTS

#include <Encoder.h>
#include <EncoderMod.h>
#include "pins_arduino.h"

// Change these two numbers to the pins connected to your encoder
Expand Down
2 changes: 1 addition & 1 deletion examples/TwoKnobs/TwoKnobs.pde
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This example code is in the public domain.
*/

#include <Encoder.h>
#include <EncoderMod.h>

// Change these pin numbers to the pins connected to your encoder.
// Best Performance: both pins have interrupt capability
Expand Down
6 changes: 5 additions & 1 deletion keywords.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
ENCODER_USE_INTERRUPTS LITERAL1
ENCODER_OPTIMIZE_INTERRUPTS LITERAL1
ENCODER_DO_NOT_USE_INTERRUPTS LITERAL1
Encoder KEYWORD1
EncoderMod KEYWORD1
read KEYWORD2
write KEYWORDD2
stepRate KEYWORD2
extrapolate KEYWORD2
4 changes: 2 additions & 2 deletions library.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"name": "Encoder",
"name": "EncoderMod",
"keywords": "encoder, signal, pulse",
"description": "Encoder counts pulses from quadrature encoded signals, which are commonly available from rotary knobs, motor or shaft sensors and other position sensors",
"repository":
{
"type": "git",
"url": "https://github.com/PaulStoffregen/Encoder.git"
"url": "https://github.com/QuentinTorg/EncoderMod"
},
"frameworks": "arduino",
"platforms":
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name=Encoder
name=EncoderMod
version=1.3
author=Paul Stoffregen
maintainer=Paul Stoffregen
Expand Down