ESP32 DEVKITV1

Potenciómetro regulador de voltaje con la ESP32 DEVKITV1

Montaje de prueba con un potenciómetro de 10K Ohms conectado a una entrada analógica de la placa ESP32 DEVKITV1 para medir voltaje. La ESP32 transmite ese voltaje a través de Wi-Fi actuando como un "Access Point" y usando WebSockets.

Pruebas entrada de potenciómetro a una entrada analógica de la placa ESP32 DEVKITV1

Esquema de los tres cables utilizados para conectar la ESP32 DEVKITV1 con el potenciómetro...

Se usan tres cables para conectar el potenciómetro a la ESP32 DEVKITV1


Conexión con el Access Point de la ESP32 DEVKITV1 desde un PC con Windows...

El AP con el nombre POTENCIOMETRO es el que corresponde a la ESP32


Vídeo del funcionamiento (Formato: .mp4 - Tamaño 40,6 MB)...

Ver un vídeo con el funciomaniento del montaje

Montaje realizado siguiendo las indicaciones y programa de la página web:

https://www.esploradores.com/practica-14-websockets-2/

El código fuente utilizado en la prueba es el publicado en la página indicada anteriormente con la salvedad de que se han realizado pequeños cambios para adaptarlo al ESP32 en lugar del ESP8266. Por ejemplo, se cambian los nombres de algunas librerías y funciones por las necesarias en el ESP32 y se varía el rango de posibles valores leídos del potenciómetro que en el ESP8266 era de 1024 (10 bits) y en el ESP32 da mayor resolución obteniéndose valores entre 0 y 4095 (12 bits).

