Table of Contents

 

Kooder

Vajalikud teadmised: [HW] Kasutajaliidese moodul, [HW] Kombomoodul, [LIB] Kooder,
[LIB] Graafiline LCD, [AVR] Loendurid/Taimerid, [AVR] Katkestused

Teooria

Optopaar

Kooder on elektro-mehaaniline seade, mis muundab võlli pöördenurga või nurkkiiruse analoogsignaaliks või digitaalkoodiks. Olemas on veel lineaarkoodrid, mis erinevad pöördliikumisele mõeldud koodritest selle poolest, et koodri liikumine toimub mööda sirget. Muus osas on tööpõhimõte sarnane.

Olemas on kahte peamist tüüpi koodreid: absoluutsed ja suhtelised (loendavad). Absoluutse koodri väljund näitab jooksvat võlli asendit. Toite katkemise korral on asend peale toite sisselülitamist uuesti tuvastatav. Alloleval pildil olev parempoolne kooderketas on lihtne absoluutkoodri ketas, mida loetakse kolme anduri abil. Moodustuv binaarkood võimaldab ketta asendit mõõta 45 kraadiste sammude täpsusega.

Koodri ketas (vasakul suhteline, paremal absoluutne)

Suhtelise koodri väljund annab informatsiooni võlli liikumise kohta, mida saab edasi töödelda. Tüüpiliselt arvutatakse liikumise kiirus ja suund. Suhteline kooder ei võimalda peale toite kadumist võlli konkreetset asendit enam kindlaks teha. Suhteline kooder annab tsüklilist väljundsignaali ainult siis, kui võll pöörleb.

Suhteline optiline kooder koosneb avade või lõhedega kettast ja optopaarist. Optopaar on IR-valgusdioodist ja fototransistorist koosnev süsteem, mille vahele on asetatud piludega kooderketas nii, et ketta pöörlemisel avad perioodiliselt katkestavad valguse ning seetõttu vastavalt lülitavad fototransistorit sisse ja välja. Selle tulemusena tekib fototransistori väljundis ristküliksignaal, mida saab kasutada võlli nurkkiiruse leidmiseks. Ühe optopaariga koodrid võimaldavad impulsside sageduse järgi mõõta ainult pöörlemiskiirust. Pöörlemissuuna kohta informatsioon puudub. Lisaks optilistele koodritele on laialt kasutusel Halli efektil põhinevad koodrid. Kooder koosneb vahelduva magnetväljaga andurikettast või püsimagnetist, mis pööreldes genereerib pooljuhis pingeimpulsse. Pingeimpulsid võimendatakse ja muudetakse kontrollerile saadetavaks digitaalseks signaaliks. Koodri signaalide lugemine on analoogne optiliste koodrite signaalide lugemise ja tõlgendamisega.

Võlli pöörlemissuuna kindlakstegemiseks on vaja lisada teine optopaar. Kui optopaarid on asetatud nii, et tekiks 90 kraadine faasinihe nende signaalide vahel on tegemist kvadratuur väljunditega. Optopaaride signaalide olekudiagramm on toodud juuresoleval pildil, kus optopaaride väljundeid on tähistatud A ja B. Väljundid loetakse tarkvaraliselt, tavaliselt katkestuste vahendusel, mis genereeritakse signaali tõusva või langeva frondi korral. Pöörlemissuuna saab määrata väljundkoodide võrdlemise abil. Näiteks, kui viimane väärtus on 00 ja uus väärtus 01, siis võll on pöördunud ühe poolsammu võrra kellaosuti liikumise suunas.

Koodri tööpõhimõte
Kellaosuti liikumise
suunaline pöörlemine
Kellaosuti liikumise
vastassuunaline pöörlemine
Faas A B A B
1 0 0 1 0
2 0 1 1 1
3 1 1 0 1
4 1 0 0 0

Praktika

Kodulaboris on koodrite sisendid seotud taimerite viikudega. Kasutada saab nii Halli anduril põhinevaid, kui ka optilisi koodreid. Elektrilised ühendused on toodud vastava plaadi riistvarakirjelduses

