Translate

domingo, 13 de diciembre de 2015

Sesión de fotografía

Ya se acerca la presentación del proyecto y por esta razón hoy hemos ido a hacer unas fotografías para ponerlas en la portada de nuestro trabajo escrito.

A continuación os dejamos lo que hemos estado haciendo.


Detector de obstaculos

A continuación os dejamos el programa que hemos hecho para que el robot no choque con obstáculos cuando su distancia sea menor de 20 
centímetros.

#include <Servo.h>  //libreria servo
long distancia;
long tiempo;

int trig = 2;
int echo = 6;
//definir las posiciones de los servos
#define SERVO_FRONT 1700
#define SERVO_REAR 1300
#define SERVO_STOP 1500

Servo ServoIzq, ServoDer;

void setup()

{
Serial.begin(9600); //inicio de la comunicación serie

pinMode(trig, OUTPUT); /*activamos el pin 9 como salida: emite un pulso ultrasónico*/
pinMode(echo, INPUT); /*activamos el pin 8 como entrada: tiempo del rebote del ultrasonido*/

ServoIzq.attach(8);
ServoDer.attach(9);

}

void loop()

{


digitalWrite(trig,LOW); /* Por cuestión de estabilización del sensor*/
delayMicroseconds(5);
digitalWrite(trig, HIGH); /* envío del pulso ultrasónico*/
delayMicroseconds(10);

tiempo=pulseIn(echo, HIGH); /* Función para medir la longitud del pulso entrante. Mide el tiempo que transcurrido entre el envío  del pulso ultrasónico y cuando el sensor recibe el rebote, es decir: desde que el pin 12 empieza a recibir el rebote, HIGH, hasta que  deja de hacerlo, LOW, la longitud del pulso entrante*/

distancia= int(0.017*tiempo); /*fórmula para calcular la distancia obteniendo un valor entero*/


 /*Monitorización en centímetros por el monitor serial*/
Serial.println("Distancia ");
Serial.println(distancia);
Serial.println(" cm");

delay (100);

//el robot va hacia delante 
ServoIzq.writeMicroseconds(SERVO_FRONT);
ServoDer.writeMicroseconds(SERVO_REAR);

 if(distancia<20) /*si la distancia del sensor con el objeto es menor de 20*/

 {
//gira a la derecha
  
   ServoIzq.writeMicroseconds(SERVO_FRONT);
   ServoDer.writeMicroseconds(SERVO_FRONT);
   

 }

  else  /*si no*/

{ 
//sigue hacia delante
ServoIzq.writeMicroseconds(SERVO_FRONT);
ServoDer.writeMicroseconds(SERVO_REAR);

}
 
}











viernes, 11 de diciembre de 2015

Prueba del modulo con el primer chasis

Una vez cargado el programa toca poner el robot en funcionamiento. Ésta prueba la hicimos con el primer chasis ya que el segundo no estaba montado. El cable que cuelga del robot es el cable que alimenta a la placa desde el ordenador, por lo tanto hemos de buscar una batería.


lunes, 7 de diciembre de 2015

Mejora del chasis

Hemos decidido construir un nuevo chasis.
El motivo de esta decisión ha sido la inestabilidad que hemos observado en el chasis anterior y además porque ahora tenemos nuevas ideas y pensamos que podemos hacerlo mejor y más estable, ya que conocemos los problemas que nos pueden surgir y los hemos estudiado y apuntado.


Montaje del chasis
Para montar este segundo chasis tuvimos que hacer unos planos nuevos, ya que es muy diferente al anterior. Lo que tuvimos muy en cuenta para hacerlo fue poner materiales más resistentes y menos flexibles (utilizamos mayoritariamente aluminio).
Lo primero que hicimos fue calcular la separación de las ruedas, con el objetivo de que las orugas estuvieran tensas sin necesidad de manipularlas. Cuando ya teníamos las distancias medidas ajustamos las ruedas a una base de teflón, a la cual le hicimos unos orificios para ajustarla.
Las ruedas delanteras y traseras no están hechas de la misma manera, ya que las delanteras tienen que girar locas para que no haya fricción con el chasis y en cambio, las traseras están fijadas a los servos.
Lo segundo que hicimos fue ajustar los motores. Lo que hicimos fue recortar las escuadras a medida del motor colocado en horizontal. A continuación unimos las dos escuadras de aluminio entre si.


