Olá! Resolvi automatizar um Nerf Elite para dar tiro curvo em um alvo, utilizando o principio do lançamento de projéteis. 
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, dois servomotores: um 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, um botão para o disparo, um resistor de Pull down (coloca nível lógico baixo na entrada do controlador), protoboard, fios, etc...


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. Resolvi fazer o meu do zero (por enquanto ainda está na fase de protótipo). Espero que gostem!

Obs.: Sugestões são sempre bem-vindas!

Modelo 3D:

https://www.tinkercad.com/things/cSM5himYF3u-nerf-launcher-cannon2#/

Fórmulas: 

Alcance: A= 〖V0〗^2/g*sin⁡(2θ) (m)
V0= velocidade inicial (m/s)
g= aceleração da gravidade (9,8m/s²)
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=√(A*g)

A distância máxima experimental alcançada pelo dardo do NERF foi de 6 metros.

V0= √(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:
θ=[sin^(-1)⁡((A*g)/〖V0〗^2 ) ]/2

No Arduino:
#include <math.h>
#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

*O resultado de uma conta com seno e cosseno, no Arduino, da um resultado em radianos. Como eu precisava do valor em “graus” para enviar para o servo, tive que converter de radiano para graus.

** RAD_TO_DEG:
360/x=(2π )/1
x=(360 )/2π
x= 57.295779513082320876798154814105 



Obs.: Para um ângulo de (45 – x) ou (45 + x), o projétil cai no mesmo lugar:

Θ= 45
V0= 7,668m/s
A= 〖V0〗^2/g*sin⁡(2*θ)
A=〖(7,668)〗^2/9,8*sin⁡(2*45)
A=5,99m
Θ2= (45-10)= 35
A2=〖(7,668)〗^2/9,8*sin⁡(2*35)
A2= 5,64 m
Θ3= (45+10)= 55
A3=〖(7,668)〗^2/9,8*sin⁡(2*55)
A3= 5,64 m


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

Simulador do circuito:

1º Clique no botão "iniciar simulação"
2º: Clique no sensor para poder simular a distância, arrastando o círculo. Com isso, o ângulo do servomotor "atualiza" automaticamente.
3º: Clique no botão para disparar (o botão foi configurado como uma interrupção e ativa o servomotor, quando for pressionado, em qualquer momento do código).

Obs.: As informações no display de LCD são apenas para facilitar o manuseio. Pressionando o botão do "Cod", vai abrir uma aba com o código e lá, vai ter um botão de "Serial Monitor", onde vão aparecer mais informações como o outro ângulo (menor) de disparo.

https://www.tinkercad.com/things/5Kg8mZwA3Cs-tst2

Código:

#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 go 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çãi 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;
}

Exibições: 881

Comentar

Você precisa ser um membro de Laboratorio de Garagem (arduino, eletrônica, robotica, hacking) para adicionar comentários!

Entrar em Laboratorio de Garagem (arduino, eletrônica, robotica, hacking)

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço