Introduction
A rotary encoder is an electro-mechanical device that converts the angular position or motion of a shaft or axle to an analog or digital code. Rotary encoders are usually placed at the side which is perpendicular to the shaft. Rotary encoders act as sensors for detecting angle, speed, length, position and acceleration in automation field.
Components
– 1 * Raspberry Pi
– 1 * Network cable (or USB wireless network adapter)
– 1 * Rotary Encoder module
– Jumper wires
Experimental Principle
Most rotary encoders have 5 pins with three functions of turning left, turning right and pressing down. Pin 4 and Pin 5 are switch wiring terminals used to press. They have no difference with buttons previously used, so we will no longer discuss them in this experiment. Pin 2 is generally connected to ground. Pin 1 and Pin 3 are first connected to pull-up resistor and then to microprocessor. In this experiment, they are connected to GPIO0 and GPIO1 of Raspberry Pi. When we rotate left and right, there will be pulse inputs in pin 1 and pin 3.
The figure shows, if both GPIO0 and GPIO1 are at high level, it indicates the switch rotates clockwise; if GPIO0 is at high level but GPIO1 is at low level, it indicates the switch rotates anti-clockwise. Therefore, during programming, you only need to check the state of pin 3 when pin 1 is at high level, then you can tell whether the switch is rotates clockwise or anti-clockwise.
Experimental Procedures
Step 1: Build the circuit
Raspberry Pi Rotary Encoder
GPIO0 ———————————- CLK
GPIO1 ———————————- DT
3.3V ———————————– +
GND ———————————– GND
Step 2: Edit and save the code (see path/Rpi_SensorKit_code/17_RotaryEncoder/ rotaryEncoder.c)
Step 3: Compile
gcc rotaryEncoder.c -lwiringPi
Step 4: Run
./a.out
Now, gently spin the knob of the rotary encoder to change the value of the variable in the above program, and you will see the value printed on the screen. When you spin it clockwise, the value will increase; when counterclockwise, the value will decrease.
Summary
Through this lesson, you have been familiar with the principle of rotary encoder and preliminarily mastered the interruption programming way of Raspberry Pi. Interruption is a very important concept and is widely used in modern computers. Interruption greatly reduces the CPU load.
rotaryEncoder.c
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <wiringPi.h>
#define SWPin 0
#define RoAPin 1
#define RoBPin 2
static volatile int globalCounter = 0 ;
unsigned char flag;
unsigned char Last_RoB_Status;
unsigned char Current_RoB_Status;
void btnISR(void)
{
globalCounter = 0;
}
void rotaryDeal(void)
{
Last_RoB_Status = digitalRead(RoBPin);
while(!digitalRead(RoAPin)){
Current_RoB_Status = digitalRead(RoBPin);
flag = 1;
}
if(flag == 1){
flag = 0;
if((Last_RoB_Status == 0)&&(Current_RoB_Status == 1)){
globalCounter ++;
}
if((Last_RoB_Status == 1)&&(Current_RoB_Status == 0)){
globalCounter --;
}
}
}
int main(void)
{
if(wiringPiSetup() < 0){
fprintf(stderr, "Unable to setup wiringPi:%s\n",strerror(errno));
return 1;
}
pinMode(SWPin, INPUT);
pinMode(RoAPin, INPUT);
pinMode(RoBPin, INPUT);
pullUpDnControl(SWPin, PUD_UP);
if(wiringPiISR(SWPin, INT_EDGE_FALLING, &btnISR) < 0){
fprintf(stderr, "Unable to init ISR\n",strerror(errno));
return 1;
}
while(1){
rotaryDeal();
printf("%d\n", globalCounter);
//printf("%d\n",globalCounter);
}
return 0;
}
Python Code
#!/usr/bin/env python
import RPi.GPIO as GPIO
import time
RoAPin = 11 # pin11
RoBPin = 12 # pin12
BtnPin = 13 # Button Pin
globalCounter = 0
flag = 0
Last_RoB_Status = 0
Current_RoB_Status = 0
def setup():
GPIO.setmode(GPIO.BOARD) # Numbers GPIOs by physical location
GPIO.setup(RoAPin, GPIO.IN) # input mode
GPIO.setup(RoBPin, GPIO.IN)
GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(BtnPin, GPIO.FALLING, callback=btnISR)
def rotaryDeal():
global flag
global Last_RoB_Status
global Current_RoB_Status
global globalCounter
Last_RoB_Status = GPIO.input(RoBPin)
while(not GPIO.input(RoAPin)):
Current_RoB_Status = GPIO.input(RoBPin)
flag = 1
if flag == 1:
flag = 0
if (Last_RoB_Status == 0) and (Current_RoB_Status == 1):
globalCounter = globalCounter - 1
if (Last_RoB_Status == 1) and (Current_RoB_Status == 0):
globalCounter = globalCounter + 1
def btnISR(channel):
global globalCounter
globalCounter = 0
def loop():
global globalCounter
tmp = 0 # Rotary Temperary
while True:
rotaryDeal()
if tmp != globalCounter:
print 'globalCounter = %d' % globalCounter
tmp = globalCounter
def destroy():
GPIO.cleanup() # Release resource
if __name__ == '__main__': # Program start from here
setup()
try:
loop()
except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the child program destroy() will be executed.
destroy()