pondelok, 10 február 2014 12:35 Written by 6555 times
Rate this item
(9 votes)

Dýchajúca LED (Apple Breathing LED)

Na indikáciu činnosti procesora sa na doskách plošných spojov často používa blikajúca LED. Rozhodol som sa však indikovať činnosť trošičku krajším spôsobom ako obyčajným blikaním. Niečím, čo by vyvolávalo pocit, že processor žije – dýcha. Samozrejme podobnú myšlienku malo Apple dávno predo mnou a tak dýchjúcu LED majú na svojich notebookoch už roky (indikuje, že MacBook je v režime spánku). Pre tých čo nevedia o čom je reč, tu sú dve videá ako to vyzerá v skutočnosti.

 

Video 1: MacBook Black 13” (Mid 2007)

Video 2: MacBook PRO 15“ (Late 2011)

Relizácia je veľmi jednoduchá. Použijeme PWM výstup procesora, ktorý budeme patrične riadiť, aby sa plynule menil jas LED. Frekvencia PWM by mala byť aspoň 100Hz, aby to nepôsobilo rušivo. Na ukážku použijem procesor Atmega16 s pripojenými dvoma LED (na 2 PWM výstupy), aby sme mohli porovnať rôzne funkciu pre riadenie jasu. Obr.1 schema

Obr.1: Schéma zapojenia


Zdrojovy kód v c :

#include <avr/io.h>
int main(void)
{
	DDRD = (1<<DDD5) | (1<<DDD4);		// porty PD.4 a PD.5 nastavene na vystup
	
	TCCR1A = (1<<COM1A1) | (1<<COM1B1) ;// nulovanie pri citani hore, nastavenie pri citani dole
	TCCR1B = (1<<WGM13) |(1<<CS12);		// fazovo a frekvencne korektne PWM
	ICR1 = 0xFF;						// horna hranica PWM
	
	OCR1A = 0x0A;						
	OCR1B = 0xF0;
	
    while(1)
    {
    }
}

Zdrojový kód obsahuje iba inicializáciu portov PD.4 a PD.5 ako výstupných a nastavenie PWM. Na porty OC1A a OC1B je pripojený časovač 1, ktorý je 16 bitový. Pre jednoduchosť som hornú hranicu PWM nastvil na 255 (ICR1), čiže v našom prípade sa správa ako bežný 8 bitový časovač. Frekvencia pre časovač je odvodená od frekvencie procesora. Tu je vydelná 256 (nastavený bit CS12), čo by mala byť frekvencia PWM okolo 122 Hz (podmienku aby to bolo aspoň 100Hz sme teda splnili). Intenzitu LED (striedu PWM) meníme hodnotami v registroch OCR1A (D1) a OCR1B (D2). 0 je strieda 0% (LED zhasnutá), 255 je strieda 100% (plná intenzita LED). Výsledok je vidieť na nasledovných obrázkoch. Dióda D1 má nízky jas (strieda 3.7%), dióda D2 ma takmer plný jas (strieda 93.9%).

 

Obr.2 ledkyPWM

Obr.2: Intenzita LED pri prvotnom nastavení PWM

 

Tak PWM funguje a môžeme sa pustiť do generovania funkcií pre PWM. Najprv vyskúšame lineárnu zmenu hodnôt od minima po maximum a následne od maxima po minimum (trojuholník). Aby bol efekt pozorovateľný, tak medzi jednotlivými zmenami je oneskorenie 10ms.

Obr.3

Obr.3: Priebeh PWM na osciloskope

Zdrojový kód v C:

#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
	int x;
	DDRD = (1<<DDD5) | (1<<DDD4);		// porty PD.4 a PD.5 nastavene na vystup
	
	TCCR1A = (1<<COM1A1) | (1<<COM1B1) ;// nulovanie pri citani hore, nastavenie pri citani dole
	TCCR1B = (1<<WGM13) |(1<<CS12);		// fazovo a frekvencne korektne PWM
	ICR1 = 0xFF;						// horna hranica PWM
	
	OCR1A = 0x00;						
	OCR1B = 0x00;
	
    while(1)
    {
		
		for (x = 0; x < 256; x++)
		{
			OCR1A = x;
			_delay_ms(10);
		}
		for (x = 255; x >= 0; x--)
		{
			OCR1A = x;
			_delay_ms(10);
		}		
    }
}

Video 3: Lineárna zmena

Ako vidno efekt nič moc . Otázka je akú použiť funkciu, aby to vyzeralo ako dýchanie. Na internete sa dá nájsť pokus o zistenie funkcie na stránke http://www.adafruit.com/blog/2010/08/26/reverse-engineering-the-mac-breathing-led-2/ . Tu je však použitá nepriama metóda, teda nemeria priamo PWM, ale jas LED na MacBooku. Každopádne to vyzerá ako absolútna hodnota sínusu. Taktiež sa dá nájsť, že aj túto srandičku má Apple patentovanú http://www.google.com/patents/US6658577

Obr.4_patent

Obr. 4: Apple patent

