Ó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