Executando verificação de segurança...
11

Como construir um robô utilizando arduino?

Introdução

Eu sou aluno de 4º período de Engenharia Mecatrônica (Controle e automação) na Universidade de Brasília e no semestre passado eu realizei uma atividade de extensão com o título: Curso de Introdução à Robótica Aplicada ao Sumô de Robôs e gostaria de compartilhar algumas das coisas que eu aprendi, assim como o projeto do robô que eu e meu grupo montamos.

Teoria

Robôs são ferramentas desenvolvidas para algum objetivo específico, normalmente tarefas repetitivas como a soldagem de peças de automóveis, limpeza, ou tarefas que oferecem risco ao ser humano como desarmamento de bombas, vistoria de plataformas de petróleo em grandes profundidades.

Existem vários tipos de robôs, dentre eles existem os com base fixa e os com base móvel. O Curso deu ênfase nos robôs móveis, então também darei mais enfoque neles, mas para título de curiosidade robôs com base fixa são aqueles como braços mecânicos que ficam presos à uma base.

Os robôs móveis são divididos em 3 tipos: Aéreos, aquáticos e terrestres. Dentre os aéreos nós temos os drones por exemplo, nos aquáticos nós temos os que operam apenas na superfície da água como barcos e aqueles que operam submersos como drones submarinos, já nos terrestres nós temos os que usam rodas e os que usam esteiras para locomoção.

Para sentir o mundo ao seu redor os robôs são munidos de diversos tipos de sensores:

  • Sensores de proximidade;
  • Sensores de luminosidade;
  • Sensores de refletância;
  • Odômetros;
  • Girômetros.
    Dentre outros.

Prática

O curso teve a duração de uma semana, então após uma breve explicação dos tipos de robôs e sensores nós tivemos uma aula breve de como usar um arduino e já fomos instruídos a construir um robô para uma disputa de sumô, basicamente um robô deve empurrar o outro para fora de uma arena circular.
O meu grupo decidiu construir um robô que utiliza um sensor ultrassônico para detectar o inimigo e 4 sensores de refletância para identificar as bordas da arena.

img_robo

Caso queiram um esquemático detalhado da eletrônica do robô deixem nos cometários que eu editarei esse post com estes dados adicionais.

Código

No grupo eu fui o responsável por desenvolver o código e a primeira coisa que eu fiz foi desenvolver a parte referente à locomoção. Para isso eu dei nome aos pinos dos motores e criei uma função go_direction que recebe um caractere, o qual pode ser "f" de forward, "b" de backward, "l" de left, "r" de right e "p" de parked.

// Pinos do motor
#define M1A 2
#define M2A 3
#define M1B 4
#define M2B 5

// Declaração da função
void go_direction(char direcao);

// Implementação da função
void go_direction(char direcao)
{
  if (direcao == 'f')
  {
    digitalWrite(M1A, 0);
    digitalWrite(M2A, 1);

    digitalWrite(M1B, 0);
    digitalWrite(M2B, 1);
  }
  else if (direcao == 'b')
  {
    digitalWrite(M1A, 1);
    digitalWrite(M2A, 0);

    digitalWrite(M1B, 1);
    digitalWrite(M2B, 0);
  }
  else if (direcao == 'r')
  {
    digitalWrite(M1A, 1);
    digitalWrite(M2A, 0);

    digitalWrite(M1B, 0);
    digitalWrite(M2B, 1);
  }
  else if (direcao == 'l')
  {
    digitalWrite(M1A, 0);
    digitalWrite(M2A, 1);

    digitalWrite(M1B, 1);
    digitalWrite(M2B, 0);
  }
  else if (direcao == 'p')
  {
    digitalWrite(M1A, 0);
    digitalWrite(M2A, 0);

    digitalWrite(M1B, 0);
    digitalWrite(M2B, 0);
  }
}

Depois de fazer o robô se mexer eu implementei a função que ficaria responsável por identificar o inimigo como o sensor ultrassônico e também uma função responsável por debugar esta.

// Importar a biblioteca para usar o sensor ultrassônico
#include <Ultrasonic.h> //https://github.com/ErickSimoes/Ultrasonic

// Pinos do sensor
#define trigger 7
#define echo 6

// Instancia o objeto ultrassonic e delimita um campo de visão pois o sensor detecta uns 2-3 m
// e a arena tinha uns 60 cm
Ultrasonic ultrasonic(trigger, echo);
const int field_of_view = 30;

// Declaração da função
bool identify_enemy();
void debug_ultrasonic_sensor();

// Implementação da função
bool identify_enemy()
{
  if (ultrasonic.read(CM) <= field_of_view)
  {
    return true;
  }
  else
  {
    return false;
  }
}

void debug_ultrasonic_sensor()
{
  Serial.print("Distância(CM): ");
  Serial.print(ultrasonic.read(CM));
  Serial.print(" cm  ");
  Serial.print("Identified enemy: ");
  Serial.println(identify_enemy());
  delay(500);
}

Com o sensor ultrassônico funcionando, eu criei uma classe para facilicar a leitura dos sensores de refletância já que eles retornam valores diferentes. Basicamente, quando o robô é iniciado ele guarda um valor base, ele considera aquilo como o chão da arena, se for identificada uma grande mudança nesse valor então o sensor está sobre uma linha.

// Pinos dos sensores de linha
#define BR A0 // back right
#define BL A1 // back left
#define FL A2 // front left
#define FR A3 // front right

class Sensor
{
  private:
    int base_value;
    int pin;
    int tolerance;
  public:
    Sensor(int pin, int tolerance)
    {
      this->base_value = analogRead(pin);
      this->pin = pin;
      this->tolerance = tolerance;
    }

