Carro RobÔ
com Arduino Mega
Lista de material:
1 Arduino Mega
1 Sensor shield v5.0
1 chassis duplo de acrílico para carro com 4 rodas
4 motores DC
4 rodas
1 módulo bluetooth HC-05 (HC-05 bluetooth module) HC-06 (HC-06 bluetooth module)
1 ponte dupla H SparkFun L298 (Dual H-Bridge motor drivers L298)
1 servo-motor SG90 (SG90 Micro-servo motor)
1 sensor de ultrassom (Ultrasonic Sensor HC-SR04)
1 placa de sensores versão 5 (Sensor Shield v5)
1 alojamento para baterias ou pilhas (3 baterias 18650 ou 4 pilhas alcalinas)
Opcionais:
1 Auto-falante piezo-elétrico (piezo speaker ou buzzer)
2 LEDs brancos 10 mm
2 LEDs vermelhos 5 mm
4 resistores 220 ohms
Opcionais para inclusão da câmera
1 ESP32-CAM
1 Conversor USB-Serial (FTDI)
Na figura acima, da esquerda para a direita:
Arduino Mega
Arduino Uno
Arduino Nano
Arduino Micro
Arduino Mini
Na figura, da esquerda para a direita:
Arduino Uno Sensor Shield
Arduino Mega Sensor Shield
Objetivos
Primeira fase - vai andar:
Módulos utilizados:
Bluetooth
Driver do motor
Sensor de proximidade
Servo-motor
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:
+5V
GND
I/O:
GPIO8: TRIGPIN
GPIO9: ECHOPIN
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:
+5V
GND
I/O:
GPIO7: SERVOPIN
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:
+5V
GND
I/O:
TX1: TxD
RX1: RxD
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:
LEDs brancos na frente. Dois LEDs brancos, cada um com um resistor de 220 Ω ligados no pino 10
LEDS vermelhos atrás. Dois LEDs vermelhos, cada um com um resistor de 220 Ω ligados no pino 12
Buzina: Uma buzina (buzzer) ligada no pino 11
Chave liga/desliga em série com as baterias.
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.
Controle Remoto
O carro é compatível com https://play.google.com/store/apps/details?id=braulio.calle.bluetoothRCcontroller.