terça-feira, 23 de julho de 2013

Problema solucionado: leitura de sensores IR e ultrassom para robôs de sumô

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