Nerf Bot - Cannon Project (simulation)
by PeckLauros in Circuits > Arduino
245 Views, 0 Favorites, 0 Comments
Nerf Bot - Cannon Project (simulation)
Olá! Resolvi automatizar um Nerf elite para dar tiro curvo em um alvo, utilizando o principio do lançamento de projéteis, visto nas aulas de física. A ideia básica foi a de atingir um alvo a uma certa distância, com alguma precisão. Para isso, utilizei um sensor ultrassônico para verificar a distância do alvo, um servomotor para alterar o ângulo de disparo e outro para acionar o gatilho, um display LCD para visualizar os dados como distância e ângulo e um Arduino para efetuar os cálculos, a leitura do sensor e acionar os servos.
Procurei algo na internet para servir como ponto de partida. Porém, não encontrava informações completas. Apenas fórmulas e alguns projetos prontos e sem maiores detalhes.
Iniciei o projeto fazendo os cálculos, depois utilizei as ferramentas do Tinkercad para simular tanto o software como o hardware, fiz um esboço de como seria o robô, em 3D e documentei alguns passos seguidos para compartilhar. Espero que gostem.
Teoria:
O dardo é lançado e cai em diferentes distâncias, de acordo com a variação do ângulo de disparo (já que a velocidade inicial (V0) não será alterada). Após um breve estudo da física envolvida, peguei algumas equações para implementar neste projeto.
Com vários ângulos diferentes, várias contas deveriam ser feitas para obter a distância do objeto lançado. Daí a ideia de “automatizar” esses cálculos.
O esboço final do robô veio após algumas ideias de como seria feito:
1) Utilizar um potenciômetro para medir o ângulo do canhão e mostra-lo em um Lcd.
2) Utilizar um servo para variar o ângulo do canhão com a ajuda do potenciômetro.
3) Utilizar alguns botões para acrescentar informações como: altura máxima da bolinha, tempo de queda, distância e ângulo.
4) Utilizar um sensor de distância para o canhão “escolher” o ângulo certo para atirar no alvo.
Aos poucos fui implementando cada as funções e aprendendo coisas novas no Arduino.
Fórmulas:
A distância máxima alcançada pelo projetil do NERF foi de 6 metros.
Para achar a V0 , utilizei um método indireto: Sabendo que o Alcance máximo dá-se com o ângulo de 45 graus, (seno de (2* 45) = 1),
Logo: V0= SQRT (A*g)
V0= SQRT(6 * 9.8)
V0= 7.668 m/s 2
No Arduino:
float V0= 7.668; // variável para estocar o valor da velocidade inicial
float g=9.8; // aceleração da gravidade
float A=0; // variável do Alcance máximo
Para Saber Qual O Ângulo Que Deve Ter Para Acertar Um Objeto a “A” (em Metros) De Distância, a Fórmula Foi Arrumada E Ficou Assim:
No Arduino:
#include
#define RAD_TO_DEG 57.295779513082320876798154814105
double O=0; //variável para o ângulo
O= (asin((A * g)/(V0*V0)))/2; // fornece o valor do ângulo em radianos
O= O*RAD_TO_DEG; //transforma de radianos para graus
Cálculo De Ângulos No Arduino
*O Resultado de uma conta com Seno e Cosseno da um resultado em radianos. Como eu precisava do valor em “graus” para enviar para o servo, tive que converter de radiano para graus.
Escolha Da Parábola:
Obs.: Para um ângulo de (45 – x) ou (45 + x), o projétil cai no mesmo lugar.
Para um ângulo de (45 +x), a parábola tem um pico maior. Por isso, resolvi utilizar esse cálculo para o canhão.
No Arduino:
if (O >0 & O < 45){ O2= (45-O)+45; // encontra o ângulo que foi subtraído de 45, soma a 45 e estoca esse valor na variável O2
Serial.print("Angulo2= "); // imprime na serial a palavra Angulo2= Serial.println(O2); // imprime na serial o valor do ângulo
O2 myservo.write(O2); // envia o valor de O2 para o servo delay(15); // aguarda 15 ms para atualizar a posição do servo
Para Um Ângulo De (45 +x), a Parábola Tem Um Pico Maior. Por Isso, Resolvi Utilizar Esse Cálculo Para O Canhão.
No Arduino:
if (O >0 & O < 45){
O2= (45-O)+45; // encontra o ângulo que foi subtraído de 45, soma a 45 e estoca esse valor na variável O2
Serial.print("Angulo2= "); // imprime na serial a palavra Angulo2=
Serial.println(O2); // imprime na serial o valor do ângulo O2
myservo.write(O2); // envia o valor de O2 para o servo
delay(15); // aguarda 15 ms para atualizar a posição do servo
Modelagem 3D
Link para o projeto do canhão:
https://www.tinkercad.com/things/cSM5himYF3u-nerf-launcher-cannon2
Simulador Do Circuito Lógico
Link do simulador do circuito:
Software:
#include <LiquidCrystal.h>
#include <math.h>
#include <Servo.h>
#define RAD_TO_DEG 57.295779513082320876798154814105
#define DEG_TO_RAD 0.017453292519943295769236907684886
LiquidCrystal lcd(A5,A4,A3,A2,A1,A0); // Inicializa o LCD
int tempo =500; //variável para estocar o tempo
const int pin1gPin = 5; // pino para conectar o sensor ultrassonico
Servo fire; // criando o objeto servo para acionar o gatilho
Servo myservo; // criando o objeto servo para movimentar o ângulo
int firePin= 3; // pino para atirar (a interrupção externa no Arduino Uno fica nos botões 2 e 3)
int flagTiro= 0; // flag para verificar se o gatilho foi acionado
int pingPin= 5; // pino para receber o sinal do sensor
double h=0; // variável para a altura (Usei "double" para representar números com frações. Também pode ser usado "float")
double h2=0;
double O=0; //variável para o ângulo
double O2=0; // variável para o ângulo2
float dist1=0; // variável da distância da borda do canhao e a base fixa
float r= (0.12); //variável(em metros) para o valor da haste
float V0= 5.6609; // variável para estocar o valor da velocidade inicial
float g=9.8; // aceleração da gravidade
float A=0; // variável do Alcance máximo
void setup(){
Serial.begin(9600); // inicia a porta serial
// rotina par aescrever no LCD
lcd.begin(16, 2); // Define o LCD com 16 colunas e 2 linhas
lcd.setCursor(0,0); // (coluna, linha)
lcd.print("Nerf Bot"); // Mostra informacoes no display
delay(tempo*3); // aguarda 1,5 segundos
lcd.clear(); // apaga o display
lcd.setCursor(0,0);
lcd.print("Distancia:");
lcd.setCursor(0,2);
lcd.print ("Angulo:");
// rotina dos servos
myservo.attach(7); // Servo do ângulo no pino 9
myservo.write(0); // posição inicial do servo do ângulo
delay(250);
fire.attach(6); // Servo do gatinho no pino 6
fire.write(0); //posição inicial do servo do gatilho
delay(250);
pinMode(firePin, INPUT);
attachInterrupt(digitalPinToInterrupt(firePin),gatilho, HIGH ); // interrupção externa para ativar o gatilho
}
void loop()
{
// rotina para a leitura do sensor de distância
long duration, cm;
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
cm = microsecondsToCentimeters(duration);
/*Serial.print(cm);
Serial.print("cm");
Serial.println();
*/
delay(100);
A= cm;
lcd.setCursor(11,0);
lcd.print(A);
lcd.setCursor(14,0);
lcd.print("cm");
Serial.print ("Distancia= ");
Serial.print(A);
Serial.println("cm");
delay(15);
A=(A/100);
O= (asin((A * g)/(V0*V0)))/2; // fornece o valor do ângulo em radianos
O= O*RAD_TO_DEG; //transforma de radianos para graus
Serial.print("Angulo= ");
Serial.println(O);
if (O >0 & O < 45){
O2= (45-O)+45;
Serial.print("Angulo2= ");
Serial.println(O2);
lcd.setCursor(8,1);
lcd.print(O2);
lcd.setCursor(10,1);
lcd.print("Graus");
delay(15);
myservo.write(O2);
delay(1000);
}
if (flagTiro > 0){
delay(500);
fire.write(0);
delay(500);
flagTiro= 0;
}
}
long microsecondsToCentimeters(long microseconds) {
return microseconds / 29 / 2;
}
void gatilho (){
fire.write(60);
flagTiro= 1;
}