Mostrando entradas con la etiqueta Proyectos con ESP8266. Mostrar todas las entradas
Mostrando entradas con la etiqueta Proyectos con ESP8266. Mostrar todas las entradas

domingo, 29 de octubre de 2017

Proyecto #4 ESP8266 – Vehículo Controlado Por WebSocket

En este proyecto vamos a ver cómo fabricar un vehículo con un protoboard, algunas piezas impresas, dos moto-reductores para Arduino y unas pocas piezas más. El vehículo está conectado a un NodeMCU mediante un driver L293D, el ESP8266 está funcionado en modo SoftAP y tiene alojado un webserver con websokets, lo que permite controlar el vehículo, sin latencia, desde una aplicación web basada en JavaScript.


Lista de Materiales:

1) NodeMCU (ESP8266)
1) L293D
1) Cargador USB portátil 5V 5600mah
1) Cable USB
2) Motor DC 3v A 6v caja reductora rueda goma para Arduino
2) Rodamientos 624zz
2) Tornilos de 5/32"W x 5/8 (ó M4x16)
2) Tuercas de 5/32"W (ó M4)
2) Arandelas grower de 5/32" 
1) Protoboard 830 puntos
1) Piezas impresas en 3D (https://www.thingiverse.com/thing:2614185)
5) Presintos de 3,6 x 200mm

vehiculo:

#include <ESP8266WiFi.h>
#include <WebSocketsServer.h>
#include <ESP8266WebServer.h>

#define PWM_IZQ     05 // D1
#define PWM_DER     04 // D2

#define IZQ_AVZ     14 // D5
#define IZQ_RET     12 // D6
#define DER_AVZ     13 // D7
#define DER_RET     02 // D4

const char* ssid = "Vehiculo";
const char* password = "asdfghjk";

String pagina ="<html>"
"<head>"
"<style type='text/css'>"
"* { margin: 0px; padding: 20px; }"
"#avz, #ret { width: 100%; height: 33%; }"
"#izq, #der { width:  49.7%; height: 33% }"
"input[type=range] { height: 26px; -webkit-appearance: none; margin: 10px 0; width: 120px; }"
"input[type=range]:focus { outline: none; }"
"input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 50px; cursor: pointer; animate: 0.2s; box-shadow: 1px 1px 1px #50555C; "
"  background: #50555C; border-radius: 25px; border: 0px solid #000000; }"
"input[type=range]::-webkit-slider-thumb { box-shadow: 0px 0px 0px #000000; border: 0px solid #000000; height: 80px; width: 80px; border-radius: 25px;"
"      background: #007FFF; cursor: pointer; -webkit-appearance: none; margin-top: -15px; }"
"input[type=range]:focus::-webkit-slider-runnable-track { background: #50555C; }"
"input[type=range]:focus::-ms-fill-lower { background: #50555C; }"
"input[type=range]:focus::-ms-fill-upper { background: #50555C; }"
"</style>"
"<script>"
"var connection = new WebSocket('ws://'+location.hostname+':81/', ['arduino']);"
"connection.onopen = function ()       { connection.send('Connect ' + new Date()); };"
"connection.onerror = function (error) { console.log('WebSocket Error ', error);};"
"connection.onmessage = function (e)   { console.log('Server: ', e.data);};"
"function sendAvz() {"
"var avz = parseInt(document.getElementById('avz').value);"
"var dir = '#';"
"if(avz < 16) {  dir = dir + '+' + avz.toString(16) + '+f'; }"
"if(avz >= 16) { avz = 31 - avz; dir = dir + '+f+' + avz.toString(16); }"
"console.log(dir);"
"connection.send(dir);"
"}"
"function sendIzq() {"
"var izq = parseInt(document.getElementById('izq').value);"
"izq = 15 - izq;"
"var dir = '#';"
"dir = dir + '-' + izq.toString(16) + '+' + izq.toString(16);" 
"console.log(dir);"
"connection.send(dir);"
"}"
"function sendDer() {"
"var der = parseInt(document.getElementById('der').value);"
"var dir = '#';"
"dir = dir + '+' + der.toString(16) + '-' + der.toString(16);"
"console.log(dir);"
"connection.send(dir);"
"}"
"function sendRet() {"
"var ret = parseInt(document.getElementById('ret').value);"
"var dir = '#';"
"if(ret < 16) {  dir = dir + '-' + ret.toString(16) + '-f'; }"
"if(ret >= 16) { ret = 31 - ret; dir = dir + '-f-' + ret.toString(16); }"
"console.log(dir);"
"connection.send(dir);"
"}"
"function SendParar() { console.log('#+0+0'); connection.send('#+0+0'); }"
"</script>"
"</head>"
"<body>"
"<input id='avz' type='range' min='0' max='31' step='1' value='16' oninput='sendAvz();' onmouseup='SendParar();' ontouchend='SendParar();'/>"
"<input id='izq' type='range' min='0' max='15' step='1' value='16' oninput='sendIzq();' onmouseup='SendParar();' ontouchend='SendParar();'/>"
"<input id='der' type='range' min='0' max='15' step='1' value='0'  oninput='sendDer();' onmouseup='SendParar();' ontouchend='SendParar();'/>"
"<input id='ret' type='range' min='0' max='31' step='1' value='16' oninput='sendRet();' onmouseup='SendParar();' ontouchend='SendParar();'/>"
"</body>"
"</html>";

