Snímání dotyku pomocí LED

Jan Daněk, UREL, FEEC, VUT Brno
xdanek00@stud.feec.vutbr.cz

Marek Müller, UREL, FEEC, VUT Brno
xmulle02@stud.feec.vutbr.cz

Obsah:

  1. Úvod
  2. Teorie
  3. Praktické pokusy
  4. Závěr
  5. Literatura

Úvod

     LED diody jsou nejčastěji používány k indikaci stavů zařízení či k jiným grafickým efektům. Ve většině případů se jedná o výstupní zařízení. Cílem tohoto projektu je prozkoumat možnosti zapojení LED diod jako zařízení vstupních. Pak je možné používat LED diodu pro signalizaci stavů i pro snímání okolí. Velmi lákavé je snímání dotyku a následná odezva pomocí svitu LED diod.

Teorie

     Snímání dotyku je založeno na měření napětí na LED diodě v závěrném směru. Toto napětí vzniká generací elektronů pomocí dopadajícího světla. Napětí na LED diodě je závislé na intenzitě okolního světla.
     Napětí vybuzené na LED diodě je velmi malé. Při měření voltmetrem se vstupním odporem 10 Mohm a běžné denní intenzitě světla je velikost napětí asi 20 až 40 mV. Toto napětí lze zesílit operačním zesilovačem či přímo změřit pomocí AD převodníku. Tato řešení však vyžadují další hardware a postrádají eleganci.
     Dalším způsobem je využití kapacity PN přechodu diody. Tato kapacita je nabita (napětí v závěrném smyslu diody) a vybíjena nábojem generovaným dopadajícím světlem. Čím větší je světelná intenzita okolí, tím pomaleji se kapacita diody vybíjí až k nulové hodnotě napětí. Princip této metody je zobrazen na obr. 1 [2]. Stav Step 1 je určen k signalizaci, dioda je zapojena běžným způsobem. Stav Step 2 je určen k nabití vnitřní kapacity LED diody. Stav Step 3 měří (zjišťuje) velikost tohoto napětí na katodě LED diody.
     Velice výhodný a elengantní je způsob vyhodnocení doby poklesu napětí diody na určitou úroveň (z log. 1 do log.0). Tento čas je měřen pomocí časovače, hodnota registru časovače odpovídá intenzitě okolního světla.

Faze prepinani LED
Obr. 1: Fáze čtení a svícení LED diody [2]

     Napětí generované dopadajícím světlem je závislé na typu pouzdra diody a vyzařované vlnové délce. Vhodné jsou diody s velkými vyzařovacími úhly. Dopadající světlo je pak směrováno z většího okolního prostoru. Vlnová délka záření diody (barva pouzdra) podle zdroje [1] příliš nerozhoduje. Nejsou zde ovšem uvedeny infračervené diody, které podle diskuzí generují vyšší napětí.
     Zajímavé je využití matice LED diod jako dotykový senzor. Na obr. 2 převzatém z [5] je uvedeno grafické vyjádření postupu pro využití matice 8x8 LED diod jako senzorového pole. První krok (Step 1) zahrnuje vybrání příslušné osvětlovací LED diody, která bude poskytovat světlo pro sousední (blízké) senzory k snímání. Druhým krokem (Step 2) je obrácení předpětí blízkých LED diod, čímž jsou připraveny se stát senzory. Dioda v sousedním řádku a sloupci musí být vybrána k zabránění elektrickému rušení z osvětlovače. V třetím kroku (Step 3) dojde k přečtení napětí na katodě diody, které tak udává světelnou úroveň detekovanou senzorem. Nakonec ve čtvrtém kroku (Step 4) pak řadič může vybrat další sousední diodu, aby ji použil jako senzor nebo se přesunout k dalšímu bodu v poli opakováním celého postupu. Pro realizaci je vhodný maticově uspořádaný LED zobrazovač se společnou anodou. V zapojení se společnou anodou a jednotlivých katodách lze odebírat proud pouze z katody jedné diody (čtení). Ostatní fáze jsou méně kritické. Svícení lze provést připojením log.1 (5V) na společnou anodu, hodnotou katody log. 0 (0V) řídit svícení jednotlivých LED. Obdobně (s obrázecenou polaritou a a K) se provede nabíjení LED diody. Všechny tyto kroky je nutné časově multiplexovat, obdobně jako při práci s obyčejným maticovým zobrazovačem LED.

