Muy buenas a todas y todos!!!
Después de la buena experiencia programando el ESP32-C3 mini junto con el módulo de la pantalla SH1106 y el encoder, y otro proyecto que aún estoy probando.
Este pequeño no comparte los mismos pines que el ESP32C3 mini así que si ya tienes un montaje realizado para el mini no te servirá, pero eso no quita que sus pines GPIO sean igual de versátiles, veamos las características y los pines de esta pequeña placa de desarrollo:
Hardware e interfaces
- 22 pines GPIO programables.
- Comunicación vía UART, SPI, I2C, I2S y USB Serie/JTAG.
- Funciones analógicas: dos SAR de 12 bits Convertidores analógico-digitales (ADC), sensor de temperatura integrado.
Procesador y memoria
- Procesador: ESP32-C3FN4/FH4, RISC-V de 32 bits de un solo núcleo, hasta 160 MHz.
- Memoria flash: 4 MB.
- Pantalla: OLED de 0,42 pulgadas para información visual directa.
- Conectividad: Wi-Fi de modo dual (802.11b/g/n) y Bluetooth 5 (LE, malla).
- Programación: Fácil vía USB, en este caso USB-C.
- Antena: Antena cerámica integrada.
Funciones de Wi-Fi y Bluetooth
El ESP32 integra conectividad dual Wi-Fi y Bluetooth 5 LE, optimizada para aplicaciones que requieren velocidad y eficiencia. Estas son sus capacidades más relevantes:
- Wi-Fi con velocidades de datos de hasta 150 Mbps, compatible con ancho de banda de 20/40 MHz.
- Bluetooth 5 LE con alta potencia de transmisión de hasta 20 dBm y red mallada.
- Coexistencia interna entre Wi-Fi y Bluetooth para el uso de antena compartida.
- Compatible con múltiples modos Wi-Fi: Estación, SoftAP y modo promiscuo.
Bajo consumo de energía y seguridad
El ESP32 ha sido diseñado para ofrecer un rendimiento óptimo en aplicaciones IoT sin sacrificar la eficiencia energética ni la protección de los datos.
A continuación, se detallan sus características más destacadas en este ámbito:
- Cuatro modos de ahorro de energía, incluyendo un modo de suspensión profunda con un consumo de corriente de tan solo 5 µA.
- Funciones de seguridad como arranque seguro y cifrado de memoria flash.
- Aceleración criptográfica por hardware: AES, SHA, RSA y más.
Aplicaciones
Gracias a su bajo consumo de energía y su versátil conectividad, esta placa es perfecta para numerosas aplicaciones como:
- Dispositivos para el hogar inteligente
- Automatización industrial
- Atención médica
- Electrónica de consumo
- Agricultura inteligente
- Robots de servicio
- Sensores IoT de bajo consumo y registradores de datos
La placa ESP32-C3 con pantalla OLED de 0,42".
Esta placa IoT compacta se basa en el chip ESP32-C3 (RISC-V) e incorpora una pantalla OLED de 0,42 pulgadas. Como la distribución de pines y el controlador de pantalla no son iguales que la de los módulos ESP32 estándar
A continuación os dejamos la información necesaria para el correcto funcionamiento de la placa.
Especificaciones del hardware
- Chip: ESP32-C3FN4 con una Memoria Flash de 4 MB, Wi-Fi y Bluetooth 5.0 BLE.
- Conexión USB: USB nativo USB-C Para Habilitar la comunicación con el monitor serial active en el IDE de Arduino "USB CDC al arrancar".
- Pantalla OLED: 0,42 pulgadas con una resolución de 72 x 40 píxeles.
- Dimensiones: Es muy compacta aproximadamente 20 x 25 mm.
Asignación de pines y conexiones
La documentación en línea suele ser confusa. Utilice la siguiente asignación de pines para esta placa específica:
- I2C OLED SDA: GPIO 5 (aunque generalmente se indica el 8.
- I2C OLED SCL: GPIO 6.
- LED Integrado: GPIO 8.
- Boton de reset: GPIO 9.
- Tx; GPIO 21.
- Rx: GPIO 20.
Configurando del IDE de Arduino
Para programar placa correctamente vamos seleccionar la siguiente configuración en el IDE de Arduino:
- Placa: Módulo de desarrollo ESP32C3 Dev Module.
- USB CDC al arrancar: Habilitado (Para salida de Serial.print).
- Modo de flasheo: DIO (predeterminado).
Algunas veces podemos experimentar problemas con la carga del programa, para solucionarlo, mantenga presionado el botón BOOT, presione RESET brevemente y luego suelte BOOT. Esto fuerza a la placa al entrar modo de programación.
Códigos de ejemplo
Comprobación de pines: Parpadeo del LED integrado
Usa este sencillo bucle en el pin 8 que controla el LED integrado.
// GPIO 8 es el LED integrado (LOW = ON)
#define LED_PIN 8
void setup() {
pinMode(LED_PIN, OUTPUT);
}
void loop() {
digitalWrite(LED_PIN, LOW); // LED On
delay(500);
digitalWrite(LED_PIN, HIGH); // LED Off
delay(500);
}
Control de la pantalla OLED
La pantalla utiliza un controlador SSD1306, pero tiene una resolución física es de solo 72x40 píxeles.
Sin embargo, el búfer interno es de 128x64.
Para solucionar este problema tenemos que aplicar un desplazamiento en los ejes X e Y para que el texto sea visible.
Necesitamos tener instalada la biblioteca U8g2 (de olikraus) a través del Administrador de bibliotecas de Arduino o desde el Repositorio de GitHub.
#include <U8g2lib.h>
#include <Wire.h>
#define SCL 6
#define SDA 5
// Iniciando un ESP32-C3 con I2C en los pines 5 SDA y 6 SCL.
// Usaremos el driver estandar de 128x64 pero solo una parte de la pantalla.
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE, SCL, SDA);
// Los Offsets se requieren para centrar la salida dentro del buffer 128x64.
const int VISIBLE_X0 = 28;
const int VISIBLE_Y0 = 24;
//configuramos la pantalla de 0.42 pulgadas
const int VISIBLE_W = 72;
const int VISIBLE_H = 40;
void setup(void) {
delay(1000); // Una pausa para estabilizar el ESP
u8g2.begin();
u8g2.setContrast(255); // Máximo brillo
u8g2.setBusClock(400000); // 400kHz velocidad del I2C
u8g2.setFont(u8g2_font_ncenB10_tr); // Elegimos el tipo de letra
}
void loop(void) {
u8g2.clearBuffer(); // Limpiamos el buffer interno
// Dibuja un marco para probar el área visible
u8g2.drawFrame(VISIBLE_X0, VISIBLE_Y0, VISIBLE_W, VISIBLE_H);
// Dibujar texto teniendo en cuenta el desplazamiento en x y el desplazamiento en y
u8g2.setCursor(VISIBLE_X0 + 6, VISIBLE_Y0 + 15);
u8g2.print("ESP32-C3");
u8g2.setCursor(VISIBLE_X0 + 25, VISIBLE_Y0 + 30);
u8g2.print("ITB");
u8g2.sendBuffer(); // Enviar datos a la pantalla
delay(1000);
}
Código: Texto con scroll lateral
El texto se mueve horizontalmente dentro de los 72 píxeles visibles y se dibuja un marco opcional para recordar los límites.
Puedes ajustar delay(30) para cambiar velocidad.
#include <U8g2lib.h>
// Configuración de la pantalla (driver SSD1306, 128x64, I2C hardware)
// Pines: SDA = 6, SCL = 5 (ajusta según tu conexión)
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE, 6, 5);
// --- Constantes de área visible real (72x40 con offset 28,24) ---
const int VISIBLE_X0 = 28;
const int VISIBLE_Y0 = 24;
const int VISIBLE_W = 72;
const int VISIBLE_H = 40;
// Texto a desplazar
const char* texto = " Infotronikblog desplazamiento lateral ";
int desplazamiento = 0;
// Función para dibujar texto teniendo en cuenta el recorte (clipping manual)
void dibujarTextoScroll(int offsetX) {
// El área de dibujo está limitada a [VISIBLE_X0, VISIBLE_X0+VISIBLE_W]
// Usamos setFont y drawStr con coordenadas absolutas (incluyendo offset)
u8g2.setFont(u8g2_font_ncenB08_tr);
int anchoTexto = u8g2.getStrWidth(texto);
// Dibujamos el texto varias veces para efecto continuo
int x = VISIBLE_X0 + offsetX;
int y = VISIBLE_Y0 + 20; // centrado vertical aprox.
u8g2.drawStr(x, y, texto);
// Si el texto se sale por la derecha, dibujamos continuación
if (x + anchoTexto < VISIBLE_X0 + VISIBLE_W) {
u8g2.drawStr(x + anchoTexto, y, texto);
}
// Si se sale por la izquierda, dibujamos la parte que falta
if (x < VISIBLE_X0) {
u8g2.drawStr(x + anchoTexto, y, texto);
}
}
void setup() {
u8g2.begin();
u8g2.setFontMode(1); // Modo transparente
u8g2.setFontDirection(0);
}
void loop() {
u8g2.firstPage();
do {
// Limpia toda la pantalla (128x64) pero solo se verá el área activa
u8g2.clearBuffer();
// Dibujar un marco alrededor del área visible (opcional, para referencia)
u8g2.drawFrame(VISIBLE_X0 - 1, VISIBLE_Y0 - 1, VISIBLE_W + 2, VISIBLE_H + 2);
// Dibujar el texto en scroll
dibujarTextoScroll(desplazamiento);
} while (u8g2.nextPage());
// Actualizar desplazamiento (velocidad ajustable)
desplazamiento--;
if (desplazamiento < -u8g2.getStrWidth(texto)) {
desplazamiento = VISIBLE_W;
}
delay(30); // 30 ms entre frames
}
Código: Cubo 3D + rebotes en los bordes
Un pequeño cubo 3D que se mueve con velocidades vx y vy iniciales semi-aleatorias.
Con rebotes realistas: al tocar cualquier borde del área visible (72×40 con offsets), invierte la componente de velocidad correspondiente, quedando siempre dentro de los límites considerando el medio lado del cubo para que no se salga.
#include <U8g2lib.h>
#include <math.h>
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE, 6, 5);
// Área visible real de tu pantalla (offset 28,24)
const int X0 = 28;
const int Y0 = 24;
const int W = 72;
const int H = 40;
// Tamaño del cubo (lado en píxeles)
const int LADO = 14; // Ajustado a 14 como pediste
// Centro del cubo (coordenadas absolutas) - posición inicial en el centro del área visible
float cx = X0 + W/2.0;
float cy = Y0 + H/2.0;
// Velocidades de desplazamiento (píxeles por frame)
float vx = 1.2;
float vy = 0.9;
// Ángulo de rotación (radianes)
float anguloY = 0.0;
// Límites de rebote: el cubo no debe salirse del rectángulo visible
// Como el cubo se dibuja centrado en (cx,cy), el medio lado se extiende a cada lado.
float limiteIzq = X0 + LADO/2.0;
float limiteDer = X0 + W - LADO/2.0;
float limiteSup = Y0 + LADO/2.0;
float limiteInf = Y0 + H - LADO/2.0;
// Proyección isométrica con rotación alrededor del eje Y
void projectPoint(float x, float y, float z, float angY, int &sx, int &sy) {
// Rotación en Y
float x1 = x * cos(angY) + z * sin(angY);
float z1 = -x * sin(angY) + z * cos(angY);
// Proyección simple (sin perspectiva, solo desplazamiento)
sx = (int)(cx + x1);
sy = (int)(cy - y + z1 * 0.3); // ligero efecto de profundidad
}
void drawCubo(float angY) {
// Vértices relativos al centro del cubo (coordenadas modelo)
int vertices[8][3] = {
{-LADO/2, -LADO/2, -LADO/2}, // 0
{ LADO/2, -LADO/2, -LADO/2}, // 1
{ LADO/2, -LADO/2, LADO/2}, // 2
{-LADO/2, -LADO/2, LADO/2}, // 3
{-LADO/2, LADO/2, -LADO/2}, // 4
{ LADO/2, LADO/2, -LADO/2}, // 5
{ LADO/2, LADO/2, LADO/2}, // 6
{-LADO/2, LADO/2, LADO/2} // 7
};
int projX[8], projY[8];
for (int i = 0; i < 8; i++) {
projectPoint(vertices[i][0], vertices[i][1], vertices[i][2], angY, projX[i], projY[i]);
}
// Aristas (12 líneas)
int edges[12][2] = {
{0,1},{1,2},{2,3},{3,0}, // base inferior
{4,5},{5,6},{6,7},{7,4}, // base superior
{0,4},{1,5},{2,6},{3,7} // verticales
};
for (int i = 0; i < 12; i++) {
u8g2.drawLine(projX[edges[i][0]], projY[edges[i][0]],
projX[edges[i][1]], projY[edges[i][1]]);
}
}
void setup() {
u8g2.begin();
randomSeed(analogRead(0));
// Velocidades iniciales aleatorias (para dar variedad)
vx = (random(80, 160) / 100.0) * 1.5;
vy = (random(60, 140) / 100.0) * 1.5;
if (random(2) == 0) vx = -vx;
if (random(2) == 0) vy = -vy;
// Asegurar que la posición inicial esté dentro de los límites
if (cx < limiteIzq) cx = limiteIzq;
if (cx > limiteDer) cx = limiteDer;
if (cy < limiteSup) cy = limiteSup;
if (cy > limiteInf) cy = limiteInf;
}
void loop() {
// 1. Actualizar posición del cubo
cx += vx;
cy += vy;
// 2. Rebotes en los bordes
if (cx < limiteIzq) { cx = limiteIzq; vx = -vx; }
if (cx > limiteDer) { cx = limiteDer; vx = -vx; }
if (cy < limiteSup) { cy = limiteSup; vy = -vy; }
if (cy > limiteInf) { cy = limiteInf; vy = -vy; }
// 3. Rotación continua
anguloY += 0.06; // velocidad angular (ajústala a gusto)
if (anguloY > 2 * M_PI) anguloY -= 2 * M_PI;
// 4. Dibujar en la pantalla
u8g2.firstPage();
do {
u8g2.clearBuffer();
// (Opcional) marco del área visible - puedes comentarlo si prefieres sin marco
u8g2.drawFrame(X0, Y0, W, H);
// Dibujar el cubo rotando
drawCubo(anguloY);
} while (u8g2.nextPage());
delay(30); // controla la velocidad de animación
}
Puedes visitar los siguiente enlaces relacionados con el microcontrolador ESP32 y Arduino:





