ESP8266WebServer server = ESP8266WebServer(80);
WebSocketsServer webSocket = WebSocketsServer(81);

void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {

    switch(type) {
        case WStype_DISCONNECTED:
            Serial.printf("[%u] Disconnected!\n", num);
            analogWrite(PWM_IZQ, 0);
            analogWrite(PWM_DER, 0);
            break;
        case WStype_CONNECTED: {
            IPAddress ip = webSocket.remoteIP(num);
            Serial.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);

            // send message to client
            webSocket.sendTXT(num, "Connected");
        }
            break;
        case WStype_TEXT:
            Serial.printf("[%u] get Text: %s\n", num, payload);

            if(payload[0] == '#') {
                if(payload[1] == '+') {
                  digitalWrite(IZQ_AVZ,  0);
                  digitalWrite(IZQ_RET,  1);
                }
                if(payload[1] == '-') {
                  digitalWrite(IZQ_AVZ,  1);
                  digitalWrite(IZQ_RET,  0);
                }
                if(payload[3] == '+') {
                  digitalWrite(DER_AVZ,  0);
                  digitalWrite(DER_RET,  1);
                }
                if(payload[3] == '-') {
                  digitalWrite(DER_AVZ,  1);
                  digitalWrite(DER_RET,  0);
                }
                uint8_t izq = (uint8_t) strtol((const char *) &payload[2], NULL, 16);
                uint8_t der = (uint8_t) strtol((const char *) &payload[4], NULL, 16);

                analogWrite(PWM_IZQ, izq);
                analogWrite(PWM_DER, der);
            }
            break;
    }
}

void setup() {
  Serial.begin(115200);
  Serial.println();

  WiFi.softAP(ssid, password);
  IPAddress myIP = WiFi.softAPIP(); 
  Serial.print("IP del access point: ");
  Serial.println(myIP);
  Serial.println("WebServer iniciado...");

  pinMode(PWM_IZQ, OUTPUT);
  pinMode(PWM_DER, OUTPUT);
  pinMode(IZQ_AVZ, OUTPUT);
  pinMode(IZQ_RET, OUTPUT);
  pinMode(DER_AVZ, OUTPUT);
  pinMode(DER_RET, OUTPUT);

  // start webSocket server
  webSocket.begin();
  webSocket.onEvent(webSocketEvent);

  // handle index
  server.on("/", []() {
      server.send(200, "text/html", pagina);
  });

  server.begin();

  digitalWrite(PWM_IZQ, 0);
  digitalWrite(PWM_DER, 0);
  digitalWrite(IZQ_AVZ,  1);
  digitalWrite(IZQ_RET,  1);
  digitalWrite(DER_AVZ,  1);
  digitalWrite(DER_RET,  1);

  analogWriteRange(15);
}

void loop() {
    webSocket.loop();
    server.handleClient();
}

domingo, 22 de octubre de 2017

Proyecto #3 ESP8266 – Manipular Modelo 3D con MPU6050 (PHP + WebGL + Three.js)

