quinta-feira, 5 de novembro de 2009

Controle de servo com o R8C/1A

Sei que faz um tempo, muita gente já estava com saudades e chorando, mas para alegria geral da nação estou de volta!

Hoje vou postar um projeto bem simples, fácil de fazer e que realmente impressiona, ou não, depende de quem ve...

Para quem não conhece, antes vamos falar um pouco de servo de aeromodelo, é um dispositivo relativamente simples, 3 pinos de ligação, VCC, GND e Sinal. Mas com ele você consegue dar movimento aos seus projetos!
VCC e GND todo mundo sabe o que é, já o Sinal vou explicar agora. A posição angular do servo é dada por um sinal PPM ligado a este pino, normalmente esse sinal deve variar de 1,25mS até 1,75mS, sendo 1,75mS eixo todo virado para um lado e 1,75mS todo virado para o outro, qualquer tempo no intervalo, 1,5mS por exemplo, vai posicionar o eixo numa posição intermediária, conforme a figura abaixo. O tempo entre cada pulso deve ser de 20mS, nos testes funcionou sem respeitar esse intervalo, mas pode ser que não funcione no servo que você tem ai na sua casa!

Isso posto, vamos ao que interessa, usei o R8C/1A, é claro... e o timer X foi o ator principal da história, a configuração ficou assim:

Explicando o código, a primeira linha faz a seleção da fonte de clock para o timer X (20MHz, periodo de 50nS), como o timer X tem dois contadores de 8 bits, carregamos um valor no prescaler (prex=24) e outro no timerx (tx=7), para saber o tempo que vai levar para estourar este timer e gerar a interrupção a conta é a seguinte:

tempo = (prex + 1)*(tx+1)*periodo = (24+1)*(7+1)*50*10^-9 = 10*10^-6 S = 10uS

Na próxima linha escolhemos o modo de operação do timer X, modo timer obviamente.
E na linha seguinte determinamos o nível de prioridade da interrupção.
A linha comentada é usada para ligar o timer X, está comentada ai mas aparece novamente no kpt_servo.c, alias que é onde está esta configuração.

Já que falamos de interrupção, o controle deste servo acontece dentro do código do intprog.c, conforme a figura abaixo:

Como fui mais esperto desta vez, comentei no código, a unica coisa importante neste código que não está comentada é a linha:

#pragma interrupt /B _timer_x (vect=22)

O que importa aqui, bom, no arquivo intprog.c temos todas as funções das interrupções, com seus protótipos e essa declaração acima, que "liga" a função descrita ao vetor, 22 neste caso, a função é chamada de timer_x e o /B é um indicador que ao atender esta interrupção você vai usar o banco 1 de registradores, voltando automaticamente ao banco 0 no final do atendimento. Isso é importante para conseguir atingir os 10uS de tempo entre as interrupções, diminui e muito a latência!

Finalmente, um video do porcotipo funcionando com um servo chines muito vagabundo!



Vale observar que o servo está em cima da placa, bem em cima do microcontrolador, e pela imagem do osciloscopio da pra ver que o consumo do servo não é baixo e gera um ruido absurdo, mas mesmo assim o micro continuou lá, firme e forte! (Me pedoem pela falta de ajuste do trigger do osciloscopio, vou ajoelhar no milho depois dessa...).

O código fonte está nos arquivos do grupo, é só copiar e sapear! Link aqui: kpt_servo.zip

Link para o grupo: http://groups.google.com.br/group/renesas_brasil

PS: Rogério, não deu tempo de fazer como você pediu, mas a partir deste você consegue modificar para o que você precisa, certo?