encender led desde web alojada en mi SD

Hola, he buscado en google y la verdad que estoy mareado por la informacion y desinformacion que hay a la vez... Tengo una placa arduino y una ethernet shield con microSD. Tengo la web en mi uSD y la levanto perfectamente, el punto es que no tengo idea como hacer para que el boton de encender y apagar el led funcione... Se que hay que hacer algo en AJAX y hay algo de info en una web en ingles...
Si alguien pudiera darme una mano agradeceria de antemano...

Saludos!

1 Like

La forma que yo utilizo es enviar un string desde la interfaz web y recibirlo con arduino entonces si recibe el string prender, prende el led y si recibe el string apagar apaga el led ! de esa forma me funciona perfectamente

te dejo un link donde usan esta misma forma que te comento !

Link prender led por petición html

1 Like

mafesolutions, lo que me pasaste en el link lo pude hacer y funciona excelente, pero la WEB esta embebida en el mismo codigo de arduino, lo que yo quiero es que la web se encuentre en la tarjeta SD que viene en la shield y me responda a los comandos. Hasta ahora logro alojar la web en la SD pero los comandos de los botones no responden.

Buenas. Yo hice lo que estas queriendo hacer y se por experiencia la información y desinforamcion sobre estos temas. Como ya habras investigado bastante te mando el código y la pagina que hice yo. Si tenes alguna pregunta especifica no dudes en consultarme.

A mi me sirvieron mucho unas aplicaciones de Android que ense√Īan estos protocolos XML Ajax HTML.

Pagina web con ajax alojada en SD de Ethernet

CODIGO ARDUINO (hay códigos que son para comparación de tiempo calendario, que no tienen q ver con la web y también lee el estado de variables de un archivo VAR tambien alojado en la SD)

#include <Time.h>
#include <SD.h>
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192, 168, 1, 77);
EthernetServer servidor(80);
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov
const int LED1=0;
String url;
byte led1;
File varfile;
File webfile;
EthernetUDP Udp;

void setup() {
  pinMode(13, OUTPUT);
  pinMode(53, OUTPUT);
  Ethernet.begin(mac, ip);
  servidor.begin();
  Udp.begin(8888);
  SD.begin(4);
  varfile = SD.open("var/var.txt");
  if (varfile) {
    varfile.seek(LED1);
    led1 =(varfile.read());
    varfile.close();
  }
}

void loop() {
  EthernetClient cliente = servidor.available();
  if (cliente) {
    while (cliente.connected()) {
      if (cliente.available()) {
        char c = cliente.read();//Leemos la petición HTTP carácter por carácter
        url.concat(c);//Unimos el String 'url' con la petición HTTP (c). De esta manera convertimos la petición HTTP a un String
        if (url.substring(url.indexOf("led1=")) == "led1=off") {led1 = 0;guardar_variable(LED1,led1);}
        if (url.substring(url.indexOf("led1=")) == "led1=on") {led1 = 1;guardar_variable(LED1,led1);}
        if (url.substring(url.indexOf("led1=")) == "led1=par") {led1 = 2;guardar_variable(LED1,led1);}
        if (url.substring(url.indexOf("act_hora"))=="act_hora") {setSyncProvider(getNtpTime);} //sincroniza la hora con servidor NTP
        if (c == '\n') {
          cliente.println("HTTP/1.1 200 OK");
          if (url.indexOf("req") > 0) {
            cliente.println("Content-Type: text/xml");
            cliente.println("Connection: keep-alive");
            cliente.println();//Página Web en XML
            XML_response(cliente);
          }
          else {
            cliente.println("Content-Type: text/html");
            cliente.println("Connection: keep-alive");
            cliente.println(); //Página Web en HTML
            // Abrimos la página de la SD y la enviamos
            webfile = SD.open("web/ajax1.htm");
            if (webfile) {
              while (webfile.available()) {
                cliente.write(webfile.read());
              }
              webfile.close();
            }
          }
          cliente.stop();
          url = "";
        }
      }
    }
  }
  if (led1 == 0) {digitalWrite(13, LOW);}
  if (led1 == 1) {digitalWrite(13, HIGH);}
  if (led1 == 2) {digitalWrite(13, HIGH);delay(100);digitalWrite(13, LOW);delay(100);}
}