En este proyecto vamos a ver una aplicación completa de IOT (Internet de las cosas), en la que explico cómo usar un NodeMCU (ESP8266) para trasmitir mediante datagramas UDP de forma inalámbrica, la inclinación que leen los acelerómetros y los giroscopios de un MPU6050; pasando por un filtro complementario y de esa manera poder manipular un modelo 3D representado en un navegador web que sea compatible con WebGL. Para todo esto eso vamos a utilizar la IDE de Arduino, HTML5, PHP, la librería de JavaScript Three.js y varias cosas más.



mpu6050udp:

#include <Wire.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

WiFiUDP Udp;

const char* ssid = "-----";
const char* password = "-----";
int contconexion = 0;

//Direccion I2C de la IMU
#define MPU 0x68
 
//Ratios de conversion
#define A_R 16384.0 // 32768/2
#define G_R 131.0 // 32768/250
 
//Conversion de radianes a grados 180/PI
#define RAD_A_DEG = 57.295779

//MPU-6050 da los valores en enteros de 16 bits
//Valores RAW
int16_t AcX, AcY, AcZ, GyX, GyY, GyZ;
 
//Angulos
float Acc[2];
float Gy[3];
float Angle[3];

String valores;

long tiempo_prev;
float dt;

void setup()
{
  Wire.begin(4,5); // D2(GPIO4)=SDA / D1(GPIO5)=SCL
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);
  Wire.write(0);
  Wire.endTransmission(true);

  Serial.begin(115200);
  Serial.println();

  WiFi.mode(WIFI_STA); //para que no inicie el SoftAP en el modo normal
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED and contconexion <50) { //Cuenta hasta 50 si no se puede conectar lo cancela
    ++contconexion;
    delay(500);
    Serial.print(".");
  }
  if (contconexion <50) {
      //para usar con ip fija
      IPAddress Ip(192,168,1,180); 
      IPAddress Gateway(192,168,1,1); 
      IPAddress Subnet(255,255,255,0); 
      WiFi.config(Ip, Gateway, Subnet); 
      
      Serial.println("");
      Serial.println("WiFi conectado");
      Serial.println(WiFi.localIP());
  }
  else { 
      Serial.println("");
      Serial.println("Error de conexion");
  }
}

void loop()
{
      
  //Leer los valores del Acelerometro de la IMU
  Wire.beginTransmission(MPU);
  Wire.write(0x3B); //Pedir el registro 0x3B - corresponde al AcX
  Wire.endTransmission(false);
  Wire.requestFrom(MPU,6,true);   //A partir del 0x3B, se piden 6 registros
  AcX=Wire.read()<<8|Wire.read(); //Cada valor ocupa 2 registros
  AcY=Wire.read()<<8|Wire.read();
  AcZ=Wire.read()<<8|Wire.read();
 
  //A partir de los valores del acelerometro, se calculan los angulos Y, X
  //respectivamente, con la formula de la tangente.
  Acc[1] = atan(-1*(AcX/A_R)/sqrt(pow((AcY/A_R),2) + pow((AcZ/A_R),2)))*RAD_TO_DEG;
  Acc[0] = atan((AcY/A_R)/sqrt(pow((AcX/A_R),2) + pow((AcZ/A_R),2)))*RAD_TO_DEG;
 
  //Leer los valores del Giroscopio
  Wire.beginTransmission(MPU);
  Wire.write(0x43);
  Wire.endTransmission(false);
  Wire.requestFrom(MPU,6,true);   //A partir del 0x43, se piden 6 registros
  GyX=Wire.read()<<8|Wire.read(); //Cada valor ocupa 2 registros
  GyY=Wire.read()<<8|Wire.read();
  GyZ=Wire.read()<<8|Wire.read();
 
  //Calculo del angulo del Giroscopio
  Gy[0] = GyX/G_R;
  Gy[1] = GyY/G_R;
  Gy[2] = GyZ/G_R;
    
  dt = (millis() - tiempo_prev) / 1000.0;
  tiempo_prev = millis();
    
  //Aplicar el Filtro Complementario
  Angle[0] = 0.98 *(Angle[0]+Gy[0]*dt) + 0.02*Acc[0];
  Angle[1] = 0.98 *(Angle[1]+Gy[1]*dt) + 0.02*Acc[1]; 

  //Integración respecto del tiempo paras calcular el YAW
  Angle[2] = Angle[2]+Gy[2]*dt;
 
  //Mostrar los valores por consola
  valores = String(Angle[0]) + "," + String(Angle[1]) + "," + String(Angle[2]);

  //Armar los paquetes UDP  
  Udp.beginPacket("192.168.1.101", 245);
  for(int i=0; i<valores.length();i++){
    Udp.write(byte(valores[i]));  
  }
  Udp.endPacket();
  
  delay(10);
}

