Servidor Web en Esp32-Cam con MicroPython




Presentación


El presente proyecto continuando sobre modos de programacion alternativa al propuesto por el IDE de Arduino que permitiera superar la molesta necesidad de que ante la menor modificacion hubiera subir todo el proyecto completo a la placa para poder probar su funcionamiento esta desarrollado tambien en MicroPython y utilizando el Thonny como IDE

Se ha utilizado una placa Esp32-Cam en virtud de que en futuros proyectos se buscara anexarle al servidor web la visualizacion de la camara.

El proyecto consiste en montar en la placa Esp32-Cam un pequeño servidor web consistente en una pagina principal que mediante botones controla el encendido y apagado del led flash incorporado a la placa



Materiales


Placa Esp32-Cam

Programador Esp32-Cam


Si bien por ser mas cómodo y práctico se ha usado el adaptador el mismo puede ser remplazado por una placa FTDI y el cableado pertinente.


Montaje del proyecto en la placa Esp8266


Para utilizar la placa Esp32-Cam con MicroPython es necesario flashear primero la misma con el firmware correspondiente. En el caso de la utilizada en este modelo se utilizo el provisto por la pagina de https://github.com/lemariva/micropython-camera-driver/tree/master/firmware

Una vez instalado el firmware en la placa utilizando la utilidad que viene provista por el IDE Thonny, o por aquella que ustedes utilicen ademas del firmware quedara grabado en la placa un archivo boot.py que debe ser reemplazo por el que se incluye en el codigo desarrollado a continuacion.


Codigo


El codigo se ha escrito en tres archivos boot.py, main.py y pagina.py.

El archivo boot.py ademas de contener los datos necesarios para el arranque de la placa, contiene los datos de la red wifi a la que se va a conectar los cuales deben ser agregados en el lugar indicado.

El archivo main.py es el nucleo del servidor, el nombre elegido para el mismo es a efectos que el programa se inicie automaticamente. Este archivo se incia con la configuracion los pines que se vayan a utilizar en este caso el pin 4 y contiene los llamadas y respuestas a las paginas web y las funciones correspondientes al manejo de los pines de la placa.

El archivo pagina.py esta destinado a contener las distintas paginas html que seran servidas por el servidor conforme las llamadas que se realicen a traves de la funcion 'pagina_web(n_pag):' que se encuentra en el archivo main.py.


boot.py



        from machine import Pin, reset
        import network
        import socket
        import time
        
        
        import esp
        esp.osdebug(None)
        
        #Recupera la memoria ocupada por objetos que no son necesarios para el programa
        import gc
        gc.collect()
        
        #Coneccion WiFi
        #completar con los datos correspondientes
        red = ' '#nombre de la red
        clave = ' ' #clave de la red
        
        indicator = Pin(0, Pin.OUT)
        wlan = network.WLAN(network.STA_IF)
        if not wlan.isconnected():
            wlan.active(True)
            wlan.connect(red, clave)
            print('Conectando a: %s' % red)
            timeout = time.ticks_ms()
            while not wlan.isconnected():
                indicator.on()
                time.sleep(0.15)
                indicator.off()
                time.sleep(0.15)
                if (time.ticks_diff (time.ticks_ms(), timeout) > 10000):
                    break
            if wlan.isconnected():
                indicator.on()
                print('Se conecto a: %s' % red)
                print('IP: %s\nSUBNET: %s\nGATEWAY: %s\nDNS: %s' % wlan.ifconfig()[0:4])
            else:
                indicator.off()
                wlan.active(False)
                print('Fallo la conexion a: %s' % ssid)
        else:
            indicator.on()
            print('Conectado a\nIP: %s\nSUBNET: %s\nGATEWAY: %s\nDNS: %s' % wlan.ifconfig())
    

