Boa noite a todos, aqui está uma pequena brincadeira que tenho vindo a fazer, é algo simples mas que volta e meia aparece nalgum forum, pois como sabemos a nossa visão não é linear, e já todos devem ter reparado que se usarmos pwm para controlar o brilho de um led, parece que o brilho do mesmo aumenta muito rapidamente até cerca de metade dos valores (em linguagem arduino isto quer dizer analogWrite(ledPin,150)) mais coisa menos coisa e que dai para cima variar o valor do pwm não parece surtir grande efeito, para corrigir isso podemos recorrer a fórmulas ou tabelas (look-up tables) para que o valor do pwm seja menos linear, regra geral aponta-se para valores exponenciais ou então para uma curva parabólica (do tipo Ax²+Bx + C), então escrevendo um pequeno programa em C, e usando uma fórmula retirada do forum AVRfreaks e uma outra que determinei, eis que tenho duas tabelas para experimentar no arduino com um led.
Usar tabelas não lineares é ainda mais perceptivel quando se usa um led rgb, pois assim nota-se uma melhor distribuição cromática e não parece apenas branco com um brilho/intensidade variavel, pode-se dizer que as cores fica mais vivas.
A comparação entre linear, exponencial e parabólico:
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fimg51.imageshack.us%2Fimg51%2F6268%2Fgraficoe.png&hash=a5c70f5dfb42379915431123949aeb8ac9453f5e)
A azul está o linear, a vermelho estão os valores da tabela parabólica e a amarelo estão os da tabela exponencial.
Aqui fica um pequeno video, a qualidade não é das melhores pois foi filmado com o telemovel e o pulsar dos led's no fim de cada ciclo é devido aos ajustes da camera em relação á luminosidade e não tem nada a ver com o pwm gerado pelo arduino.
Nos dois casos o led com pwm linear está á esquerda, estando o outro com a tabela não linear á direita:
Non linear look up tables to control led brightness using pwm (http://www.youtube.com/watch?v=aijhK3HX5qY#)
E aqui fica o programa em que gerou as duas tabelas, é só copiar e colar no vosso programa do arduino, são um pouco extensas sim, mas no final dos exames irei actualizar o programa para guardar essas mesmas tabelas na flash do arduino e talvez fazer um tutorial de como usar os atributos PROGMEM. Este programa compila sem erros usando o gcc 4.4.3.
#include <stdio.h>
#include <math.h>
/*
Programa para gerar as duas tabelas usadas
Tiago Angelo
7/7/2010
Para compilar: gcc log.c -lm -o log
*/
int calc(int num){
return (((1<<(num/32))-1) + ((1<<(num/32))*((num%32)+1)+15)/32);}
int calc2(int num){
return (num*num*0.00392);}
int main(void){
int i=0;
for(i=0;i<256;i++){
if(i==0){printf("uint8_t expn[256] = {%d,",calc(i));}
else if(i==255){printf("%d}; \n",calc(i));}
else {printf("%d,",calc(i));}}
printf("\n");
for(i=0;i<256;i++){
if(i==0){printf("uint8_t parab[256] = {%d,",calc2(i));}
else if(i==255){printf("%d}; \n",calc2(i)+1);}
else {printf("%d,",calc2(i));}}
}
E o programa que o arduino está a correr é o seguinte:
/*Demonstração de uso de tabelas de dados não lineares para controlo do brilho de leds via pwm
Tiago Angelo
7/7/2010
*/
uint8_t expn[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,7,7,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,11,11,11,11,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,65,67,69,71,73,75,77,79,81,83,85,87,89,91,93,95,97,99,101,103,105,107,109,111,113,115,117,119,121,123,125,127,131,135,139,143,147,151,155,159,163,167,171,175,179,183,187,191,195,199,203,207,211,215,219,223,227,231,235,239,243,247,251,255};
uint8_t parab[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,2,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,7,7,7,8,8,9,9,9,10,10,11,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19,20,20,21,22,22,23,23,24,25,25,26,27,27,28,28,29,30,31,31,32,33,33,34,35,36,36,37,38,39,39,40,41,42,43,44,44,45,46,47,48,49,50,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,79,80,81,82,83,84,85,87,88,89,90,91,92,94,95,96,97,99,100,101,102,104,105,106,108,109,110,111,113,114,115,117,118,120,121,122,124,125,127,128,129,131,132,134,135,137,138,140,141,143,144,146,147,149,150,152,153,155,156,158,159,161,163,164,166,167,169,171,172,174,176,177,179,181,182,184,186,188,189,191,193,194,196,198,200,201,203,205,207,209,210,212,214,216,218,220,222,223,225,227,229,231,233,235,237,239,241,243,244,246,248,250,252,255};
char var;
void setup() {
Serial.begin(9600);
Serial.write("Envia s para tabela exponencial e S para tabela parabolica");
}
void loop() {
if(Serial.available()){
var=Serial.read();
if(var=='s'){
for(int i=0; i<256; i++){
analogWrite(6,expn);
analogWrite(5,i);
delay(100);
Serial.print(i);
Serial.print(" ");
Serial.println(expn,DEC);
}
}
if(var=='S'){
for(int i=0; i<256; i++){
analogWrite(6,parab);
analogWrite(5,i);
delay(100);
Serial.print(i);
Serial.print(" ");
Serial.println(expn,DEC);
}
}
}
}
Digam o que acham ;)