Uniform Server 8.9.2 Coral

a380.stl

proyecto3.zip

lunes, 18 de septiembre de 2017

Proyecto #2 ESP8266 – Control Remoto Universal - Versión 1

En este proyecto de IOT (internet de las cosas), explico cómo en realizar un control remoto infrarrojo (IR) universal utilizando un ESP8266. Primero se capturan los datos enviados por diversos controles remotos, utilizando un receptor de 38Khz (VS1838B), para luego ser transmitidos mediante un LED infrarrojo. El dispositivo es controlado desde un servidor web que está alojado dentro del ESP8266, lo que posibilita acceder desde cualquier dispositivo (PC, Smartphone, Tablet, etc.) que estén conectados en la red LAN.






Lista de Materiales:

1) NodeMCU (ESP8266)
1) VS1838B
1) LED Infrarrojo
1) Transistor BC337
1) Resistencia de 100
1) Resistencia de 1K

lecturaCRemoto:

uint16_t datos[50];

void setup() {
  Serial.begin(115200);
  Serial.println("");
  Serial.println("");
  pinMode(5, INPUT);  // D1
}

void loop() {
  if (digitalRead(5) == 0) {
    for (int i=0; i <= 48; i = i + 2){
      uint16_t old = micros();
      while (digitalRead(5) == 0 and datos[i] < 32000) { //lee los valores bajos (caundo llega señal) - 32000 indica que desbordó
         datos[i] = micros() - old;
      }
      old = micros();
      while (digitalRead(5) == 1 and datos[i+1] < 32000) { //lee los valores altos (caundo NO llega señal) - 32000 indica que desbordó
        datos[i+1] = micros() - old;
      }
    }
    Serial.println("");
    
    int j = 0;
    while (datos[j] < 20000) { // buscar el último bit, es decir que desbordó o el control remoto envió un bit de parada (21000uSec aprox.)
      j = j + 1;
    }
    
    Serial.print("int datosEnviar[" + String(j) + "] = {"); //imprimo el array hasta el último valor
    for (int i=0; i < j; i++){
      Serial.print(datos[i]);
      if (i != j-1) {
        Serial.print(","); //coloca la coma en todos los valores menos el último
      }
    }
    Serial.println("};");
    
    for (int i=0; i <= 50; i++){ // limpio el array
      datos[i] = 0;
    }
    delay(500);
  }
}


controlRemoto:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

const char* ssid = "____";
const char* password = "____";
int contconexion = 0;

int datos[50];
boolean bandera = true;

ESP8266WebServer server(80);

//----------------------------------------------------------------------------------
String principal = "<!DOCTYPE html>"
"<html>"
"<head>"
"<title>Control Remoto</title>"
"<meta charset='UTF-8'>"
"<style type='text/css'>"
"*{margin: 5px; padding: 5px;}"
"span {float: left; width: 150px;}"
".boton {width: 800px; height:250px; font-family: sans-serif; font-size: 50px;}"
"</style>"
"</head>"
"<body>"
"<a href='tv'><button class='boton'>TV</button></a><br><br>"
"<a href='pc'><button class='boton'>PC</button></a><br>"
"</body>"
"</html>";

String tv = "<!DOCTYPE html>"
"<html>"
"<head>"
"<title>Control Remoto - TV</title>"
"<meta charset='UTF-8'>"
"<style type='text/css'>"
"*{margin: 5px; padding: 5px;}"
"span {float: left; width: 150px;}"
".boton {width: 250px; height:250px; font-family: sans-serif; font-size: 50px;}"
"</style>"
"</head>"
"<body>"
"<table>"
"<tr>"
"<td><a href='power'><button class='boton'>POWER</button></td>"
"<td></td>"
"<td><a href='mute'><button class='boton'>MUTE</button></td>"
"</tr>"
"<tr>"
"<td></td>"
"<td><a href='masCh'><button class='boton'>+CH</button></td>"
"<td></td>"
"</tr>"
"<tr>"
"<td><a href='menosVol'><button class='boton'>-VOL</button></td>"
"<td><a href='/'><button class='boton'>HOME</td>"
"<td><a href='masVol'><button class='boton'>+VOL</button></td>"
"</tr>"
"<tr>"
"<td></td>"
"<td><a href='menosCh'><button class='boton'>-CH</button></td>"
"<td></td>"
"</tr>"
"</table>"
"</body>"
"</html>";

