Capa de percepción - Sesión 3
- Aprender a usar la tarjeta de desarrollo ESP32.
- Comprender la API básica de entrada y salida del lenguaje Arduino.
Referencias principales
- La mayor parte de esta clase tomará como base la lección 2 A deeper dive into IoT (lección 2) del curso IoT for Beginners (link).
- También mucha de la información se tomó de la pagina: https://randomnerdtutorials.com/
- ESP32 Arduino Core’s documentation (link)
- Páginas de referencia fundamentales (para ver lo que se puede hacer):
Arduino Framework
Cuando hablamos de arduino no solo nos referimos a un microcontrolador especifico, en realidad estamos hablando del framework para microcontroladores mas popular en la actualidad.
Arduino es una plataforma opensource de electronica que combina software y hardware. Al ser esta plataforma open hardware, es posible usar el modelo de programación de Arduino para escribir codigo para cualquier otra plataforma compatible con Arduino (placas genericas o de otroa fabricantes).
El modelo de programación de arduino esta basado en el API de arduino el cual espone un conjunto de funciónes y estructuras (constantes, variables, tipos de datos, objetos, etc) que permiten la interacción del microcontrolador con hardware externo (sensores y actuadores). La información del API se encuentra en la pagina Language Reference (link).
Funciones basicas del API de Arduino
Las funciones basicas del API de Arduino se encuentran online en Language Reference (link)
Entrada y Salida digital
Las funciones de entrada y salida permiten básicamente dos cosas:
- Configurar los puertos (pines) como entradas o salidas digitales.
- Leer o escribir dichos puertos de acuerdo a la forma como fueron configurados.
Función | Información de la función |
---|---|
digitalWrite() | Descripción (link): Escribe un valor HIGH o LOW en un puerto determinado. Sintaxis: digitalWrite(pin, value) Parámetros: HIGH o LOW ). |
digitalRead() | Descripción (link): Lee el valor de un puerto determinado. Sintaxis: digitalRead(pin) Parámetros: HIGH o LOW ). |
pinMode() | Descripción (link): Permite configurar un puerto como entrada o salida. Sintaxis: pinMode(pin, mode) Parámetros: INPUT , OUTPUT o INPUT_PULLUP . |
Funciones de entrada y salida análoga
Permiten interactuar (leer o escribir) con puertos que funcionan como entradas o salidas análogas. La siguiente tabla muestra resume algunas de estas:
Función | Información de la función |
---|---|
analogRead() | Descripción (link): Lee el valor de un puerto análogo determinado devolviendo un valor entero asociado al voltaje que tiene este puerto. Sintaxis: analogRead(pin) Parámetros: A0 – A5 para la mayoría de las placas) del ArduinoValores retornados: Valor análogo leído en el pin. El rango dependerá de la resolución del conversor análogo digital asociado a el pin (0 – 1024 cuando la resolución es de 10 bits o 0 – 4096 cuando la resolución es de 12 bits). |
analogWrite() | Descripción (link): Escribe un valor análogo (modificando el valor del ciclo de dureza de una onda PWM) a un puerto. Sintaxis: analogWrite(pin, value) Parámetros: |
Bases de tiempo
Son funciones empleadas para la crear retardos y generar marcas de tiempos en los programas, existen varias funciones para este fin como delay()
, delayMicroseconds()
, micros()
y millis()
. La siguiente tabla describe la función delay()
que fue la empleada en los ejemplos anteriores:
Función | Información de la función |
---|---|
delay() | Descripción (link): Detiene el programa por una cantidad de tiempo (en milisegundos) especificada como parámetro. Sintaxis: delay(ms) Parámetros: |
Funciones de interacción con el puerto serial
Son funciones empleadas para la configuración e interacción con el puerto serial (link). La siguiente figura muestra algunas funciones de uso común
Función | Descripción |
---|---|
Serial.begin() | Configura la velocidad de transmisión serial (bits por segundo = baud). Sintaxis: Serial.begin(speed) Parámetros: speed : Velocidad de transmisión |
Serial.print() | Imprime los datos del puerto serial en formato ASCII. Sintaxis: Serial.print(val) Serial.print(val, format) Parámetros: val : Valor a imprimir. El valor puede ser de cualquier tipo.format : Formato de representación del ASCII (DEC , HEX , OCT o BIN ). |
Serial.available() | Obtiene el número de bytes (caracteres) disponibles por leer en el puerto serial. Estos son datos que ya han llegado y han sido almacenados en el buffer de recepción serial (el cual almacena 64 bytes). Sintaxis: Serial.available() Valores retornados: Número de bytes disponibles para leer. |
Serial.read() | Lee un dato que entra a través del serial. Sintaxis: Serial.read() Valores retornados: Primer byte de los datos seriales disponibles (o -1 si no hay datos disponibles). El tipo de dato leído es int . |
Pasos para programar un dispositivo usando el Framework de Arduino
Arduino Cheat Sheet: Existen referencias breves que muestran de manera resumida el API de arduino. La referecia Arduino Cheat Sheet (link) es uno de estos casos (URL principal)
Para usar el API de arduino es necesario tener en cuenta los siguientes pasos:
- Si la placa es generica, verificar esta es Arduino compatible (link wikipedia)
- Identificar claramente, las caracteristicas, los pines y la funcionalidad de la placa a usar. Para esto es necesario revisar el manual de usuario de la placa, A continuación se muestran algunos ejemplos:
- Proceder a programar el codigo del firmware siguiendo el modelo de programación de Arduino.
Ejemplos introductorios
A continuación se muestra mediante varios ejemplos como se aplican los pasos mencionados para tres de las plataformas basadas en microcontroladores disponibles en el laboratorio:
Arduino UNO
Material requerido
Pinout
Para empezar a trabajar con cualquier plataforma de desarrollo es necesario conocer como mínimo el mapa de pines, el cual se muestra a continuación:
Es importante notar, que los pines son multifuncionales, es decir, pueden ser empleados para diferentes funciones. La determinación de la función que puede llevar un pin se hace por programación.
Para mas información sobre esta tarjeta, le recomendamos revisar el link Overview of the Arduino UNO Components [link].
Funciones
El documento Arduino Cheat Sheet [link] contine un resumen de algunas de las principales funciones que se usan para programar plataformas Arduino. Para mas información sobre estas puede consultar la sección Language Reference.
Librerias
Ademas de las funciones, propias del API de Arduino, es posible hacer uso de librerias para agregar funcionalidad extra (tal y como sucede con el software). Una de las mayores fortalezas de la plataforma Arduino se encuentra en que esta posee una gran numero de librerias. En la sección Libraries [link] se encuentra toda la información relacionada con diferentes librerias existentes, hardware soportado y, adicionalmente, se muestra como realizar una libreria. Hay tres cosas fundamentales para trabajar con librerias:
- Instalación de librerias (Installing Libraries [link])
- Escritura de librerias (Writing a Library for Arduino [link])
- Guia de estilo (Arduino Style Guide for Creating Libraries [link])
Ejemplos basicos
Cuando se tienen unas nociones basicas de programación, la mejor manera para aprender consiste en leer, ejecutar y comprender código a traves del desarrollo de ejemplos sencillos. Luego, y luego, aplicando lo ya aprendido realizar la adaptación del código al caso particular. Para hacer esto, nuestra recomendación es que tenga a la mano los siguientes materiales:
Item | Material | Link |
---|---|---|
1 | Language Reference | https://www.arduino.cc/reference/en/ |
2 | Built-in Examples | https://docs.arduino.cc/built-in-examples/ |
3 | Libraries | https://www.arduino.cc/reference/en/libraries/ |
4 | Tutorials | https://docs.arduino.cc/tutorials/ |
Como punto de partida tenga a la mano, minimamente los enlaces asociados a los items 1 y 2 de la tabla anterior y la Arduino Cheat Sheet [link]. La idea es empezar a mirar unos cuantos ejemplos los cuales vienen implementados en IDE de arduino tal y como se muestra en la siguiente figura:
Veamos algunos ejemplos.
Ejemplo 1
En este ejemplo se pone a parpadear un led a un periodo de 2 segundos. La descripción completa del ejemplo se encuentra en Blink. El codigo se muestra a continuación:
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
Tambien se muestra el esquematico asociado:
Y el diagrama de conexión:
Ejemplo 2
Este ejemplo se encuentra en How to Wire and Program a Button [link]. En éste se prende un led cuando se presiona un switch.
El codigo asociado se muestra a continuación:
const int buttonPin = 2;
const int ledPin = 13;
int buttonState = 0;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
}
void loop() {
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
digitalWrite(ledPin, HIGH);
}
else {
digitalWrite(ledPin, LOW);
}
}
El esquematico asociado se muestra a continuación:
Finalmente, el diagrama de conexión es el siguiente:
Ejemplo 3
Este ejemplo es tomado de Fading [link]. En este ejemplo se modifica el brillo de un led de manera automatica.
int ledPin = 9;
void setup() {
// nothing happens in setup
}
void loop() {
for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {
analogWrite(ledPin, fadeValue);
delay(30);
}
for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {
analogWrite(ledPin, fadeValue);
delay(30);
}
}
El esquematico del ejemplo se muestra a continuación:
Finalmente, las conexiones son las siguientes:
Ejemplo 4
Este ejemplo es tomado de Analog Read Serial [link]. Aqui, se lee un potenciometro y se imprime su estado a traves del monitor serial.
void setup() {
Serial.begin(9600);
}
void loop() {
int sensorValue = analogRead(A0);
Serial.println(sensorValue);
delay(1);
}
El esquematico se muestra a continuación:
Finalmente, el diagrama de conexión es el siguiente:
Ejemplo 5
Este ejemplo es tomado de Analog In, Out Serial [link]. Aqui, se usa un potenciometro para controlar el brillo de un led; adicionalmente, se imprime su estado a traves del monitor serial.
const int analogInPin = A0;
const int analogOutPin = 9;
int sensorValue = 0;
int outputValue = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
sensorValue = analogRead(analogInPin);
outputValue = map(sensorValue, 0, 1023, 0, 255);
analogWrite(analogOutPin, outputValue);
Serial.print("sensor = ");
Serial.print(sensorValue);
Serial.print("\t output = ");
Serial.println(outputValue);
delay(2);
}
El esquematico de este ejemplo es el siguiente:
Por otro lado, las conexiones entre los componentes se muestran a continuación:
Implementación de los ejemplos
Para implementar cada uno de los ejemplos se pueden llevar a cabo los siguientes pasosEl proceso de trabajo a lo largo de esta sesión de trabajo será (siendo los pasos 2 y 3 son intercambiables):
- Escribir el programa en el IDE
- Descargar codigo.
- Montar circuito.
- Probar.
ESP8266
El NodeMCU es una plataforma de código abierto con conectividad wifi basada en el SoC ESP8266 (datasheet). Esto la hace una plataforma ideal para el desarrollo de proyectos IoT.
Material requerido
- Tarjeta NodeMcu V3 para ESP8266
- Cable USB tipo C.
- Grove - Starter Kit v3 (link)
- Grove Base Shield for NodeMCU V1.0 (link)
Trabajo previo con fritzing
Para realizar prototipado empleando elementos (de diferentes fabricantes) disponibles en kits de desarrollo a trabajar en el laboratorio siga los pasos ilustrados en el tutorial How to Add Components in Fritzing (para comprender bien el procedimiento puede ver el siguiente video antes de empezar). Para ello agregar los siguientes componentes:
- NodeMCU y otros componentes: Estos componentes se pueden obtener del siguiente repositorio mas exactamente realizar la descarga de la siguiente pagina seleccionando el archivo Fritzing.parts (Pagina del autor: https://www.studiopieters.nl/esp8266-programmer/)
- Grove: Descargar el archivo seeed_fritzing_parts.fzbz del siguiente repositorio
- Elegoo: Las partes se encuentran en el siguiente repositorio. Para ello descargue Elegoo-0.6.3.fzbz
- Adafruit: Descargue el siguiente archivo Fritzing-Library-master.zip, luego descomprima y agregue a la libreria el archivo AdaFruit.fzbz.
Una vez hecho lo anterior estara en la facultad de dibujar diagramas y montajes con los diferentes componentes del laboratorio.
Pinout
Tal y como se menciono en clases anteriores, siempre el punto de partida es conocer el diagrama de pines de la tarjeta de desarrollo; este se muestra a continuación:
El mapa de pines del NodeMCU ESP8266:
- 17 GPIO’s
- SPI
- I2C (implemented on software)
- I2S interfaces with DMA
- UART
- 10-bit ADC
Adicionalmente, el esquema de numeración de los pines de la tarjeta NodeMCU (por ejemplo el pin marcado como D0
) es diferente del esquema de numeración del ESP8266 (esquema interno). Por ejemplo, el pin D0
de la tarjeta esta mapeado al pin interno GPIO16
. La recomendación es usar el esquema de numeración externo.
La siguiente tabla muestra una equivalencia entre la numeración de la tarjeta y la numeración interna:
NodeMCU pin | ESP8266 pin |
---|---|
D0 | GPIO16 |
D1 | GPIO5 |
D2 | GPIO4 |
D3 | GPIO0 |
D4 | GPIO2 |
D5 | GPIO14 |
D6 | GPIO12 |
D7 | GPIO13 |
D8 | GPIO15 |
D9 | GPIO3 |
D10 | GPIO1 |
D11 | GPIO9 |
D12 | GPIO10 |
Según la tabla anterior, es posible codificar sketches usando cualquiera de las dos nomenclaturas. Para comprender lo anterior observe el siguiente fragmento de código donde se usa el pin D2
(GPIO4
) como salida.
-
Nomenclatura del NodeMCU
pinMode(D2, OUTPUT);
digitalWrite(D2, HIGH); -
Nomenclatura del ESP8266
pinMode(4, OUTPUT);
digitalWrite(4, HIGH);
Es importante tener en cuenta que el pin D0
(GPIO16
) solo puede ser usado para GPIO read/write
. No soporta open-drain/interrupt/PWM/I²C
o 1-Wire
. Para comprender mas sobre el esquema de mapeo ver la pagina ESP8266 Pinout Reference: Which GPIO pins should you use? (link)
Arduino core for ESP8266 WiFi chip
Gracias a este pluging (Arduino core for ESP8266 WiFi chip) es posible programar el ESP8266 usando el funciones y librerias propias de API de arduino.
Para consultar la documentación del ESP8266 Arduino core puede consultar el siguiente link [Documentación en ingles|Documentación en español].
En el siguiente link se resumen algunas de las funciones del pluging del arduino para el ESP8266.
Para usar el ESP8266 Arduino core siga las instrucciones mostradas en el siguiente tutorial.
A continuación se van a mostrar los ejemplos hechos en Arduino adaptados a la plataforma ESP8266.
Ejemplo 1
Poner parpadear un led a un periodo de 2 segundos usando el led de la tarjeta NodeMCU. (Código tomado de Cómo programar NodeMCU con el IDE de Arduino [link])
#define LED_BUILTIN 2
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
El funcionamiento (tomado de la pagina original) se muestra a continuación:
Por otro lado, si lo que se hubiera pedido hubiera sido poner a parparear un led, pero en esta ocasión usando el puerto D5 (GPIO14), el código tendria un minimo cambio tal y como se muestra a continuación (Codigo tomado de Example Sketch: Blink [link]):
#define ESP8266_LED D5 // D5 = 14
void setup() {
pinMode(ESP8266_LED, OUTPUT);
}
void loop() {
digitalWrite(ESP8266_LED, HIGH);
delay(500);
digitalWrite(ESP8266_LED, LOW);
delay(500);
}
La conexión asociada al codigo anterior se muestra a continuación:
Ejemplo 2
Prender el led integrado de la placa NodeMCU cuando se presiona un switch. (Código tomado de Cómo programar NodeMCU con el IDE de Arduino [link])
#define LED_BUILTIN 2
#define BUTTON_BUILTIN 0
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
pinMode(BUTTON_BUILTIN, INPUT);
}
void loop() {
int estado = digitalRead(BUTTON_BUILTIN);
digitalWrite(LED_BUILTIN, estado);
}
La siguiente imagen (tomada de la pagina original) muestra el funcionamiento del codigo anterior una vez este ha sido descargado a la tarjeta.
A continuación se muestra el mismo ejemplo anterior pero en este caso se usan los siguientes puertos:
Elemento | Puerto | Componente |
---|---|---|
Switch | D6 (GPIO12 ) | Grove - Red LED |
Led | D1 (GPIO5 ) | Grove - Button |
/* Pin Definitions */
const int LED_PIN = 5; // D1 = GPIO5
const int BUTTON_PIN = 12; // D6 = GPIO12
void setup() {
pinMode(LED_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT);
}
void loop() {
int estado = digitalRead(BUTTON_PIN);
digitalWrite(LED_PIN, estado);
}
A continuación se muestra la conexión del ejemplo anterior usando los componentes (Grove - Red LED y Grove - Button) del kid groove:
Ejemplo 3
Modifica el brillo de un led (conectado al pin D2
(GPIO4
)) de manera automatica.
/* Pin Definitions */
const int ledPin = D2; // D1 = GPIO4
void setup() {
// nothing happens in setup
}
void loop() {
for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {
analogWrite(ledPin, fadeValue);
delay(30);
}
for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {
analogWrite(ledPin, fadeValue);
delay(30);
}
}
A continuación se muestra el diagrama de conexión usando el Grove - Red LED para el código anterior:
Ejemplo 4
En este ejemplo se imprime en el monitor serial una valor de voltaje analogo asociado a un potenciometro:
/* Pin Definitions */
const int ANALOG_PIN = A0; // A0
void setup() {
Serial.begin(9600);
}
void loop() {
int sensorValue = analogRead(ANALOG_PIN);
Serial.println(sensorValue);
delay(1);
}
Para este caso, se conecto al pin A0
el Grove - Rotary Angle Sensor
ESP32
El ESP32 (ESP32 Series Datasheet) es el sucesor del ESP8266. Este ademas de soportar conectividad Wi-Fi, soporta tambien conectividad Bluetooth (4.2 y Low Energy).
Existen diferentes plataformas de desarrollo (ESP32 Development Boards Review and Comparison). En nuestro caso vamos a usar la NodeMCU-32S de Ai-Thinker (Nodemcu-32s Datasheet)
Material requerido
- Tarjeta NodeMCU-32S
- Cable USB tipo C.
- Grove - Starter Kit v3 (link)
- Grove Base Shield for NodeMCU V1.0 (link)
Trabajo previo con fritzing
Para realizar prototipado empleando elementos (de diferentes fabricantes) disponibles en kits de desarrollo a trabajar en el laboratorio siga los pasos ilustrados en el tutorial How to Add Components in Fritzing (para comprender bien el procedimiento puede ver el siguiente video antes de empezar). Para ello agregar los siguientes componentes:
-
ESP32: Cuya parte (ESP32S_HiLetgo.fzpz) puede ser decargada de la paginaESP32S-HiLetgo Dev Boad with Pinout Template. El pinout de esta parte (en fritzing) se muestra en la siguiente imagen:
-
Kid de sensores Elegoo: Ver link anterior...
Pinout
A continuación se muestra el diagrama de pines:
Mas exactamente para el NodeMCU-32s tiene un total de 38 pines los cuales se resumen en la siguiente figura:
La siguiente tabla tomada del datasheet, describe cada uno de estos pines:
No. | Pin Name | Functional Description |
---|---|---|
1 | 3.3V | Module power supply pin |
2 | EN | Chip Enabled Pin, Active High |
3 | SVP | GPIO36,ADC1_CH0,RTC_GPIO0 |
4 | SVN | GPIO39,ADC1_CH3,RTC_GPIO3 |
5 | P34 | GPIO34,ADC1_CH6,RTC_GPIO4 |
6 | P35 | GPIO35,ADC1_CH7,RTC_GPIO5 |
7 | P32 | GPIO32, XTAL_32K_P (32.768kHz Crystal input), ADC1_CH4, TOUCH9,RTC_GPIO9 |
8 | P33 | GPIO33, XTAL_32K_N (32.768kHz Crystal output),ADC1_CH5, TOUCH8,RTC_GPIO8 |
9 | P25 | GPIO25,DAC_1,ADC2_CH8,RTC_GPIO6,EMAC_RXD0 |
10 | P26 | GPIO26,DAC_2,ADC2_CH9,RTC_GPIO7,EMAC_RX_DV |
11 | P27 | GPIO27,ADC2_CH7,TOUCH7,RTC_GPIO17,EMAC_RX_DV |
12 | P14 | GPIO14, ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, HS2_CLK,SD_CLK, EMAC_TXD2 |
13 | P12 | GPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI, HSPIQ, HS2_DATA2,SD_DATA2, EMAC_TXD3 |
14 | GND | GND |
15 | P13 | GPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3,SD_DATA3, EMAC_RX_ER |
16 | SD2 | GPIO9, SD_DATA2, SPIHD, HS1_DATA2, U1RXD |
17 | SD3 | GPIO10, SD_DATA3, SPIWP, HS1_DATA3, U1TXD |
18 | CMD | GPIO11, SD_CMD, SPICS0, HS1_CMD, U1RTS |
19 | 5V | Module power supply pin |
20 | CLK | GPIO6, SD_CLK, SPICLK, HS1_CLK, U1CTS |
21 | SD0 | GPIO7, SD_DATA0, SPIQ, HS1_DATA0, U2RTS |
22 | SD1 | GPIO8, SD_DATA1, SPID, HS1_DATA1, U2CTS |
23 | P15 | GPIO15, ADC2_CH3, TOUCH3, MTDO, HSPICS0, RTC_GPIO13, HS2_CMD,SD_CMD, EMAC_RXD3 |
24 | P2 | GPIO2, ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, HS2_DATA0,SD_DATA0 |
25 | P0 | GPIO0, ADC2_CH1, TOUCH1, CLK_OUT1,RTC_GPIO11, EMAC_TX_CLK; Download mode: external pull low, running mode: floating or external pull high |
26 | P4 | GPIO4, ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, HS2_DATA1,SD_DATA1, EMAC_TX_ER |
27 | P16 | GPIO16, HS1_DATA4, U2RXD, EMAC_CLK_OUT |
28 | P17 | GPIO17, HS1_DATA5, U2TXD, EMAC_CLK_OUT_180 |
29 | P5 | GPIO5, VSPICS0, HS1_DATA6, EMAC_RX_CLK |
30 | P18 | GPIO18, VSPICLK, HS1_DATA7 |
31 | P19 | GPIO19, VSPIQ, U0CTS, EMAC_TXD0 |
32 | GND | GND |
33 | P21 | GPIO21, VSPIHD, EMAC_TX_EN |
34 | RX | GPIO3, U0RXD, CLK_OUT2 |
35 | TX | GPIO1, U0TXD, CLK_OUT3, EMAC_RXD2 |
36 | P22 | GPIO22, VSPIWP, U0RTS, EMAC_TXD1 |
37 | P23 | GPIO23, VSPID, HS1_STROBE |
38 | GND | GND |
Para conocer mas sobre el uso de los pines para esta plataforma se recomienda ver la pagina: ESP32 Pinout Reference: Which GPIO pins should you use?
Arduino core for the ESP32, ESP32-S2, ESP32-S3 and ESP32-C3
De manera similar al ESP8266, el ESP32 puede programarse usando el API arduino. Para mas información puede consultar la documentación de este Core en el siguiente link.
Antes de empezar a usar el core para el esp32s, es necesario instalar las librerias necesarias para ello. Para esto siga las instrucciones que se describen en el link Installing the ESP32 Board in Arduino IDE (Windows, Mac OS X, Linux)
Antes de analizar los ejemplos que se muestran a continuación se recomuenda que de un vistazo al link Getting Started with the ESP32 Development Board
Antes de empezar a realizar los ejemplos, se debe seleccionar la tarjeta con la cual se va a trabajar (NodeMCU-32s) tal y como se muestra en la siguiente figura:
A continuación se van a mostrar los ejemplos hechos en arduino adaptados a la plataforma ESP32.
Ejemplo 1
Poner parpadear un led a un periodo de 2 segundos usando el led de la tarjeta ESP32 (Ejemplo adaptado de: Blink).
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
- Simulación online ejemplo 1: link
Ejemplo 2
Prender el led integrado de la placa ESP32 cuando se presiona un switch. (Código adaptado para el ESP32 del link How to Wire and Program a Button)
const int buttonPin = 5; // (GPIO5)
const int ledPin = LED_BUILTIN;
// variables will change:
int buttonState = 0;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
}
void loop() {
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
}
- Simulación online ejemplo 2: link
A continuación se muestra el diagrama de conexión para este ejemplo:
Para entender mas se recomienda que mire el tutorial ESP32 Digital Inputs and Digital Outputs (Arduino IDE).
Ejemplo 3
Modifica el brillo de un led (conectado al pin GPIO2) de manera automatica. (Código adaptado para el ESP32 del link Fading a LED)
int ledPin = 2; // GPIO2
void setup() {
// nothing happens in setup
}
void loop() {
for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {
analogWrite(ledPin, fadeValue);
delay(30);
}
for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {
analogWrite(ledPin, fadeValue);
delay(30);
}
}
- Simulación online ejemplo 3: link
El diagrama de conexión se muestra a continuación:
Para reforzar los conceptos adquiridos anteriormente ver el enlace ESP32 PWM with Arduino IDE (Analog Output).
Ejemplo 4
Llevar al puerto serial el valor de voltaje de un potenciometro leido a traves del puerto analogo. Adicionalmente empleando una señal PWM, variar el grado de luminosidad del led integrado en la tarjeta ESP32.
const int analogInPin = 15; // GPIO15
const int analogOutPin = LED_BUILTIN; // ESP32 led
int sensorValue = 0;
int outputValue = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
sensorValue = analogRead(analogInPin);
outputValue = map(sensorValue, 0, 4095, 0, 255); // ADC de 12 bits
analogWrite(analogOutPin, outputValue);
Serial.print("sensor = ");
Serial.print(sensorValue);
Serial.print("\t output = ");
Serial.println(outputValue);
delay(2);
}
- Simulación online ejemplo 4: link
El diagrama de conexión se muestra a continuación:
Para comprender mejor este ejemplo se recomienda reforzar viendo el link ESP32 ADC – Read Analog Values with Arduino IDE.
A lo largo de lo que resta la capa de percepción nos vamos a enfocar en la placa ESP32 la cual es una de las mas empleadas en la actualidad en proyectos IoT.
Trabajo de clase
Primeros pasos con el ESP32
Existen diferentes plataformas basadas en el ESP32 (link wikipedia). En el laboratorio del LIS se encuentra la placa NodeMCU-32s (NodeMCU-32 Specification) de la empresa china ai-thinker (http://www.ai-thinker.com/).
Antes de empezar, tenga a la mano, el diagrama de pines del NodeMCU:
Luego, despues de realizar las conexiones de los montajes, realizar los siguientes pasos:
-
Siga los pasos descritos en Installing the ESP32 Board in Arduino IDE (Windows, Mac OS X, Linux) (link).
-
Usando la IDE de Arduino, proceder a codificar los ejemplos que se muestran a continuación eligiendo como targeta de desarrollo la NodeMCU-32s que es la disponible en el laboratorio:
-
Teniendo en cuenta el montaje realizado, codifique el programa para la plataforma elegida. Como el ESP32 es compatible con Arduino la documentación se encuentra en Arduino-ESP32 (link).
-
Descargue el programa en la placa:
Importante: Tenga en cuenta que antes de empezar la descarga del programa debe presionar el botón boot de la placa del ESP32 y liberarlo cuando salga el mensaje "Connecting..." en el IDE de Arduino. (Para más información ver la sección Troubleshooting en el siguiente link)
Ejemplo de clase
Una de las aplicaciones mas utilies del puerto serial es que facilita el debug de aplicaciones gracias a que por medio de este se pueden imprimir, en tiempo de ejecución, mensajes de log que sirven como verificar el correcto funcionamiento de la logica del programa al usar un programa como el monitor serial o cualquier programa similar.
Es muy comun imprimir variables (que pueden indican el estado o valor de un sensor, mensajes de la aplicación, etc). Suponga que se desea probar el siguiente circuito.
Para lo cual se pide que realice las siguientes actividades:
-
Realice la implementación en Fritzing del circuito.
-
Codificar el siguiente programa (usando el API de arduino) y analizarlo para comprender su funcionamiento. Para facilitar las cosas puede correr una simulación de wokwi (https://wokwi.com) en el siguiente link
Codigo: Guarde el programa como esp32-ejemplo.ino:
/*-------------- Debug --------------*/
// Comentar siguiente linea para no hacer debug serial
#define DEBUG 1
/*-------------- Puertos --------------*/
// Swichtes
#define SW1 22
#define SW0 23
// Leds switches
#define LED_SW1 21
#define LED_SW0 19
// Leds secuencia
#define LED_PWM 4
// Potenciometro
#define POT 2
/*-------------- Variables --------------*/
int pot_value = 0; // Valor del potenciometro (0 - 2013)
int val_pwm = 0; // Valor del pwm (0 - 255)
int sw_val1;
int sw_val0;
int num_seq;
int loop_time = 500;
void setup() {
// Inicializacion de las entradas
inicializar_entradas();
inicializar_salidas();
// Debug Serial
#if DEBUG
Serial.begin(9600);
Serial.println("Configuración de I/O -> OK");
#endif
}
void loop() {
/* Entrada analoga */
#if DEBUG
Serial.println("------------------------------------");
#endif
// Lectura de la entrada analoga (Potenciometro)
pot_value = analogRead(POT);
// Mapeo y escritura analoga (PWM)
val_pwm = map(pot_value, 0 , 4095, 0, 255);
analogWrite(LED_PWM,val_pwm);
#if DEBUG
// --- Mensajes de debug (Variables analogas) --- //
Serial.print("POT: ");
Serial.print(pot_value);
Serial.print(" - LED (PWM): ");
Serial.println(val_pwm);
#endif
// Lectura de los switches
sw_val0 = digitalRead(SW0);
sw_val1 = digitalRead(SW1);
// --- Mensajes de debug (Entradas digitales) --- //
#if DEBUG
Serial.print("SW0: ");
Serial.print(sw_val0);
Serial.print(" - SW1: ");
Serial.println(sw_val1);
#endif
// Obtencion de la secuencia binaria
num_seq = obtener_numero_secuencia(sw_val1, sw_val0);
#if DEBUG
// --- Mensajes de debug Opcion --- //
Serial.print("Opcion: ");
Serial.println(num_seq, BIN);
#endif
// Encendido de los leds
encender_leds_indicadores(num_seq);
delay(loop_time);
}
void inicializar_entradas() {
// Inicialice aqui las entradas
pinMode(SW1, INPUT);
pinMode(SW0, INPUT);
}
void inicializar_salidas() {
// Inicialice aqui las salidas
pinMode(LED_SW1, OUTPUT);
pinMode(LED_SW0, OUTPUT);
}
int obtener_numero_secuencia(int sw1, int sw0) {
// Obtiene el numero asociado a una combinación de switches
int number;
if ((sw1 == LOW)&&(sw0 == LOW)) {
number = 0;
}
else if ((sw1 == LOW)&&(sw0 == HIGH)) {
number = 1;
}
else if ((sw1 == HIGH)&&(sw0 == LOW)) {
number = 2;
}
else {
number = 3;
}
return number;
}
void encender_leds_indicadores(int number) {
// Encendido de luces indicadores
switch(number) {
case 0:
digitalWrite(LED_SW1,LOW);
digitalWrite(LED_SW0,LOW);
break;
case 1:
digitalWrite(LED_SW1,LOW);
digitalWrite(LED_SW0,HIGH);
break;
case 2:
digitalWrite(LED_SW1,HIGH);
digitalWrite(LED_SW0,LOW);
break;
default:
digitalWrite(LED_SW1,HIGH);
digitalWrite(LED_SW0,HIGH);
}
}
Circuitos a montar
Para los siguientes circuitos realizar lo siguiente:
- Hacer el diagrama en fritzing de cada uno de los montajes y subalos a la correspondiente carpeta. Use los módulos del 37 Sensor Kit (de Elegoo o de Landzo).
- Realice el montaje en fisico, codifique el programa (entendiendolo obviamente) y muestre su funcionamiento.
Circuito 1: Parpadeo de un led (link)
-
Montaje:
-
Código: esp32-ej1.ino
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
Circuito 2: Lectura de una señal digital (link)
-
Montaje:
-
Código: esp32-ej2.ino
#define LED_BUILTIN 2
const int buttonPin = 5; // (GPIO5 - D5)
const int ledPin = LED_BUILTIN;
// variables will change:
int buttonState = 0;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
}
void loop() {
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
}
Circuito 3: Manejo de una señal PWM (link)
-
Montaje:
-
Código: esp32-ej3.ino
int ledPin = 2; // GPIO2
void setup() {
// nothing happens in setup
}
void loop() {
for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {
analogWrite(ledPin, fadeValue);
delay(30);
}
for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {
analogWrite(ledPin, fadeValue);
delay(30);
}
}
Circuito 4: Lectura de una entrada Análoga (link).
-
Montaje:
-
Código: esp32-ej4.ino
const int analogInPin = 15; // GPIO15
const int analogOutPin = LED_BUILTIN; // ESP32 led
int sensorValue = 0;
int outputValue = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
sensorValue = analogRead(analogInPin);
outputValue = map(sensorValue, 0, 4095, 0, 255); // ADC de 12 bits
analogWrite(analogOutPin, outputValue);
Serial.print("sensor = ");
Serial.print(sensorValue);
Serial.print("\t output = ");
Serial.println(outputValue);
delay(2);
}
Para profundizar: Para ver mas cosas de lo que se puede realizar con la ESP32 puede consultar dentro de la pagia de randomnerdtutorials el link 160+ ESP32 Projects, Tutorials and Guides with Arduino IDE (link)
Referencias
Para ir mas alla puede consultar las siguientes referencias:
- http://www.ee.ic.ac.uk/pcheung/teaching/DE1_EE/Lectures/
- https://randomnerdtutorials.com/projects-esp32/
- https://esphome.io/components/esp32.html
- https://www.espressif.com/en
- https://docs.ai-thinker.com/en/welcome
- https://docs.platformio.org/en/latest/boards/espressif32/nodemcu-32s2.html
- https://reference.arduino.cc/reference/en/libraries/esp32-control/
- https://www3.ntu.edu.sg/home/ehchua/programming/arduino/arduino.html
- https://www3.ntu.edu.sg/home/ehchua/programming/index.html
- https://fab.cba.mit.edu/classes/863.16/
- https://blob.tomerweller.com/