Kodulabori teek võimaldab lugeda koodri pulsse. Koodri pulsside loendamine toimub viigu langeva frondi korral genereeritava katkestuse kaudu. Katkestuse toimumise korral suurendatakse vastava koodri pulsside arvu muutujat ühe võrra.

Koodri kasutamiseks on Kodulabori teegis olemas funktsioon encoder_init, mis seadistab koodri viigud sisendiks ja seab töökorda katkestuse. Funktsioon encoder_get_pulses tagastab koodri pulsside arvu ja funktsioon encoder_reset_pulses nullib valitud koodri pulsside arvu.

Järgnevalt on toodud näide koodrite lugemisest ATmega2561 kontrolleriga.

// Koodrite arv
#define NUM_ENCODERS 2
 
// Koodri pulsside arvu määramine sekundis
#define ENCODER_TICKS (F_CPU / 8 / 256)
 
// Viikude määramine
static pin encoder_pins[NUM_ENCODERS] =
{
	PIN(E, 6),
	PIN(E, 7)
};
 
typedef struct
{	
	unsigned short num_pulses;
}
encoder_data;
 
static encoder_data encoder[NUM_ENCODERS];
 
// Katkestuste töötleja
void encoder_pulse(unsigned char index)
{
	encoder[index].num_pulses++;
}
 
// Katkestused
ISR(INT6_vect) {
	encoder_pulse(0);
}
 
 
ISR(INT7_vect) {
	encoder_pulse(1);
}
 
// Koodrite seadistamine
void encoder_init(unsigned char index)
{
	// Viigu sisendiks seadistamine koos pull-up takistite lubamisega
	pin_setup_input_with_pullup(encoder_pins[index]);
 
	// Välise katkestuse võimaldamine, genereeritakse langeva frondi tekkides
	switch (index)
	{
		case 0:
			bit_set(EICRB, ISC61);
			bit_clear(EICRB, ISC60);
			bit_set(EIMSK, INT6);
			break;
 
		case 1:
			bit_set(EICRB, ISC71);
			bit_clear(EICRB, ISC70);
			bit_set(EIMSK, INT7);
			break;
	}
 
	// Algväärtustamine
	encoder[index].num_pulses = 0;
}
 
// Valitud koodri nullimine
void encoder_reset_pulses(unsigned char index)
{	
	cli();
	encoder[index].num_pulses = 0;
	sei();
}
 
// Koodri pulsside arvu loendamine
unsigned short encoder_get_pulses(unsigned char index)
{	
	return encoder[index].num_pulses;	
}

Funktsioonide kasutamist demonstreerib näiteprogramm, mis kuvab koodri pulsside arvu ekraanile. Nupp S2 nullib koodri ja alustab uuesti loendamist.

// Kodulabori koodri kasutamise näidisprogramm
// LCD-le kuvatakse koodri pulsside arv
#include <stdio.h>
#include <homelab/module/lcd_gfx.h>
#include <homelab/delay.h>
#include <homelab/module/encoders.h>
#include <homelab/pin.h>
 
// Põhiprogramm
int main(void)
{
	unsigned short pulses = 0;
	char text[16];
 
	// Nupu seadistamine
	pin_setup_input_with_pullup(S2);
 
	// Koodri algväärtustamine
	encoder_init(1);
 
	// Loendamise nullimine ja käivitamine
	encoder_reset_pulses(1);
 
	// LCD ekraani algseadistamine
	lcd_gfx_init();
	lcd_gfx_clear();
	lcd_gfx_backlight(true);	
	lcd_gfx_goto_char_xy(3, 1);
	lcd_gfx_write_string("Kooder");
 
	// Lõputu tsükkel	
	while (1)
	{
		pulses = encoder_get_pulses(1);
 
		// Teksti moodustamine.
		sprintf(text, "Pulsse: %5d",pulses);
 
		lcd_gfx_goto_char_xy(0, 3);
		lcd_gfx_write_string(text);
 
		// Nupp S2 alla vajutatud?
		if(button_read(S2))
		{
			// Loendamise nullimine ja käivitamine
			encoder_reset_pulses(1);
 
			// Vana teksti tühikutega ülekirjutamine
			lcd_gfx_write_string("    ");
		} 
 
		// Paus 10 millisekundit
		sw_delay_ms(10);
	}
}