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.
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.
Pingback: Menu for the audio amplifier | diymicro.org
Pingback: Pic Lab, PIC18, Experiment #4, Encoder | diymicro.org