LusoRobótica - Robótica em Português
Sistemas específicos => Arduino / AVR => Tópico iniciado por: daniboy em 16 de Fevereiro de 2013, 16:34
-
Boa tarde a todos,
sou um novato quanto a posts.
Estou a desenvolver um pequeno robot diferencial com 2 rodas acopladas a 2 motores DC.
Estou neste momento com problemas nas rotinas relativas aos encoders.
A ideia dos encoders era saber com precisão quanto as rodas rodaram, e de uma forma aproximada, tendo em conta o solo e os deslizamentos, poderia saber as deslocação do veiculo.
Não estou a usar encoders de quadratura, pois através do código sei se me encontro a andar em frente ou para trás, e por isso apenas uso um fio para detectar o estado do encoder (1 ou 0).
no meu caso pretendo contar as transições de 1 para 0.
A ideia passa por ligar o encoder aos interrupts e a cada transição, é gerada uma interrupção e executadas determinadas funções (incremento dos pulsos, calculo de distancias, etc).
a realidade é que ao usar os interrupts, estou a ter algumas dificuldades, porque basta o feixe ser interrompido, e o arduino fica a incrementar a variavel de pulsos.
este foi o codigo que estou a utilizar.
// CODE //
int MotorA1 = 9;
int MotorB1 = 10;
// variable to be updated by the interrupt
const int encoderPinA = 2;
int Pos, oldPos;
volatile int encoderPos = 0;
/* volatile variables are forced to reside in RAM, not in registers */
void setup() {
pinMode(encoderPinA, INPUT);
digitalWrite(encoderPinA, HIGH);
pinMode(MotorA1, OUTPUT);
pinMode(MotorB1, OUTPUT);
//enable interrupt 0 which uses pin 2
//jump to the incrementa function on falling edge
Serial.begin(9600);
attachInterrupt(0, incrementa, RISING);
}
void loop() {
analogWrite(MotorA1, 0);
analogWrite(MotorB1, 110);
uint8_t oldSREG = SREG;
cli();
Pos = encoderPos;
SREG=oldSREG;
if(Pos != oldPos){
Serial.print("Numero de pulsos lidos: ");
Serial.println(Pos);
float pulsos;
pulsos = Pos;
float distancia;
// 1cm equivale a 40 pulsos
distancia = pulsos/40;
Serial.print("Distancia percorrida: ");
Serial.println(distancia);
Serial.print(" cm");
oldPos = Pos;
}
}
// Interrupt service routine for interrupt 0
void incrementa() {
digitalRead(EncoderPinA);
encoderPos++;
}
Será que alguem tem alguma experiencia com este tipo de situação???
-
O teu problema é provavelmente que nas transições estás a ter várias interrupções, e/ou a posição do encoder fica no limite da transição e "micro vibrações" ficam a movê-lo "micro passos" fazendo com que cause transições na linha.
O que deves começar por fazer é, quando detectas uma transição, ignorar transições durante algum tempo e só depois voltar a olhar para elas. Quanto tempo? Isso depende do teu encoder e da velocidade máxima que tencionas atingir. Tem que ser um tempo um pouco menor do que o tempo minimo (a velocidade máxima) que é suposto veres impulsos. Se ele der digamos 100 por volta e o teu veiculo atingir uma velocidade máxima equivalente a 5 voltas por segundo, o intervalo minimo entre impulsos será, ora 100 x 5 = 500 impulsos por segundo que corresponde a 1s/500 = 2 milisegundos, portanto digamos aí 1.5 - 1.75ms, é uma questão de experimentar valores perto do minimo de 2ms.
Se tivesses um osciloscópio podias confirmar isto, pois verias que nas transições as coisas não são tão simples como parecem ;)
p.s. O teu attach diz "RAISING" portanto é de 0 para 1, mas na verdade neste caso é indiferente ser 0->1 ou 1->0