void XML_response(EthernetClient cl) {
  cl.print("<?xml version = \"1.0\" ?>");
  cl.print("<inputs>");
  cl.print("<LED>");
  if (led1 == 0) {cl.print("off");}
  if (led1 == 1) {cl.print("on");}
  if (led1 == 2) {cl.print("parpadeando");}
  cl.println("</LED>");
  cl.print("<DATE>");
  if (hour()<10){cl.print("0");}
  cl.print(hour());
  cl.print(":");
  if (minute()<10){cl.print("0");}
  cl.print(minute());
  cl.print(":");
  if (second()<10){cl.print("0");}
  cl.print(second());
  cl.print(" ");
  cl.print(dayStr(weekday()));
  cl.print(" ");
  if (day()<10){cl.print("0");}
  cl.print(day());
  cl.print("/");
  if (month()<10){cl.print("0");}
  cl.print(month());
  cl.print("/");
  cl.println(year());
  cl.println("</DATE>");
  cl.print("</inputs>");
}

void guardar_variable(int linea,int variable){
      varfile = SD.open("var/var.txt", FILE_WRITE);
    if (varfile) {
      varfile.seek(linea);
      varfile.write(variable);
      varfile.close();
    }
}

/*-------- NTP code ----------*/

byte packetBuffer[48];

time_t getNtpTime()//carga la hora al arduino
{
  while (Udp.parsePacket() > 0) ;
  sendNTPpacket(timeServer);
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500) {
    int size = Udp.parsePacket();
    if (size >= 48) {
      Udp.read(packetBuffer, 48);
      unsigned long secsSince1900;
      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      return secsSince1900 - 2208988800UL + (-3) * SECS_PER_HOUR;//(-3)=gmt (argentina)
    }
  }
  return 0;
}

// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address)
{
  memset(packetBuffer, 0, 48);
  packetBuffer[0] = 0b11100011;
  packetBuffer[1] = 0;
  packetBuffer[2] = 6;
  packetBuffer[3] = 0xEC;
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
  Udp.beginPacket(address, 123);
  Udp.write(packetBuffer, 48);
  Udp.endPacket();
}

PAGINA WEB ALOJADA EN SD.

<title>Arduino Ajax I/O</title>
<script>
function GetArduinoIO()
{
	nocache = "&nocache=" + Math.random() * 1000000;
	var request = new XMLHttpRequest();
	request.onreadystatechange = function()
		{
			if (this.readyState == 4) {
				if (this.status == 200) {
					if (this.responseXML != null) {
						if (this.responseXML.getElementsByTagName('LED')[0].childNodes[0].nodeValue === "on") {
								document.getElementById("LED").innerHTML = "LED is ON";
							}
						if (this.responseXML.getElementsByTagName('LED')[0].childNodes[0].nodeValue === "off"){
								document.getElementById("LED").innerHTML = "LED is OFF";
							}
						if (this.responseXML.getElementsByTagName('LED')[0].childNodes[0].nodeValue === "parpadeando"){
								document.getElementById("LED").innerHTML = "LED is PARPADEANDO	";
							}
						document.getElementById("DATE").innerHTML =this.responseXML.getElementsByTagName('DATE')[0].childNodes[0].nodeValue;
						}
					}
				}
			}
			// send HTTP GET request with LEDs to switch on/off if any
			request.open("GET", "ajax_inputs" + nocache, true);
			request.send(null);
			setTimeout('GetArduinoIO()', 1000);
		}
</script>
</head>
<body width=100% height=100% onload="GetArduinoIO()">
<center>
<h1>CONTROL DE LAMPARA</h1>


<p id="DATE">...</p>
<p id="LED">...</p>
<input type=submit value=ON style=width:200px;height:75px onClick=location.href='./?LED=T'>
<input type=submit value=OFF style=width:200px;height:75px onClick=location.href='./?LED=F'>
<input type=submit value=PARPADEO style=width:200px;height:75px onClick=location.href='./?LED=P'>
<input type=submit value=ACT.HORA style=width:200px;height:75px onClick=location.href='./?LED=S'>
</center>
</body>
</body>
</html>

Gracias por la informacion, recien lo veo, en estos dias voy a estudiar tu codigo para entenderlo a fondo porque mas alla de tenerlo resuelto quiero entenderlo, yo de htm y ajax no entiendo demasiado pero me las ire rebuscando. Gracias por el dato!

Jorge, he probado y modificado el codigo… lo que no entiendo es en que pin enciende el led… (supongo que es el pin 13 del arduino en donde tengo conectado mi led)…

Dejo el codigo modificado tanto del arduino como el de la web con AJAX a ver si encuentras el error dado que no logro encender y apagar el led…

