quarta-feira, 10 de setembro de 2014

Medindo o ângulo de inclinação

Ótimo! 
Já temos o motor funcionando e controlado pelo arduino (e depois apenas pelo atmega328). Mas para o skate funcionar do jeito que eu quero, preciso aferir o ângulo de inclinação dele. Para isso, após umas pesquisas na internet, cheguei ao famoso filtro complementar

Um elemento essencial em robôs autobalanceáveis é a aferição do ângulo de inclinação. De acordo com a inclinação aferida, transfere-se mais ou menos potência para o motor movimentar o robô na direção e com a força necessária para cancelar aquela inclinação.

Existem vários filtros para medir um ângulo de inclinação usando um acelerômetro e um giroscópio. Não é meu objetivo aqui testar um ou outro. Apenas usei o mais comum nesse tipo de projeto. O próximo passo seria testar o filtro Kalman para verificar se há alguma melhoria na sensação de resposta do skate.

Primeira implementação do filtro complementar


De qualquer forma, após ler o artigo "The balance filter", fiz a aferição da taxa de execução do loop do meu programa para ajustar os pesos do acelerômetro e do giroscópio no filtro complementar.


Melhoria nas variáveis do filtro complementar

Hoje na versão utilizável do skate, eu estou usando o filtro complementar. Esse filtro é composto por duas leituras. Uma parte usa o ângulo aferido pelo giroscópio e a outra parte usa o ângulo medido pelo acelerômetro. A sugestão inicial é usar o peso de 98% do cálculo para o giroscópio e 2% para o acelerômetro. Mas esses parâmetros dependem, como eu disse, da taxa da execução do loop. Pra quem não quer ler o artigo, é só substituir na fórmula:

a = t/(t+dt)

Onde a é o peso que se dará ao giroscópio (o peso do acelerômetro é 1-a), t é o tempo de resposta aceitável que se espera do filtro e dt é o tempo total em segundos que o seu loop leva para executar.

Uma coisa importante a se considerar é o t. O tempo de resposta do filtro. Essa variável é o tempo aceitável para que o filtro envie uma resposta confiável para você. Eu costumo usar 0,5s. Isso quer dizer que o meu filtro é sensível a variações de ângulo cujo tempo é maior que 0,5s, para evitar que qualquer trepidação momentânea altere a leitura do ângulo aferido.

Hoje, o meu loop leva 0,003268s para ser executado. Eu utilizo 0,5s como constante de tempo de resposta. A minha constante de peso do giroscópio está em 0,9935 (e a do acelerômetro é 1-0,9935).

Esse assunto pode se estender por vários parágrafos (e como uma pessoa de exatas, odeio escrever). Portanto, recomendo fazer experimentos mesmo:
  • Use as variáveis em 98% e 2%;
  • Mexa um pouco na distribuição dos pesos;
  • Faça a aferição do tempo de execução do seu loop;
  • Mexa no tempo de resposta do cálculo do peso do giroscópio;
  • Sinta a resposta de cada experimento.

Segue um pequeno exemplo de uma função simples para aferir o ângulo de inclinação pelas leituras de um giroscópio e de um acelerômetro:

float obterAnguloInclinacao() {
 float angle = 0.0;
float y = gyro.data.y;
LeituraAcelerometro reading = lerAcelerometro();
unsigned long currentMillis = millis();
double dt = currentMillis - previousMillis;
dt = dt / 1000.0;
previousMillis = currentMillis;
float pesoGiroscopio = 0.9935;
float pesoAcelerometro = 1 - pesoGiroscopio;
angle = (pesoGiroscopio) * (angle + y * dt)
+ (pesoAcelerometro) * (reading.x);
return angle;
}


Por enquanto é isso :)

Abraços!


Nenhum comentário:

Postar um comentário