Z obr. 4 je zrejmé, že priebeh je niečo podbné ako sínus. Poďme teda vyskúšať sínus. Pre jednoduchosť budeme počítať funkciu pre hodnoty do 0 do 255 a výstup funkcie by mal mať maximum 255 (plný jas LED). Úpravami dostaneme takúto funkciu:

Obr.5: Funkcia sin(x)

Obr.5: Funkcia sin(x)

Tento priebeh budeme opakovať v nekonečnej slučke. Teda minimálny jas bude velmi krátku dobu, zatiaľ čo jas okolo maxima sa bude meniť pozvoľne. Pripravíme si preto ešte “inverznú“ funkciu tejto, ktorá by mala maximálny jas len krátku dobu, zatiaľ čo v oblasti minimálne jasu, by sa funkcia zdržala podstatne dlhšie. Vyzerá to takto:

Obr.6_otocenysinus

Obr.6: Funkcia 1-sin(x)

Praktická realizácia týchto fukcií je v nasledujúcom výpise. Dióda D1 je budená otočeným sínusom, zatiaľ čo dióda D2 je budená bežným sínusom.

Zdrojový kód v C:

#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
	int x;
	double funkcia; 
	
	DDRD = (1<<DDD5) | (1<<DDD4);		// porty PD.4 a PD.5 nastavene na vystup
	
	TCCR1A = (1<<COM1A1) | (1<<COM1B1) ;// nulovanie pri citani hore, nastavenie pri citani dole
	TCCR1B = (1<<WGM13) |(1<<CS12);		// fazovo a frekvencne korektne PWM
	ICR1 = 0xFF;						// horna hranica PWM
	
	OCR1A = 0x00;						
	OCR1B = 0x00;
	
    while(1)
    {
	
		
		for (x = 0; x < 256; x++)
		{
			// 1 - sinus
			funkcia = (1-( sin( x * (M_PI / 255.0) ) ) )*255.0;
			OCR1A = (uint8_t) funkcia;	
			
			// sinus
			funkcia = ( sin( x * (M_PI / 255.0) ) ) *255.0;
			OCR1B = (uint8_t) funkcia;
			_delay_ms(20);
			
		}
    }
}

Video 4: Funkcia otočeného sínusu a sínusu

Výsledok je zachytený na videu.Je zrejmé, že otočený sínus poskytuje lepší výsledok optoti obyčajnému sínusu. V článku na adafruit jeden z komentárov uvádza, že funkcia by mala byť exp(sin(x)) aby korigovala logaritmickú odozvu optického systému. Úprava tejto funkcie pre požadovaný rozsah hodnôt je už trošičku zložitejšia. Celý postup úpravy funkcie tu nebudem rozpisovať – kto ovláda trochu matematiku, tak si to dokáže odvodiť sám. Výsledná funkcia vyzerá takto:

Obr.7: Funkcia exp(sin(x))

Obr.7: Funkcia exp(sin(x))

Obr.8: Zelená – otočený sinus, ružová – exponenciálna funkcia

Obr.8: Zelená – otočený sinus, ružová – exponenciálna funkcia

Zdrojový kód pre porovnanie jasu diód. D1 je 1-sin(x) a D2 je exp(sin(x)).

Zdrojový kód v C:

#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
	int x;
	double funkcia; 
	
	DDRD = (1<<DDD5) | (1<<DDD4);		// porty PD.4 a PD.5 nastavene na vystup
	
	TCCR1A = (1<<COM1A1) | (1<<COM1B1) ;// nulovanie pri citani hore, nastavenie pri citani dole
	TCCR1B = (1<<WGM13) |(1<<CS12);		// fazovo a frekvencne korektne PWM
	ICR1 = 0xFF;						// horna hranica PWM
	
	OCR1A = 0x00;						
	OCR1B = 0x00;
	
    while(1)
    {
		
	for (x = 0; x < 256; x++)
	{
	// exp(sin(x))
	funkcia = ( ( (-1.0/M_E) + ( exp ( cos( (2.0 * M_PI * x) / 255.0) ) )  ) / M_E ) * ( 255.0 / ( 1 - ( 1 / (M_E * M_E) ) ) ); 
	OCR1A = (uint8_t) funkcia;
							
			// 1 - sinus
	funkcia = (1-( sin( x * (M_PI / 255.0) ) ) )*255.0;
	OCR1B = (uint8_t) funkcia;
_delay_ms(20);
			
								}							
    }
}

Video 5: výsledok:

Exponenciálny sínus verzus otočený sínus. Rozdiel nie je moc markantný. Otázne je či treba zabíjať procesorový čas počítaním zložitých funkcií kvôli indikačnej dióde (kto nechce môže samozrejme použiť LUT – lookup table). Osobne používam funkciu 1-sin(x) a oneskorenie okolo 10ms. Tí čo chcú presnú kópiu Apple LED sa musia pohrať s časovaním a pridaním oneskorenia medzi jednotlivé priebehy. Presná kópia však nebola cieľom článku. Skôr som chcel predostrieť spôsob realizácie jednoduchého efektu.

 

Last modified on utorok, 11 február 2014 08:30
CUBETECH

Komplexné služby v oblasti vývoja zákazkovej elektroniky, priemyselnej a procesnej automatizácie, priemyselných testovacích a meracích systémov.

Website: www.cubetech.sk