Problem with encoder

Hello,
I have a probleme while programming my arduino.
I’m a beginner and I don’t master perfectly the arduino language.

here’s my situation : I want to know a X distance that I traveled whit my encoder .I want that the distance appear on my LCD screen . I’m using a rotatif encoder with 2000 pulses.

There’s a program that I found and I try but it doesn’t indicate me when I go backward.

Thank to help me

#include <FastIO.h>
#include <I2CIO.h>
#include <LCD.h>
#include <LiquidCrystal.h>
#include <LiquidCrystal_I2C.h>
#include <LiquidCrystal_SR.h>
#include <LiquidCrystal_SR2W.h>
#include <LiquidCrystal_SR3W.h>
#include <avr/interrupt.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // Using version 1.2.1
#define encoder0PinA 2 //Quadrature Track A
#define encoder0PinB 3 //Quadrature Track B
#define encoder0PinC 4 //Index Track
const int buttonPin = 5;
int buttonState = 0;

//encoder variables
volatile unsigned int encoder0Pos = 0; //the encoder position variable.
int start = true; //variable used to indicate the first time the encoder sees the index track.
int turn = 0; //the total turns.
int decimal = 0; //tenths of a turn.
int encoderHome = 0; //used to reset encoder0Pos if any counts are missed during a rotation.
int ccw = false; //which direction the encoder is spinning.
int display = 0; //variable for display data on LCD screen.
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

void setup(){

//encoder pinModes
pinMode(encoder0PinA, INPUT);
digitalWrite(encoder0PinA, HIGH); // turn on pullup resistor
pinMode(encoder0PinB, INPUT);
digitalWrite(encoder0PinB, HIGH); // turn on pullup resistor
pinMode(encoder0PinC, INPUT);
digitalWrite(encoder0PinC, HIGH); // turn on pullup resistor

attachInterrupt(1, doEncoder, CHANGE); // encoder track A on interrupt 1 - pin 3
attachInterrupt(0, doIndex, RISING); // encoder Index track on interupt 0 - pin 2

lcd.begin(16,2); // sixteen characters across - 2 lines
lcd.backlight();
lcd.print(“Nb tour”);
}

void loop(){

buttonState = digitalRead(buttonPin);
int analog_value = encoder0Pos;
if (buttonState == HIGH) {

encoder0Pos=0;
}

decimal = (encoder0Pos / 200); //500 encoder counts per rev divided by 50 is tenths.
if (turn <= -1){ //if turns goes into negative numbers do some stuff to show negative on the LCD.
display = (abs(turn + 1));
decimal = (9 - decimal); //tenths now counts in the reverse direction when turns is negative.
Serial.print ("-"); //print a negative sign when turns is negative
} else {
display = turn; //if turns is not negative then the display equals the turns
}
lcd.setCursor(0, 1);
lcd.print (display); //show turns on LCD
lcd.print("."); //print a decimal point after the turns
lcd.print (decimal); //print the tenths of a turn after the decimal point.
delay(20); //delay 20ms so that the LCD screen doesnt flood
}

void doIndex(){ //every time the index track comes around doIndex will run.
if (start == true){ //if this is the first time the index track has come around
encoderHome = encoder0Pos; //the encoder Home position will equal the current encoder position.
start = false; //tell the arduino that start is over
} else {
encoder0Pos = encoderHome; } //if this is not the first time index has come around reset the encoder position
} //so that if any counts are missed because of high speed or too high of resolution
//they do not mess up the total turns.
void doEncoder(){ //every time a change happens on encoder pin A doEncoder will run.

if (digitalRead(encoder0PinA) == HIGH) { // found a low-to-high on channel A
if (digitalRead(encoder0PinB) == LOW) { // check channel B to see which way encoder is spinning
ccw = true; // CCW
} else {
ccw = false; // CW
}
} else { //found a high-to-low on channel A
if (digitalRead(encoder0PinB) == LOW) { // check channel B to see which way encoder is spinning
ccw = false; // CW
} else {
ccw = true; // CCW
}
}
if (ccw == true){
encoder0Pos = (encoder0Pos - 1); //if encoder is spinning CCW subtract a count from encoder position
if (encoder0Pos == -1){ // if encoder position is equal to -1
encoder0Pos = 1999; //make encoder position equal to 499. (500 count encoder, change if needed)
turn = (turn - 1); } //if concoder position is changed to 499 subtract 1 from turns.
//this keeps rolling over the encoder positions so that it never
//gets below 0 counts
} else {
encoder0Pos = (encoder0Pos + 1); //if encoder is spinning CW add a count to encoder position
if (encoder0Pos == 2000){ // if encoder position is equal to 500.(500 count encoder, change if needed)
encoder0Pos = 0; //make encoder position equal to 0.
turn = (turn + 1); } //if concoder position is changed to 0 then add 1 to turns.
} //this keeps rolling over the encoder positions so that it never
} //gets over 499 counts

