Quando iniciamos a preparação para a OBR de 2013 notamos um problema toda vez que acionávamos os sensores de infravermelho digital junto com o sensor de ultrassom: o robô simplesmente ignorava a leitura de linha e travava o movimento. Para tanto usamos a versão 2.0 do Simulino (santo simulino) e criamos um ambiente de teste, onde os 2 ldr´s da simulação funcionam como sensores IR digitais e o sensor de ultrassom como ele mesmo. Em vez de usarmos os motores, usamos led´s para facilitar a visualização do que está acontecendo, sendo que, o robô deveria reagir conforme fluxograma abaixo:
Para tanto seguimos a seguinte programação:
int emissor=10;
int receptor=9;
long cm1,duracao;
int sensor_d = 6; //conectar ao pino digital
int sensor_e = 7; //conectar ao pino digital
int diff1;
int diff2;
void setup(){
pinMode (emissor, OUTPUT);
pinMode (receptor, INPUT);
pinMode (13, OUTPUT);
pinMode (12, OUTPUT);
Serial.begin (9600);
}
void loop(){
//leitura dos sensores de IR
int linha_d = direita(); //armazena o valor de leitura na viarável linha_d
int linha_e = esquerda();//armazena o valor de leitura na variável linha_e
sonar();
Serial.print (linha_d);
Serial.print (", ");
Serial.print (linha_e);
Serial.print (", ");
Serial.println (cm1);
//se a leitura das linhas corresponder a branco, executa esta função
if (linha_d<800 || linha_e<800){
if (cm1<30){
digitalWrite (13, HIGH); //acende o led no pino 13
digitalWrite (12, LOW); //desliga o led pino 0
}
if (cm1>30){
digitalWrite (13, LOW); //desliga o led no pino 13
digitalWrite (12, HIGH); //liga o led pino 0
}
}
if (linha_d>=800||linha_e>=800){
digitalWrite (13, HIGH); //acende o led no pino 13
digitalWrite (12, LOW); //desliga o led pino 0
delay (10);
digitalWrite (13, LOW); //desliga o led no pino 13
digitalWrite (12, HIGH); //liga o led pino 0
delay (10);
}
}
int sonar(){
digitalWrite (emissor, LOW);
delayMicroseconds (2);
digitalWrite (emissor, HIGH);
delayMicroseconds (2);
digitalWrite (emissor, LOW);
duracao=pulseIn(receptor,HIGH);
cm1=microsecondstocentimeters(duracao);
}
long microsecondstocentimeters(long microseconds){
return microseconds/29/2;
}
int direita(){
pinMode( sensor_d, INPUT );
int leitura_d=digitalRead(sensor_d);
if (leitura_d==HIGH){
diff1=700;
}
else{
diff1=900;
}
return diff1;
}
int esquerda(){
pinMode( sensor_e, INPUT );
int leitura_e=digitalRead(sensor_e);
if (leitura_e==HIGH){
diff2=700;
}
else{
diff2=900;
}
return diff2;
}
Após rodar esta programação, o robô simulou o mesmo erro que observamos nos nossos treinos, onde o robô passa direto pela linha independente de encontrar a linha preta ou não (900 no virtual terminal), acendendo a luz amarela direta.
Para corrigir alteramos os seguintes trechos:
...
void loop(){
//leitura dos sensores de IR
int linha_d = direita(); //armazena o valor de leitura na viarável linha_d
int linha_e = esquerda();//armazena o valor de leitura na variável linha_e
...
Retirando a leitura do sonar e colocando-a de forma a agilizar a leitura dos sensores, fazendo com que a leitura do ultrassom só seja feita se o robô está sobre a linha branca, conforme abaixo:
...
//se a leitura das linhas corresponder a branco, executa esta função
if (linha_d<800 || linha_e<800){
sonar();
...
Além disso, na função sonar mudamos o valor do tempo em HIGH de 2 microssegundos para 10 microssegundos evitando erros de leitura:
...
int sonar(){
digitalWrite (emissor, LOW);
delayMicroseconds (2);
digitalWrite (emissor, HIGH);
delayMicroseconds (10);
digitalWrite (emissor, LOW);
duracao=pulseIn(receptor,HIGH);
cm1=microsecondstocentimeters(duracao);
}
...
O resultado final pode ser visto no vídeo abaixo,com a pequena alteração de colocar um led vermelho para identificar quando está sobre a a linha preta, um led amarelo para representar sobre a linha branca sem nenhum objeto à frente e, o led verde representando sobre a linha branca com objeto a menos de 30 cm:
Ainda assim, você pode notar que os led´s piscam alternadamente, mostrando que há interferência, causada pela leitura dos sensores. Isso pode provocar movimentos involuntários do robô interferindo no planejamento inicial. Para eliminar o problema criamos uma função que interpreta o sinal dos sensores:
...
//função que transforma a leitura dos sensores em uma variável, eliminando erros:
if (linha_d<800||linha_e<800){
estado = 100;
}
if (linha_d>=800||linha_e>=800){
estado = 300;
}
...
Essa função retorna o valor de 100 para branco e 300 para preto, eliminando o defeito anterior. Se baseia no princípio de Máquina de Estados Finitos que pode ser assim definido:
" é um modelo matemático usado para representar programas de computadores ou circuitos lógicos. O conceito é concebido como uma máquina abstrata que deve estar em um de seus finitos estados. A máquina está em apenas um estado por vez, este estado é chamado de estado atual. Um estado armazena informações sobre o passado, isto é, ele reflete as mudanças desde a entrada num estado, no início do sistema, até o momento presente. Uma transição indica uma mudança de estado e é descrita por uma condição que precisa ser realizada para que a transição ocorra. Uma ação é a descrição de uma atividade que deve ser realizada num determinado momento."
Desta forma, conforme o vídeo abaixo, o problema foi finalmente corrigido:
Nenhum comentário:
Postar um comentário