Na data de 26/05/2013 fiz uma breve introdução à programação C para Arduino no The Developer´s Conference (TDC2013), aqui em Florianópolis. A apresentação é apenas um indicativo do que foi falado. Download na figura abaixo.
Mensagem
"Sonhar mais um sonho impossível, lutar quando é fácil ceder, vencer o inimigo invencível, negar quando a regra é vender."
Miguel de Cervantes.
Miguel de Cervantes.
"Os microprocessadores RISC funcionam a partir do princípio genial de se encarregar das coisas mais fáceis e deixar todas as partes difíceis para outras pessoas resolverem."
Douglas Adams.
uGame
Este
projeto foi desenvolvido para a programação básica de jogos, foi baseado em um
projeto que encontrei em um site japones
(http://nicotak.com/avr/ledgame.html). O hardware emprega 4 matrizes de 8x8 LEDs
(pixel quadrado) e o 74HC595 para a expansão de I/O, o circuito pode ser visto
aqui. Infelizmente a placa de circuito impresso foi
desenvolvida com um erro na posição das matrizes de LEDs (tenho certa culpa no
processo). Dessa forma, necessitei fazer uma placa de correção. Assim, não
estou disponibilizando o seu desenho (se alguém o desejar, é só me escrever).
Fiz um
programa básico onde realizo a varredura da matriz de LEDs dentro de uma
interrupção do timer do ATmega328 (microcontrolador utilizado), o que
resultou em torno de 750 bytes de programação.
A matriz de LEDs é mapeada no programa por
um vetor de 16 posições com 16 bits cada (unsigned int), o que permite a
qualquer momento escrever em qualquer pixel da matriz. Por incrível que possa
parecer, dada a estrutura da matriz, utilizar variáveis de 16 bits em
detrimento as de 8 bits (no caso do ATmega), resultou em um código mais
eficiente.
Também fiz algumas rotinas de som, o que
permite tocar algumas notas músicais de forma simples.
Como gosto de aproveitar o hardware, acabei
incluindo um sensor de tempertura (LM35). Dessa forma, utilizo um filtro de
média móvel de 64 amostras para a suavização da leitura.
O programa demo é quase uma pintura, pelo
menos nas funcionalidades básicas, vale a pena analisá-lo (download aqui).
Desenvolvi o jogo da cobra, adaptação
daquele antigo jogo de celular onde uma cobrinha vai comento os pixels e
aumentado de tamanho. Nessa parte da programação, a coisa já ficou mais confusa
e menos otimizada. Criei um vetor que armazena as coodenadas XY da cabeça da
cobra a cada passo e permite aumentar e movimentar a cobra. No vídeo
abaixo é possível ver a funcionalidade do jogo.
Em resumo, a necessidade de desenvolver
algoritmos diferentes de acordo com o jogo é bem desafiadora, e sem dúvida, é
necessário um bom projeto para um jogo bem programado.
Um aprendizado dessa brincadeira: quanto
mais elegante forem as funcões desenvolvidas, mais fácil é criar o
restante da programação, a lógica do jogo.
Filtro de Média Móvel
Muitas vezes, para eliminar ou diminuir algum ruído indesejável em um sinal, é necessário filtrá-lo. Isso é comum quando se trabalha com sinais provenientes do ADC. Essa filtragem é, então, feita através da programação. O problema é que a teoria sobre filtros digitais é complexa e o programador a evita sempre que possível. Todavia, pode-se utilizar um filtro bem simples, chamado de média móvel, que pode resolver o problema do ruído.
O filtro de média móvel é obtido
calculando-se a média de um conjunto de valores, sempre se adicionando um novo
valor ao conjunto e se descartando o mais velho. Não é apenas uma média de um
conjunto isolado de valores. O filtro de média móvel é representado por:
onde
n é o tempo
atual (é o índice dos vetores utilizados), N +1 é o número
de amostras utilizadas para a filtragem, y[n] é o sinal filtrado e x[n-k]
representa o conjunto dos valores a serem somados. A equação acima pode ser
representada pelo diagrama da figura 1, com os valores de b0,b1...bN iguais a
1/(N+1).
Fig.
1 - Diagrama de um filtro digital não recursivo.
O diagrama da fig. 1 representa um filtro
chamado não recursivo, pois o sinal de saída y[n] depende somente do sinal de
entrada x[n]. Caso o sinal de saída dependesse de valores passados da saída, o
filtro seria chamada recursivo. No projeto de um filtro digital, determinam-se
os coeficientes de multiplicação para as amostras, no caso b0,
b1, ... bN para o diagrama citado. Esses coeficientes podem ser
determinados com o uso de alguma ferramenta computacional como o MATLAB®
ou MATCAD®, e o programador apenas necessita realizar as somas e
multiplicações nas amostras certas. A qualidade do filtro e o tipo de filtro
(passa baixa, passa alta, passa faixa) vai depender do número de coeficientes
utilizados (quantidade de amostras) e dos seus valores.
Ao utilizar coeficientes fixos, o filtro
de média móvel produz um filtro passa baixa suave, reduzindo os sinais de alta
frequência. Caso se deseje outro tipo de filtragem, será necessário a
multiplicação com valores fracionários, o que exigirá o uso de ponto flutuante
no programa. Isso pode ser um problema para microcontroladores de 8 bits pelo
consumo maior de memória e da limitada capacidade de processamento da CPU.
Na fig. 2, é apresentada a resposta em
frequência de um filtro de média móvel para 16 amostras. O eixo horizontal é a
frequência em Hertz, o número 1 representa a frequência de amostragem do sinal
dividida por 2. Desta forma, supondo uma frequência de amostragem 20 kHz,
cada linha vertical do gráfico corresponderia a 1 kHz.
Fig.
2 – Resposta em frequência de um filtro de média móvel de 16 amostras.
A resposta apresentada na fig. 2 mostra
que o desempenho de um filtro de média móvel é razoável, estando a atenuação
dos sinais indesejados na faixa de
aproximadamente -20 dB (90 %).
A seguir, é apresentado um exemplo para a
programação de um filtro de média móvel de 16 amostras para os valores
convertidos pelo ADC do ATmega (deve-se observar o tamanho das variáveis
declaradas para não ocorrer estouro na contagem).
Obs.: havia um erro no algoritmo abaixo, faltava inicializar com zero o valor media antes do somatório das amostras, o que aumentava um pouco a média.
Obs.: havia um erro no algoritmo abaixo, faltava inicializar com zero o valor media antes do somatório das amostras, o que aumentava um pouco a média.
//---------------------------------------------------------------------
// Filtro de média móvel com 16 amostras para o sinal do ADC
//---------------------------------------------------------------------
unsigned int filtro[16], media,
unsigned char k=0;
. . .
ISR(ADC_vect)
{
unsigned char j;
// Filtro de média móvel com 16 amostras para o sinal do ADC
//---------------------------------------------------------------------
unsigned int filtro[16], media,
unsigned char k=0;
. . .
ISR(ADC_vect)
{
unsigned char j;
filtro[k] = ADC; //valor do ADC entra no filtro, na amostra mais antiga
k++; if(k==16) k=0;
media = 0;
for(j=0; j<16; j++)
media += filtro[j]; //somatório das amostras
media /=16; //média dos valores
}
//----------------------------------------------------------------------
Obs.: Este material faz parte do capítulo 19 do livro AVR e Arduino:
Técnicas de Projeto. O
programa é diferente no livro, aconselho comparação.
Assinar:
Postagens (Atom)