Faze cinnosti matice LED
Obr. 2: Jednotlivé fáze činnosti matice 8x8 LED, kdy 1 LED dioda osvětluje sousední snímací LED diody [5]

Praktické pokusy

     Použitý přípravek je nachystán na připojení k vývojové desce s procesorem ATmega16. Schéma zapojení a deska plošných spojů jsou vytvořeny v programu Eagle na obr. 3. Přípravek je nachystán k obousměrnému připojení LED diod s ochranným odporem 330 Ohm. Anoda LED diody je připojena na port A, katoda na port B mikroprocesoru. Toto zapojení umožnuje vyzkoušet možnosti měření pomocí AD převodníku i poklesem do log.0. Při využití AD převodníku ke čtení velikosti napětí, jsou diody zapojeny katodou na port A. Anoda je uzemněna portem B. Při čtení velikosti napětí vnitřním hradlem jsou porty A a B zapojeny jako digitální vstupy/výstupy.

Schema zapojeni LED diod
Obr. 3: Schéma zapojení LED diod a zrcadlový obraz desky plošných spojů

     Prvním zkoušeným přístupem bylo měření hodnoty pomocí AD převodníku. V hlavní smyčce je inicializace LCD displeje a AD převodníku. Poté program cyklicky čte hodnotu AD převodníku a porovnává ji s vypočtenou hranicí pro vyhodnocení stisku. Hranice je vypočtena ,,na světle", tzn. bez stisku. Toto provedení má rozdíl mezi stisknutím a uvolněním asi 20-40 mV. To není příliš pro spolehlivé vyhodnocení. Tento problém se dá částečně obejít přídáním hystereze a vhodného průměrování. Stisk je signalizován rozsvícením signalizačních LED diod připojených na portu D. Poté je na LCD displej vypsána hodnota změřená AD převodníkem.
#include <avr\io.h>
#include <stdlib.h>
#include <avr\iom16.h>
#include <avr\interrupt.h>
#include "lcd_c.c"
/* Frekvence krystalu */
#define F_OSC 16000000

