Pic Lab, PIC16, Experiment #20.1, The encoder, the polling states method 

In the previous article, there were a number of faulty determinations. Initially, I thought it should be OK for me, but after some debugging, I realized that such a fault percentage is not tolerable for my project.

a picture is taken from sparkfun

Posting a picture from the previous article again:

if you look carefully at the data, you could see that AC creates a certain decimal sequence in dependence on the rotation direction.

For one direction we have: 0 1 3 2 0 1 3 2 …

For another direction we have: 0 2 3 1 0 2 3 1 0 …

So, comparing the current condition with the previous one or two we can say where we are rotating the knob. One last thing to do – to set the timer for the refresh interval. To increase the accuracy we could decrease the refresh interval, and I did so – my refresh interval is equal to 1ms.

#include <htc.h>
#include <stdio.h>
#include "usart.h"
 
#define _XTAL_FREQ 4000000
 
#define left RB1                                     // пин энкодера А
#define right RB2                                    // пин энкодера С
 
volatile unsigned char EncData;                      //глобальная переменная для сохранения текущего состояния линий энкодера
__CONFIG(WDTDIS & UNPROTECT & LVPDIS & HS);
 
void main()
{
unsigned char OldEncData = 3;                        //сохраням старое значение линий, инициализируем с 3
unsigned char upcount = 0;
unsigned char downcount = 0;
 
TRISB1 = 1;
TRISB2 = 1;
init_comms();                                       //инициализируем уарт для дебага
OPTION = 0b11010001;                                //настраиваем таймер 0, на 1 мс
TMR0 = 0;
T0IE = 1;
GIE = 1;
 
while (1) {
 
if (OldEncData != EncData) {                       //если новое значение отличается от старого
    switch (OldEncData) {
             case 0 : if (EncData == 1) {upcount++; downcount=0; }
                      if (EncData == 2) {downcount++; upcount = 0; }
                      break;
             case 1 : if (EncData == 3) {upcount++; downcount=0; }
                      if (EncData == 0) {downcount++; upcount = 0; }
                      break;
             case 2 : if (EncData == 0) {upcount++; downcount=0; }
                      if (EncData == 3) {downcount++; upcount = 0; }
                      break;
             case 3 : if (EncData == 2) {upcount++; downcount=0; }
                      if (EncData == 1) {downcount++; upcount = 0; }
                      break;
                       }
  OldEncData = EncData;                           //текущее значение = старое значение
}
 
if (upcount >= 4) {                              //флаг поворота направо
printf("\r\n UP");
upcount = 0;
}
if (downcount >= 4 ) {                          //флаг поворота налево
printf("\r\n Down");
downcount = 0;
}
 
}
 
}
 
interrupt isr() {
 
if (T0IF) {
TMR0 = 0;
EncData = PORTB & 0b00000110;
EncData >>= 1;
T0IF = 0;
}
 
}

Initially I was catching variables upcount and downcount each single time, but I noticed that test message was showing 4 times per one turn, so I started to count them 4 times without any hestitation.

After code was uploaded to the uC, I was so surprised, no any single issue, perfectly great routine without issues even with my old shitty encoder.

The sources!

1 thought on “Pic Lab, PIC16, Experiment #20.1, The encoder, the polling states method 

  1. Pingback: Menu for the audio amplifier | diymicro.org

Leave a Reply

Your email address will not be published.