String pc = "<!DOCTYPE html>"
"<html>"
"<head>"
"<title>Control Remoto - TV</title>"
"<meta charset='UTF-8'>"
"<style type='text/css'>"
"*{margin: 5px; padding: 5px;}"
"span {float: left; width: 150px;}"
".boton {width: 250px; height:250px; font-family: sans-serif; font-size: 50px;}"
"</style>"
"</head>"
"<body>"
"<table>"
"<tr>"
"<td><a href='clicL'><button class='boton'>L</button></td>"
"<td></td>"
"<td><a href='clicR'><button class='boton'>R</button></td>"
"</tr>"
"<tr>"
"<td></td>"
"<td><a href='subir'><button class='boton'>^</button></td>"
"<td></td>"
"</tr>"
"<tr>"
"<td><a href='izq'><button class='boton'><</button></td>"
"<td><a href='/'><button class='boton'>HOME</td>"
"<td><a href='der'><button class='boton'>></button></td>"
"</tr>"
"<tr>"
"<td></td>"
"<td><a href='bajar'><button class='boton'>v</button></td>"
"<td></td>"
"</tr>"
"</table>"
"</body>"
"</html>";

//----------------------------------------------------------------------------------
void paginaPrincipal() {
  server.send(200, "text/html", principal); 
}
void paginaPc() {
  server.send(200, "text/html", pc); 
}
void paginaTv() {
  server.send(200, "text/html", tv); 
}

