Translate

domingo, 6 de diciembre de 2015

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;
  }
}

No hay comentarios:

Publicar un comentario