    bool find_line()
    {
      int current_value = analogRead(pin);
      if (abs(base_value - current_value) >= tolerance)
      {
        return true;
      }
      else
      {
        return false;
      }
    }
};

// Instancia os objetos sensores
Sensor BRS(BR, 50);
Sensor BLS(BL, 50);
Sensor FRS(FR, 50);
Sensor FLS(FL, 50);

void debug_line_sensor()
{
  Serial.print("BR: ");
  Serial.print(analogRead(BR));
  Serial.print("  BL: ");
  Serial.print(analogRead(BL));
  Serial.print("  FR: ");
  Serial.print(analogRead(FR));
  Serial.print("  FL: ");
  Serial.println(analogRead(FL));
  delay(500);
}

A seguir colocarei o código completo pois algumas funções podem ser melhor interpretadas no contexto geral.

#include <Ultrasonic.h> //https://github.com/ErickSimoes/Ultrasonic

// Motor
#define M1A 2
#define M2A 3
#define M1B 4
#define M2B 5

// Sensor de linha
#define BL A3
#define BR A2
#define FR A1
#define FL A0

// Ultrassom
#define trigger 7
#define echo 6

Ultrasonic ultrasonic(trigger, echo);
const int field_of_view = 20;


//==================================================================
class Sensor
{
  private:
    int base_value;
    int pin;
    int tolerance;
  public:
    Sensor(int pin, int tolerance)
    {
      this->base_value = analogRead(pin);
      this->pin = pin;
      this->tolerance = tolerance;
    }

    bool find_line()
    {
      int current_value = analogRead(pin);
      if (abs(base_value - current_value) >= tolerance)
      {
        return true;
      }
      else
      {
        return false;
      }
    }
};


void go_direction(char direcao);
void attack();
void look_for_enemy();

bool identify_enemy();

void debug_line_sensor();
void debug_ultrasonic_sensor();

//==================================================================
void setup()
{
  pinMode(M1A, OUTPUT);
  pinMode(M2A, OUTPUT);
  pinMode(M1B, OUTPUT);
  pinMode(M2B, OUTPUT);

  pinMode(BR, INPUT);
  pinMode(BL, INPUT);
  pinMode(FR, INPUT);
  pinMode(FL, INPUT);

  Serial.begin(9600);
}

Sensor BRS(BR, 30);
Sensor BLS(BL, 30);
Sensor FRS(FR, 30);
Sensor FLS(FL, 30);

//==================================================================
void loop()
{

  if (identify_enemy())
  {
    attack();
  }
  else
  {
    look_for_enemy();
  }

  //debug_line_sensor();
  //debug_ultrasonic_sensor();
}

//==================================================================
bool identify_enemy()
{
  if (ultrasonic.read(CM) <= field_of_view)
  {
    return true;
  }
  else
  {
    return false;
  }
}

//==================================================================
void attack()
{
  if (!FRS.find_line() || !FLS.find_line())
  {
    go_direction('b');
    delay(500);
  }
  else
  {
    go_direction('f');
  }
}

//==================================================================
void look_for_enemy()
{
  if (!FRS.find_line() || !FLS.find_line())
  {
    go_direction('b');
    delay(500);
  }
  else
  {
    go_direction('l');
    delay(100);
    go_direction('p');
    delay(100);
  }
}

//==================================================================
void go_direction(char direcao)
{
  if (direcao == 'f')
  {
    digitalWrite(M1A, 0);
    digitalWrite(M2A, 1);

    digitalWrite(M1B, 0);
    digitalWrite(M2B, 1);
  }
  else if (direcao == 'b')
  {
    digitalWrite(M1A, 1);
    digitalWrite(M2A, 0);

    digitalWrite(M1B, 1);
    digitalWrite(M2B, 0);
  }
  else if (direcao == 'r')
  {
    digitalWrite(M1A, 1);
    digitalWrite(M2A, 0);

    digitalWrite(M1B, 0);
    digitalWrite(M2B, 1);
  }
  else if (direcao == 'l')
  {
    digitalWrite(M1A, 0);
    digitalWrite(M2A, 1);

    digitalWrite(M1B, 1);
    digitalWrite(M2B, 0);
  }
  else if (direcao == 'p')
  {
    digitalWrite(M1A, 0);
    digitalWrite(M2A, 0);

    digitalWrite(M1B, 0);
    digitalWrite(M2B, 0);
  }
}

//==================================================================
void debug_line_sensor()
{
  Serial.print("BR: ");
  Serial.print(analogRead(BR));
  Serial.print("  BL: ");
  Serial.print(analogRead(BL));
  Serial.print("  FR: ");
  Serial.print(analogRead(FR));
  Serial.print("  FL: ");
  Serial.println(analogRead(FL));
  delay(500);
}

//==================================================================
void debug_ultrasonic_sensor()
{
  Serial.print("Distância(CM): ");
  Serial.print(ultrasonic.read(CM));
  Serial.print(" cm  ");
  Serial.print("Identified enemy: ");
  Serial.println(identify_enemy());
  delay(500);
}

Conclusão

O robô deveria ter o seguinte comportamento: Se detectar um inimigo acelera com tudo na direção dele, se não fica girando até encontrar.
O nosso robô, embora tivesse vários sensores ele ficou em 4º na competição, e quem ficou em 1º foi um robô que só tinha 1 sensor de refletância na frente, ele ia reto e se encontrasse uma linha ele dava meia volta, deixando o poder da probabilidade decidir se ele batia de frente ou não com outro robô. Isso nos mostra que nem sempre o mais complexo é a melhor solução, até porque na vida real não possuímos recursos infinitos.

Carregando publicação patrocinada...