PROYECTO R2D2
El proyecto consiste en la impresión en 3d del robot R2D2 de la Guerra de las Galaxias y la programación en Arduino del control de los dos motores 360 que producen el desplazamiento del robot, el control del servo que produce el giro de la cabeza,el buzzer que reproduce la música de la Guerra de las Galaxias y dos sensores ópticos que convierten al robot en seguidor de línea negra. Todo ello controlado a través de una App.
FUNCIONAMIENTO
CIRCUITO Y MONTAJE
PROGRAMA ARDUINO
/*
R2D2HS
(c) HIRUDI/SICNOVA3D
GPL v3
This programs controls remotely the printbot R2D2HS.
It's derived from:
*/
// Library for working with servos
#include <Servo.h>
#include <SoftwareSerial.h>
SoftwareSerial BT(2, 3);
//seguidor de línea
const int sensorIzquierdoPin = 5;
const int sensorDerechoPin = 7;
//servo
const int servoIzquierdoPin = 6;
const int servoDerechoPin = 9;
// último sensor IR en cambiar al salir de línea
char ultimoIR = 'N'; //si empieza fuera de línea
boolean fuera = false; // control de vuelta a línea
char data;
int ledPin = 13;
//led for visualization (use 13 for built-in led)
int speakerPin = 12;
//speaker connected to one of the PWM ports
//Ahora creamos un par de objetos "servo" para que podamos trabajar con ellos.
Servo servoL;
Servo servoR;
Servo miniservo;
// DEFINE
#define c 261
#define d 294
#define e 329
#define f 349
#define g 391
#define gS 415
#define a 440
#define aS 455
#define b 466
#define cH 523
#define cSH 554
#define dH 587
#define dSH 622
#define eH 659
#define fH 698
#define fSH 740
#define gH 784
#define gSH 830
#define aH 880
//frequencies for the tones we're going to use
//used http://home.mit.bme.hu/~bako/tonecalc/tonecalc.htm to get these
//Ahora preparamos nuestra placa freaduino
void setup() {
Serial.begin(9600);
BT.begin(9600);
disable();
pinMode(ledPin, OUTPUT);
// sets the ledPin to be an output
pinMode(speakerPin, OUTPUT);
//sets the speakerPin to be an output
// Inicialización de los pines de los sensores como entrada
pinMode(sensorIzquierdoPin, INPUT);
pinMode(sensorDerechoPin, INPUT);
}
// Indicamos los pines de los servos
void enable(){
servoR.attach(servoDerechoPin);
servoL.attach(servoIzquierdoPin);
miniservo.attach(10);
}
void disable()
{
servoR.detach();
servoL.detach();
}
// Creamos la funcion para parar
void stop(){
//digitalWrite (12, LOW);
disable();
delay(10);
}
// Creamos la funcion para avanzar
void forward(){
enable();
digitalWrite (12, LOW); //Ponemos en estado bajo el pin 12 para un posterior giro hacia adelante
servoL.write(0); //Con estos valores el robot avanzara
servoR.write(180);
delay(10);
}
// Creamos la funcion para retroceder
void backward(){
enable();
servoL.write(180); //Con estos valores el robot retrocedera
servoR.write(0);
digitalWrite (12, HIGH); //Ponemos en estado alto el pin 12 para un posterior giro hacia atras
delay(10);
}
// Creamos la funcion que girara a la derecha
void right(){
enable();
if (digitalRead(12)){ //Leemos el estado del pin 12, si esta activo girara retrocediendo
servoL.write(0);
servoR.write(80);
delay(10);
}
else{ //Y si esta desactivado girara avanzando
servoL.write(55);
servoR.write(100);
delay(10);
}
}
//Creamos la funcion que girara a la izquierda
void left()
{
enable();
if (digitalRead(12)) //Leemos el estado del pin 12, si esta activo girara retrocediendo
{
servoL.write(100);
servoR.write(180);
delay(10);
}
else
{ //Y si esta desactivado girara avanzando
servoL.write(80);
servoR.write(135);
delay(10);
}
}
void head_right()
{
miniservo.write(0);
delay(10);
}
void head_left()
{
miniservo.write(180);
delay(10);
}
void seguidor()
{
enable();
// Lectura de los sensores IR
bool sensorIzquierdoDetectaNegro = digitalRead(sensorIzquierdoPin);
bool sensorDerechoDetectaNegro = digitalRead(sensorDerechoPin);
// Comportamiento del seguidor de línea
if (sensorIzquierdoDetectaNegro && sensorDerechoDetectaNegro) {
// Ambos sensores en línea negra (avanzar recto)
servoL.write(180); // Servo izquierdo avanza
servoR.write(0); // Servo derecho avanzaºº
ultimoIR = 'N';
fuera = false; // regreso a la linea
} else if (!sensorIzquierdoDetectaNegro && sensorDerechoDetectaNegro && fuera) {
// Solo el sensor derecho en línea negra (girar a la derecha)
servoL.write(180); // Servo izquierdo avanza
servoR.write(0); // Servo derecho se detiene
ultimoIR = 'D';
} else if (!sensorIzquierdoDetectaNegro && sensorDerechoDetectaNegro && !fuera) {
// Solo el sensor derecho en línea negra (girar a la derecha)
servoL.write(180); // Servo izquierdo avanza
servoR.write(90); // Servo derecho se detiene
ultimoIR = 'D';
} else if (sensorIzquierdoDetectaNegro && !sensorDerechoDetectaNegro && fuera) {
// Solo el sensor izquierdo en línea negra (girar a la izquierda)
servoL.write(180); // Servo izquierdo se detiene
servoR.write(0); // Servo derecho avanza
ultimoIR = 'I';
} else if (sensorIzquierdoDetectaNegro && !sensorDerechoDetectaNegro && !fuera) {
// Solo el sensor izquierdo en línea negra (girar a la izquierda)
servoL.write(90); // Servo izquierdo se detiene
servoR.write(0); // Servo derecho avanza
ultimoIR = 'I';
}
else if( !sensorIzquierdoDetectaNegro && !sensorDerechoDetectaNegro && ultimoIR == 'D') // Derch 0 , Izqu 0 , Girar Derecha Cerrada
{
servoL.write(180); // Servo izquierdo se detiene
servoR.write(90); // Servo derecho avanza
fuera = true;
}
else if( !sensorIzquierdoDetectaNegro && !sensorDerechoDetectaNegro && ultimoIR == 'I') // Derch 0 , Izqu 0 , Girar Izquierda Cerrada
{
servoL.write(90); // Servo izquierdo se detiene
servoR.write(0); // Servo derecho avanza
fuera = true;
}
else if( !sensorIzquierdoDetectaNegro && !sensorDerechoDetectaNegro && ultimoIR == 'N') // Derch 0 , Izqu 0 , Recto para encontrar línea
{
servoL.write(180); // Servo izquierdo se detiene
servoR.write(0);
fuera = true;
}
else {
// Ningún sensor en línea negra (detenerse)
servoL.write(90); // Servo izquierdo detenido
servoR.write(90); // Servo derecho detenido
fuera = true;
}
// Pequeño retraso para evitar lecturas erráticas
delay(10);
}
void beep (unsigned char speakerPin, int frequencyInHertz, long timeInMilliseconds)
{
digitalWrite(ledPin, HIGH);
//use led to visualize the notes being played
int x;
long delayAmount = (long)(1000000/frequencyInHertz);
long loopTime = (long)((timeInMilliseconds*1000)/(delayAmount*2));
for (x=0;x<loopTime;x++)
{
digitalWrite(speakerPin,HIGH);
delayMicroseconds(delayAmount);
digitalWrite(speakerPin,LOW);
delayMicroseconds(delayAmount);
}
digitalWrite(ledPin, LOW);
//set led back to low
delay(20);
//a little delay to make all notes sound separate
}
void march()
{
//while(Serial.available() > 0){
//for the sheet music see:
//http://www.musicnotes.com/sheetmusic/mtd.asp?ppn=MN0016254
//this is just a translation of said sheet music to frequencies / time in ms
//used 500 ms for a quart note
beep(speakerPin, a, 500);
beep(speakerPin, a, 500);
beep(speakerPin, a, 500);
beep(speakerPin, f, 350);
beep(speakerPin, cH, 150);
beep(speakerPin, a, 500);
beep(speakerPin, f, 350);
beep(speakerPin, cH, 150);
beep(speakerPin, a, 1000);
//first bit
beep(speakerPin, eH, 500);
beep(speakerPin, eH, 500);
beep(speakerPin, eH, 500);
beep(speakerPin, fH, 350);
beep(speakerPin, cH, 150);
beep(speakerPin, gS, 500);
beep(speakerPin, f, 350);
beep(speakerPin, cH, 150);
beep(speakerPin, a, 1000);
/*
//second bit...
beep(speakerPin, aH, 500);
beep(speakerPin, a, 350);
beep(speakerPin, a, 150);
beep(speakerPin, aH, 500);
beep(speakerPin, gSH, 250);
beep(speakerPin, gH, 250);
beep(speakerPin, fSH, 125);
beep(speakerPin, fH, 125);
beep(speakerPin, fSH, 250);
delay(250);
beep(speakerPin, aS, 250);
beep(speakerPin, dSH, 500);
beep(speakerPin, dH, 250);
beep(speakerPin, cSH, 250);
//start of the interesting bit
beep(speakerPin, cH, 125);
beep(speakerPin, b, 125);
beep(speakerPin, cH, 250);
delay(250);
beep(speakerPin, f, 125);
beep(speakerPin, gS, 500);
beep(speakerPin, f, 375);
beep(speakerPin, a, 125);
beep(speakerPin, cH, 500);
beep(speakerPin, a, 375);
beep(speakerPin, cH, 125);
beep(speakerPin, eH, 1000);
//more interesting stuff (this doesn't quite get it right somehow)
/*
beep(speakerPin, aH, 500);
beep(speakerPin, a, 350);
beep(speakerPin, a, 150);
beep(speakerPin, aH, 500);
beep(speakerPin, gSH, 250);
beep(speakerPin, gH, 250);
beep(speakerPin, fSH, 125);
beep(speakerPin, fH, 125);
beep(speakerPin, fSH, 250);
delay(250);
beep(speakerPin, aS, 250);
beep(speakerPin, dSH, 500);
beep(speakerPin, dH, 250);
beep(speakerPin, cSH, 250);
//repeat... repeat
beep(speakerPin, cH, 125);
beep(speakerPin, b, 125);
beep(speakerPin, cH, 250);
delay(250);
beep(speakerPin, f, 250);
beep(speakerPin, gS, 500);
beep(speakerPin, f, 375);
beep(speakerPin, cH, 125);
beep(speakerPin, a, 500);
beep(speakerPin, f, 375);
beep(speakerPin, c, 125);
beep(speakerPin, a, 1000);
*/
//and we're done \รณ/
// }
}
//Ahora entramos en el nucleo del programa, donde utilizamos las funciones anteriormente creadas
void loop() {
if (BT.available()){
data = BT.read();
Serial.println(data);
switch (data) //Leemos el dato que nos envia el bluetooth y lo almacenamos en la variable
{
case 'F': //Si en la variable tenemos una "g" ejecutaremos la funcion avanzar
forward();
break;
case 'L': //Si en la variable tenemos una "h" ejecutaremos la funcion girar izquierda
left ();
break;
case 'S': //Si en la variable tenemos una "i" ejecutaremos la funcion parar
stop();
break;
case 'R': //Si en la variable tenemos una "j" ejecutaremos la funcion girar derecha
right();
break;
case 'B': //Si en la variable tenemos una "k" ejecutaremos la funcion retroceder
backward();
break;
case 'W': //Si en la variable tenemos una "k" ejecutaremos la funcion retroceder
head_left();
break;
case 'V': //Si en la variable tenemos una "k" ejecutaremos la funcion retroceder
march();
break;
case 'w': //Si en la variable tenemos una "k" ejecutaremos la funcion retroceder
head_right();
break;
case 'U':
seguidor();
break;
default:
stop();
break;
}//switch
}//if
}//loop