Este es el codigo ARDUINO:

#include <SD.h>
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192, 168, 1, 85);
EthernetServer servidor(80);
const int LED1=0;
String url;
byte led1;
File webfile;


void setup() {
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
  Serial.begin(9600);  
  // Inicializo la tarjeta SD
  /*
    Ethernet.begin(mac, ip);
  servidor.begin();
  SD.begin(4);*/
     Serial.println("Initializing SD card...");
    if (!SD.begin(4)) {
        Serial.println("ERROR - SD card initialization failed!");
        return;    // init failed
    }
    Serial.println("SUCCESS - SD card initialized.");
    // check for index.htm file
    if (!SD.exists("index.htm")) {
        Serial.println("ERROR - Can't find index.htm file!");
        return;  // can't find index file
    }
  Ethernet.begin(mac, ip);  // initialize Ethernet device
  servidor.begin();           // start to listen for clients
}

void loop() {
  EthernetClient cliente = servidor.available();
  if (cliente) {
    while (cliente.connected()) {
      if (cliente.available()) {
        char c = cliente.read();//Leemos la petición HTTP carácter por carácter
        url.concat(c);//Unimos el String 'url' con la petición HTTP (c). De esta manera convertimos la petición HTTP a un String
        if (url.substring(url.indexOf("led1=")) == "led1=off") {led1 = 0;}
        if (url.substring(url.indexOf("led1=")) == "led1=on") {led1 = 1;}
                
        if (c == '\n') {
          cliente.println("HTTP/1.1 200 OK");
          if (url.indexOf("req") > 0) {
            cliente.println("Content-Type: text/xml");
            cliente.println("Connection: keep-alive");
            cliente.println();//Página Web en XML
            XML_response(cliente);
          }
          else {
            cliente.println("Content-Type: text/html");
            cliente.println("Connection: keep-alive");
            cliente.println(); //Página Web en HTML
            // Abrimos la página de la SD y la enviamos
            webfile = SD.open("index.htm");
            if (webfile) {
              while (webfile.available()) {
                cliente.write(webfile.read());
              }
              webfile.close();
            }
          }
          cliente.stop();
          url = "";
        }
      }
    }
  }
  if (led1 == 0) {digitalWrite(13, LOW);}
  if (led1 == 1) {digitalWrite(13, HIGH);}
  
}

void XML_response(EthernetClient cl) {
  cl.print("<?xml version = \"1.0\" ?>");
  cl.print("<inputs>");
  cl.print("<LED>");
  if (led1 == 0) {cl.print("off");}
  if (led1 == 1) {cl.print("on");}
}

Este es el codigo WEB:

<title>Arduino Ajax I/O</title>
<script>
function GetArduinoIO()
{
	nocache = "&nocache=" + Math.random() * 1000000;
	var request = new XMLHttpRequest();
	request.onreadystatechange = function()
		{
			if (this.readyState == 4) {
				if (this.status == 200) {
					if (this.responseXML != null) {
						if (this.responseXML.getElementsByTagName('LED')[0].childNodes[0].nodeValue === "on") {
								document.getElementById("LED").innerHTML = "LED is ON";
							}
						if (this.responseXML.getElementsByTagName('LED')[0].childNodes[0].nodeValue === "off"){
								document.getElementById("LED").innerHTML = "LED is OFF";
							}
						
						
					}
				}
			}
			// send HTTP GET request with LEDs to switch on/off if any
			request.open("GET", "ajax_inputs" + nocache, true);
			request.send(null);
			setTimeout('GetArduinoIO()', 1000);
		}
</script>
</head>
<body width=100% height=100% onload="GetArduinoIO()">
<center>
<h1>CONTROL DE LAMPARA</h1>


<p id="DATE">...</p>
<p id="LED">...</p>
<input type=submit value=ON style=width:200px;height:75px onClick=location.href='./?LED=T'>
<input type=submit value=OFF style=width:200px;height:75px onClick=location.href='./?LED=F'>
</center>
</body>
</body>
</html>

Por lo que veo asi muy por encima esta todo bien. Pero a ver... teniendo la pagina abierta el indicador de estado del led cambia de ON a OFF? si aca cambia pero el led no entonces hay un problema de cableado con el led. si tampoco cambia el estado del indicador de la pagina web, entonces hay otro problema. ma√Īana voy a probar a ver si encuentro el c√≥digo. Lo √ļnico que mextra√Īa es toda la inicializaci√≥n que hiciste en el void setup. a mi ese tipo de c√≥digo me trajo muchos problemas en el funcionamiento. proba quitando todo eso tambi√©n. Suerte. Ma√Īana empiezo mis vacaciones asi lo reviso bien y te cuento

Aparentemente la pagina funciona bien porque en la barra de direcciones del navegador me aparecen las intrucciones de encendido y apagado http://192.168.1.85/?LED=F y http://192.168.1.85/?LED=T.

El codigo que utilice en el inicio del void lo hice porque no funcionaba el led y pense que quiza era problema de inicializacion o algo por el estilo.

Otra cosa, no se como desde arduino compara la variable del led con el estado F o T de la barra de direcciones en vez de 0 y 1 para los estados on off, eso no lo entiendo desde el codigo de arduino.

Tincho encontr√© el error. Lo que pasaba era que yo te mande el c√≥digo y la pagina de dos proyectos diferentes. Son parecido pero tienen peque√Īas diferencias que fui cambiando. Como por ejemplo que en la web manda el url LED=T/F y si te fijas el arduino compara led1=on/off. el led nunca prende por que el arduino espera un led=on y la web le manda un LED=T. Asi que lo que tendr√≠as que hacer es que ambas cosas sean iguales ya sea cambiando la pagina o en el c√≥digo de arduino. lo que preferias. yo lo probe y anda cambiando el c√≥digo solo en el arduino te quedar√≠a asi.

if (url.substring(url.indexOf("LED=")) == "LED=F") {led1 = 0;}
if (url.substring(url.indexOf("LED=")) == "LED=T") {led1 = 1;}

Respecto a tu duda...lo que hace es almacenar la url del navegador en un string con la función concat y luego "leer" el string con la función substring y si el string contiene LED=T asigna un 1 a la variable LED1 con un if.

char c = cliente.read();//Leemos la petición HTTP carácter por carácter
        url.concat(c);//Unimos el String 'url' con la petición HTTP (c). De esta manera convertimos la petición HTTP a un String
        if (url.substring(url.indexOf("LED=")) == "LED=F") {led1 = 0;}
        if (url.substring(url.indexOf("LED=")) == "LED=T") {led1 = 1;}

en la guia de referencia de la pagina de arduino explica muy bien el uso de substring e indexOf.

Jorge, mil gracias!!! En cuanto pueda modifico el codigo y lo pruebo!!! Si esta todo bien vuelvo a comentar dejando los codigos para que el resto pueda tener un minimo ejemplo de como encender un led con la web en la SD, ya que la informacion que hay es en ingles y escasa.

Nuevamente gracias!

Jorge, estoy medio perdido porque no logro que encienda y apague el led conectado al pin 13… modifique esos dos if que me indicaste en el codigo arduino (reemplace los on/off por T/F, luego cambie led1 por LED pensando que era eso lo que me afectaba) y no obtuve resultados…

El codigo inicial era asi:

if (url.substring(url.indexOf(‚Äúled1=‚ÄĚ)) == ‚Äúled1=off‚ÄĚ) {led1 = 0;}
if (url.substring(url.indexOf(‚Äúled1=‚ÄĚ)) == ‚Äúled1=on‚ÄĚ) {led1 = 1;}

Luego lo probe con esta modificacion:
if (url.substring(url.indexOf(‚Äúled1=‚ÄĚ)) == ‚Äúled1=F‚ÄĚ) {led1 = 0;}
if (url.substring(url.indexOf(‚Äúled1=‚ÄĚ)) == ‚Äúled1=T‚ÄĚ) {led1 = 1;}

y por ultimo esta otra modificacion:

if (url.substring(url.indexOf(‚ÄúLED=‚ÄĚ)) == ‚ÄúLED=F‚ÄĚ) {led1 = 0;}
if (url.substring(url.indexOf(‚ÄúLED=‚ÄĚ)) == ‚ÄúLED=T‚ÄĚ) {led1 = 1;}

La placa ethernet se inicializa 10 puntos, la web levanta perfectamente, lo que estoy mirando es que tengo una declaracion al principio del codigo y no se esta utilizando luego que es LED1 (estan las dos LED1 y led1.

1 Like

Jorge, ya lo solucione, cambie el pin utilizado por el pin 8, dado que siempre me queda encendido el pin 13, ahora si funciona!!! Dejo el codigo terminado y funcionando!

Codigo ARDUINO:

#include <SD.h>
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192, 168, 1, 85);
EthernetServer servidor(80);
const int LED=0;
String url;
byte led1;
File webfile;


void setup() {
  pinMode(8, OUTPUT);
    Serial.begin(9600);  
  // Inicializo la tarjeta SD
 
     Serial.println("Initializing SD card...");
    if (!SD.begin(4)) {
        Serial.println("ERROR - SD card initialization failed!");
        return;    // init failed
    }
    Serial.println("SUCCESS - SD card initialized.");
    // check for index.htm file
    if (!SD.exists("index.htm")) {
        Serial.println("ERROR - Can't find index.htm file!");
        return;  // can't find index file
    }
  Ethernet.begin(mac, ip);  // initialize Ethernet device
  servidor.begin();           // start to listen for clients
}

void loop() {
  EthernetClient cliente = servidor.available();
  if (cliente) {
    while (cliente.connected()) {
      if (cliente.available()) {
        char c = cliente.read();//Leemos la petición HTTP carácter por carácter
        url.concat(c);//Unimos el String 'url' con la petición HTTP (c). De esta manera convertimos la petición HTTP a un String
        if (url.substring(url.indexOf("LED=")) == "LED=F") {led1 = 0;}
        if (url.substring(url.indexOf("LED=")) == "LED=T") {led1 = 1;}
                
        if (c == '\n') {
          cliente.println("HTTP/1.1 200 OK");
          if (url.indexOf("req") > 0) {
            cliente.println("Content-Type: text/xml");
            cliente.println("Connection: keep-alive");
            cliente.println();//Página Web en XML
            XML_response(cliente);
          }
          else {
            cliente.println("Content-Type: text/html");
            cliente.println("Connection: keep-alive");
            cliente.println(); //Página Web en HTML
            // Abrimos la página de la SD y la enviamos
            webfile = SD.open("index.htm");
            if (webfile) {
              while (webfile.available()) {
                cliente.write(webfile.read());
              }
              webfile.close();
            }
          }
          cliente.stop();
          url = "";
        }
      }
    }
  }
  if (led1 == 0) {digitalWrite(8, LOW);}
  if (led1 == 1) {digitalWrite(8, HIGH);}
  
}

void XML_response(EthernetClient cl) {
  cl.print("<?xml version = \"1.0\" ?>");
  cl.print("<inputs>");
  cl.print("<LED>");
  if (led1 == 0) {cl.print("off");}
  if (led1 == 1) {cl.print("on");}
}

EL codigo del htm (index.htm):

<title>Arduino Ajax I/O</title>
<script>
function GetArduinoIO()
{
	nocache = "&nocache=" + Math.random() * 1000000;
	var request = new XMLHttpRequest();
	request.onreadystatechange = function()
		{
			if (this.readyState == 4) {
				if (this.status == 200) {
					if (this.responseXML != null) {
						if (this.responseXML.getElementsByTagName('LED')[0].childNodes[0].nodeValue === "on") {
								document.getElementById("LED").innerHTML = "LED is ON";
							}
						if (this.responseXML.getElementsByTagName('LED')[0].childNodes[0].nodeValue === "off"){
								document.getElementById("LED").innerHTML = "LED is OFF";
							}
						
						
					}
				}
			}
			// send HTTP GET request with LEDs to switch on/off if any
			request.open("GET", "ajax_inputs" + nocache, true);
			request.send(null);
			setTimeout('GetArduinoIO()', 1000);
		}
</script>
</head>
<body width=100% height=100% onload="GetArduinoIO()">
<center>
<h1>CONTROL DE LAMPARA</h1>


<p id="DATE">...</p>
<p id="LED">...</p>
<input type=submit value=ON style=width:200px;height:75px onClick=location.href='./?LED=T'>
<input type=submit value=OFF style=width:200px;height:75px onClick=location.href='./?LED=F'>
</center>
</body>
</body>
</html>

Una vez mas, agradecido por la ayuda proporcionada!

1 Like

perfecto! no hay mucha información sobre esto asi que muy bien. yo lo logre a pruba y error y leyendo ejemplos en ingles y comparando bastantes códigos para ver que me servia y que no.

Si sos maniático con los códigos tenes muchas cosas que están de mas y podes simplificar. por ejemplo la const int LED no la usa y después el código en Ajax en la pagina web tampoco te sirve. me alegra haberte ayudado. Cualquier duda si avanzas y se te complica con algo me consultas no tengo problema en ayudar en lo que pueda.

Se puede adaptar el codigo para 2 o mas led¬īs ?