En las fotografías se puede observar el nuevo chasis:


En la siguiente fotografía se puede observar el mecanismo de engranajes multiplicador que hemos colocado para que el robot vaya a mayor velocidad, y cómo ahora los servomotores están montados en horizontal y no en vertical como en el anterior chasis. Este cambio de posición de los servos lo hemos hecho para que sean más estables y no vibren al girar.

domingo, 6 de diciembre de 2015

Resultados del programa

Una vez cargado el programa, abrimos el monitor serie. Al principio aparecen una serie de mensajes de bienvenida y después muestra datos de la conexión, entre ellos la dirección IP a la que está conectado el módulo. Lo que debemos hacer es poner la dirección IP en el navegador del dispositivo que estemos utilizando y éste debe estar conectado a la misma red que el módulo.

Una vez hecho eso, se nos abrirá una página web desde donde podemos controlar nuestro robot. 


Al seleccionar cualquiera de las ordenes podemos visualizarlas por el monitor serie siempre que la placa ese conectada al ordenador


Servidor web

Para poder enviar ordenes a nuestro Arduino a través de Internet necesitamos crear un servidor web. Podemos crear éste servidor web con código HTML des de la siguiente página: w3schools.com. En ésta página tenemos tutoriales sobre como programar con código HTML.

La pàgina tiene que ser lo más simple posible debido a que cada vez que demos una orden se    cargará de nuevo y contra más simple sea antes se cargará.

Para poder visualizar la pagina que hemos creado tenemos que conectarnos con cualquier dispositivo (ordenador, móvil o  tablet) a la misma red a la que está conectado nuestro módulo wifi.El código HTML se tiene que introducir dentro del programa hecho con Arduino. Una vez tengamos el programa listo lo tenemos que cargar en la placa.Como podemos comprobar en la imagen, al seleccionar una orden, su casilla se marca en color verde en el caso del control del motor y en amarillo en el caso del control de las luces. El motivo de ésto es para que podamos saber en todo momento la acción que está realizando el robot. 


    









     




Programa

Este es el programa definitivo que utiliza nuestro robot
Tenemos que agradecer a Jose Luis Calero, ingeniero de telecomunicaciones, la ayuda que nos ha prestado para entender la información que hemos encontrado en la red y adaptarla a nuestro caso concreto:

/* En la primera parte del programa se establecen las variables y las directivas, y se insertan las librerías */

#include <Adafruit_CC3000.h>  //incluimos la libreria de Adafruit
#include "utility/debug.h"
#include “utility/socket.h"
#include <SPI.h>  //incluimos la libreria SPI
#include <Servo.h> //incluimos la libreria servo

/* Después de haber introducido las librerías debemos declarar las directivas define y las variables.
Las directivas #define son un tipo de variables que indican al procesador que debe sustituir en el código del programa todas las ocurrencias del nombre de la constante por la secuencia de caracteres antes de la compilación. Por ejemplo, si ponemos #define PI 3.141592 cada vez que ponemos la palabra "PI" en el programa, ésta se sustituirá por el número 3.141592 */

// Se definen como variables los pines 3, 5 i 10:
#define ADAFRUIT_CC3000_IRQ   3   
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10

Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT, SPI_CLOCK_DIVIDER);

// Introducimos el nombre de la red wifi con su respectiva contraseña i establecemos el tipo de seguridad:
#define WLAN_SSID  "ArduinoPanzer"  
#define WLAN_PASS  "Arduino1234"
#define WLAN_SECURITY  WLAN_SEC_WPA2
#define LISTEN_PORT  80     // El protocolo HTTP utiliza el puerto 80 por defecto
#define MAX_ACTION  10      // Duración máxima de la acción HTTP que se puede analizar
#define MAX_PATH  64        // Longitud máxima de la solicitud HTTP que se puede analitzar
#define BUFFER_SIZE  MAX_ACTION + MAX_PATH + 20 //Medida de la memoria para datos de solicitudes entrantes
#define TIMEOUT_MS  500     // Tiempo en milisegudos para esperar una solicitud entrante para acabar

