Em diversos projetos, pode ser necessário medir a velocidade, seja de motores ou de quaisquer outros eixos rotativos. Com um encoder, é possível utilizar um Arduino para medir, de forma simples, a velocidade de qualquer motor, roda ou eixo.
Neste blog, veremos como medir RPM utilizando um Arduino UNO em conjunto com um módulo encoder.
Sumário
1. Circuito
Para este projeto, utilizamos um Motor de Corrente Contínua (CC) com Caixa de Redução e Eixo Duplo, conforme mostrado na figura a seguir.
Para medir a velocidade, utilizamos um módulo encoder juntamente com um disco de vinte dentes, como mostrado na figura a seguir.
O disco deve ser fixado no eixo que desejamos medir a velocidade. Para este exemplo, o disco foi fixado no eixo do motor, conforme mostrado na figura a seguir.
Quando os furos do disco passam pelo encoder, eles geram uma onda quadrada na saída do módulo. Medindo o período dessa onda quadrada, é possível calcular a velocidade de rotação do eixo. Na figura a seguir, podemos ver como o circuito foi montado.
Perceba que a saída do módulo está conectada ao pino 2 do Arduino, que é um pino de interrupção externa. Para a correta utilização desse módulo, é necessário colocar um capacitor de 100nF entre o pino de saída e o GND, a fim de eliminar ruídos que podem gerar erros na medição.
2. Programa
O objetivo aqui é medir o período do sinal gerado pelo encoder. Existem várias formas de fazer isso, por exemplo, utilizando a função pulseIn. No entanto, aqui vamos utilizar a interrupção externa, pois com ela podemos realizar a medição de forma automática, sem precisar interromper o código principal.
O primeiro passo é configurar a interrupção externa. Para isso, utilizamos a diretiva "#define" para atribuir o nome "encoder" ao pino 2. Dentro da função setup, vamos configurar o pino como entrada (pinMode) e, em seguida, configurar a interrupção (attachInterrupt).
A sintaxe do attachInterrupt é a seguinte: primeiro, informamos qual interrupção será usada com a função digitalPinToInterrupt. Em seguida, informamos qual função será executada quando ocorrer a interrupção; neste caso, será a função "contagem" (descrita posteriormente). Por fim, especificamos o tipo de disparo, que será na borda de subida (RISING).
Além disso, também inicializamos a comunicação serial para visualizar os resultados no monitor serial. O código utilizado pode ser visto a seguir.
#define encoder 2
void setup() {
Serial.begin(9600);
pinMode(encoder, INPUT);
attachInterrupt(digitalPinToInterrupt(encoder), contagem, RISING);
}
Agora vamos programar a função "contagem". Nela, vamos medir o tempo entre cada borda de subida do sinal do encoder. Para isso, utilizaremos a função "micros". Sempre que o programa entrar na função "contagem", ele salvará o tempo obtido pela função "micros" e calculará a diferença entre o tempo atual e o tempo armazenado da última vez que ocorreu uma interrupção. Essa diferença será chamada de "Delta".
Conhecendo o valor de "Delta", podemos calcular a velocidade em RPM utilizando a equação a seguir, onde "Delta" é o tempo em segundos e "N" é o número de furos do encoder.
O código completo da função pode ser visto a seguir. No código, estamos dividindo "Delta" por 1,000,000, pois o tempo fornecido pela função micros está em microssegundos, e a fórmula para calcular a RPM requer o tempo em segundos.
void contagem() {
tf = micros();
long delta = tf - ti;
RPMmedido = (60.0) / (float(delta) / 1000000.0 * 20.0);
ti = tf;
}
Na função "loop", vamos apenas enviar para o monitor serial o valor da variável "RPMmedido", conforme mostrado a seguir.
void loop() {
Serial.println(RPMmedido);
delay(1000);
}
Na figura a seguir, podemos ver o resultado obtido pelo programa.
Essa é uma versão simplificada para medir RPM. É possível implementar diversas melhorias no código para reduzir as oscilações do valor medido e zerar a velocidade quando o motor parar.
No entanto, este é um excelente ponto de partida para o seu projeto e pode ser utilizado como base para implementar desde um simples velocímetro até sistemas de controle mais elaborados. A seguir, você pode ver o código completo utilizado neste projeto.
long tf, ti;
float RPMmedido;
#define encoder 2
void setup() {
Serial.begin(9600);
pinMode(encoder, INPUT);
attachInterrupt(digitalPinToInterrupt(encoder), contagem, RISING);
}
void loop() {
Serial.println(RPMmedido);
delay(1000);
}
void contagem() {
tf = micros();
long delta = tf - ti;
RPMmedido = (60.0) / (float(delta) / 1000000.0 * 20.0);
ti = tf;
}
Assista ao vídeo a seguir para ver uma aplicação do algoritmo apresentado nesse blog.
Autor: Thales Ferreira
Comments