Como usar motor DC com encoder no Arduino
Neste post vamos mostrar um motor muito usado em projetos de robótica, que é um motor DC com encoder embutido. Esse tipo de motor permite que você possa calcular a distância percorrida pelo robô, ou ajustar a velocidade do motor de acordo com a leitura de sensores.
O motor que vamos utilizar é o motor DC 6V com encoder embutido, o mesmo mostrado na imagem acima. Ele tem uma pequena placa na parte de trás onde estão instalados os sensores hall que vão ler as informações relativas à rotação do motor.
São 2 sensores na placa, e com ele podemos medir não só a velocidade como também o sentido de rotação. Isso pode ser muito útil na hora de configurar o robô para evitar obstáculos, virar para direita/esquerda, retornar, etc.
Conexões do motor DC com encoder embutido
Essa placa tem um conector com 6 pinos, onde vamos ligar tanto a alimentação do motor (pinos M- e M+), a alimentação dos sensores do encoder (GND e 3.3V) e onde teremos o sinal de saída, nos pinos C1 (canal A do encoder) e C2 (canal B do encoder):
Assim, precisamos de apenas dois pinos do Arduino para ler as informações dos sensores do encoder. O pino C1 será ligado ao pino 2 do Arduino (interrupção 0), e o pino C2 será ligado ao pino digital 4.
Ligação do Motor DC 6V 210 RPM no Arduino
Como esse motor exige mais corrente do que a suportada pelos pinos do Arduino, vamos usar no nosso circuito um módulo ponte H L298N (abaixo), controlando o sentido de rotação com um potenciômetro de 10K ligado ao pino digital A0.
Ligamos então o motor em uma das saídas da ponte H (OUT1 e OUT2), os pinos GND e 3.3V da placa do encoder nos pinos correspondentes no Arduino, a saída C1 no pino digital 2, e a saída C2 no pino digital 4:
Os pinos 6 e 7 controlam o sentido de rotação do motor; sentido horário (pino 6 HIGH e pino 7 LOW) ou anti-horário (pino 6 LOW e pino 7 HIGH).
Programa motor com arduino
O programa abaixo não utiliza bibliotecas específicas, efetuando a leitura dos pinos 2 (interrupção 0 do Arduino, utilizado para a contagem de pulsos) e 4 (usado para identificar o sentido de rotação do motor).
//Programa: Motor DC com encoder //Autor: Arduino e Cia const byte Encoder_C1 = 2; const byte Encoder_C2 = 4; byte Encoder_C1Last; int duracao; boolean Direcao; //Pinos de ligacao ponte H L298N #define pino_motor1 6 #define pino_motor2 7 void setup() { Serial.begin(57600); //Pino potenciometro pinMode(A0, INPUT); //Definicao pinos ponte H pinMode(pino_motor1, OUTPUT); pinMode(pino_motor2, OUTPUT); //Definicao do encoder EncoderInit(); } void loop() { Serial.print("Pulso: "); Serial.print(duracao); int valor = analogRead(A0); if (valor >= 512) { digitalWrite(pino_motor1, LOW); digitalWrite(pino_motor2, LOW); //delay(1000); digitalWrite(pino_motor1, LOW); digitalWrite(pino_motor2, HIGH); Serial.println(" Sentido: Anti-horario"); } else { digitalWrite(pino_motor1, HIGH); digitalWrite(pino_motor2, LOW); Serial.println(" Sentido: Horario"); } duracao = 0; delay(100); } void EncoderInit() { pinMode(Encoder_C2, INPUT); attachInterrupt(0, calculapulso, CHANGE); } void calculapulso() { int Lstate = digitalRead(Encoder_C1); if ((Encoder_C1Last == LOW) && Lstate == HIGH) { int val = digitalRead(Encoder_C2); if (val == LOW && Direcao) { Direcao = false; //Reverse } else if (val == HIGH && !Direcao) { Direcao = true; //Forward } } Encoder_C1Last = Lstate; if (!Direcao) duracao++; else duracao--; }
Conforme o valor enviado pelo potenciômetro ligado na porta analógica A0, o sentido de rotação do motor é alterado. Essa alteração pode ser acompanhada no Serial Monitor, onde também é mostrada a quantidade de pulsos lida pelo encoder. Não esqueça de alterar a velocidade da serial para 57600:
Experimente incorporar ao circuito um potenciômetro para controlar também a velocidade do motor, assim você pode acompanhar a variação na quantidade de pulsos lidos.
Gostou? Confira outros posts usando motores aqui mesmo no Arduino e Cia!
tem previsão de fazer testes com clone de controle de ar condicionado??? Já tem 3 semanas que estou apanhando aqui…não consigo de jeito nenhum infelizmente…
A cada vez que aperto o mesmo botão recebo código diferente, quando envio o código, sempre é enviado um diferente(usando um arduino para enviar e outro para receber – testes)…Será a biblioteca?
http://www.instructables.com/id/Ar-Condicionado-controlado-por-Arduino-via-infrave/
Qual a relação da quantidade de pulsos lidos com a velocidade?
Aparentemente, a relação é de aproximadamente 340 ppr (pulsos por revolução) segundo uma pagina do AliExpress que vende o mesmo produto.
Aparentemente, a relação é de aproximadamente 340 ppr (pulsos por revolução) segundo um artigo do Aliexpress que vende o mesmo produto.
cOMO FAZERPARA FREIAR MOTOR quando chegar numero de pulsos no encoder
Olá! Inverta a polaridade no controlador L298. Acho que pela corrente que esse motor consome não deverá estragar o driver.
Embora eu tenha tido problemas com controladores da china com troca de sentido muito rápidas. Os diodos Schotty são pequenos e queimam com facilidade.
certo seria usar PID e usar como referência a quantidade de pulsos, que ele já vai estar parado quando chegar no ponto, inverter a polaridade acho que não seria uma boa ideia, dependendo da aplicação.
Qual a quantidade de pulsos geradas por um encoder desses em cada volta?
Quando eu coloco essa programação junto ao motor girante em um único sentido, os pulsos vão de -1, … , -32000. Depois cai de +3200, …, +1. alguem pode me explicar o por quê?
No serial mostra que meu encoder somente com valor negativo, tanto para sentido horario como anti horario, sera que ele esta com defeito?
Gostaria de ligar esse enconder ao meu projeto que é um carrinho controlado..
Como relaciona ,a velocidade com RPM?
Alguem pode me explicar?
Tenho ainda duvida no código:
void calculapulso()
{
int Lstate = digitalRead(Encoder_C1);
if ((Encoder_C1Last == LOW) && Lstate == HIGH)
{
int val = digitalRead(Encoder_C2);
if (val == LOW && Direcao)
{
Direcao = false; //Reverse
}
else if (val == HIGH && !Direcao)
{
Direcao = true; //Forward
}
}
Encoder_C1Last = Lstate;
if (!Direcao) duracao++;
else duracao–;
}
Entao um sensor indica o sentido de rotacao e o outro indica o numero de pulsos na rotacao?????????????
Se Encoder_C1Last esta configurado como byte, porque verifica se ele é low ou righ, ou seja sinal de bit??? Nao deveria verificar o valor armazenado no byte Encoder_C1Last para saber a posicao ou rotacao?? Que sao variaveis de byte????
Pulso —> RPM
mudar isso
Serial.print("pulso: ");
Serial.print(duracao);
para isso
Serial.print("RPM: ");
Serial.print(duracao);
tem como usar um potenciomentro no lugar do encoder??
Oi John,
Para esse caso específico não.
Abraço!
Adilson
Entendi. No meu caso então eu deveria mudar o sketch?
Oi John,
Exato.. Eu tenho vários exemplos de uso do potenciômetro com Arduino aqui no blog, dá uma olhada, por favor:
https://cse.google.com.br/cse?cx=partner-pub-0984070935969312:2218065364&ie=UTF-8&q=potenciometro&sa=Pesquisar
Abraço!
Adilson
Boa tarde .
depois de meses ou dias eu obtive um retorno desse site.. eu curto muito mais bem que poderia ter um retorno mais rapido e ate mesmo discutirmos sobre assusto do artigo…obrigado
Boa noite,
Desculpe, aconteceu um pequeno problema na moderação dos comentários, por isso a demora.
No que eu posso te ajudar?
Abraço!
Adilson
Boa tarde, gostaria de medir a distância com o encoder, sem utilizar o potenciômetro. Como faço?
Obrigado!
Boa tarde,
Esse motor já vem com um sistema de redução incluso, como esse:
https://www.banggood.com/6V-210RPM-Encoder-Motor-DC-Gear-Motor-with-Mounting-Bracket-and-Wheel-p-1044064.html?p=970719369296201312SG&cur_warehouse=CN
??
Necessito de um motor DC com encoder e caixa de redução
Este motor tem um defeito e um problema.
O defeito: a montagem da placa de circuito impresso não possui nenhum isolamento entre o lado das soldas e a carcaça do motor, gerando curto-circuitos facilmente. Resolvi isso dessoldando a placa, cortando um pouco os pinos do conector, colocando fita isolante entre a placa e a carcaça e soldando novamente.
Já o outro problema não sei como resolver. O sensor gera a mesma sequência de bits tanto no sentido horário quanto no anti-horário nos pinos C1 e C2: 01 11 10 11. Observem que 00 não ocorre nunca, e portanto a regra da quadratura não se aplica. Testei dezenas de sketches diferentes até deduzir que o problema era no motor.
Para quem se interessar, meu sketch de teste é: #define encoder0PinA 2
#define encoder0PinB 3
#define M1 9
#define M2 10
void setup()
{
pinMode(encoder0PinA, INPUT);
pinMode(encoder0PinB, INPUT);
attachInterrupt(digitalPinToInterrupt(encoder0PinA), enc1, CHANGE);
attachInterrupt(digitalPinToInterrupt(encoder0PinB), enc2, CHANGE);
Serial.begin(57600);
Serial.println("ready");
//analogWrite(M1, 255);
//analogWrite(M2, 0);
}
void loop()
{
}
void enc1()
{
byte a = digitalRead(encoder0PinA);
byte b = digitalRead(encoder0PinB);
Serial.print("ENC1 ");
Serial.print(a);
Serial.print(" ");
Serial.println(b);
}
void enc2()
{
byte a = digitalRead(encoder0PinA);
byte b = digitalRead(encoder0PinB);
Serial.print("ENC2 ");
Serial.print(a);
Serial.print(" ");
Serial.println(b);
}
E o resultado é:
ENC1 0 1
ENC1 1 1
ENC2 1 0
ENC2 1 1
ENC1 0 1
ENC1 1 1
ENC2 1 0
ENC2 1 1
etc.
Alguém sabe fazer esse código ou qualquer código para usar um encoder como esse no Raspberry pi?
O PWM controla a velocidade mas o torque sempre cai junto com a velocidade. Com PWM o torque (força do motor) não devaria se manter mesmo em baixar velocidades? Existe alguma solução para rodar esse sketch em baixíssima velocidade sem perder a força?
Como ficaria trocando o arduíno pelo raspberry pi zero w?
Oi Fernando,
Estou preparando um post exatamente sobre isso, deve sair em breve, ok?
Abraço!
Adilson
Ok. obrigado. Gostaria de aproveitar hj as promoções da FF e pegar a bateria e carregador tb. Qual você indica para dois motores desse em um projeto de self balance robot? Peguei a um tempo os motores aqui mas recém vou usá-los e tô sem baterias!
Olá, usarei um motor que ao invés de 3.3V ele é 5V, teria que apenas alterar conectando no pino 5V do arduino, além das outras coisas também conectadas nesse pino? E para ligar mais de um motor, como poderia fazer já que apenas um no esquemático ocupou vários pinos, utilizando uma protoboard?
Oi Leonardo,
Recomendo que você use uma fonte externa. Se você ligar o motor no pino 5V do Arduino vai sobrecarregar a porta da placa.
Abraço!
Adilson
Como posso calcular a velocidade de rotação em função dos pulsos?
Oi Cláudio,
Dê uma olhada nesse link aqui, por favor: https://forum.arduino.cc/t/como-calcular-a-velocidade-usando-um-encoder-arduino-e-labview/336771
Abraço!
Adilson