Carro RobÔ
com Arduino Mega

Lista de material:

Opcionais:

Opcionais para inclusão da câmera

Na figura acima, da esquerda para a direita:

Na figura, da esquerda para a direita:

Objetivos

Primeira fase - vai andar:

Módulos utilizados:

Nessa fase, vamos usar um módulo Bluetooth para receber os comandos de movimentação do carro. O Arduino irá acionar o módulo de potência dos motores para avançar, recuar e fazer curvas. O servo-motor será utilizado para fazer com que o sensor de proximidade aponte sempre para a direção que o carro está se movendo. Vamos usar esse sensor para (tentar) evitar que o carro colida com obstáculos

Segunda fase - aprimoramentos básicos:

Os aprimoramentos são bem básicos mas importantes para o carro. Vamos colocar faróis, luzes de freio e buzina.

Terceira fase - vamos ver e ser vistos (ainda em estudos):

Uso do ESP32-CAM para incluir câmera no carro. Desenvolvimento de aplicativo para visualizar as imagens da câmera. Na 3a fase, parte B, o aplicativo será portado para óculos 360°. Provavelmente será difícil dirigir o carro usando as imagens da câmera porque é esperado um atraso significativo que pode inviabilizar a direção.

Nesta fase também está previsto a inclusão de sensor de rotação nas 4 rodas para verificar se as rodas estão girando mesmo depois de ordem para o carro parar, ou seja, vamos implementar um ABS!


Montagem:

Montagem dos motores

Solde os fios vermelhos e pretos nos quatro motores, criando quatro conjuntos iguais. Não existe problema de polaridade, uma vez que o carro irá andar para frente e para trás, ou seja, durante o funcionamento, haverá inversão natural de tensão. Apenas certifique-se de que todos os motores foram montados igualmente.

Use um par de presilhas em cada motor para fixar o motor na parte de cima da placa do chassis inferior. As cabeças dos parafusos devem ficar voltadas para o lado de fora do carro enquanto que as porcas, para o lado de dentro.

Fixe as rodas. Os discos pretos vazados não serão utilizados nesse projeto.

Fixe as rodas com cuidado para não quebrar o acrílico. Certifique-se que as rodas estejam firmemente colocadas.

Uma boa referência para esse montagem está nesse blog.

Montagem do chassis

O servo-motor vai ser utilizado para direcionar o sensor ultrassom quando o carro andar para frente ou fizer alguma curva da mesma forma que os faróis dos carros topo de linha trabalham. Posicione o servo-motor abaixo do chassis de cima, dentro do furo maior, no lado que você considerar a frente do carro (qualquer ponta pode ser a frente). Marque e fure (dois furos) usando uma broca de aço rápido. Fixe o motor, fixe uma das barras brancas no eixo do servo. Marque e fure (dois furos) o acrílico em L. Fixe usando um parafuso para plástico bem fino. Fixe o sensor ultrassom usando cola quente no acrílico em L.

Posicione o Arduino logo após o sensor em L, depois a ponte, com o dissipador de calor voltado para frente, e, na parte mais distante do sensor ultrassom, o alojamento das baterias. Note que dificilmente algum furo vai poder ser aproveitado. Faça as marcações e novos furos para fixar os três elementos. Fixe os três elementos.

Fixe os seis espaçadores separando as duas camadas do chassis.

Após essa etapa, as partes mecânicas devem estar prontas, faltando o cabeamento e o software.

Cabeamento

Coloque o sensor shield sobre o Arduino.

Cabeamento do sensor ultrassom:

Alimentação:

I/O:

Para fixar o sensor no suporte acrílico em L foi necessário fazer 4 furos com brocas de 1 mm. Para encaixar o cristal foi necessário limar um pouco o acrílico porque eu utilizei parafusos de óculos e eles eram curtos.

Usando um cabo de quatro fios, conecte o sensor no shield como mostrado a seguir:

Cabeamento do servo-motor

Alimentação:

I/O:

O servo-motor é usado para posicionar o sensor ultrassônico sempre na direçao do movimento do carro.

O acrílico deve ser aparafusado em cima do motor usando a barra reta que vem com o motor.