// Variables para el control de los servomotores: 
// para un valor de 1700 el motor avanza, para 1300 retrocede, y para 1500 se para
#define SERVO_FRONT 1700
#define SERVO_REAR 1300
#define SERVO_STOP 1500

//Instrucciones que pertenecen a las conexiones con la red:
Adafruit_CC3000_Server httpServer(LISTEN_PORT);
uint8_t buffer[BUFFER_SIZE+1];
int bufindex = 0;
char action[MAX_ACTION+1];
char path[MAX_PATH+1];

//Variables de control y de servomotores: 
int AccionMotor=3, Luces=0;
Servo ServoIzq, ServoDer;


/* La segunda parte del programa es el "void setup". El "void setup" es la primera función en ejecutarse en un programa en Arduino. Es el lugar donde se inician las funciones que llevará a cabo el microcontrolador. En el "void setup" establecemos los criterios que requieren una ejecución única. Por ejemplo, si queremos que el programa utilice comunicación serial, estableceremos el comando Serial.begin para indicarlo. En El "void setup" determinamos también las órdenes necesarias para el funcionamiento de los actuadores */

void setup(void)
{
  pinMode(7, OUTPUT);   // pin 7 como salida digital (LEDs del robot)
  ServoIzq.attach(8);   // envio de señales servo al motor izquierdo, conectado al pin 8
  ServoDer.attach(9);   // envio de señales servo al motor derecho, conectado al pin 9
  ServoIzq.writeMicroseconds(SERVO_STOP);  // al empezar la ejecución, motor derecho e izquierdo parados
  ServoDer.writeMicroseconds(SERVO_STOP);

  Serial.begin(9600);  // comenzamos la comunicación serie a 9600 bps
  Serial.println(F("Hello, CC3000!\n"));   //mensaje de bienvenida  

  // Inicialización del mòdulo WiFi:
  Serial.println(F("Initializing..."));
  if (!cc3000.begin())
  {
    Serial.println(F("Couldn't begin()! Check yout wiring?"));  // si no se puede iniciar, revisa las conexiones
    while(1);
  }
  Serial.print(F("Attempting to connect to ")); 
  Serial.println(WLAN_SSID);   //intentando conectar a la red
  if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) 
  {
    Serial.println(F("Failed!"));  //si no se conecta, mensaje de error
    while(1);
  }
  Serial.println(F("Connected!"));  //conectado a la red
  Serial.println(F("Request DHCP"));
  while (!cc3000.checkDHCP())
  {
    delay(100); 
  }

  // Muestra la direccion IP , DNS, Gateway, etc:
  while (! displayConnectionDetails()) {
  delay(1000);
  // Esperar conexiones de la red
  httpServer.begin();
  Serial.println(F("Listening for connections..."));
}


/* La tercera y última parte del programa es el "void loop". Esta función se ejecuta un número indefinido de veces. Cuando se enciende nuestro controlador Arduino ejecuta el código setup y después el loop que se ejecuta indefinidamente hasta que se apague o se reinicie el controlador */

