Arduino y php consulta (SOLUCIONADO)

Bueno mi problema es q necesito comunicar el arduino con un servidor web estoy en un proyecto de domotica, si bien me compre el ethernet shield el servidor web dentro de arduino lo noto demasiado lento... ahora mis consultas son:

  1. Se puede hacer q arduino trabaje como cliente web y pida variables a un servidor web que este alojado en mi maquina y de acuerdo a eso realize las acciones necesarias?, sera mas rapido q el servidor web estando en arduino?

2)Coneccion de Arduino con php, he leido mucho al respecto pero no logro q funcione, alguien tiene algun ejemplo funcional? yo voy a poner mi codigo basico de como me parece q tendria q estar funcionando pero nada :(.

Codigo en arduino:

void setup()
{
  Serial.begin(9600);
}
void loop()
{
  while (Serial.available() == 0);
   int val = Serial.read() - '0';
    Serial.println(val);
}

Codigo Php:

<?
	$datos= 1;
        exec ("echo ".$datos." > /dev/ttyACM0");
	delay(5000);
        
?>

bueno cualquier ayuda que me den gracias :), saludos a la comunidad

es totalmente posible, de hecho yo lo tengo montado en mi casa con una gran cantidad de sensores, funciones, base de datos, interface web, ....
vamos que es realizable.

Yo me baso en la idea de que el arduino no tiene que ser el servidor que para eso ya estan los servidores online con mas capacidad, velocidad, y accesibilidad. Entonces lo que mi arduino (master) hace es recoger datos y enviarlos al servidor online. Como? pues llamando a un archivo php y pasandole los valores en la llamada.
get http://miservidor.com/upload.php?A=1234&B=32435&C=25456
luego dentro del archivo php hago un GET de los parametros y los trabajo, guardandolos en la base de datos mysql, hace calculos, envia emails, etc etc.

lo mismo se podria hacer si por ejemplo llamas a un php preguntando si hay el arduino tiene que hacer alguna accion
get http://miservidor.com/actions.php

y que el php haga las consultas en bases de datos o lo que sea e imprima por pantalla con un simple ECHO los comando que debe hacer el arduino.
luego el arduino lee la respuesta de la web que sera una linea de texto tipo
luces1=1;motor1=0 etc
o codificado de alguna forma
L1M0....

suerte y ves poniendo tus progresos e intentaremos ayudarte.

Bueno la verdad que despues de probar y probar intentando utilizar el comando exec en php no he logrado resultados...asi q me pondre a ver como tu lo dices...mas o menos me hago la idea de lo que me explicaste, pero mucho no capte como hacerlo...pero bue me pondre e ire postiando mis avances o estancadas :smiley: ja ja gracias por la ayuda saludos.

Sergegsx he estado platicando toda la tarde, ya me arden hasta los ojos jeje no logro captar tu idea, he echo los ejemplos del libro arduino cookbook pero no los puedo adaptar a lo q quiero, y si bien tu idea en mi mente la entiendo no logro transcribirla a la practica :smiley: je, si podes o alguien puede hacerme un mini ejemplo funcional de como seria, asi puedo continuar gracias, igual voy a seguir viendo si entiendo como es la movida y tratar de seguir avanzando....

#if ARDUINO > 18
#include <SPI.h> // needed for Arduino versions later than 0018
#endif

##include <Ethernet.h>
#include <TextFinder.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,1,177 };

Server server(80);

void setup()
{
Serial.begin(9600);
Ethernet.begin(mac, ip);
server.begin();
Serial.println("ready");
}