/* Ejemplo de comunicación WebSocket Servidor <---> Cliente. Escrito por Dani No www.esploradores.com

Este sofware está escrito bajo la licencia CREATIVE COMMONS con Reconocimiento-CompartirIgual(CC BY-SA) https://creativecommons.org/

-Redistributions of source code must retain the above creative commons and this list of conditions and the following disclaimer.
-Redistributions in binary form must reproduce the above creative commons notice, this list of conditions and the following disclaimer in
 the documentation and/or other materials provided  with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
COPYRIGHTHOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES INCLUDING, 
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#if defined(ESP8266)
    #define HARDWARE "ESP8266"
    #include "ESP8266WiFi.h"
#elif defined(ESP32)
    #define HARDWARE "ESP32"
    #include "WiFi.h"
#endif

#include <WebServer.h>

// #include <ESP8266WiFi.h>                         // Incluye una librería externa para gestionar la conexión WiFi

#include <WebSocketsServer.h>                    // Incluye una librería externa para gestionar la conexión WebSocket
// #include "./WebSockets-2.3.6/src/WebSocketsServer.h"
// #include <WebSockets_Generic.h>
// #include <ESP8266WebServer.h>                    // Incluye una librería externa para facilitar la gestión del servidor
#define analog_ip A0                             //-analog_ip-   Nombre del pin analógico (A0) de entrada de datos -analog input-

static unsigned long last;                       //-last-        Variable para almacenar el tiempo (ms) que lleva el procesador encendido
int inputVal;                                    //-inputVal-    Variable para almacenar el último valor leído en la entrada analógica
float voltVal;                                   //-voltVal-     Variable para almacenar el voltaje (calculado a partir de inputVal)
float voltValPrev = 0 ;                          //-VoltValPrev- Variable para almacenar el voltaje tomado en la lectura previa 
String myString;                                 //-myString-    Variable para almacenar el voltaje convertido a cadena de texto

const char* ssid = "POTENCIOMETRO";              //Nombre de la red -SSID- (Access Point) que vamos a crear
const char* password = "12345678";               //Clave de la red -PASSWORD-

static const char INDEX_HTML[] PROGMEM = R"(     <!--Documento HTML para almacenar en la memoria flash (En la variable INDEX_HTML)-->
<!DOCTYPE html>                                                                       <!--Declaración del tipo de documento: HTML5-->
<html>                                                                                <!--Inicio del documento HTML-->
  <head>                                                                              <!--Inicio de la cabecera -inf.sobre el doc.-->
      <meta charset=utf-8>                                                            <!--Config. de carácteres utilizada: UTF-8-->
      <meta name='viewport' content='initial-scale=1, maximum-scale=1'>               <!--Control de la composición del documento
                                                                                         (hace que se muestre similar en distintos
                                                                                          dispositivos y navegadores)-->
      <title>WebSocket ESP32 - POTENCIOMETRO</title>                                  <!--Título del documento -->
  </head>                                                                             <!--Fin de la cabecera -->
  <body>                                                                              <!--Inicio el cuerpo -contenido visible del doc.-->
    <h1>LECTURA DE UN POTENCIÓMETRO JIDS</h1>                                         <!--Texto de enabezado -título principal (h1)-->
    <p>Comunicación vía WebSocket: Servidor (ESP32) <---> Cliente</p>                 <!--Párrafo-->
    <canvas id="myCanvas" width="350" height="350" style="border:1px solid #d3d3d3;"> <!--Área de dibujo (canvas) de 350x350px. con-->
    Tu navegador no soporta el elemento CANVAS de HTML5.</canvas>                     <!--borde de 1px gris. Nombre de ID: 'myCanvas' -->
                                                                                      <!--Si es incompat. con nav.se muestra msg.error-->
    <script>                                                                          //Inicio del JavaScript -programación del docum.-
       var connection = new WebSocket('ws://'+location.hostname+':81/', ['arduino']); /*Crea un WebSocket conectándose con el servidor
                                                                                       ws://[IP del servidor]:81/ con el protocolo
                                                                                       de 'arduino'*/
       connection.onopen = function () {                                              //Al abrir la conexión...
         connection.send('Conectado  -  ' + new Date());                              //...envía 'Conectado' + fecha y hora al servidor
         console.log('Conectado  -  ' + new Date());                                  //...envía 'Conectado' + fecha y hora a la consola
       }
       connection.onmessage = function (event) {                                      //Al recibir un msg...(voltaje leído por ESP8266)
         console.log('Servidor (recibe): ', event.data);                              //...envía 'Serv. (recibe):'+ mensaje a la consola
         verValor();                                                                  //...ejecuta la función verValor()
       }
       connection.onerror = function (error) {                                        //Si hay un error en la conexión...
         console.log('WebSocket Error!!!', error);                                    //...envía 'WS Error!!!'+tipo de error a la consola
       }
       function verValor() {                                                          //Declara la función verValor() Cuando se ejecuta:
         var valor = event.data;                                                      //Asigna a la variable local valor el msg.recibido
         var c = document.getElementById('myCanvas');                                 //Crea el nodo DOM para el elemento c (canvas)
         var ctx = c.getContext('2d');                                                //Establece el contexto de representación (2D)
         ctx.clearRect(0, 0, myCanvas.width, myCanvas.height);                        //Limpia el canvas (para evitar superposiciones)
         ctx.beginPath();                                                             //Comienza un nuevo trazado (una parte del dibujo)
         ctx.lineWidth = 40;                                                          //Anchura de los trazos: 40 pixels
         ctx.strokeStyle = '#EEEEEE';                                                 //Color de los trazos: gris claro
         ctx.arc(175,175,100,0.75*Math.PI,0.25*Math.PI);                              /*Trazo: arco con centro (175,175), radio 100px
                                                                                       y ángulo de giro entre 0.75π y 0.25π rad*/
         ctx.stroke();                                                                //Representa en pantalla el trazado
         ctx.beginPath();                                                             //Comienza un nuevo trazado
         ctx.strokeStyle = '#87CEEB';                                                 //Color de los trazos: azul cielo (sky blue)
         ctx.arc(175,175,100,(0.25-(1.5/3.3)*valor)*Math.PI,0.25*Math.PI);            /*Trazo: arco con centro (175,175), radio 100px
                                                                                       y ángulo de giro proporcional al voltaje medido
                                                                                       3.3V serán 1.5π rad.El arco termina en 0.25π rad*/
         ctx.stroke();                                                                //Representa en pantalla el trazado
         ctx.font = 'bold 40px Arial';                                                //Fuente de texto: arial, 40 px negrilla
         ctx.fillStyle = '#87CEEB';                                                   //Color de texto: azul cielo
         ctx.textAlign = 'center';                                                    //Posición de texto: centrado
         ctx.fillText(valor+"V",175, 185);                                            //Texto a representar: mensaje+V. Centro (175,185)
       }
    </script>                                                                         <!--Fin del JavaScrip-->
  </body>                                                                             <!--Fin del cuerpo-->