main.py



        import pagina
        #Configuracion de Pines
        led = Pin(4, Pin.OUT)
        #Pagina Web
        def pagina_web():
            html = pagina.pagina(1)
            return html
        #Socket Configuracion
        try:
            tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            tcp_socket.bind(('', 80))
            tcp_socket.listen(5)
            time.sleep(1)
            print('Configuracion de socket exitosa\n')
        except OSError as e:
            print('Fallo configuracion de socket. Reeinicia...\n')
            time.sleep(3)
            reset()
            print('Listo...!\n********************************\n')
        
        while True:
            try:
                if gc.mem_free() < 102000:
                    gc.collect()
                conn, addr = tcp_socket.accept()
                conn.settimeout(3.0)
                print('Nueva conexion de: %s' % str(addr[0]))
                request = conn.recv(1024)
                conn.settimeout(None)
                request = str(request)
                #print('Request: %s' % request)
                if request.find('/?control1=on') == 6:
                    print('LED: ON')
                    led.value(1)
                if request.find('/?control1=off') == 6:
                    print('LED: OFF')
                    led.value(0)
                conn.send('HTTP/1.1 200 OK\n')
                conn.send('Content-Type: text/html\n')
                conn.send('Connection: close\n\n')
                conn.sendall(pagina_web())
                conn.close()
            except OSError as e:
                conn.close()
            time.sleep(0.1)
        pagina
        
        #Configuracion de Pines
        led = Pin(4, Pin.OUT)
        #Pagina Web
        def pagina_web():
            html = pagina.pagina(1)
            return html
        
        #Socket Configuracion
        try:
            tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            tcp_socket.bind(('', 80))
            tcp_socket.listen(5)
            time.sleep(1)
            print('Configuracion de socket exitosa\n')
        except OSError as e:
            print('Fallo configuracion de socket. Reeinicia...\n')
            time.sleep(3)
            reset()
        print('Listo...!\n********************************\n')
        
        while True:
            try:
                if gc.mem_free() < 102000:
                    gc.collect()
                conn, addr = tcp_socket.accept()
                conn.settimeout(3.0)
                print('Nueva conexion de: %s' % str(addr[0]))
                request = conn.recv(1024)
                conn.settimeout(None)
                request = str(request)
                #print('Request: %s' % request)
                if request.find('/?control1=on') == 6:
                    print('LED: ON')
                    led.value(1)
                if request.find('/?control1=off') == 6:
                    print('LED: OFF')
                    led.value(0)
                conn.send('HTTP/1.1 200 OK\n')
                conn.send('Content-Type: text/html\n')
                conn.send('Connection: close\n\n')
                conn.sendall(pagina_web())
                conn.close()
            except OSError as e:
                conn.close()
            time.sleep(0.1)
      
    

pagina.py



      
        def pagina(ped):

    if ped == 1:
        pagina_html = """
            <!DOCTYPE html>
            <html>
            <head>
                <title>MicroPython</title>
                <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1">

                <style type="text/css">
                        *{
                        padding: 0px; margin: 0px;
                    }
                    .home{
                        padding: 0px 0px 10px 0px; background-color: #ffffff;
                    }
                    .nav{
                        box-sizing: border-box; display: inline-block;
                        padding: 10px 0px 10px 0px; background-color:#F8DB9C;
                        width: 100%; height: auto;
                    }
                    .control{
                        box-sizing: border-box; display: inline-block;
                        padding: 0px 0px 15px 0px; background-color: #D6F89C;
                        border: 4px solid #46FF33; border-radius: 20px;
                        width: auto; height: auto; margin: 30px;
                    }
                    .myline {
                        border: 2px solid #46FF33;
                    }
                    #t1{
                        font-family: Helvetica; font-weight: bold;
                        text-align: center; font-size: 50px; color: red;
                    }
                    #t2{
                        font-family: Helvetica; font-weight: bold;
                        text-align: center; font-size: 20px; color: white;
                    }
                    #t3{
                        font-family: Helvetica; font-weight: bold;
                        font-size: 30px; color: #db1c13;
                    }
                    #imag{
                        width: 200px; height: 200px; padding: 25px;
                    }
                    #on{
                        border: 4px solid green; border-radius: 20px;
                        background-color:white; color: green;
                        font-weight: bold; font-size: 20px;
                        width: 150px; height: 50px; cursor:pointer;
                    }
                    #off{
                        border: 4px solid red; border-radius: 20px;
                        background-color:white; color: red;
                        font-weight: bold; font-size: 20px;
                        width: 150px; height: 50px; cursor:pointer;
                    }
                </style>
            </head>
            <body>
                <div class='nav'>
                    <h1 id='t1'>Servidor Web Esp32-Cam</h1>
                </div>
                <div class="home">
                    <center>
                    <div class="control">
                        <img id="imag"  src="https://cdn.pixabay.com/animation/2022/11/17/00/47/00-47-21-570_512.gif">
                        <hr class="myline"><br />  
                        <button id='on' type="button" onclick="window.location.href='/?control1=on'">ON</button>  
                        <button id='off' type="button" onclick="window.location.href='/?control1=off'">OFF</button>  
                    </div>
                    <p>Enciende y apaga el Led de la Esp32-Cam</p>
                    </center>
                </div>
            </body>
            </html>
            """
        return pagina_html

    if ped == 0:
        pagina_html = """<html>
                <head>
                </head>
                <body align="center">
                    <br>
                    <h1>Pagina inexistente</h1>
                </body>
                </html>"""
        return pagina_html

      
    

Cerrar