Cabeamento do módulo Bluetooth:

Alimentação:

I/O:

Prenda com uma gravatinha (ou um lacre de embalagem de pão) o módulo Bluetooth HC-05 (poderia ser também o HC-06). Note que ele não tem furação de fixação. Com um cabo de quatro fios, conecte o módulo no shield como mostrado a seguir:

Cabeamento da ponte:

Conecte os dois fios vermelhos dos motores direito em OUT4.

Conecte os dois fios pretos dos motores direito em OUT3.

Conecte os dois fios vermelhos dos motores esquerdo em OUT2.

Conecte os dois fios pretos dos motores esquerdo em OUT1.

Termine o cabeamento da ponte como mostrado a seguir (antes, retire os dois jumpers que estão na ponte para fazer o cabeamento):

Cabeamento da energia:

Conecte o fio vermelho da bateria em +12V da  ponte.

Conecte o fio preto da bateria em GND da ponte. Nesse mesmo ponto, conecte um fio preto até GND do sensor shield.

Conecte o fio vermelho de VCC da ponte até VCC do shield.

Opcionalmente, conecte o positivo (vermelho) do suporte da bateria no módulo de potência através de uma chave liga-desliga.

Cabeamento completo:

A imagem apresenta o cabeamento completo do carro.

Opcionais:


Cabeamento completo:

A imagem apresenta o cabeamento completo, incluindo quatro LEDs e buzina opcionais.

ESP32-CAM

Programação

IMPORTANTE: ao usar FTDI, certifique-se de colocar o jumper para 5V, diferentemente do que é usado ao programar ESP12 ou ESP32

Conexões


Resumo das conexões

D00 - NC

D01 - LEDs vermelhos

D02 - DC motor drive

D03 - DC motor drive

D04 - DC motor drive

D05 - DC motor drive

D06 - DC motor drive

D07 - Servo

D08 - Ultrasom

D09 - Ultrasom

D10 - LEDs brancos

D11 - Buzzer

D12 - NC

D13 - DC motor drive

TX - Bluetooth

RX - Bluetooth

Código

Essa pode não ser a última versão do código. Para a última versão estável, use https://github.com/AlexandreMeslin/RobotCar.

IMPORTANTE: antes de fazer upload do código, não se esqueça de desconectar os pinos TX e RX do shield. Eles estão conectados ao Bluetooth, que usa os mesmos pinos da interface serial USB. Lembre-se de reconectar para poder usar o carro.

/*

*/


#include <Servo.h>

#include <NewPing.h>


void forward(void);

void back(void);

void left(void);

void right(void);

void stopAll(void);

int readPing(void);

void forwardRight(void);

void forwardLeft(void);


/*

 * Ultrasonic sensor

 */

#define TRIGPIN 8

#define ECHOPIN 9

const int maximumDistance = 100;

NewPing sonar(TRIGPIN, ECHOPIN, maximumDistance); //sensor function

int distance;

unsigned long previousMillis = 0;        // will store last time distance was updated

 

/*

 * Motor

 */

unsigned char carSpeed = 255;

boolean movingForward = false;

const int turningFactor = 70;    // unbalance factor to turn left or right, and move forward simultaneously

// Left Motor

const int motorEnLeft = 5;

const int motorInLeft1 = 3;

const int motorInLeft2 = 2;

// Right Motor

const int motorEnRight = 6;

const int motorInRight3 = 13;

const int motorInRight4 = 4;


/*

 * Servo

 */

int servoPin = 7; // Declare the Servo pin 

Servo servo;      // Create a front servo object 


/*

 * Lights

 */

const int ledPinFrontRight = 11;  // the number of the LED pin

const int ledPinFrontLeft  = 10;

const int ledPinRearRight  = 1;  // the number of the LED pin

const int ledPinRearLeft   = 12;  // the number of the LED pin


// Generally, you should use "unsigned long" for variables that hold time

// The value will quickly become too large for an int to store