//reset the counter (display) with start=true, encoder0Pos=0, and turns=0


jean-michelchabot16: Hello, I have a probleme while programming my arduino. I'm a beginner and I don't master perfectly the arduino language.

here's my situation : I want to know a X distance that I traveled whit my encoder .I want that the distance appear on my LCD screen . I'm using a rotatif encoder with 2000 pulses.

There's a program that I found and I try but it doesn't indicate me when I go backward.

Thank to help me

You need to understand how rotary encoders work.

The have two output, normally labeled A and B. There is a phase relationship between A and B. The black lines are the signals from A and B, The blue dotted vertical lines are the important events.

There are a couple of simple rules to understand an Quadrature Encoder.

  • the order of HIGH to LOW translations indicates direction.
  • Only One signal can change at a time.

|500x407 To understand this picture (fig.24); I'm going to state my assumptions: when A leads B, the rotation direction is ClockWise. Both A and B are LOW.

The first interesting point labeled (N-2) A goes HIGH. Since A and B were the same, then A changed, the direction is Clockwise.

The second interesting point is labeled (N-1) B goes HIGH. Since A was already HIGH, this means that it is still rotating ClockWise.

Now both signals are HIGH.

At (N) A goes LOW. Since B is HIGH the direction is ClockWise.

At (0) B goes LOW. Since A is LOW the direction is Clockwise.

and Now Both signals are LOW, back to the starting point. This cycle repeats as long as the encoder is rotating clockwise.

The same rules apply if you start from the Right side of the graphic. But Since B is now the leading signal, the direction is reversed.

Code to implement these rules is pretty simple:

volatile bool encoderA=low; // current value for the Encoder A signal 
volatile bool encoderB=low; // current value for the Encoder B signal
volatile long pos=0; // starting at 'zero' position

#define EncoderAPin 2     // Arduino pin that the 'A' channel is connected to
#define EncoderBpin 3

// interrupt routine watching signal A
void encoderAservice(void){
encoderA = digitalRead(EncoderAPin);
if(encoderA!=encoderB){ // 'A' is leading so CW
  pos = pos + 1;
  }
else { // 'A' is following CCW
  pos = pos -1;
  }
} 

// interrupt routine watching signal B
void encoderBservice(void){
encoderB = digitalRead(EncoderBPin);
if(encoderB!=encoderA){ // 'B' is leading so CCW
  pos = pos -  1;
  }
else { // 'B' is following CW
  pos = pos + 1;
  }
} 

void setup(){
attachInterrupt(digitalPinToInterrupt(EncoderAPin),encoderAservice, CHANGE);
attachInterrupt(digitalPinToInterrupt(EncoderBPin),encoderBservice, CHANGE);
Serial.begin(9600);
}

static long oldPos=0;

void loop(){
if((oldPos!=pos)&&(Serial.availableForWrite()>10)){ // new position, and there is room in the
  // serial buffer for the next position, I don't want to over fill the serial buffer,  so I only
  // send new position when there is space in the Serial Monitor Buffer.

  noInterrupts(); // pos can change at any time, so I 'freeze it' by disabling interrupts
  oldPos = pos; // then I copy the value 
  interrupts();  // then I turn interrupts back on
  Serial.println(oldPos,DEC); // display the current position
  }
}

Chuck.

Thanks for reply me but it's still have things not declared in the scope. I have difficulty with de meaning of this error . Thanks

jean-michelchabot16: Thanks for reply me but it's still have things not declared in the scope. I have difficulty with de meaning of this error . Thanks

Capitalization errors.

make low LOW

EncoderAPin EncoderApin EncoderBpin EncoderBpin

Chuck.