My encoder tick counter looses it's accuracy when I introduce a lcd.print call.
In the "//STill Moving" section of my code, when I un-comment the lcd.print call, the encoder returns results that are two high by around 20%. I should be able to turn my encoder 1 turn and get 1440 ticks, but is counting 1500 + ticks. If I take the lcd.print calls out in this section of my code, all works right.
Can the lcd calls be keeping the interrupt code from processing correctly? I would think it would count less ticks, but is always more? Any ideas?
Thanks!
/*
*Quadrature Decoder
*/
#include "Arduino.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <digitalWriteFast.h> // library for high performance reads and writes by jrraines
// see http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1267553811/0
// and http://code.google.com/p/digitalwritefast/
// It turns out that the regular digitalRead() calls are too slow and bring the arduino down when
// I use them in the interrupt routines while the motor runs at full speed.
// Quadrature encoders
// Left encoder
#define c_EncoderInterruptA 0
#define c_EncoderInterruptB 1
#define c_EncoderPinA 2
#define c_EncoderPinB 3
//#define EncoderIsReversed
volatile bool _EncoderASet;
volatile bool _EncoderBSet;
volatile bool _EncoderAPrev;
volatile bool _EncoderBPrev;
volatile long _EncoderTicks = 0;
long deltaTicks = 0;
// initialize the library with the numbers of the interface pins
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
long l_lastPrint;
long _pauseTime = 1500;
long _StartTime = 0;
volatile long _LastEncoderTicks;
bool _isMoving = false;
long _lastMoveTime;
void setup()
{
Serial.begin(9600);
// Quadrature encoders
// Left encoder
pinMode(c_EncoderPinA, INPUT_PULLUP); // sets pin A as input
// digitalWrite(c_EncoderPinA, LOW); // turn on pullup resistors
pinMode(c_EncoderPinB, INPUT_PULLUP); // sets pin B as input
// digitalWrite(c_EncoderPinB, LOW); // turn on pullup resistors
attachInterrupt(c_EncoderInterruptA, HandleLeftMotorInterruptA, CHANGE);
attachInterrupt(c_EncoderInterruptB, HandleLeftMotorInterruptB, CHANGE);
l_lastPrint = millis();
_LastEncoderTicks = _EncoderTicks;
lcd.init(); //initialize the lcd
lcd.backlight(); //open the backlight
lcd.setCursor(0,0);
lcd.print("Length: ");
}
void loop()
{
delay(10);
deltaTicks = abs(_LastEncoderTicks - _EncoderTicks);
//Start Moving
if (deltaTicks > 1 && _isMoving == false)
{
_LastEncoderTicks = _EncoderTicks;
_isMoving = true;
//Serial.print(_LastEncoderTicks - _EncoderTicks);
_lastMoveTime = millis();
Serial.print("Moving\n");
}
//STill Moving
if (deltaTicks > 1 && _isMoving ==true )
{
_lastMoveTime = millis();
//lcd.setCursor(7,0);
//lcd.print("Moving: ");
//lcd.print((float(_EncoderTicks)/1440.0)*6.0,3);
//lcd.print(" ");
}
//Stop Moving
if ((deltaTicks < 1) && (_isMoving == true) && millis() - _lastMoveTime > 3000 )
{
_LastEncoderTicks = _EncoderTicks;
_isMoving = false;
Serial.print((float(_EncoderTicks)/1440.0)*6.0,3);
Serial.print(" Stopped\n");
lcd.setCursor(0,0);
lcd.print("LengthF: ");
lcd.print((float(_EncoderTicks)/1440.0)*6.0,3);
lcd.print(" ");
_EncoderTicks = 0;
}
_LastEncoderTicks = _EncoderTicks;
// Output to serial for debug
if (millis() - l_lastPrint > 1000)
{
//Serial.print(millis() - l_lastPrint);
l_lastPrint = millis();
Serial.print("Encoder Ticks: ");
Serial.print(_EncoderTicks);
Serial.print(" Revolutions: ");
Serial.print(_EncoderTicks/1440.00);//4000 Counts Per Revolution
Serial.print("\n");
} //endifM
}
// Interrupt service routines for the left motor's quadrature encoder
void HandleLeftMotorInterruptA(){
_EncoderBSet = digitalReadFast(c_EncoderPinB);
_EncoderASet = digitalReadFast(c_EncoderPinA);
_EncoderTicks+=ParseEncoder();
_EncoderAPrev = _EncoderASet;
_EncoderBPrev = _EncoderBSet;
}
// Interrupt service routines for the right motor's quadrature encoder
void HandleLeftMotorInterruptB(){
// Test transition;
_EncoderBSet = digitalReadFast(c_EncoderPinB);
_EncoderASet = digitalReadFast(c_EncoderPinA);
_EncoderTicks+=ParseEncoder();
_EncoderAPrev = _EncoderASet;
_EncoderBPrev = _EncoderBSet;
}
int ParseEncoder(){
if(_EncoderAPrev && _EncoderBPrev){ //pre both hgh
if(!_EncoderASet && _EncoderBSet) return 1;
if(_EncoderASet && !_EncoderBSet) return -1;
}else if(!_EncoderAPrev && _EncoderBPrev){ //pre A low, B High
if(!_EncoderASet && !_EncoderBSet) return 1;
if(_EncoderASet && _EncoderBSet) return -1;
}else if(!_EncoderAPrev && !_EncoderBPrev){ //pre both low
if(_EncoderASet && !_EncoderBSet) return 1;
if(!_EncoderASet && _EncoderBSet) return -1;
}else if(_EncoderAPrev && !_EncoderBPrev){ //pre A high, b low
if(_EncoderASet && _EncoderBSet) return 1;
if(!_EncoderASet && !_EncoderBSet) return -1;
}
}