void setup() {

  // Serial setup

  Serial.begin(9600);

  

  // Motor setup

  pinMode(motorInLeft1, OUTPUT);

  pinMode(motorInLeft2, OUTPUT);

  pinMode(motorInRight3, OUTPUT);

  pinMode(motorInRight4, OUTPUT);


  pinMode(motorEnLeft, OUTPUT); 

  pinMode(motorEnRight, OUTPUT); 


  // Servo setup

  servo.attach(servoPin); 


  // Light setup

  // set the digital pin as output:

  pinMode(ledPinFrontRight, OUTPUT);

  pinMode(ledPinFrontLeft, OUTPUT);

  pinMode(ledPinRearRight, OUTPUT);

  pinMode(ledPinRearLeft, OUTPUT);

  digitalWrite(ledPinFrontRight, LOW);

  digitalWrite(ledPinFrontLeft, LOW);

  digitalWrite(ledPinRearRight, LOW);

  digitalWrite(ledPinRearLeft, LOW);


  /*

   * Ultrasonic

   */

  pinMode(TRIGPIN, OUTPUT);

  pinMode(ECHOPIN, INPUT);

  delay(2000);

  distance = readPing();

  delay(100);

  distance = readPing();

  delay(100);

  distance = readPing();

  delay(100);

  distance = readPing();

  delay(100);

  

  Serial.println("Começando...\n");

}


void loop() {

  // here is where you'd put code that needs to be running all the time.

  static char command;


  if(distance < 20) {

      digitalWrite(ledPinFrontRight, HIGH);

      digitalWrite(ledPinFrontLeft, HIGH);

      digitalWrite(ledPinRearRight, HIGH);

      digitalWrite(ledPinRearLeft, HIGH);

      if(movingForward) stopAll();

  }


  command = Serial.read();

  switch(command) {

    case 'b':

    case 'B': // move back

      servo.write(90);

      back();

      break;

    case 'D': // Stop all

      stopAll();

      break;

    case 'f':

    case 'F': // move forward

      servo.write(90);

      forward();

      break;

    case 'G': // Move forward left

      servo.write(90+45);

      forwardLeft();

      break;

    case 'H': // Move back left

      servo.write(90);

      backLeft();

      break;

    case 'I': // Move forward right

      servo.write(90-45);

      forwardRight();

      break;

    case 'J': // Move back right

      servo.write(90);

      backRight();

      break;

    case 'L': // move left

      servo.write(180);

      left();

      break;

    case 'R': // Right

      servo.write(0);

      right();

      break;

    case 'S': // Stop

      stopAll();

      break;

    case 'W': // Front lights on

      digitalWrite(ledPinFrontRight, HIGH);

      digitalWrite(ledPinFrontLeft, HIGH);

      break;

    case 'w': // Front lights off

      digitalWrite(ledPinFrontRight, LOW);

      digitalWrite(ledPinFrontLeft, LOW);

      break;

    case 'U': // back lights on

      digitalWrite(ledPinRearRight, HIGH);

      digitalWrite(ledPinRearLeft, HIGH);

      break;

    case 'u': // back ligths off

      digitalWrite(ledPinRearRight, LOW);

      digitalWrite(ledPinRearLeft, LOW);

      break;

    case '0': // Speed 0;

      carSpeed = 255*0/100;

      break;

    case '1': // Speed 10;

      carSpeed = 255*10/100;

      break;

    case '2': // Speed 20;

      carSpeed = 255*20/100;

      break;

    case '3': // Speed 30;

      carSpeed = 255*30/100;

      break;

    case '4': // Speed 40;

      carSpeed = 255*40/100;

      break;

    case '5': // Speed 50;

      carSpeed = 255*50/100;

      break;

    case '6': // Speed 60;

      carSpeed = 255*60/100;

      break;

    case '7': // Speed 70;

      carSpeed = 255*70/100;

      break;

    case '8': // Speed 80;

      carSpeed = 255*80/100;

      break;

    case '9': // Speed 90;

      carSpeed = 255*90/100;

      break;

    case 'q': // Speed 100;

      carSpeed = 255*100/100;

      break;

  }

  distance = readPing();

}


/**

 * Motor forward

 */