// Global variables
char LED_touch;
unsigned long avg=190;						                	//default value for this LED
// Main function 
int main(void)
{

	// LCD init
	lcd_init();

	//AD init
	ADMUX|=(1<<REFS0)|(1<<REFS1);			                  		// 2,56V Reference
	ADCSRA|=(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);	                           	// clk/64
	ADCSRA|=(1<<ADEN);								// Enable ADC
	while(1){

		//LED0
		DDRB|=(1<<0);			
		PORTB&=~(1<<0);									// A low
		DDRA&=~(1<<0);									// K input
		ADCSRA|=(1<<ADSC);							// Start ADC
		while((ADCSRA&(1<<ADSC)));                                              // wait for end of conversion
	
		if (ADC>avg+5){								// shadow											
			DDRD=0xf0;								//LED ON PORTD
			PORTD=0x00;
		} else {									// light								
			DDRD=0xf0;								//LED OFF PORTD
			PORTD=0xf0;
			avg=(9*avg+ADC)/10;
		}		
					
		zobraz(avg);  
     }

     Lepším přístupem je vyhodnocování poklesu napětí na LED diodě do log.0. U tohoto přístupu není potřeba AD převodník, pro jednu LED diodu stačí jen dva piny procesoru. V hlavní smyčce main je funkce LED_read(), která slouží ke změření dopadajícího světla (stisku) a dále funkce _delay_ms(), která vymezuje čas pro signalizaci LED diodami.
     Funkce LED_read() pracuje s porty A a B, na kterých jsou připojeny LED diody (A na PORTB a K na PORTA). U čteného portu musí být vypnuty odpory pull-up!!! Tyto odpory totiž spotřebují náboj, který se pracně získal přepólováním LED diod. Funkce využívá časovač 1 pro měření doby poklesu. Délka měření jedné LED diody je dána hlavně dobou poklesu napětí na úroveň log.0. Celková doba měření je asi 3 ms. Jestliže je toto měření vloženo do stálého svitu LED diody, je tato doba už patrná lidským okem jako blikání.
     Na začátku funkce jsou uloženy hodnoty portů A a B, které se budou pro potřeby měření dále měnit. Tyto hodnoty jsou na konci funkce zase obnoveny. V další části funkce se na LED přivede opačné napětí (na A 0V a na K +5V), LED je tak v závěrném režimu a dochází k nabití vnitřní kapacity. Proces nabíjení je ihned hotov, není třeba čekat delší dobu. Po nabití se spustí časovač 1 a opakovaně se čte katoda diody (PORT A). Opakované čtení je nutné, protože toto neustálé čtení vytváří odběr z katody a úroveň napětí poklesne relativně rychle. Při pokusu o přečtení po určité době byla úroveň napětí mnohem větší. Čtení je prováděno, dokud úroveň na katodě nedosáhne úrovně napětí log.0 a v tu chvíli se zastaví čítač. Hodnota čítacího registru TCNT1 udává čas, za který poklesla úroveň napětí k nule. Tento čas je ovlivněn dopadajícím světlem. Čím větší je intenzita dopadajícího světla, tím více je čas poklesu delší. Při zatemněné diodě je hodnota čítacího registru TCNT1 = 0 až 15 000, při denním osvětlení je hodnota čítacího registru TCNT1 = 50 000. Tyto hodnoty jsou pouze orientační a dochází k jejím postupným změnám v závislosti na okolním osvětlení. Další část funkce vyhodnocuje stisk tlačítka v závislosti na hodnotě registu TCNT1. Stisk tlačítka je signalizován 4 LED diodami na portu D. Hraniční hodnota 20 000 byla zvolena experimentálně a pro univerzálnost by bylo nejvhodnější ji vypočítat z prvního měření. Hodnota čítacího registru je poté vynulována. Pro účely testování je zakomentována část kódu [3] využívající LCD displej k zobrazení aktuální hodnoty čítacího registru.
#include <avr\io.h>
#include <stdlib.h>
#include <avr\iom16.h>
#include <avr\interrupt.h>
#include "lcd_c.c"
#define F_OSC 16000000
// Global variables
char LED_touch=0;
unsigned long avg;					             		//default value for this LED

// Main function 
int main(void)
{
/*
// kontrola led vsechny sviti
	DDRB=0xff;			
	PORTB=0xff;									// A High port B
	DDRA=0xff;									// K Low port A
	PORTA=0x00;	
	while(1);
*/

	// LCD init
        // lcd_init();

	SFIOR|=(1<<PUD);	                                                 	//pullups off
	//LED on
	DDRB=0xff;			
	PORTB=0xff;									// A High port B
	DDRA=0xff;									// K Low port A
	PORTA=0x00;		
	while(1){
		LED_read();
//	PORTB=LED_touch;
		_delay_ms(250);

	}
	return 0;
}

void LED_read(){
		unsigned char outputB,outputA;
		unsigned char bit_num=0;

	//storing LED output value
	        outputB=PORTB;	
	        outputA=PORTA;	
	// charging LED,reverse voltage
		DDRB|=(1<<bit_num);									
		PORTB&=(1<<bit_num);		                        		// A low
		DDRA|=(1<<bit_num);									
		PORTA|=(1<<bit_num);		                         		// K high

	//LED discharge,read time					
		DDRB|=(1<<bit_num);			
		PORTB&=~(1<<bit_num);	                                           	// A low
		DDRA&=~(1<<bit_num);		                                  	// K input
	
		TCCR1B|=(1<<CS01);				                       	//run timer fclk
		while(PINA&(1<<bit_num));
		TCCR1B&=~(1<<CS01);				                     	//stop timer fclk

		if (TCNT1/100>200){		           			        // ligth											
			DDRD=0xf0;							//LED OFF PORTD
			PORTD=0xf0;
	     	        LED_touch=0x00;
		} else {								// shadow							
			DDRD=0xf0;					    	        //LED ON PORTD
			PORTD=0x00;
			LED_touch=0xff;
		}
		
//		zobraz(TCNT1/100);
										
		TCNT1=0;
	
	// return LED output value
		DDRA=0xff;
		DDRB=0xff;
		PORTB=outputB;
		PORTA=outputA;
}

/* Funkce pro zobrazeni poctu pulzu na LCD */
void zobraz(unsigned long co)
{	
	unsigned int pom;
	char dig1,dig2,dig3,dig4,dig5;
	char text[] = "     \n";

	dig1=co/10000;
    pom=co-10000*(unsigned int)dig1;
	dig2=pom/1000;
    pom=pom-1000*(unsigned int)dig2;
	dig3=pom/100;
    pom=pom-100*(unsigned int)dig3;
	dig4=pom/10;
    pom=pom-10*(unsigned int)dig4;
	dig5=pom;

    text[0]=48+dig1;				// number to CHAR
    text[1]=48+dig2;
    text[2]=48+dig3;
    text[3]=48+dig4;
    text[4]=48+dig5;

	lcd_clrscr();			     	
	lcd_puts(text);
     }

     Výše uvedený přípravek a kód byl vyzkoušen na mikroprocesoru ATmega16 s využitím školní vývojové desky BUT FEEC UREL 2006. Byly použity SMD LED diody těchto parametrů: SMD žlutá, pouzdro B0805, vlnová délka 595 nm, svítivost Iv = 50 mcd při proudu v propustném směru If = 20 mA, vyzařovací úhel 120°, napětí Uf = 2,1 V a odpory SMD o hodnotě 330 ohmů.
     První metoda měření bez ,,přepólování" vykazovala malou citlivost na intenzitu okolního světla. Odpojením odporu pull-up a ,,přepólováním" diody došlo ke zvýšení citlivosti avšak za cenu nestabilních výsledků. Při zastínění diody nevodivým předmětem se zařízení chová uspokojivě a signalizuje stisk, ale při přiblížení vodivé plochy (lidské ruky) dochází také k signalizaci stisku, ale přerušovanému. Velikost měřeného náboje je příliš malá a je ovlivňována přeslechy a rušením ve vývojové desce a také v samotném přípravku, který není dostatečně odstíněn.

Závěr

     Byly představeny dvě hlavní metody použití standardních LED diod k měření intenzity dopadajícího světla. Uspokojivé výsledky přinesla metoda s ,,přepólováním". Uvedený kód je pouze konceptem, který vykazuje určité výsledky, ale nepříliš stabilní. Velkým problémem je okolní rušení. Toto rušení by mohlo jít částečně kompenzovat pomocí průměrování a lepším návrhem desky plošných spojů s důkladným stíněním. Z časových důvodů nebylo provedeno bližší zkoumání. Zajímavou možností je využití okolní LED diody, která není právě měřena, ke svícení. Tím by se zvýšila intenzita světla dopadajícího na měřenou LED diodu. Došlo by tak ke zvýšení citlivosti na dotyk. Tento způsob se jeví jako nejvhodnější. Využití matice 8x8 LED diod bylo pouze teoreticky naznačeno [5], praktické provedení už z časových důvodů provedeno nebylo. Další informace jsou uvedeny zejména v [4].

Celý projekt je možné stáhnout zde. RAR obsahuje soubory programu Eagle, zdrojové soubory AVR Studia i html dokumentaci.

Literatura

[1] ZACHOVALOVÁ, V., Fotovoltaický jev u diod, 2010 [Online] Dostupné z WWW: < http://hw.cz/Teorie-a-praxe/Dokumentace/ART1031-Fotovoltaicky-jev-u-diod-LED.html >.
[2] LED Touch Sensor, 2010 [Online] Dostupné z WWW: < http://forums.parallax.com/forums/default.aspx?f=21&m=128674 >.
[3] Počítačová cvičení MMIA, 2010.
[4] Forum LEDs As Sensors, 2010 [Online] Dostupné z WWW: < http://projects.dimension-x.net/technology-and-projects/ledsensors >.
[5] Matrices as Sensors, 2010 [Online] Dostupné z WWW: < http://projects.dimension-x.net/archives/63 >.