Motor Encoder

Sample

Components

  • Arduino Uno
  • 4x4 Keypad
  • I2C LCD
  • DC Motor with encoder
  • L293D Motor Driver

Connections

Display connections

From (I2C display)To (arduino)
1VCC5V
2GNDGND
3SDASDA
4SCLSCL

Keypad connections

From (Keypad)To (arduino)
1Row 1D13
2Row 2D12
3Row 3D11
4Row 4D10
5Col 1D9
6Col 2D8
7Col 3D7
8Col 4D4

Motor connections

From (Motor)To
1Motor negativeOutput 4 (L293D)
2Motor positiveOutput 3 (L293D)
3Encoder groundGND (L293D)
4Channel BD3 (arduino)
5Channel AD2 (arduino)
6Encoder power5V (arduino)

L293D connections

From (L293D)To (arduino)
1Power 15V
2Input 4D5
3Output 4refer above
4GroundGND (both arduino/motor)
5GroundGND (both arduino/motor)
6Output 3refer above
7Input 3D6
8Enable 3,45V
9Enable 1,25V
10Input 1N/A
11Output 1N/A
12GroundGND
13GroundGND
14Output 2N/A
15Input 2N/A
16Power 25V

Code

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// ----------
// keypad setup
#include <Keypad.h>

const byte numRows= 4; //number of rows on the keypad
const byte numCols= 4; //number of columns on the keypad

// global keypad variables
String enteredValue = "";
int encoderSpeed = 0;
float debugEncoderSpeed = 0.00; // (encoderSpeed * 100) / 255

//keymap defines the key pressed according to the row and columns just as appears on the keypad
char keymap[numRows][numCols]= 
{
{'1', '2', '3', 'A'}, 
{'4', '5', '6', 'B'}, 
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};

//Code that shows the the keypad connections to the arduino terminals
byte rowPins[numRows] = {13,12,11,10}; //Rows 0 to 3
byte colPins[numCols]= {9,8,7,4}; //Columns 0 to 3

Keypad myKeypad= Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols);

// ----------
// lcd setup
#include <Adafruit_LiquidCrystal.h>
Adafruit_LiquidCrystal lcd_1(0);
int LCDRow = 0;

#define motorA 5
#define motorB 6
int encoderPin1 = 2;
int encoderPin2 = 3;
volatile int lastEncoded = 0;
volatile long encoderValue = 0;
volatile long correctEncoderValue =0;
 
long lastencoderValue = 0;
 
int lastMSB = 0;
int lastLSB = 0;

void setup() {
  Serial.begin (9600);
  pinMode(encoderPin1, INPUT);
  pinMode(encoderPin2, INPUT);
  digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
  digitalWrite(encoderPin2, HIGH); //turn pullup resistor on
  attachInterrupt(0, updateEncoder, CHANGE);
  attachInterrupt(1, updateEncoder, CHANGE);
  
  pinMode(motorA,OUTPUT);
  pinMode(motorB,OUTPUT);
  
  lcd_1.begin(16, 2);
  lcd_1.print("Enter value:");
  lcd_1.setCursor(LCDRow, 10);
}

void loop() {
  // encoder control statements
  correctEncoderValue = encoderValue/4;
  
  Serial.println(correctEncoderValue);
  
  if ( 0<=correctEncoderValue && correctEncoderValue < 3000) {
    analogWrite(motorA,encoderSpeed);
    digitalWrite(motorB,LOW);
  } else {
    analogWrite(motorA,0);
    digitalWrite(motorB,LOW);
  }
  delay(100);
  
  // keypad control statements
  char keypressed = myKeypad.getKey();
  if (keypressed != NO_KEY) {
  Serial.println(keypressed);
  }
  
  // getting the key pressed from the user
  if (keypressed){
    // gets triggered for numeric key presses
    if (keypressed != 'D' && keypressed != 'A' && keypressed != 'B' && keypressed != 'C') {
    	Serial.println(keypressed);
    	lcd_1.print(keypressed);
    	lcd_1.setCursor(++LCDRow, 10);
      enteredValue += keypressed;
    // a - clear the entered value
    } else if (keypressed == 'A') {
      lcd_1.clear();
      lcd_1.print("Enter value:");
      lcd_1.setCursor(++LCDRow, 10);
      enteredValue = "";
      encoderSpeed = 0;
    // d - update the entered value
    } else {
      LCDRow = 0;
      lcd_1.clear();
      lcd_1.print("Value updated");
      delay(500);

      // taking the encoder speed from the user
      // encoder value lies between 0 and 255
      // we take the value only if its between 0 and 255
      if (enteredValue == "") {
        encoderSpeed = 0;
        Serial.println("Case 1: Blank entered value");
      } else if (enteredValue.toInt() > 0 && enteredValue.toInt() < 255) {
        encoderSpeed = enteredValue.toInt();
        Serial.println("Case 2: Accepted entered value");
      } else {
        encoderSpeed = 0;
        Serial.println("Case 3: Out of of bounds entered value");
      }
    } // special keypresses end
  } // keypressed trigger end
  debugEncoderSpeed = (encoderSpeed * 100) / 255;
  Serial.println(debugEncoderSpeed);

}

void updateEncoder(){
  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit
 
  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value
 
  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;
 
  lastEncoded = encoded; //store this value for next time
}

How to use this

Click the link below and press simulate. You can see the debug output in the serial monitor.
To enter a value press a key on the keypad. To update the value press D and to clear the value press A.

Click here

References