void forward(void){

  movingForward = true;

//  if(distance < 20) {

//    stopAll();

//  } else {

    analogWrite(motorEnLeft,carSpeed);

    analogWrite(motorEnRight,carSpeed);

    digitalWrite(motorInLeft1,HIGH);

    digitalWrite(motorInLeft2,LOW);

    digitalWrite(motorInRight3,LOW);

    digitalWrite(motorInRight4,HIGH);

//  }

  Serial.println("Forward");

}

 

void back(){

  movingForward = false;

  analogWrite(motorEnLeft,carSpeed);

  analogWrite(motorEnRight,carSpeed);

  digitalWrite(motorInLeft1,LOW);

  digitalWrite(motorInLeft2,HIGH);

  digitalWrite(motorInRight3,HIGH);

  digitalWrite(motorInRight4,LOW);

  Serial.println("Back");

}

 

void backLeft(void){

  movingForward = false;

  analogWrite(motorEnLeft,carSpeed * turningFactor / 100);

  analogWrite(motorEnRight,carSpeed);

  digitalWrite(motorInLeft1,LOW);

  digitalWrite(motorInLeft2,HIGH);

  digitalWrite(motorInRight3,HIGH);

  digitalWrite(motorInRight4,LOW);

  Serial.println("Back");

}

 

void backRight(void){

  movingForward = false;

  analogWrite(motorEnLeft,carSpeed);

  analogWrite(motorEnRight,carSpeed * turningFactor / 100);

  digitalWrite(motorInLeft1,LOW);

  digitalWrite(motorInLeft2,HIGH);

  digitalWrite(motorInRight3,HIGH);

  digitalWrite(motorInRight4,LOW);

  Serial.println("Back");

}

 

void left(){

  analogWrite(motorEnLeft,carSpeed);

  analogWrite(motorEnRight,carSpeed);

  digitalWrite(motorInLeft1,LOW);

  digitalWrite(motorInLeft2,HIGH);

  digitalWrite(motorInRight3,LOW);

  digitalWrite(motorInRight4,HIGH); 

  Serial.println("Left");

}

 

void forwardLeft(void){

    movingForward = true;

//  if(distance < 20) {

//    stopAll();

//  } else {

    analogWrite(motorEnLeft,carSpeed * turningFactor / 100);

    analogWrite(motorEnRight,carSpeed);

    digitalWrite(motorInLeft1,HIGH);

    digitalWrite(motorInLeft2,LOW);

    digitalWrite(motorInRight3,LOW);

    digitalWrite(motorInRight4,HIGH);

//  }

  Serial.println("Left");

}

 

void right(){

  analogWrite(motorEnLeft,carSpeed);

  analogWrite(motorEnRight,carSpeed);

  digitalWrite(motorInLeft1,HIGH);

  digitalWrite(motorInLeft2,LOW);

  digitalWrite(motorInRight3,HIGH);

  digitalWrite(motorInRight4,LOW);

  Serial.println("Right");

}

 

void forwardRight(){

  movingForward = true;

//  if(distance < 20) {

//    stopAll();

//  } else {

    analogWrite(motorEnLeft,carSpeed);

    analogWrite(motorEnRight,carSpeed * turningFactor / 100);

    digitalWrite(motorInLeft1,HIGH);

    digitalWrite(motorInLeft2,LOW);

    digitalWrite(motorInRight3,LOW);

    digitalWrite(motorInRight4,HIGH);

//  }

  Serial.println("Right");

}

 

void stopAll(){

  movingForward = false;

  digitalWrite(motorEnRight,LOW);

  digitalWrite(motorEnLeft,LOW);

  digitalWrite(ledPinRearRight, HIGH);

  digitalWrite(ledPinRearLeft, HIGH);

  Serial.println("Stop!");

}


/**

 * Ultrasonic sensor reader

 */

int readPing(){

  static unsigned long currentMillis;

  static unsigned long deltaT;


  currentMillis = millis();

  deltaT = currentMillis - previousMillis;

  previousMillis = currentMillis;

  if(deltaT < 70) delay(70 - deltaT);

//  delay(70);

  int cm = sonar.ping_cm();

  if (cm==0){

    cm=250;

  }

  return cm;

}

Link para o código, cabeamento e muito mais: https://github.com/AlexandreMeslin/RobotCar.