Wednesday, April 3, 2013

Arduino + Android: Como controlar un Aire Acondicionado

Para mi primer proyecto de Arduino y Android decidí controlar mi aire acondicionado con receptor infrarrojo con una aplicación de android en mi celular desde cualquier lugar que me encuentre que tenga acceso a internet.

Video del resultado final




Este proceso lo realicé en un ambiente Windows pero es lo mismo para Linux.

Aquí les explicaré como lo logré.

Prerequisitos:
- Aire Acondicionado
- Control remoto del aire acondicionado (Tiene que funcionar para poder decodificar el IR)

Hardware: 
- Arduino MEGA 2560  - Lo compré aquí
- Arduino compatible Ethernet Shield  Lo compré aquí
- Small breadboard Lo compré aquí
Jumper Cables Lo compré aquí
(1) IR Receiver Diode Lo compré aquí
- (1) IR LED Lo compré aquí

Software:
- Arduino SDK - http://arduino.cc/en/main/software
- IR Remote Arduino Library - Descarga (Site oficial del autor de esta librería)


Ya estamos listos!

Primero añadimos (unzip) las librerias que descargamos la carpeta de libraries donde se instaló el SDK de Arduino. 
X:\...\arduino-1.0.4\libraries
Luego nos aseguramos que el Arduino este conectado a la computadora y que Windows haya instalado bien el driver.

Ahora tenemos que decirle al SDK que board y que puerto de comunicación utilizaremos.

Tools > Board > Arduino Mega 2560 or Mega ADK

Tools > Serial Port > (El puerto donde se haya detectado tu arduino)

Ahora tenemos que conectar el IR Receiver al Arduino de la siguiente manera:

Pin 1 va al pin 19 del Arduino.
Pin 2 va al pin de Ground.
Pin 3 va al pin de 5V.

Ilustración:

Luego copiamos este sketch en el Arduino SDK. 

/*
 * IRremote: IRrecvDump - dump details of IR codes with IRrecv
 * An IR detector/demodulator must be connected to the input RECV_PIN.
 * Version 0.1 July, 2009
 * Copyright 2009 Ken Shirriff
 * http://arcfn.com
 * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
 */

#include <IRremote.h>

int RECV_PIN = 19;

IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}

// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
// void * to work around compiler issue
//void dump(void *v) {
//  decode_results *results = (decode_results *)v
void dump(decode_results *results) {
  int count = results->rawlen;
  if (results->decode_type == UNKNOWN) {
    Serial.print("Unknown encoding: ");
  } 
  else if (results->decode_type == NEC) {
    Serial.print("Decoded NEC: ");
  } 
  else if (results->decode_type == SONY) {
    Serial.print("Decoded SONY: ");
  } 
  else if (results->decode_type == RC5) {
    Serial.print("Decoded RC5: ");
  } 
  else if (results->decode_type == RC6) {
    Serial.print("Decoded RC6: ");
  }
  else if (results->decode_type == PANASONIC) { 
    Serial.print("Decoded PANASONIC - Address: ");
    Serial.print(results->panasonicAddress,HEX);
    Serial.print(" Value: ");
  }
  else if (results->decode_type == JVC) {
     Serial.print("Decoded JVC: ");
  }
  Serial.print(results->value, HEX);
  Serial.print(" (");
  Serial.print(results->bits, DEC);
  Serial.println(" bits)");
  Serial.print("Raw (");
  Serial.print(count, DEC);
  Serial.print("): ");

  for (int i = 0; i < count; i++) {
    if ((i % 2) == 1) {
      Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
    } 
    else {
      Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
    }
    Serial.print(" ");
  }
  Serial.println("");
}


void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    dump(&results);
    irrecv.resume(); // Receive the next value
  }
}
Quedará algo así:


Oprimimos  (verify) para que se valide/compile el código y luego 
 (upload) para que suba a nuestro Arduino.

En este momento debes ir a al menú de Tools y abrir el Serial Monitor. Luego de que lo abras, con el control remoto del aire acondicionado apunta al IR Receiver y aprietas los botones uno a uno. Obtendrás algo así:


En este caso el control de mi AC resultó ser uno marca NEC con los siguientes codigos:

Decoded NEC: 80FF48B7 (32 bits) - AC ON
Decoded NEC: 80FFC837 (32 bits) - TEMP UP
Decoded NEC: 80FF58A7 (32 bits) - TEMP DOWN
Decoded NEC: 80FFD827 (32 bits) - TIMER

Ya tenemos una parte completada. Ahora hacemos otro sketch, esta ves para implementar el webserver que nos va a ayudar a ejecutar los comandos en el arduino. Para hacer esto utilicé y modifiqué el ejemplo de Web_Demo de la librería de Webduino.