//----------------------------------------------------------------------------------
void teclaPower() {
  Serial.println("Power");
  int datosEnviar[23] = {844,961,1701,921,855,920,853,920,854,919,857,961,812,961,812,947,828,1807,855,947,1716,946,828};
  int datosEnviar2[23] = {844,948,827,947,1714,949,827,947,827,947,828,948,828,945,828,946,827,1836,826,949,1716,946,827};
  if (bandera) {
    for (int i=0; i <= sizeof(datosEnviar)/sizeof(datosEnviar[0]); i++){ // sizeof(datosEnviar)/sizeof(datosEnviar[0] es la cantidad de elementos en el array
      datos[i] = datosEnviar[i];
    }
    bandera = false;
  }
  else {
    for (int i=0; i <= sizeof(datosEnviar2)/sizeof(datosEnviar2[0]); i++){ 
      datos[i] = datosEnviar2[i];
    }
    bandera = true;
  }
  enviar();
  server.send(200, "text/html", tv); 
}
void teclaMute() {
  Serial.println("Mute");
  int datosEnviar[23] = {882,951,1712,951,823,925,849,951,824,951,823,951,821,926,850,925,850,1814,849,951,1710,1813,850};
  int datosEnviar2[23] = {840,925,850,926,1737,952,821,926,850,923,850,927,848,924,850,926,849,1814,849,924,1740,1812,848};
  if (bandera) {
    for (int i=0; i <= sizeof(datosEnviar)/sizeof(datosEnviar[0]); i++){ 
      datos[i] = datosEnviar[i];
    }
    bandera = false;
  }
  else {
    for (int i=0; i <= sizeof(datosEnviar2)/sizeof(datosEnviar2[0]); i++){ 
      datos[i] = datosEnviar2[i];
    }
    bandera = true;
  }
  enviar();
  server.send(200, "text/html", tv); 
}
void teclaMasCh() {
  Serial.println("MasCh");
  int datosEnviar[23] = {847,961,1701,947,826,962,814,962,811,949,828,961,812,1849,1701,961,813,919,855,960,814,960,813};
  int datosEnviar2[23] = {848,963,813,947,1716,947,828,947,827,961,811,950,827,1850,1700,947,828,962,812,960,813,963,812};
  if (bandera) {
    for (int i=0; i <= sizeof(datosEnviar)/sizeof(datosEnviar[0]); i++){ 
      datos[i] = datosEnviar[i];
    }
    bandera = false;
  }
  else {
    for (int i=0; i <= sizeof(datosEnviar2)/sizeof(datosEnviar2[0]); i++){ 
      datos[i] = datosEnviar2[i];
    }
    bandera = true;
  }
  enviar();
  server.send(200, "text/html", tv); 
}
void teclaMenosCh() {
  Serial.println("MenosCh"); 
  int datosEnviar[23] = {844,947,1740,923,825,949,827,947,827,948,825,948,827,1836,1740,922,827,947,827,948,825,1835,828};
  int datosEnviar2[23] = {845,947,828,947,1739,925,827,947,827,947,827,949,825,1837,1739,922,828,947,826,946,828,1835,827};
  if (bandera) {
    for (int i=0; i <= sizeof(datosEnviar)/sizeof(datosEnviar[0]); i++){ 
      datos[i] = datosEnviar[i];
    }
    bandera = false;
  }
  else {
    for (int i=0; i <= sizeof(datosEnviar2)/sizeof(datosEnviar2[0]); i++){ 
      datos[i] = datosEnviar2[i];
    }
    bandera = true;
  }
  enviar();
  server.send(200, "text/html", tv); 
}
void teclaMasVol() {
  Serial.println("MasVol");
  int datosEnviar[23] = {869,923,1741,921,851,923,852,923,826,948,845,931,841,931,851,1812,1741,922,851,922,829,945,853};
  int datosEnviar2[23] = {882,921,830,944,1742,923,851,921,827,949,827,947,852,923,851,1809,1740,923,832,943,851,923,827};
  if (bandera) {
    for (int i=0; i <= sizeof(datosEnviar)/sizeof(datosEnviar[0]); i++){ 
      datos[i] = datosEnviar[i];
    }
    bandera = false;
  }
  else {
    for (int i=0; i <= sizeof(datosEnviar2)/sizeof(datosEnviar2[0]); i++){ 
      datos[i] = datosEnviar2[i];
    }
    bandera = true;
  }
  enviar();
  server.send(200, "text/html", tv); 
}
void teclaMenosVol() {
  Serial.println("MenosVol");
  int datosEnviar[23] = {846,947,1742,922,850,924,827,947,827,949,833,941,851,922,827,1836,1741,922,828,947,850,1811,828};
  int datosEnviar2[23] = {858,931,850,924,1740,923,828,947,850,923,852,924,826,948,851,1811,1740,922,852,922,828,1835,827};
  if (bandera) {
    for (int i=0; i <= sizeof(datosEnviar)/sizeof(datosEnviar[0]); i++){ 
      datos[i] = datosEnviar[i];
    }
    bandera = false;
  }
  else {
    for (int i=0; i <= sizeof(datosEnviar2)/sizeof(datosEnviar2[0]); i++){ 
      datos[i] = datosEnviar2[i];
    }
    bandera = true;
  }
  enviar();
  server.send(200, "text/html", tv); 
}

//----------------------------------------------------------------------------------
void teclaClicL() {
  Serial.println("ClicL");
  int datosEnviar[33] = {238,1875,262,1851,263,1851,232,822,261,793,262,794,261,1849,264,793,259,1849,264,794,260,793,263,1849,262,791,262,794,259,793,263,789,234};
  for (int i=0; i <= sizeof(datosEnviar)/sizeof(datosEnviar[0]); i++){ 
    datos[i] = datosEnviar[i];
  }
  enviar();
  server.send(200, "text/html", pc); 
}
void teclaClicR() {
  Serial.println("ClicR");
  int datosEnviar[33] = {216,1886,226,1888,224,1889,222,831,222,860,194,832,223,1916,195,830,222,835,221,860,194,1888,222,832,222,861,193,834,219,833,224,859,195};
  for (int i=0; i <= sizeof(datosEnviar)/sizeof(datosEnviar[0]); i++){ 
    datos[i] = datosEnviar[i];
  }
  enviar();
  server.send(200, "text/html", pc); 
}
void teclaSubir() {
  Serial.println("Subir");
  int datosEnviar[33] = {223,1880,231,1881,231,1880,232,824,230,824,230,851,206,1879,231,836,218,1881,230,824,232,825,230,824,231,823,231,851,203,824,231,824,230};
  for (int i=0; i <= sizeof(datosEnviar)/sizeof(datosEnviar[0]); i++){ 
    datos[i] = datosEnviar[i];
  }
  enviar();
  server.send(200, "text/html", pc); 
}
void teclaBajar() {
  Serial.println("Bajar");
  int datosEnviar[33] = {219,1880,232,1880,231,1881,231,824,231,824,231,826,229,1882,229,825,230,824,230,1882,230,825,230,822,232,825,230,824,230,825,231,823,230};
  for (int i=0; i <= sizeof(datosEnviar)/sizeof(datosEnviar[0]); i++){ 
    datos[i] = datosEnviar[i];
  }
  enviar();
  server.send(200, "text/html", pc); 
}
void teclaIzq() {
  Serial.println("Izq");
  int datosEnviar[33] = {217,1882,230,1880,232,1882,230,852,203,850,204,827,229,1862,250,836,218,1881,232,849,205,1865,247,1881,230,851,204,851,204,850,205,850,202};
  for (int i=0; i <= sizeof(datosEnviar)/sizeof(datosEnviar[0]); i++){ 
    datos[i] = datosEnviar[i];
  }
  enviar();
  server.send(200, "text/html", pc); 
}
void teclaDer() {
  Serial.println("Der");
  int datosEnviar[33] = {243,1858,253,1856,230,1882,230,826,255,799,231,826,230,1881,230,826,230,835,220,833,223,1891,219,1891,222,832,221,834,223,830,223,832,219};
  for (int i=0; i <= sizeof(datosEnviar)/sizeof(datosEnviar[0]); i++){ 
    datos[i] = datosEnviar[i];
  }
  enviar();
  server.send(200, "text/html", pc); 
}