void loop()
{
Client client = server.available();
if (client) {
TextFinder finder(client );
while (client.connected()) {
if (client.available()) {
// counters to show the number of pin change requests
int digitalRequests = 0;
int analogRequests = 0;
if( finder.find("GET /") ) {
// find tokens starting with "pin" and stop on the first blank line
while(finder.findUntil("pin", "\n\r")){
char type = client.read(); // D or A
int pin = finder.getValue();
int val = finder.getValue();
if( type == 'D') {
Serial.print("Digital pin ");
pinMode(pin, OUTPUT);
digitalWrite(pin, val);
digitalRequests++;
}
else if( type == 'A'){
Serial.print("Analog pin ");
analogWrite(pin, val);
analogRequests++;
}
else {
Serial.print("Unexpected type ");
Serial.print(type);
}
Serial.print(pin);
Serial.print("=");
Serial.println(val);
}
}

Este es el ejemplo del libro que creo viene por ahi la onda, pero no lo logro adaptar, si hacemos con este ejemplo pasamos por url localhost?pinD13=1 prende el led lo mas bien, por eso pense q por ahi venia la idea, entonces hice la siguiente pagina intentando captar pero no lo logre:

Pero no logro hacerlo funcionar se que algo esta fallando pero necesito saber que pliss je je.

Pipper no te preocupes, y tranquilo que ya veras que facil que es.
Esta tarde te escribo todo en detalle.
enviame un privado a sobre las 18:00 si aun no te he escrito

Te escribi y al rato te desconectaste je...bueno cualquier cosa mandame un privado o acordate de poner escribir :), yo mientras voy a seguir probando esa y alguna otra alternativa a ver si sale algo :D, saludos

Bueno he logrado comunicarme con php via Serial ahora voy a poner por si ha alguien le sirve... el tema de esto q no me convence es que tendria q tener el arduino conectado a una maquina todo el tiempo o no? mmmmm no me convence.

Bueno para los que les interese ahi les paso la data:

Es una clase echa por Remy Sanchez Clase

Nuestro codigo php quedaria:

<?php

// Include the PHP serial class
include "php_serial.class.php";

// Start a new serial class
$serial = new phpSerial;

// Specify the device being used
$serial->deviceSet("/dev/ttyACM0");

// Set baud rate
$serial->confBaudRate(9600);
$serial->confParity("none");
$serial->confCharacterLength(8);
$serial->confStopBits(1);
$serial->confFlowControl("none");

// Open the device
$serial->deviceOpen();

// Write to the device
$serial->sendMessage("1");

// Close the port
$serial->deviceClose();

?>

El codigo de arduino para leer:

void setup()
{
Serial.begin(9600);
}

void loop()
{
if (Serial.available() > 0) {
byte variable = Serial.read(); 
Serial.println(variable);
}
}

Lo que si no logro es por ejemplo si quiero hacer dos botones que prendan y apagen un led probe poniendo en el action el $serial->sendMessage("1"); pero cada ves q se actualiza la pagina se me ejecuta todo :S....

Bueno el que me quiera ir ayudando gracias desde ya seguire postiando a medida que vaya avanzando :D, saludos.

Bueno avances al dia de la fecha: hoy pude entender como mandar a traves de ethernet shield a un servidor web una el valor de una variable:

Codigo Arduino:

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0x11, 0xAC };
byte ip[] = { 192, 168, 1, 19 };
byte server[] = { 192,168,1,33 }; 

Client client(server, 80);

void setup()
{
  Ethernet.begin(mac, ip);
  Serial.begin(9600);
  Serial.println("Coneccion Cliente");
  Serial.println();

  delay(1000);

  Serial.println("connecting...");

  if (client.connect()) {
    Serial.println("connected");
    //client.println("GET /arduino.txt HTTP/1.0");
    client.println("GET /prueba1.php?led=18 HTTP/1.0"); // aca mando la variable led con el valor 18 
    client.println();
  } else {
    Serial.println("connection failed");
  }
}

void loop()
{
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  if (!client.connected()) {
    
    
    Serial.println();
    Serial.println("disconnecting.");
    Serial.println("");
    client.stop();
    for(;;);
  }
}

El codigo php para recibir la variable seria

<?php
$variable = $_GET['led'];
?>

Bien ahora mi consulta es la siguiente como hago lo mismo de modo inverso, osea como mando el valor de una variable desde php a arduino... espero alguien me ayude que la verdad nadie postea raro en una comunidad de este tipo, bueno saludos

ya te puse como hacerlo

lo mismo se podria hacer si por ejemplo llamas a un php preguntando si hay el arduino tiene que hacer alguna accion
get http://miservidor.com/actions.php

y que el php haga las consultas en bases de datos o lo que sea e imprima por pantalla con un simple ECHO los comando que debe hacer el arduino.
luego el arduino lee la respuesta de la web que sera una linea de texto tipo
luces1=1;motor1=0 etc
o codificado de alguna forma
L1M0....

es decir el arduino llama a un php como has echo antes, el php hace la consulta mysql, luego el php imprime con un ECHO los resultados. finalmente el arduino despues de hacer la llamada al php lee la respuesta de la llamada al php, por lo que leera el ECHO que ha enviado el php.

luego el arduino separa la linea que ha recibido en los parametros que se le han pasado. por ejemplo separados por un ";".
mirate el ejemplo de WebClient que viene con arduino, en el se llama a un web, y se lee por serial el texto que contesta la web.

Se que me habias puesto como hacerlo, pero te pedi un ejemplo funcional para poder entenderlo jeje, asi todo teorico si me lo imagino pero no lo veo todo tan claro, pensa q vos lo entendes por q sabes hacerlo pero yo no :(, por eso necesito ir guiandome de algunos ejemplos para ver como funciona la comunicacion entre ambos... esta noche vere como lo hago de la otra forma saludos.

luego el arduino separa la linea que ha recibido en los parametros que se le han pasado. por ejemplo separados por un ";".
mirate el ejemplo de WebClient que viene con arduino, en el se llama a un web, y se lee por serial el texto que contesta la web.

No logro hacer esa parte como separo las lineas??, intente usar Textfinder pero no me funciona...

a veces se aprende mas intentando hacer las cosas uno mismo que recibiendo la solución y haciendo un copia/pega.
ademas te he dado un ejemplo de como hacerlo, se llama WebClient y viene con arduino.
en el tienes la parte de:

  1. llamar a una web
  2. recibir los datos que contesta la web
  3. mostrarlos por serial

ahora solo te faltaria a la vez que los muestras por seria, guardarlos en unas variables.

este ultimo punto a mi me costo infinidad de horas, y cuando lo resolvi habia aprendido un monton. de hecho tienes un post mio de no hace mucho tratando el tema, buscalo

Sergegsx:
es totalmente posible, de hecho yo lo tengo montado en mi casa con una gran cantidad de sensores, funciones, base de datos, interface web, ....
vamos que es realizable.

@Segegsx

Que tal anda el tema de delay en el sistema que tienes montado?
Cuando haces clic en el comando en tu página web, cuanto tarda?
Lo tienes montado en local o con IP publica.

Estoy pensando en hacer data plotting a una pagina web por lo que la velocidad es importante:

Arduino>>>serial port>>>web server>>>> internet

un saludo.

Otra ves yo con espero algunos adelantos je, bueno primero voy a poner los codigos despues mis preguntas...

Codigo Arduino:

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0x11, 0xAC };
byte ip[] = { 192, 168, 1, 19 };
byte server[] = { 192,168,1,33 };
int posicion=0;
int prend;
int foco;
Client client(server, 80);

void setup()
{
  Ethernet.begin(mac, ip);
  Serial.begin(9600);
  Serial.println("Coneccion cliente");
  Serial.println();

  delay(1000);

  Serial.println("connecting...");

  if (client.connect()) {
    Serial.println("connected");
    //client.println("GET /arduino.txt HTTP/1.0");
    client.println("GET /prueba2.php?led=1");
    //client.println("GET /prueba2.php?led=2");
    client.println();
  } else {
    Serial.println("connection failed");
  } 
}

void loop()
{
    
    if (client.available()) {
    char dato_recibido = client.read();
   if (dato_recibido=='B' && posicion==0){
      posicion=1;
      //Serial.println("POSICION 1");
      //Serial.println(dato_recibido);
    }
    if (((dato_recibido=='H')) && posicion==1){
      posicion=2;
      //Serial.println("POSICION 2");
      //Serial.println(dato_recibido);
    }
    if (((dato_recibido=='1')||(dato_recibido=='2')||(dato_recibido=='3')||(dato_recibido=='4')||(dato_recibido=='5')) && posicion==2){
      posicion=3;
      if (dato_recibido=='1')  foco=13;
      //Serial.println("POSICION 3");
      //Serial.println(dato_recibido);
    }
    if (((dato_recibido=='A')||(dato_recibido=='Y')) && posicion==3){
      posicion=4;
      if (dato_recibido=='A')  prend=1;     //A led encendido
      if (dato_recibido=='Y')  prend=0;    //Y  led apagado
      //Serial.println("POSICION 4");
      //Serial.println(dato_recibido);
      //Serial.println(prend);
    }
    if (dato_recibido=='F' && posicion==4){
      posicion=0;
      pinMode(foco, OUTPUT);
      digitalWrite(foco,prend);
      //Serial.println("POSICION 5");
      //Serial.println(dato_recibido);
      //Serial.println(prend);
      //Serial.println(foco);
    }
}
if (!client.connected()) {
    
    Serial.println();
    Serial.println("disconnecting.");
    Serial.println("==================================");
    Serial.println("");
    client.stop();
    for(;;);
  }
}

Bueno mas o menos la idea es recibir tramas por ejemplo BH1AF (donde B el inicio de mi trama, H para decir q se trata de habitacion, 1 numero de la habitacion, A o Y led encendido o apagado, F final de la trama).

Codigo Php:

<b>Apretar Boton para prender o Apagar led</b>
<form action='/prueba2.php' method='GET'><p><input type='hidden' name='pin' value='0'>
<input type='submit' value='Off'/></form>
<form action='/prueba2.php' method='GET'><p><input type='hidden' name='pin' value='1'>
<input type='submit' value='On'/></form>
<?php
$estado=$_GET["pin"]; //esta es la variable que modifico con los botones
$val =$_GET["led"];    //esta es la variable que consulta el arduino.
$con = mysql_connect("localhost", "*****", "*****");
if(!$con)
	{
	die('Could not connect: ' .mysql_error());
	}
mysql_select_db("arduino", $con);

$result = mysql_query("SELECT `numero`, `estado` FROM `habitacion` WHERE numero=$val");  //aca consulto la base de datos con elarduino
while($rs = mysql_fetch_array($result)) {
echo "$rs[1]";
mysql_close($con);
}
echo $estado;
if ($estado==0){
mysql_query("UPDATE habitacion set estado='BH1YF' WHERE numero=1");
mysql_close($con);
}
if ($estado==1){
mysql_query("UPDATE habitacion set estado='BH1AF' WHERE numero=1");
mysql_close($con);
}
//mysql_query("INSERT INTO `led`(`habitacion`) VALUES ($val)");
?>

Bien lo que hago hasta ahora con mi pagina son dos botones On y Off y se apretas actualiza el valor en la base de datos del estado de nuestro led....Ahora bien mis preguntas que he estado probando no logro entender bien, como hacer varias consultas desde el arduino osea preguntar por varias variables, hice varios client.print(GET /) pero solo ejecuta el primero (se q se debe a como se ejecuta por partes el codigo en arduino pero no logro entender).

Mi otra pregunta es mas o menos similar como hago en ese codigo de arduino para que quede a la escucha de alguna variable, por que siempre se ejecuta y se termina el codigo queda en disconect, intente varias modificaciones sin lograr lo que queria probe con while, probe sacando el disconect, probe sacando el for que hay (sucede algo asi como un lazo infinito :S)...bue, me gustaria saber como le doy ahora mas dinamismo a la cosa...yo voy a seguir probando opciones, pero si alguno me va ayudando con tips se lo agradesco, saludos y seguimos avanzando wiiii.

Bueno no logro hacer q el cliente se quede preguntando por las variables al servidor, osea se ejecuta una ves se ejecuta bien y tomo todas las variables que necesito, pero necesito repetir el prosedimiento si no se corta tengo q volver a correr el arduino me explico??.

Lo que hice fue crear una funcion y la llamo desde el loop(), pero no logro q se ejecute como yo quiero, osea se llama bien a la funcion pero no hace lo q esta dentro de ella que seria preguntar por los datos con GET y mostrarlos por serial....

A ver si alguien me da una mano :(...

sin ver el codigo no podemos ayudarte.
no hace falta que pongas 2 paginas de código, tan solo lo que este relacionado con el problema. intenta hacer un código básico que haga solamente lo que dices, pedir al servidor datos continuamente, pruebalo y si no funciona pon el código aquí.

Bueno a ver esto es lo mas cerca q he estado...

#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 88 };
byte server[] = {192, 168, 1,33  };


void setup()
{
Serial.begin(9600);		   
}
void loop()
{
 delay(500);
 recibirdatos();					
}
void recibirdatos()
{
Ethernet.begin(mac, ip);
Client client(server, 80);
Serial.println("Dentro de la funcion");
delay(100);						

if (client.connect()) {
Serial.println("Connected");
client.println("GET /prueba2.php?led=1");
char c = client.read();
Serial.println(c);
			   }
else
{
Serial.println("No se puede conectar");
}
 client.stop();
 while(client.status() != 0)
{
  delay(5);
}
}

Lo que me devuelve por pantalla es:

Dentro de la funcion
connected
y //esa y con dos puntitos arriba

osea se repite varias veces logro eso pero no obtengo las variables como cuando lo hacia solo una ves... solo obtengo esa y con dos puntitos...

me cuesta creer que me has hecho caso las 2 o 3 veces que te he puesto que te leas el ejemplo Webclient que viene con arduino, pero bueno, aqui va lo que detecto en tu codigo.

#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 88 };
byte server[] = {192, 168, 1,33 };

void setup()
{
Serial.begin(9600);
Ethernet.begin(mac, ip); // SOLO TIENES QUE INICIAR LA PLACA ETHERNET UNA VEZ, IGUAL QUE LO HACES CON EL SERIAL.
Client client(server, 80); // LO MISMO AL DECLARAR EL CLIENTE.
}
void loop()
{
delay(2500); // AUMENTA ESTE DELAY INICIALMENTE PARA DARLE TIEMPO AL ARDUINO A CONECTAR Y DESCONECTAR DEL SERVIDOR SIN SATURARLO
recibirdatos();
}

void recibirdatos()
{
Serial.println("Dentro de la funcion");
delay(100);

if (client.connect()) {
Serial.println("Connected");
client.println("GET /prueba2.php?led=1");
char c = client.read();// SI HUBIESES MIRADO EL EJEMPLO QUE TE PROPUSE VERIAS QUE NECESITAS UN while PARA LEER TODO LO QUE CONTESTA LA PAGINA WEB PHP, TU SOLO ESTAS LEYENDO 1 CARACTER AQUI
Serial.println(c);

if (client.available()) {
char c = client.read();
Serial.print(c);
}

}
else
{
Serial.println("No se puede conectar");
}
~~ client.stop();~~
while(client.status() != 0) // ESTO NO SE PORQUE LO PONES, YO EN MIS EJEMPLOS NUNCA LO HE USADO AUNQUE TIENE SENTIDO LO QUE HACES
{
~~ delay(5);~~
}

// if the server's disconnected, stop the client:
if (!client.connected()) { // DE TODAS FORMAS YO PROBARIA CON LO QUE TE VIENE EN EL EJEMPLO WEBCLIENT.
Serial.println();
Serial.println("disconnecting.");
client.stop();

}

Elimina todo lo que este en rojo.
si te funciona todo bien, vuelve a poner el codigo que funciona aqui para que otros puedas beneficiarse

Bueno a ver:

1° En post anteriores mios esta postiado el ejemplo del "webclient" andando bien consultando mas de una variable, pero, si leyeron, que me parece q no...justamente lo que preguntaba como podia adaptarlo para leer constantemente en el servidorweb, es mas puse las modificaciones que le habia echo sin exito para lograr lo que sigo preguntando...

2°Si no declaro el client dentra la funcion, vos me pones que lo declare en el setup, me tira un error que no se ha declarado dentro del scope, por eso yo lo habia puesto dentro de la funcion (debido a pruebas anteriores que he echo), despues el codigo sigue sin resolver lo q intento, entra en la funcion entra en el if pero no imprime nada....

saludos

en el ejemplo de WebClient lo pone arriba del todo.
(yo me he colado y lo he metido en el setup)

/*
  Web client
 
 This sketch connects to a website (http://www.google.com)
 using an Arduino Wiznet Ethernet shield. 
 
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 
 created 18 Dec 2009
 by David A. Mellis
 
 */

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,1,177 };
byte gateway[] = { 192,168,1,1 };
byte server[] = { 74,125,39,147 };  //{ 173,194,33,104 }; // Google

// Initialize the Ethernet client library
// with the IP address and port of the server 
// that you want to connect to (port 80 is default for HTTP):
Client client(server, 80);

void setup() {
  // start the Ethernet connection:
    Ethernet.begin(mac, ip, gateway);		// Ethernet.begin(mac, ip);
  // start the serial library:
  Serial.begin(9600);
  // give the Ethernet shield a second to initialize:
  delay(1000);
  Serial.println("connecting...");

  // if you get a connection, report back via serial:
  if (client.connect()) {
    Serial.println("connected");
    // Make a HTTP request:
    client.println("GET /search?q=arduino HTTP/1.0");
    client.println();
  } 
  else {
    // kf you didn't get a connection to the server:
    Serial.println("connection failed");
  }
}

void loop()
{
  // if there are incoming bytes available 
  // from the server, read them and print them:
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();

    // do nothing forevermore:
    for(;;)
      ;
  }
}