</html>                                                                               <!--Fin del documento HTML-->
)";
// ESP8266WebServer server (80);                                                        //Puerto de conex. del Servidor (Access Point) nº80
WebServer server (80);                                                        //Puerto de conex. del Servidor (Access Point) nº80
WebSocketsServer webSocket = WebSocketsServer(81);                                    //Puerto de conex. del WebSocket nº81

void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {   /*Declara la función webSocketEvent para gestionar
                                                                                       los 'eventos' relativos a la conexión WebSocket*/
  switch(type) {                                                                      //SI EL 'EVENTO' ES...
    case WStype_CONNECTED: {                                                          //...UNA NUEVA CONEXIÓN WEBSOCKET CON UN CLIENTE:
      IPAddress ip = webSocket.remoteIP(num);                                         /*Asigna a la variable ip la dirección IP
                                                                                       de la conexión y el nº de conexión del WS*/
      Serial.printf("[%u] Conectado a través de la URL: %d.%d.%d.%d - %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);
                                                                                      //Envía al Mon. Serie el nº de conex. y direcc. IP 
      myString = String(voltVal);                                                     //Convierte el voltaje medido en una cadena de txt.
      webSocket.sendTXT(num,myString);                                                //Envía la cadena de texto al nuevo cliente
      }                                                            
      break;                                                                          //Finaliza el evento

    case WStype_DISCONNECTED:                                                         //...EL CESE DE UNA CONEXIÓN WEBSOCKET:
      Serial.printf("[%u] Desconectado!\n", num);                                     //Envía al Mon.Serie el msg. con nº WS desconectado
      break;                                                                          //Finaliza el evento

    case WStype_TEXT:                                                                 //...UN MENSAJE DE TEXTO RECIBIDO POR LA CONEX. WS:
      Serial.printf("Número de conexión: %u  -  Carácteres recibidos: %s\n  ", num, payload);
                                                                                      //Envía al Mon. Serie el msg. con nº WS de origen
      break;                                                                          //Finaliza el evento

    case WStype_ERROR:                                                                //...UN ERROR EN LA CONEXIÓN WEBSOCKET
      Serial.printf("Se ha recibido un error. \n");                                   //Envía al Monitor Serie el mensaje de error
      break;                                                                          //Finaliza el evento
    }
  }

void setup() {                                        //Declara la func. SETUP -Configuración inicial del sketch-
  Serial.begin(115200);                               //Velocidad del Puerto Serie en baudios (115200)
  Serial.println();                                   //Salto de línea en el Puerto Serie

  WiFi.softAP(ssid, password);                        //Inicializa la conexión WiFi -Access Point- (AP)
  IPAddress myIP = WiFi.softAPIP();                   //Asigna a la variable myIP la dirección IP del AP                     
  Serial.print("IP del access point: ");              //Envía al Monitor Serie el texto
  Serial.println(myIP);                               //Envía al Monitor Serie el la dirección IP del AP
  
  webSocket.begin();                                  //Inicializa la conexión WebSocket
  webSocket.onEvent(webSocketEvent);                  /*Cuando se recibe un 'evento' relativo al WS
                                                       se ejecuta la función webSocketEvent para su gestión*/

  server.on("/", []() {                               //Si el servidor recibe la dirección IP del AP (myIP) desde un cliente...
      server.send_P(200, "text/html", INDEX_HTML);    //...envía la página WEB almacenada en la memoria flash al cliente
  });
  server.begin();                                     //Inicializa el servidor
  Serial.println("WebServer iniciado...");            //Envía al Monitor Serie el texto 
}

void loop() {                                         //Declara la func. LOOP -Funciones del sketch que se repiten indefinidamente-
  webSocket.loop();                                   //El servidor 'escucha' los 'eventos' de la conexión WebSocket
  server.handleClient();                              /*El servidor 'escucha' las peticiones entrantes de los clientes. Conforme a lo 
                                                       programado solo puede responder a la petición de la página WEB almacenada*/

  if (labs(millis()-last) > 100) {                     //Cada 100 ms (0,1s)... 
    inputVal = analogRead (analog_ip);                //...se realiza la lectura del pin analógico. Da valores entre 0 y 4095 (12 bits)
    // voltVal = 0.01*(round(inputVal*3.30/1023*100));   /*...se mapea el resultado entre 0 y 3.30 para obtener el voltaje que deja pasar
    voltVal = 0.01*(round(inputVal*3.30/4095*100));   /*...se mapea el resultado entre 0 y 3.30 para obtener el voltaje que deja pasar
                                                       el potenciómetro y se redondea a dos decimales*/
    last = millis();                                  //...se toma el tiempo de referencia para volver a ejecutar esta func. condicional
  }

  if (voltVal != voltValPrev) {                       //Si el voltaje ha cambiado respecto a la lectura previa...
    Serial.println (voltVal);                         //...envía al Monitor Serie el nuevo voltaje
    myString = String(voltVal);                       //...convierte el voltaje de nº(float) a cadena de texto (String) 
    webSocket.broadcastTXT(myString);                 //...envía el voltaje como txt. a todos los dispositivos conectados vía WebSocket
    voltValPrev = voltVal;                            //...se toma el voltaje de referencia para volver a ejecutar esta func. condicional
    }
}

Principales cambios realizados en el código original para usarlo con el ESP32...

En la línea 17 se comentan algunas líneas requeridas por la ESP8266 y se modifican por las librerías equivalentes de la ESP32...

#if defined(ESP8266)
    #define HARDWARE "ESP8266"
    #include "ESP8266WiFi.h"
#elif defined(ESP32)
    #define HARDWARE "ESP32"
    #include "WiFi.h"
#endif

#include <WebServer.h>

// #include <ESP8266WiFi.h>                         // Incluye una librería externa para gestionar la conexión WiFi

#include <WebSocketsServer.h>                       // Incluye una librería externa para gestionar la conexión WebSocket
// #include "./WebSockets-2.3.6/src/WebSocketsServer.h"
// #include <WebSockets_Generic.h>
// #include <ESP8266WebServer.h>                    // Incluye una librería externa para facilitar la gestión del servidor

En la línea 102 se realiza el siguiente cambio...

// ESP8266WebServer server (80);                                              //Puerto de conex. del Servidor (Access Point) nº80
WebServer server (80);                                                        //Puerto de conex. del Servidor (Access Point) nº80

En la línea 161 se realiza varía el rango de bits que procesa el ESP32 con respecto al ESP8266 para determinar la posición del potenciómetro...

    // voltVal = 0.01*(round(inputVal*3.30/1023*100)); /*...se mapea el resultado entre 0 y 3.30 para obtener el voltaje que deja pasar
    voltVal = 0.01*(round(inputVal*3.30/4095*100));    /*...se mapea el resultado entre 0 y 3.30 para obtener el voltaje que deja pasar
                                                         el potenciómetro y se redondea a dos decimales*/