//----------------------------------------------------------------------------------
void enviar() {
  for (int i=0; i <= 48; i = i + 2){
    int old = micros();
    while (micros() - old < datos[i]){ //envia los valores altos modulados a 38khz
      digitalWrite(4, 1);
      delayMicroseconds(9); // 1/38000 = 26 uSec... 26/2 = 13 uSec - 4uSec(para otros procesos)= 9 uSec
      digitalWrite(4, 0);
      delayMicroseconds(9);
    };
    old = micros();
    while (micros() - old < datos[i+1]){ //envío los valores bajos
      digitalWrite(4, 0);
      delayMicroseconds(9);
      digitalWrite(4, 0);
      delayMicroseconds(9);
    };
  }
  
  for (int i=0; i <= 50; i++){ //limpio el array
    datos[i] = 0;
  };
}

//----------------------------------------------------------------------------------
void setup() {
  Serial.begin(115200);
  Serial.println("");
  Serial.println("");
  pinMode(5, INPUT);  // D1 Receptor
  pinMode(4, OUTPUT); // D2 Emisor
  
  digitalWrite(4, 0);
  
  WiFi.mode(WIFI_STA); //para que no inicie solamente en modo estación
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED and contconexion <50) { //Cuenta hasta 50 si no se puede conectar lo cancela
    ++contconexion;
    Serial.print(".");
    delay(500);
  }
  if (contconexion <50) {
      //para usar con ip fija
      IPAddress Ip(192,168,1,180); 
      IPAddress Gateway(192,168,1,1); 
      IPAddress Subnet(255,255,255,0); 
      WiFi.config(Ip, Gateway, Subnet); 
      
      Serial.println("");
      Serial.println("WiFi conectado");
      Serial.println(WiFi.localIP());
          
      Serial.println("WebServer iniciado...");

      server.on("/", paginaPrincipal);
      server.on("/pc", paginaPc);
      server.on("/tv", paginaTv); 

      server.on("/power", teclaPower);
      server.on("/mute", teclaMute); 
      server.on("/masCh", teclaMasCh); 
      server.on("/menosCh", teclaMenosCh); 
      server.on("/masVol", teclaMasVol); 
      server.on("/menosVol", teclaMenosVol); 

      server.on("/clicL", teclaClicL);
      server.on("/clicR", teclaClicR); 
      server.on("/subir", teclaSubir); 
      server.on("/bajar", teclaBajar); 
      server.on("/izq", teclaIzq); 
      server.on("/der", teclaDer);    
      
      server.begin(); //incia el webserver
      
  }
  else { 
      Serial.println("");
      Serial.println("Error de conexion");
  }
}

//----------------------------------------------------------------------------------
void loop() {
  server.handleClient();   
}

https://www.eevblog.com
https://www.youtube.com/user/EEVblog
https://github.com/markszabo/IRremoteESP8266