Snímanie polohy optickým enkodérom
Zo stránky SensorWiki
Záverečný projekt predmetu MIPS / LS2025 - Lukáš Čapla
Zadanie
Cieľom projektu je snímanie polohy natočenia optickým rotačným enkóderom, a túto polohu vypísať cez sériovú komunikáciu na počítač.

Literatúra:
Analýza a opis riešenia
V zadaní použijeme optický rotačný enkodér (LPD3806-600BM Rotary Encoder 600 Pulse NPN) teda 600 pulzov na jednu otáčku hriadeľa.

Schéma zapojenia

Signály A a B rotačného enkóderu.

zdroj: https://www.makerguides.com/quadrature-rotary-encoder-with-arduino/
Algoritmus a program
Algoritmus programu využíva prerušenia, pretože inak by sa mohlo stať, že niektoré signály procesor nespracuje. Teda použijeme piny PD2 a PD3 ako vstupy so zapnutými prerušeniami v sledovaní nábežnej hrany, čo je veľmi výhodné aj využiť, keďže princíp činnosti by sa dal vtedy opísať: ak signál A PD2 (INT0) prejde z 0 do 1, teda nábežná hrana sig. A a zároveň signál B nadobudne hodnotu 1, jedná sa o smer po smeru hodinových ručičiek teda inkrementujeme premennú counter, z obrázku signálov vyššie je zrejmé, že ak točíme hriadeľ opačným smerom, postup signálov sa jednoducho vymení, a teda pracujeme s prerušením signálu B PD3.
Použitý enkodér má 600 impulzov na otáčku, čo znamená 600 nábežných hrán na jednom kanáli (napríklad A) za jednu úplnú otáčku. Keďže v tomto programe spracovávame nábežné hrany na oboch kanáloch A aj B, dostávame dvojnásobok impulzov – teda 1200 impulzov na otáčku (Counts Per Revolution, CPR). Ide o tzv. 2x kvadratúrne dekódovanie. Keby sme sledovali aj zostupné hrany (falling edge), bolo by možné dosiahnuť až 4x dekódovanie a teda 2400 impulzov na otáčku.
Ďalej sa v hlavnom programe len vypisuje aktuálne natočenie hriadeľa cez UART sériovú linku na počítač, teda využívame knižnicu uart.h ako na cvičeniach.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include "uart.h"
#include <util/delay.h>
volatile long counter = 0;
volatile long temp = 0;
#define BAUD 9600
FILE mystdout = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);
// External Interrupt 0 (INT0) Handler (PD2)
ISR(INT0_vect) {
if (!(PIND & (1 << PIND3))) {
counter++;
} else {
counter--;
}
}
// External Interrupt 1 (INT1) Handler (PD3)
ISR(INT1_vect) {
if (!(PIND & (1 << PIND2))) {
counter--;
} else {
counter++;
}
}
int main(void) {
uart_init(); // Uart init
stdout = &mystdout;
// Set PD2 and PD3 as inputs with pull-up
DDRD &= ~((1 << DDD2) | (1 << DDD3)); // Inputs
PORTD |= (1 << PORTD2) | (1 << PORTD3); // Enable pull-up resistors
uart_init();
// Enable external interrupts on INT0 and INT1 on rising edge
EICRA |= (1 << ISC01) | (1 << ISC00); // INT0: Rising edge
EICRA |= (1 << ISC11) | (1 << ISC10); // INT1: Rising edge
EIMSK |= (1 << INT0) | (1 << INT1); // Enable INT0 and INT1
sei(); // Enable global interrupts
while (1) {
if (temp != counter) {
temp = counter;
printf("natocenie: %ld\r",counter);
}
}
return 0;
}
Zdrojový kód: zdrojaky.zip
Overenie
Funkciu sme overili pomocou seriového terminálu https://libhal.github.io/web-serial/ a teda ako je možné vidieť na videu, natočením hriadeľa snímame počet pulzov, čo by sme mohli následne previesť na stupne prípadne radiány, to by záviselo od konkrétneho použitia tohto typu senzoru, samozrejme môžeme takisto pracovať aj v týchto arbitrárnych číslach.

Video:
Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.