void loop(void)
{
  // Intenta conseguir un cliente que se conecte
  Adafruit_CC3000_ClientRef client = httpServer.available();
  if (client) 
  {
    Serial.println(F("Client connected."));
    // Proceso de la solicitud  hasta que se complete 

    // Elimina el buffer de datos entrantes y llévala al inicio de esta
    bufindex = 0;
    memset(&buffer, 0, sizeof(buffer));
    memset(&action, 0, sizeof(action));
    memset(&path, 0, sizeof(path));

    // Poner una interrupción para leer los datos entrantes
    unsigned long endtime = millis() + TIMEOUT_MS;
    
    // Leer los datos entrantes hasta que pueda ser analizado o la interrupción expire
    bool parsed = false;
    while (!parsed && (millis() < endtime) && (bufindex < BUFFER_SIZE)) 
    {
      if (client.available()) 
      {
        buffer[bufindex++] = client.read();
      }
      parsed = parseRequest(buffer, bufindex, action, path);
    }

  // Utilizar la solicitud si se analiza:
  if (parsed) 
  {
    Serial.println(F("Processing request"));
    Serial.print(F("Action: ")); Serial.println(action);
    Serial.print(F("Path: ")); Serial.println(path);

    if (strcmp(action, "GET") == 0) 
    {       // comprovar que la acción para ver se trata de una petición GET
      if (strstr(path,"Luces=0") != NULL) 
      {     // si llega del servidor web Luces=0; led apagado
        Luces = 0;
        Serial.print("Luces OFF\n");
        digitalWrite(7, LOW);
      }
      else if (strstr(path, "Luces=1") != NULL) 
      {   //si llega del servidor web Luces=1; led encandido
        Luces = 1;
        Serial.print("Luces ON\n");
        digitalWrite(7, HIGH);
      }
      //si llega del servidor web AccionMotor=1; motores hacia delante
      else if (strstr(path,"Accion=1") != NULL) 
      { 
        AccionMotor = 1;
        Serial.print("Accion Motor DELANTE\n");
        ServoIzq.writeMicroseconds(SERVO_FRONT);
        ServoDer.writeMicroseconds(SERVO_REAR);
      }
      //si llega del servidor web AccionMotor=2; motores hacia la izquierda
      else if (strstr(path,"Accion=2") != NULL) 
      {
        AccionMotor = 2;
        Serial.print("Accion Motor IZQUIERDA\n");
        ServoIzq.writeMicroseconds(SERVO_REAR);
        ServoDer.writeMicroseconds(SERVO_REAR);
       }
      //si llega del servidor web AccionMotor=3; motores parados
      else if (strstr(path,"Accion=3") != NULL) 
      {
        AccionMotor = 3;
        Serial.print("Accion Motor STOP\n");
        ServoIzq.writeMicroseconds(SERVO_STOP);
        ServoDer.writeMicroseconds(SERVO_STOP);
      }

      //si llega del servidor web AccionMotor=4; motores hacia la derecha
      else if (strstr(path,"Accion=4") != NULL) 
      {
        AccionMotor = 4;
        Serial.print("Accion Motor DERECHA\n");
        ServoIzq.writeMicroseconds(SERVO_FRONT);
        ServoDer.writeMicroseconds(SERVO_FRONT);
      }
      //si llega del servidor web AccionMotor=5; motores hacia atrás
      else if  (strstr(path,"Accion=5") != NULL) 
      {
        AccionMotor = 5;
        Serial.print("Accion Motor DETRAS\n");
        ServoDer.writeMicroseconds(SERVO_FRONT);
        ServoIzq.writeMicroseconds(SERVO_REAR);
      }

      /* Código HTML para la visualización de una página web simple en el servidor web */

      client.fastrprintln(F("<!DOCTYPE html>"));
      client.fastrprintln(F("<html><head><style>"));
      client.fastrprintln(F("table, th, td {border: 1px solid black; border-collapse: collapse;}"));
      client.fastrprintln(F("th, td {padding: 25px; text-align: center;}"));
      client.fastrprintln(F("</style></head>"));
      client.fastrprintln(F("<body style='background-color:lightgrey'>"));
      client.fastrprintln(F("<h1 style='color:blue'>Control de Luces</h1>"));
      client.fastrprintln(F("<table>"));
      client.fastrprintln(F("<tr>"));
      if (Luces == 1)         
        client.fastrprintln(F("<td bgcolor='#FFFF00'>"));
      else                  
        client.fastrprintln(F("<td bgcolor=lightgrey>"));
        client.fastrprintln(F("<form><input type='hidden' name='Luces' value='1'><input type='submit' value='ON'></form>"));
        client.fastrprintln(F("</td>"));
      if (Luces == 1)         
        client.fastrprintln(F("<td bgcolor='#FFFF00'>"));
      else                  
        client.fastrprintln(F("<td bgcolor=lightgrey>"));
        client.fastrprintln(F("<form><input type='hidden' name='Luces' value='0'><input type='submit' value='OFF'></form>"));
        client.fastrprintln(F("</td>"));
        client.fastrprintln(F("</tr>"));
        client.fastrprintln(F("</table>"));
        client.fastrprintln(F("<h1 style='color:blue'>Control de Motor</h1>"));
        client.fastrprintln(F("<table>"));
        client.fastrprintln(F("<tr>"));
        client.fastrprintln(F("<td></td>"));
      if (AccionMotor == 1)         
        client.fastrprintln(F("<td bgcolor='#00FF00'>"));
      else
        client.fastrprintln(F("<td bgcolor=lightgrey>"));
        client.fastrprintln(F("<form><input type='hidden' name='Accion' value='1'><input type='submit' value='DELANTE'></form>"));
        client.fastrprintln(F("</td>"));
        client.fastrprintln(F("<td></td>"));
        client.fastrprintln(F("</tr>"));
        client.fastrprintln(F("<tr>"));
      if (AccionMotor == 2)         
        client.fastrprintln(F("<td bgcolor='#00FF00'>"));
      else
        client.fastrprintln(F("<td bgcolor=lightgrey>"));
        client.fastrprintln(F("    <form><input type='hidden' name='Accion' value='2'><input type='submit' value='IZQUIERDA'></form>"));
        client.fastrprintln(F("    </td>"));
      if (AccionMotor == 3)         
        client.fastrprintln(F("<td bgcolor='#FF0000'>"));
      else
        client.fastrprintln(F("<td bgcolor=lightgrey>"));
        client.fastrprintln(F("<form><input type='hidden' name='Accion' value='3'><input type='submit' value='STOP'></form>"));
        client.fastrprintln(F("</td>"));
      if (AccionMotor == 4)         
        client.fastrprintln(F("<td bgcolor='#00FF00'>"));
      else
        client.fastrprintln(F("<td bgcolor=lightgrey>"));
        client.fastrprintln(F("<form><input type='hidden' name='Accion' value='4'><input type='submit' value='DERECHA'></form>"));
        client.fastrprintln(F("</td>"));
        client.fastrprintln(F("</tr>"));
        client.fastrprintln(F("<tr>"));
        client.fastrprintln(F("<td></td>"));
      if (AccionMotor == 5)         
        client.fastrprintln(F("<td bgcolor='#00FF00'>"));
      else
        client.fastrprintln(F("<td bgcolor=lightgrey>"));
        client.fastrprintln(F("<form><input type='hidden' name='Accion' value='5'><input type='submit' value='DETRAS'></form>"));
        client.fastrprintln(F("</td>"));
        client.fastrprintln(F("<td></td>"));
        client.fastrprintln(F("</tr>"));
        client.fastrprintln(F("</table>"));
        client.fastrprintln(F("</body></html>"));
      }
      else 
      {
       //Acción no compatible, responder con un HTTP 405 Mètoda error no permitido.  
       client.fastrprintln(F("HTTP/1.1 405 Method Not Allowed"));
       client.fastrprintln(F(""));
      }
    }

    // Espera un corto período de tiempo para asegurarse que la respuesta se ha podido enviar
    delay(100);
    // Cierra la conexión:
    Serial.println(F("Client disconnected"));
    client.close();
  }
}
bool parseRequest(uint8_t* buf, int bufSize, char* action, char* path) 
{  // Comprueba si la petición finaliza con \r \n para indicar el final de la primera línea:
  if (bufSize < 2)
    return false;
  if (buf[bufSize-2] == '\r' && buf[bufSize-1] == '\n') 
  {
    parseFirstLine((char*)buf, action, path);
    return true;
  }
  return false;
}

// Analiza la acción y la ruta de la primera línea de una petición HTTP:
void parseFirstLine(char* line, char* action, char* path) 
{  // Analiza la primera palabra hasta los espacios en blanco como una acción.
  char* lineaction = strtok(line, " ");
  if (lineaction != NULL)
    strncpy(action, lineaction, MAX_ACTION);
  // Analiza la segunda palabra hasta los espacios en blanco como una acción.
  char* linepath = strtok(NULL, " ");
  if (linepath != NULL)
    strncpy(path, linepath, MAX_PATH);
}

// Intenta leer la dirección IP y otros detalles de la conexión:
bool displayConnectionDetails(void)
{
  uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;
  if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))
  {
    Serial.println(F("Unable to retrieve the IP Address!\r\n"));
    return false;
  }
  else
  {
    Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);
    Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);
    Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);
    Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);
    Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);
    Serial.println();
    return true;
  }
}