Aqui debes asegurarte de definir las siguientes cosas:

-Tengas el EthernetShield ya instalado en tu MEGA 2560.
-Debes definir el MAC Address de tu Ethernet Shield y su IP.
-Debes definir el puerto donde el webserver estará corriendo.
-Debes cambiar los comandos infrarrojos por los que obtuviste.
-El IR LED debe estar en el arduino con el ánodo (negativo) en GRD y el cátodo (patita mas larga, positivo) en el pin #9.



* Web_Demo.pde -- sample code for Webduino server library */

/*
 * To use this demo,  enter one of the following USLs into your browser.
 * Replace "host" with the IP address assigned to the Arduino.
 *
 * http://host/
 * http://host/acOn
 *
 * This URL turns on the Air Conditioner
 * 
 */

#include "SPI.h"
#include "Ethernet.h"
#include "WebServer.h"
#include <IRremote.h>


// no-cost stream operator as described at 
// http://sundial.org/arduino/?page_id=119
template<class T>
inline Print &operator <<(Print &obj, T arg)
{ obj.print(arg); return obj; }

//IR Variable declaration
IRsend irsend;

// CHANGE THIS TO YOUR OWN UNIQUE VALUE
static uint8_t mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

// CHANGE THIS TO MATCH YOUR HOST NETWORK
static uint8_t ip[] = { 192, 168, 1, X };

#define PREFIX ""

WebServer webserver(PREFIX, 80 ); //ASSIGN PORT HERE

// commands are functions that get called by the webserver framework
// they send the IR Code to the AC

void acOn(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  if (type == WebServer::POST)
  {
    server.httpFail();
    return;
  }

  //server.httpSuccess(false, "application/acOn");
  server.httpSuccess();

  //Replace for your IR Code here. 
  irsend.sendNEC(0x80FF48B7, 32); //irsend.send(IRTYPE)(0x(IRCODE), (BITS)); 
  delay(40);
}

void tempUp(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  if (type == WebServer::POST)
  {
    server.httpFail();
    return;
  }

  server.httpSuccess();
  
 //Replace for your IR Code here. 
  irsend.sendNEC(0x80FFC8A7, 32); //irsend.send(COMPANYIR)(0x(IRCODE), (BITS)); 
  delay(40);
 
}

void tempDown(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  if (type == WebServer::POST)
  {
    server.httpFail();
    return;
  }

  server.httpSuccess();

  //Replace for your IR Code here.
  irsend.sendNEC(0x80FF5837, 32); // 
  delay(40);
}


void timer(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  if (type == WebServer::POST)
  {
    server.httpFail();
    return;
  }

  server.httpSuccess();

  //Replace for your IR Code here.
  irsend.sendNEC(0x80FFD827, 32); // 
  delay(40);
}


void setup()
{

  Ethernet.begin(mac, ip);
  webserver.begin();

//Rename the commands to your liking
  webserver.addCommand("acon", &acOn);
  webserver.addCommand("tempup", &tempUp);
  webserver.addCommand("tempdown", &tempDown);
  webserver.addCommand("timer", &timer);
}

void loop()
{
  // process incoming connections one at a time forever
  webserver.processConnection();

  // if you wanted to do other work based on a connecton, it would go here
}



Oprimimos  (verify) para que se valide/compile el código y luego 
 (upload) para que suba a nuestro Arduino.


En este momento ya puedes manejar tu aire acondicionado desde el web browser de alguna computadora conectada a tu misma red. Con poner (IP simulado) http://192.168.1.20/acon  el aire acondicionado debe prender.

Ahora esto es opcional y bajo su reponsabilidad por las posibles consecuencias de seguridad que pueda traer. Para poder manejar el arduino de cualquier lugar en el internet necesitaremos hacer una regla de "Port Forward" en nuestro router. La misma debe contener el IP del arduino y el puerto escogido para el webserver. Les recomiendo que utilicen un puerto que no sea el 80.

Luego de que hagan esa regla van a poder acceder el webserver en el arduino desde el internet y no limitado a su network.

La aplicación de android no es realmente necesaria pues ya puedes controlar el aire desde tu web browser desde el internet. Pero es mas interesante (y se ve mas cool) tener un app para esto.

Soy un beginner programando en android asi que muchas de las cosas que hice lo mas probable se pueden hacer de una manera mas efectiva.

Aquí les dejo el projecto de la aplicación de Android: Descarga

Modifiquenla de acuerdo a su setup y ya!


Cualquier pregunta dejenme saber!