Autor Tema: Esp8266 & LUA  (Leído 15635 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
Re:Esp8266 & LUA
« Respuesta #15 en: 03 de Enero de 2016, 12:42:32 »
hola elgarbe.ya te puse el codigo como me decias.no habia caido en eso.pero como tu lo pusistes no se puede copiar y pegar sin los numeros
de linea.cosa que es un estorbo.si se pudiera poner del estilo que tu indicas pero sin numeros.quedaria genial.

ahora.las primeras pruebas que hizistes es con el firmware que trae por defecto estos modulos.como tu ya sabes.y que ya estube
practicando aqui: http://www.todopic.com.ar/foros/index.php?topic=45498.0

lo malo del firmware original es que esta muy limitado.y no se puede usar el modulo de forma autonoma.
lo de alimentar el modulo.por el momento a mi el Esp8266-1 con el usb de mi portatil tiene de sobra.otra cosa seria el Esp8266-12
que pude que consuma mas corriente.aunque quizas dependa de las salidas que controlemos.



hola Carl47D.yo por el momento no uso la actulizacion por internet.en la version original se que se puede.pero con LUA no tengo ni idea.
y de todas formas actualizarias el firmware.no el codigo que quieras implementar.o almenos es lo que creo.

si implementas algun tipo de bootloader.y lo actualizas por internet.pues como todas las cosas en internet.tendrias que hacerlo con una
conexion segura.pero por el momento no he llegado a la parte de los bootloader ni se si LUA lo implementa.


Snaut.como siempre dispuesto a ayudar en lo que pueda.por ahora mi intencion es convertir al Esp8266-1 en un sistema de transmision
de datos como si de un modulo Bluetooth se tratase.
haber si hoy lo consigo.y continuo con las practicas para el aprendizage de las diferentes funciones que tiene integradas.
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8110
Re:Esp8266 & LUA
« Respuesta #16 en: 03 de Enero de 2016, 12:44:32 »
Citar
.pero como tu lo pusistes no se puede copiar y pegar sin los numeros
de linea.cosa que es un estorbo.si se pudiera poner del estilo que tu indicas pero sin numeros

Cuando copias y pegas dentro de los tags code, los numeros no molestan.
Y te digo por que siempre copio y pego algun que otro codigo al bloc de notas para editarlo y luego volverlo a poner.

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Esp8266 & LUA
« Respuesta #17 en: 03 de Enero de 2016, 13:14:32 »
Ahora el mismo ejemplo de groundman para hacer un led on / led off, pero usando el navegador. El ejemplo fue tomado de acá:
http://randomnerdtutorials.com/esp8266-web-server/

el código es este:

Código: C
  1. wifi.setmode(wifi.STATION)
  2. wifi.sta.config("YOUR_NETWORK_NAME","YOUR_NETWORK_PASSWORD")
  3. wifi.sta.setip({ip="192.168.1.5",netmask="255.255.255.0",gateway="192.168.1.1"})   --configura IP fija
  4. led1 = 3
  5. led2 = 4
  6. gpio.mode(led1, gpio.OUTPUT)
  7. gpio.mode(led2, gpio.OUTPUT)
  8. srv=net.createServer(net.TCP)
  9. srv:listen(80,function(conn)
  10.     conn:on("receive", function(client,request)
  11.         local buf = "";
  12.         local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
  13.         if(method == nil)then
  14.             _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");
  15.         end
  16.         local _GET = {}
  17.         if (vars ~= nil)then
  18.             for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do
  19.                 _GET[k] = v
  20.             end
  21.         end
  22.         buf = buf.."<h1> ESP8266 Web Server</h1>";
  23.         buf = buf.."<p>GPIO0 <a href=\"?pin=ON1\"><button>ON</button></a>&nbsp;<a href=\"?pin=OFF1\"><button>OFF</button></a></p>";
  24.         buf = buf.."<p>GPIO2 <a href=\"?pin=ON2\"><button>ON</button></a>&nbsp;<a href=\"?pin=OFF2\"><button>OFF</button></a></p>";
  25.         local _on,_off = "",""
  26.         if(_GET.pin == "ON1")then
  27.               gpio.write(led1, gpio.HIGH);
  28.         elseif(_GET.pin == "OFF1")then
  29.               gpio.write(led1, gpio.LOW);
  30.         elseif(_GET.pin == "ON2")then
  31.               gpio.write(led2, gpio.HIGH);
  32.         elseif(_GET.pin == "OFF2")then
  33.               gpio.write(led2, gpio.LOW);
  34.         end
  35.         client:send(buf);
  36.         client:close();
  37.         collectgarbage();
  38.     end)
  39. end)
  40.  

cambié la opcion de ip dinámica por IP fijada por mí.

El funcionamiento:


saludos!
-
Leonardo Garberoglio

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
Re:Esp8266 & LUA
« Respuesta #18 en: 03 de Enero de 2016, 14:55:55 »
valla.vas avanzando. la verdad es que lo mejor es usar una IP fija.en una practica que he hecho he configurado el modulo con
la IP 192.168.1.5  y he puesto una condicional para que mediante un cliente pueda cambiarla a otra IP.la idea es crear una red en el hogar
pero cambiando todas las IP de cada uno de los modulos sin tener que programarlos uno a uno.

este es parte del codigo:
 
Código: [Seleccionar]
        staticIp=string.gsub (payload, "ip=","" )    --busqueda y reemplazo
        out=string.match(payload,"ip=")            --comprueba si coincide el patron
        if out~=nil then wifi.sta.setip({ip=staticIp}) end  --imprime resultado
lo que hace es buscar la cabecera "ip=" y cojer los datos que hay detras de esta combinacion.en este caso la IP

pero me falta almacenar el dato de la IP en la memoria y tambien la restauracion de esta cuando se inicia el modulo.
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Esp8266 & LUA
« Respuesta #19 en: 03 de Enero de 2016, 15:08:47 »
Me pareció muy interesante el ejemplo anterior y empecé a estudiar un poco el funcionamiento.
El firmware que le flasheamos es un intérprete de lua y microphyton.  En este ejemplo se ve el poder de phyton para manejar cadenas. Veamos que hace cada línea. He modificado un poco el código para poder capturar y mostrar las transferencias http que se suceden:

Código: C
  1. wifi.setmode(wifi.STATION)
  2. wifi.sta.config("elgarbe","1234567890123")
  3. wifi.sta.setip({ip="192.168.1.5",netmask="255.255.255.0",gateway="192.168.1.1"})   --configura IP fija
  4. led1 = 3
  5. led2 = 4
  6. gpio.mode(led1, gpio.OUTPUT)
  7. gpio.mode(led2, gpio.OUTPUT)
  8. srv=net.createServer(net.TCP)
  9. srv:listen(80,function(conn)
  10.     conn:on("receive", function(client,request)
  11.         print("Request: " .. request)
  12.         local buf = "";
  13.         local a, b, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
  14.         if (a ~= nil)then
  15.             print("Start: " .. a)
  16.         end
  17.         if (b ~= nil)then
  18.             print("End: " .. b)
  19.         end
  20.        
  21.         if (method ~= nil)then
  22.             print("Method: " .. method)
  23.         end
  24.         if (path ~= nil)then
  25.             print("Path: " .. path)
  26.         end
  27.         if (vars ~= nil)then
  28.             print("Vars: " .. vars)
  29.         end
  30.         if(method == nil)then
  31.             _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");
  32.         end
  33.         local _GET = {}
  34.         if (vars ~= nil)then
  35.             for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do
  36.                 _GET[k] = v
  37.             end
  38.         end
  39.         buf = buf.."<h1> ESP8266 Web Server</h1>";
  40.         buf = buf.."<p>GPIO0 <a href=\"?pin=ON1\"><button>ON</button></a>&nbsp;<a href=\"?pin=OFF1\"><button>OFF</button></a></p>";
  41.         buf = buf.."<p>GPIO2 <a href=\"?pin=ON2\"><button>ON</button></a>&nbsp;<a href=\"?pin=OFF2\"><button>OFF</button></a></p>";
  42.         local _on,_off = "",""
  43.         if(_GET.pin == "ON1")then
  44.               gpio.write(led1, gpio.HIGH);
  45.         elseif(_GET.pin == "OFF1")then
  46.               gpio.write(led1, gpio.LOW);
  47.         elseif(_GET.pin == "ON2")then
  48.               gpio.write(led2, gpio.HIGH);
  49.         elseif(_GET.pin == "OFF2")then
  50.               gpio.write(led2, gpio.LOW);
  51.         end
  52.         client:send(buf);
  53.         client:close();
  54.         collectgarbage();
  55.     end)
  56. end)
  57.  

Las primeras líneas son típicas, configurar el nodo como estacion y lo conectan al router que elijamos, finalmente nos damos una ip fija:

Código: C
  1. wifi.setmode(wifi.STATION)
  2. wifi.sta.config("elgarbe","1234567890123")
  3. wifi.sta.setip({ip="192.168.1.5",netmask="255.255.255.0",gateway="192.168.1.1"})   --configura IP fija
  4.  

Luego viene la inicializacion del hardware:
Código: C
  1. led1 = 3
  2. led2 = 4
  3. gpio.mode(led1, gpio.OUTPUT)
  4. gpio.mode(led2, gpio.OUTPUT)
  5.  

porque el gpio0 es igual a 3 y el gpio2 es igual a 4 es algo que estoy averiguando.

Luego viene la creacion del webserver escuchando en el puerto 80 y la funcion a llamar cuando se recive el evento on receive
Código: C
  1. srv=net.createServer(net.TCP)
  2. srv:listen(80,function(conn)
  3.     conn:on("receive", function(client,request)
  4.  

dentro de "request" tenemos la informacion que envía el navegador web que quiere conectarse
Si ejecutáramos el código hasta ahí tendríamos lo siguiente:


* Captura de pantalla 2016-01-03 14.24.39.png
(133.52 kB, 1366x768 - visto 1059 veces)


como se ve, la primer línea del reques es: GET / HTTP/1.1

cuando en el navegador pasamos algún argumento en la direccion, como por ejemplo http://192.168.1.5/?pin=OFF2 esa cadena adicion aparecerá en esa línea.
Agreguemos más codigo:

Código: C
  1.     conn:on("receive", function(client,request)
  2.         print("Request: " .. request)
  3.         local buf = "";
  4.         local a, b, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
  5.         if (a ~= nil)then
  6.             print("Start: " .. a)
  7.         end
  8.         if (b ~= nil)then
  9.             print("End: " .. b)
  10.         end
  11.        
  12.         if (method ~= nil)then
  13.             print("Method: " .. method)
  14.         end
  15.         if (path ~= nil)then
  16.             print("Path: " .. path)
  17.         end
  18.         if (vars ~= nil)then
  19.             print("Vars: " .. vars)
  20.         end
  21.     end)
  22.  
Aquí aparece el phyton, que debería haver estudiado antes!!!!.
Cada instruccion (string.find por ejemplo) la podemos encontrar en el manual que puso groundman al principio.
En este caso la instruccion  local a, b, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
declara 5 variables locales. a y b almacenan el comienzo y el final del string buscado ("([A-Z]+) (.+)?(.+) HTTP") en la cadena request.
Luego method, path y vars almacenan el texto encontrado según el pattern ("([A-Z]+) (.+)?(.+) HTTP"). Cada variable almacena lo que está en paréntesis.
Entonces method almacenará la cadena que concuerde con el pattern [A-Z]+ esto es, tantos caracteres como haya mientras que estén dentro del entorno A-Z
Luego se buscará un espacio en blanco
luego se buscará un caracter cualquiera (.) y tantos como haya (+) y se almacenará en path. Aquí estimo que la cantidad de caracteres se corta al hayar el próximo del pattern general, en este caso el ?
Luego el signo de pregunta
Luego se busca cualquier caracter y tantos como haya hasta encotrar el resto del pttern " HTTP" y se almacena en vars.
Etonces el código anterior con la siguiente direccion del navegador: http://192.168.1.5/?pin=OFF2 devuelve:


* Captura de pantalla 2016-01-03 14.42.03.png
(140.82 kB, 1366x768 - visto 1034 veces)


como vemos el resutado es:
Código: HTML5
  1. > Request: GET /?pin=OFF2 HTTP/1.1
  2. Host: 192.168.1.5
  3. User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:43.0) Gecko/20100101 Firefox/43.0
  4. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  5. Accept-Language: es-AR,es;q=0.8,en-US;q=0.5,en;q=0.3
  6. Accept-Encoding: gzip, deflate
  7. Connection: keep-alive
  8.  
  9.  
  10. Start: 1
  11. End: 19
  12. Method: GET
  13. Path: /
  14. Vars: pin=OFF2
  15.  

Como ven se almacena en cada variable la parte del GET que nos interesa. Lo importante acá es vars que nos da el comando a ejecutar.

Luego, como start y end (a y b) no nos interesa lo podemos reemplazar por "_":

Código: C
  1. wifi.setmode(wifi.STATION)
  2. wifi.sta.config("elgarbe","1234567890123")
  3. wifi.sta.setip({ip="192.168.1.5",netmask="255.255.255.0",gateway="192.168.1.1"})   --configura IP fija
  4. led1 = 3
  5. led2 = 4
  6. gpio.mode(led1, gpio.OUTPUT)
  7. gpio.mode(led2, gpio.OUTPUT)
  8. srv=net.createServer(net.TCP)
  9. srv:listen(80,function(conn)
  10.     conn:on("receive", function(client,request)
  11.         print("Request: " .. request)
  12.         local buf = "";
  13.         local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
  14.        
  15.         if (method ~= nil)then
  16.             print("Method: " .. method)
  17.         end
  18.         if (path ~= nil)then
  19.             print("Path: " .. path)
  20.         end
  21.         if (vars ~= nil)then
  22.             print("Vars: " .. vars)
  23.         end
  24.     end)
  25. end)
  26.  

Hasta ahora en el explorador no aparece nada al escrivir la direccion. Agreguemos ahora código para la interfaz:

Código: C
  1. wifi.setmode(wifi.STATION)
  2. wifi.sta.config("elgarbe","1234567890123")
  3. wifi.sta.setip({ip="192.168.1.5",netmask="255.255.255.0",gateway="192.168.1.1"})   --configura IP fija
  4. led1 = 3
  5. led2 = 4
  6. gpio.mode(led1, gpio.OUTPUT)
  7. gpio.mode(led2, gpio.OUTPUT)
  8. srv=net.createServer(net.TCP)
  9. srv:listen(80,function(conn)
  10.     conn:on("receive", function(client,request)
  11.         print("Request: " .. request)
  12.         local buf = "";
  13.         local a, b, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
  14.         if (a ~= nil)then
  15.             print("Start: " .. a)
  16.         end
  17.         if (b ~= nil)then
  18.             print("End: " .. b)
  19.         end
  20.        
  21.         if (method ~= nil)then
  22.             print("Method: " .. method)
  23.         end
  24.         if (path ~= nil)then
  25.             print("Path: " .. path)
  26.         end
  27.         if (vars ~= nil)then
  28.             print("Vars: " .. vars)
  29.         end
  30.  
  31.         buf = buf.."<h1> ESP8266 Web Server</h1>";
  32.         buf = buf.."<p>GPIO0 <a href=\"?pin=ON1\"><button>ON</button></a>&nbsp;<a href=\"?pin=OFF1\"><button>OFF</button></a></p>";
  33.         buf = buf.."<p>GPIO2 <a href=\"?pin=ON2\"><button>ON</button></a>&nbsp;<a href=\"?pin=OFF2\"><button>OFF</button></a></p>";
  34.  
  35.         client:send(buf);
  36.         client:close();
  37.         collectgarbage();
  38.     end)
  39. end)
  40.  

Con ese código ya tenemos la página web que nos permitirá enviar los comandos con 4 botones de comando.

Ahora veamos el código que determina el comando (ON OFF) y el pin (1 o 2).

Código: C
  1.         if(method == nil)then
  2.             _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");
  3.         end
  4.         local _GET = {}
  5.         if (vars ~= nil)then
  6.             for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do
  7.                 _GET[k] = v
  8.                 print("k: " .. k .. "\nv: " .. v)
  9.             end
  10.         end
  11.  

En estas líneas no entiendo bien la funcion del primer if.
Luego si vars no es nulo (o sea, si hemos agregado algun GET en la direccion del explorador) hacemos un for buscando en vars el pattern que esta entre paréntesis. vars contiene, por ejemplo pin=ON2. El patern está dividido por el signo "=" y lo que se busca de un lado y del otro es %w (todos los caracteres alfanuméricos) y el + es tantos como haya. Entonces al ejecutar el código con ese agregado obtenemos al precionar ON del LED 2:

Código: HTML5
  1. Request: GET /?pin=ON2 HTTP/1.1
  2. Host: 192.168.1.5
  3. User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:43.0) Gecko/20100101 Firefox/43.0
  4. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  5. Accept-Language: es-AR,es;q=0.8,en-US;q=0.5,en;q=0.3
  6. Accept-Encoding: gzip, deflate
  7. Referer: http://192.168.1.5/
  8. Connection: keep-alive
  9.  
  10.  
  11. Method: GET
  12. Path: /
  13. Vars: pin=ON2
  14. k: pin
  15. v: ON2
  16.  

Entonces se ha separado pin de comando. La variable _GET es tipo array y la instruccion _GET[k] = v hace que GET[pin] tome el valor de v (ON2)

Finalmente, el código que toma el array GET y actua sobre los led:

Código: C
  1.         local _on,_off = "",""
  2.         if(_GET.pin == "ON1")then
  3.               gpio.write(led1, gpio.HIGH);
  4.         elseif(_GET.pin == "OFF1")then
  5.               gpio.write(led1, gpio.LOW);
  6.         elseif(_GET.pin == "ON2")then
  7.               gpio.write(led2, gpio.HIGH);
  8.         elseif(_GET.pin == "OFF2")then
  9.               gpio.write(led2, gpio.LOW);
  10.         end
  11.  

aquí no se bien para que sirve         local _on,_off = "",""

Bueno, hemos podido explicar el primer ejemplo, el cual puede ser base de cualquier otro proyecto que espere comndos para actuar en cuestion.

Saludos!
-
Leonardo Garberoglio

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Esp8266 & LUA
« Respuesta #20 en: 03 de Enero de 2016, 15:14:18 »
valla.vas avanzando. la verdad es que lo mejor es usar una IP fija.en una practica que he hecho he configurado el modulo con
la IP 192.168.1.5  y he puesto una condicional para que mediante un cliente pueda cambiarla a otra IP.la idea es crear una red en el hogar
pero cambiando todas las IP de cada uno de los modulos sin tener que programarlos uno a uno.

este es parte del codigo:
 
Código: [Seleccionar]
        staticIp=string.gsub (payload, "ip=","" )    --busqueda y reemplazo
        out=string.match(payload,"ip=")            --comprueba si coincide el patron
        if out~=nil then wifi.sta.setip({ip=staticIp}) end  --imprime resultado
lo que hace es buscar la cabecera "ip=" y cojer los datos que hay detras de esta combinacion.en este caso la IP

pero me falta almacenar el dato de la IP en la memoria y tambien la restauracion de esta cuando se inicia el modulo.

lo de la ip fija es para poder identificar cada módulo en particular, no? habría que ver si no se puede implementar un pequeño DNS privado para los módulos así podes usar IP dinámica...

sds.
-
Leonardo Garberoglio

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Esp8266 & LUA
« Respuesta #21 en: 03 de Enero de 2016, 15:28:21 »
Acá esta el mapeo del GPIO
http://esp8266.co.uk/tutorials/introduction-to-the-gpio-api/

y una forma interesante de crear la tabla de pines:
https://gist.github.com/paulcuth/f646f220a617a5fe43a1

saludos!
-
Leonardo Garberoglio

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
Re:Esp8266 & LUA
« Respuesta #22 en: 03 de Enero de 2016, 15:32:54 »
ufff. un servidor de nombres.supongo que eso habria que configurarlo en el router.que es al que estan conectados
todos los modulos.no estoy muy familiarizado con las DNS. el router asignaria una IP dinamica a cada modulo
y este responde con el nombre que le tengamos asignado.

seria mejor para nosotros porque es mas comodo recordar un nombre que un numero.habria que estudiarlo.
haber si termino con la uart.y le hechamos un vistazo.
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
Re:Esp8266 & LUA
« Respuesta #23 en: 03 de Enero de 2016, 16:47:58 »

jo.estoy negro.no se como borrar el buffer de entrada de la uart.queria enviar datos hexagesimales.y por eso no puedo usar el metodo
de fin de trama con el caracter \r = 0x0d   ya que podria cortarme la trama.

y el sistema de indicar el numero de bytes a enviar es un problema.ya que las tramas que quiero enviar no tienen una longitud definida.
y si se envia un byte de mas o de menos.se lia el follon.

se me ha ocurrido la idea de poner un timer que borre el buffer de recepcion despues de un tiempo determinado.y asi estar a la espera
de recibir otra trama.
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Esp8266 & LUA
« Respuesta #24 en: 03 de Enero de 2016, 17:26:22 »
Un ejemplo para manejar el GPIO con webserver y hacer PWM extraido de acá:
http://www.esp8266.com/viewtopic.php?f=19&t=990
Hice algunas modificaciones para debugear y ver como funciona:

Código: C
  1. wifi.setmode(wifi.STATION)
  2. wifi.sta.config("elgarbe","1234567890123")
  3. outpin=4 -- Select right IO index !! Here is settings for GPIO2 (Lua build 20141219)
  4.  
  5. srv=net.createServer(net.TCP)
  6. srv:listen(80,function(conn)
  7.     conn:on("receive",function(conn,payload)
  8.         --next row is for debugging output only
  9.         --print(payload)
  10.    
  11.         function ctrlpower()
  12.             pwm.close(outpin)
  13.             gpio.mode(outpin,gpio.OUTPUT)
  14.             dotaz=string.sub(payload,kdesi[2]+1,#payload)
  15.             if dotaz=="ON"  then
  16.                 gpio.write(outpin,gpio.HIGH)
  17.                 return
  18.             end
  19.             if dotaz=="OFF" then
  20.                 gpio.write(outpin,gpio.LOW)
  21.                 return
  22.             end
  23.             if dotaz=="FLC" then
  24.                 pwm.setup(outpin,2,512)
  25.                 pwm.start(outpin)
  26.                 return
  27.             end
  28.             pwm.setup(outpin,1000,dotaz*10)
  29.             pwm.start(outpin)
  30.         end
  31.         --parse position POST value from header
  32.         kdesi={string.find(payload,"pwmi=")}
  33.         --If POST value exist, set LED power
  34.         if kdesi[2]~=nil then
  35.             print("\nPayload: "..payload)
  36.             print("\nkdesi: "..kdesi[1].." "..kdesi[2])
  37.             ctrlpower()
  38.         end
  39.    
  40.         conn:send('HTTP/1.1 200 OK\n\n')
  41.         conn:send('<!DOCTYPE HTML>\n')
  42.         conn:send('<html>\n')
  43.         conn:send('<head><meta  content="text/html; charset=utf-8">\n')
  44.         conn:send('<title>ESP8266</title></head>\n')
  45.         conn:send('<body><h1>Sample GPIO output control</h1>\n')
  46.         conn:send('<h3>For Lua NodeMcu 0.9.2 build 20141219 only !!!</h3>\n')
  47.         conn:send('<h3>Tested with IE 11. and Chrome 39.</h3>\n')
  48.         conn:send('<IMG SRC="http://esp8266.fancon.cz/common/led.gif" WIDTH="150" HEIGHT="101" BORDER="1"><br><br>\n')
  49.         conn:send('<form action="" method="POST">\n')
  50.         conn:send('<input type="submit" name="pwmi" value="OFF">\n')
  51.         conn:send('<input type="submit" name="pwmi" value="10">\n')
  52.         conn:send('<input type="submit" name="pwmi" value="20">\n')
  53.         conn:send('<input type="submit" name="pwmi" value="30">\n')
  54.         conn:send('<input type="submit" name="pwmi" value="40">\n')
  55.         conn:send('<input type="submit" name="pwmi" value="50">\n')
  56.         conn:send('<input type="submit" name="pwmi" value="60">\n')
  57.         conn:send('<input type="submit" name="pwmi" value="70">\n')
  58.         conn:send('<input type="submit" name="pwmi" value="80">\n')
  59.         conn:send('<input type="submit" name="pwmi" value="90">\n')
  60.         conn:send('<input type="submit" name="pwmi" value="ON"> % of power<br><br>\n')
  61.         conn:send('<input type="submit" name="pwmi" value="FLC"> HW blinker</form>\n')
  62.         conn:send('</body></html>\n')
  63.     conn:on("sent",function(conn) conn:close() end)
  64.     end)
  65. end)
  66.  

Esta muy interesante tanto el uso del PWM como el uso de los form input y el método POST. Para ver bien esto habría que estudiar un poco HTML...

El módulo PWM se usa segú este manual:
http://www.eluaproject.net/doc/master/en_refman_gen_pwm.html

Aquí, cada pulsador hace un POST con la variable pwmi seguido de un valor que puede ser, On OFF, FCL o el valor deseado para el duty cicle del PWM. La funcion ctrlpower() se encarga de obtener la cadena del POST y actuar en cuestion. Pero antes hay que verificar que el pedido es un POST y para ello esta esta parte de código:
Código: C
  1.         --parse position POST value from header
  2.         kdesi={string.find(payload,"pwmi=")}
  3.         --If POST value exist, set LED power
  4.         if kdesi[2]~=nil then
  5.             print("\nPayload: "..payload)
  6.             print("\nkdesi: "..kdesi[1].." "..kdesi[2])
  7.             ctrlpower()
  8.         end
  9.  
aquí almacenamos en kdesi (2 valores) el comienzo y el final de la cadena "pwmi=" si es que existe en payload.
Cuando ejecutamos el código y apretamos OFF obtenemos lo siguiente:

Código: HTML5
  1. Payload: POST / HTTP/1.1
  2. Host: 192.168.1.32
  3. User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:43.0) Gecko/20100101 Firefox/43.0
  4. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  5. Accept-Language: es-AR,es;q=0.8,en-US;q=0.5,en;q=0.3
  6. Accept-Encoding: gzip, deflate
  7. Referer: http://192.168.1.32/
  8. Connection: keep-alive
  9. Content-Type: application/x-www-form-urlencoded
  10. Content-Length: 8
  11.  
  12. pwmi=OFF
  13.  
  14. kdesi: 401 405
  15.  

como vemos pwmi= está al final del payload. Insisto, esto debe estar explicado en el standar HTML. Dentro de payload, pwmi= arranca en el caracter 401 y termina en el caracter 405.

Si se ha encontrado esa cadena entonces se llama a la funcion que controla el power (ctrlpower()).

En ella tenemos esta línea: dotaz=string.sub(payload,kdesi[2]+1,#payload)
Esto devuelve una sub string, tomando payload como cadena base, arrancando desde el final de la cadena pwmi= y con una longitud igual a la longitud de payload. Con ese comando se asegura de leer los caracteres que van desde el = hasta el final del payload y que corresponden a la accion a arealizar.
Finalmnete en funcion de dicha cadena hace PWM o no, apaga o enciende el LED o hace un PWM a 2 Hz para que parezca que el led parpadea.

El resultado:
 

La verdad que usar el módulo como viene, sin conectar ningún micro y sin comandos AT es una genialidad. Lastima que tengo modulos muy báscios, el esp-02 y el esp-01 con poco pines disponibles... a ver si me condigo uno 12!!!! también estuve viendo estos módulos:

http://www.aliexpress.com/item/V3-Wireless-module-NodeMcu-4M-bytes-Lua-WIFI-Internet-of-Things-development-board-based-ESP8266-for/32469517132.html
y esta base:
www.aliexpress.com/item/NodeMcu-base-ESP8266-testing-DIY-Breadboard/32549681298.html
estarían geniales para experimentar!

saludos
-
Leonardo Garberoglio

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
Re:Esp8266 & LUA
« Respuesta #25 en: 03 de Enero de 2016, 18:11:13 »

no te preocupes.pronto llegara el ESP32.y quizas con un precion apetecible.

respecto a las pruebas que estoy realizando con la uart.me he dado cuenta de que ni caracter de control \r ni numero de bytes a recibir.
ya que si especificamos un numero minimo de bytes a recibir,no se producira el evento de recepcion hasta que no se llene el buffer.

asi que la opcion esta en recibir los datos de byte en byte.ire creando un string caracter a caracter dentro de un tiempo predeterminado.


PD: es magnifica la informacion que estas poniendo.haber si llenamos esto de ejemplos y tener un sitio donde referirse.
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Esp8266 & LUA
« Respuesta #26 en: 03 de Enero de 2016, 20:10:35 »

no te preocupes.pronto llegara el ESP32.y quizas con un precion apetecible.

respecto a las pruebas que estoy realizando con la uart.me he dado cuenta de que ni caracter de control \r ni numero de bytes a recibir.
ya que si especificamos un numero minimo de bytes a recibir,no se producira el evento de recepcion hasta que no se llene el buffer.

asi que la opcion esta en recibir los datos de byte en byte.ire creando un string caracter a caracter dentro de un tiempo predeterminado.


PD: es magnifica la informacion que estas poniendo.haber si llenamos esto de ejemplos y tener un sitio donde referirse.

justamente estaba pensando en eso antes de salir y ahora veo que ya lo pusiste vos. Recibir byte por byte he ir armando el string y chequeando el fin de resepcion. Muchos parseadores de GPS hacen eso. Como no sabes cuantos bytes trae cada línea, porque es variable, se lee byte por byte y se va parseando, chequeando los encabezados de cada parte del mensaje y luego los datos.

si, mi idea es ir probando los distintos periféricos de ejemplos que hay dando vuelta y tratar de explicarlos. A ver si convertimos a este post como un post de referencia de ejemplos de códigos que pueden servir como base de proyectos.

Saludos!
-
Leonardo Garberoglio

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
Re:Esp8266 & LUA
« Respuesta #27 en: 03 de Enero de 2016, 21:07:30 »


pues ya lo he hecho.queria hacer como cuando se transmite con un modulo bluetooth.sin tener que indicar caracter de fin de linea
ni cantidad de bytes a enviar.me ha costado un monton de pruebas.ya que estoy empezando con esto.

aqui lo tienes:
Código: [Seleccionar]
trama=""

wifi.setmode(wifi.STATION)        --modo estacion
 wifi.sta.config("SSID","clave")    --nombre del punto de acceso wi-fi de nuestro router.y la clave
 wifi.sta.setip({ip="192.168.1.5",netmask="255.255.255.0",gateway="192.168.1.1"})   --configura IP fija
 wifi.sta.connect()         --conectar
 print("ESP8266 mode is: " .. wifi.getmode())               --indica el modo wi-fi.(estacion en este caso)
 print("The module MAC address is: " .. wifi.ap.getmac())   --indica la mac de nuestro dispositivo
 print("Config done, IP is "..wifi.sta.getip())             --indica la IP que nos ha asignado el router.

 srv=net.createServer(net.TCP,60)                           --crea el servidor.y si no hay trafico,cierra conexion pasados 60s
 srv:listen(80,function(conn)                               --estar a la escucha en el puerto 80.
    conn:on("receive",function(conn,payload)                --evento de recepcion y carga el valor leido en payload
    print(payload)                                          --envia al puerto serie lo que se recive desde el cliente

    tmr.delay(1000000)                                      -- 1 segundo de retardo
    conn:send(trama)                                        --envia al cliente.datos recibidos de la uart
    trama=""                                                --borra la trama
    end)
end)

   
--configura uart
    uart.setup(0,9600,8,0,1)
    print ("uart.setup(0,9600,8,0,1) finished")
    print ("waiting for serial data....")

--recepcion de la usart
 uart.on("data",1,                                          --recepcion de caracter en caracter
      function(data)
     
        trama=trama..data--recepcion                        --concatenar strings

          --esta rutina solo es para modo debug.ya que al trabajar con valores hexagesimales no podemos prescindir de ningun
          --valor entre 0x00 y oxff
         
          --if data=="-" then                               --palabra para salir del modo usart
          --print ("salida....")
          --uart.on("data")
          --end       
       
    end, 0)-- valor 0 no entra en modo interprete.pero acepta binarios
           -- valor 1 pude entrar en modo interprete



al final fue mas facil de lo que pensaba.en el codigo si fueramos a enviar una trama muy larga.quizas hubiera que aumentar el
tiempo de retardo del delay.aunque creo que un segundo es tiempo de sobra ya que lo maximo que envia son 255 bytes.y a una velocidad
de 9600bps son 1200 bytes/s
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Esp8266 & LUA
« Respuesta #28 en: 04 de Enero de 2016, 21:20:35 »
Trabajando con el I2C

El driver del I2C (http://www.nodemcu.com/docs/i2c-module/) es muy util en estos módulos devido a su reducida cantidad de pines. Podemos conectar prácticamente cualquier dispositivo I2C a los dos pines libres (GPIO0, GPIO2) de todos los módulos.
Antes que nada quería mostrar una info que encontré sobre las consideraciones que hay que tener al conectar dispositivos en los GPIO 0 y 2 ya que esos pines determinan, en el arranque, como bootea el ESP:
http://www.forward.com.au/pfod/ESP8266/GPIOpins/ESP8266_01_pin_magic.html

En mi caso, estoy probando el I2C con un sensor de temperatura, el LM92 de TI (http://www.ti.com/lit/ds/symlink/lm92.pdf)
Para utilizarlo tenía ya diseñada una plaquita para montarlo y con un conector IDC10 poder conectarlo a distintos circuitos:


* IMG_20160104_205248571.jpg
(55.95 kB, 1024x448 - visto 942 veces)


la calidad de la foto es un desastre!

Bueno, una vez hechas las conexiones, tenemos un simple script (tomado de aquí: http://www.esp8266.com/viewtopic.php?f=19&t=1049), el cual escanea los pines y direcciones en busqueda de un dispositivo conectado al bus.
Al correrlo obtengo:


* Captura de pantalla 2016-01-04 21.09.51.png
(150.06 kB, 1366x768 - visto 939 veces)


O sea que encontró my sensor conectado a los pines con index 3 y 4 (gpio 0 y 2) y en la direccion 0x48.

El script en cuestion es este:

Código: C
  1. -- Based on work by sancho and zeroday among many other open source authors
  2. -- This code is public domain, attribution to gareth@l0l.org.uk appreciated.
  3.  
  4. id=0  -- need this to identify (software) IC2 bus?
  5. gpio_pin= {4,3,0,1,2} -- this array maps internal IO references to GPIO numbers
  6.  
  7. -- user defined function: see if device responds with ACK to i2c start
  8. function find_dev(i2c_id, dev_addr)
  9.      i2c.start(i2c_id)
  10.      c=i2c.address(i2c_id, dev_addr ,i2c.TRANSMITTER)
  11.      i2c.stop(i2c_id)
  12.      return c
  13. end
  14.  
  15. print("Scanning all pins for I2C Bus device")
  16. for scl=1,7 do
  17.      for sda=1,7 do
  18.           tmr.wdclr() -- call this to pat the (watch)dog!
  19.           if sda~=scl then -- if the pins are the same then skip this round
  20.                i2c.setup(id,sda,scl,i2c.SLOW) -- initialize i2c with our id and current pins in slow mode :-)
  21.                for i=0,127 do -- TODO - skip invalid addresses
  22.                     if find_dev(id, i)==true then
  23.                     print("Device is wired: SDA to GPIO - IO index "..sda)
  24.                     print("Device is wired: SCL to GPIO - IO index "..scl)
  25.                     print("Device found at address 0x"..string.format("%02X",i))
  26.                     end
  27.                end
  28.           end
  29.      end
  30. end

bien, sabiendo que el ESP se comunica con el sensor de temperatura podemos realizar un driver para leer la temperatura.

Pero antes analicemos como funciona este script.

al principio vemos la definicion de una funcion "find_dev", al cual se le pasa como parámetro el Id del bus (0 en este caso) y la direccion que queremos verificar. La funcion pone una condicion de START en el bus, luego pone la direccion en el bus con el modo correcto, en este caso TRANSMIT. Si hay algún dispositivo en esa direccion pondrá un ACK en el bus y la funcion adress la detectará. Finalmente pone un STOP en el bus y devuelve True or False de acuerdo a si hubo ACK.

Luego vienen los lazos for que permitirán recorrer todas las combinaciones de pines posibles para cada señal. Se inicializa el i2c con la combinacion de pines proporcionadas por los for y para cada combinacion se recorren las direcciones 0 a 127. Si se encuentra dispositivo en esa combinacion de pines, se imprime dichos indices y la direccion en cuestion, en formato hexadecimal. Simple!

En la proxima veremos si puedo hacer andar el sensor.

Saludos!
-
Leonardo Garberoglio

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Esp8266 & LUA
« Respuesta #29 en: 04 de Enero de 2016, 23:32:48 »
Con este módulo las cosas son tan simples que es de no creer!!!
Me puse a buscar algún driver para el LM92 y..... el mismo nodeMCU trae un driver!!!
https://github.com/nodemcu/nodemcu-firmware/tree/master/lua_modules/lm92

debo confesar que me ha costado un poquito al principio el tema de compilar el módulo para luego usar la sentenci node.require.

El tema, según entendí es mas o menos así: Cada vez que en el ESplorer cargamos un .lua este va a parar a la flash del usuario en el ESP. pero cada script que cargamos no borra los anteriores, excepto que tenga el mismo nombre. Eso por un lado. Por otro lado, como los módulos en formato script ocupan mucho espacio, se pueden compilar en la flash y obtener un archivo .lc, el cual podemos utilizar luego como si de librerías en el ESP se tratara.

Entonces, en el caso del LM92 lo que tenemos que hacer es, primero cargar el lm92.lua a la flash. Pero antes de hacer eso, primero voy a formatear la flash para que no quede ningun script. Eso lo hacemos con el botón Format que está bien a la derecha y arriba en la pantalla. Luego cargo en la flash el lm92.lua y presiono el botón reload debajo de Format. El resultado:


* Captura de pantalla 2016-01-04 23.20.28.png
(137.84 kB, 1366x768 - visto 918 veces)


Bien, como vemos tenemos solo el lm92.lua en la flash. Este script es un módulo con funciones, como un driver del dispositivo. Para utilizarlo debemos compilarlo (una sola vez) y luego llamarlo con require. Entonces hago un script llamado Read_Temp.lua con este código (tomado del README del lm92.lua en nodemcu):

Código: C
  1. node.compile("lm92.lua")
  2. LM92 = require("lm92")
  3. gpio0 = 3
  4. gpio2 = 4
  5. sda = gpio0
  6. scl = gpio2
  7. addr = 0x48
  8. LM92.init(sda, scl,addr)
  9.  
  10. t = LM92.getTemperature()
  11. print("Got temperature: "..t.." C")
  12.  

La primera ves que lo ejecuto dejo sin comentar la primer instruccion, la que compila. Lo cargo al ESP y lo ejecuto. Al finalizar preciono el botón Reload para ver los nuevos files en la flash:


* Captura de pantalla 2016-01-04 23.24.45.png
(129.59 kB, 1366x768 - visto 917 veces)


Como pueden ver el lm92.lc es mucho mas chico que el lm92.lua. Tambien vemos que nos arroja la temperatura!!!! (el modulo esta en la salida de aire de la notebook, por eso esa temperatura tan alta).
Ahora borro el lm92.lua de la flash, comento la primer línea, la que compila el lm92.lua, vuelvo a cargar el Read_Temp.lua y vuelvo a correr el programa:


* Captura de pantalla 2016-01-04 23.28.09.png
(128.96 kB, 1366x768 - visto 938 veces)


Como ven, desapareció el lm92.lua de la flash y el programa sigue corriendo ya que utiliza el lm92.lc

Como ven en cuestion de un par de horas podemos tener nuestro ESP usando sensores de forma muy simple.
Ahora lo que quedaría por hacer es un webserver que muestre la temperatura en el navegador web.

Saludos!

-
Leonardo Garberoglio