Generador de señales con esp32
Generador de Señales — ESP32 + OLED
ESP32 DAC 8-bit
SSD1306 128×64
4 formas de onda
Una señal senoidal continua varía suavemente en todo instante de tiempo. Sin embargo, el ESP32 solo puede generar valores en instantes discretos separados por un período de muestreo Ts. El DAC interno de 8 bits produce 256 niveles de tensión entre 0 V y 3.3 V.
y[n] = A · sin(2π · n / N) n = 0, 1, 2, ..., N−1
— Línea azul = señal continua ideal · ● Puntos naranjas = muestras del DAC
Simulación 1:1 · SSD1306 128×64 px · Fósforo verde
ESP32 DevKit v1
DAC integrado 8-bit
Canales GPIO25 / GPIO26
Canales GPIO25 / GPIO26
OLED 0.96" SSD1306
128×64 px, I²C
Alimentación 3.3 V
Alimentación 3.3 V
Potenciómetro 10 kΩ ×2
WH148 multivuelta lineal
Frecuencia + Amplitud
Frecuencia + Amplitud
Pulsador táctil ×1
6×6 mm, 4 pines
Cambio de forma de onda
Cambio de forma de onda
Protoboard 400 pts
+ cables Dupont
M-M y M-H
M-M y M-H
Resistencias 10 kΩ ×2
Pull-down pulsador
y divisor de tensión
y divisor de tensión
Cable USB micro
Programación y
alimentación 5 V
alimentación 5 V
Condensador 100 nF
Desacoplo salida DAC
(opcional, mejora la señal)
(opcional, mejora la señal)
⚠ El ESP32 incluye dos canales DAC de 8 bits (0–3.3 V en GPIO25 y GPIO26). Para mayor resolución se puede agregar un DAC externo MCP4725 (I²C, 12-bit, ~$1 USD en Mercado Libre).
// ─── Generador de Señales ESP32 + OLED ─────────────────── #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define OLED_W 128 #define OLED_H 64 #define POT_FREQ 34 // ADC1 canal 6 — solo entrada #define POT_AMP 35 // ADC1 canal 7 — solo entrada #define BTN_PIN 32 // Pulsador con INPUT_PULLUP #define DAC_PIN 25 // DAC Canal 1 (0–3.3 V) #define N_SAMPLES 64 // Muestras por ciclo Adafruit_SSD1306 display(OLED_W, OLED_H, &Wire, -1); const char* sigNames[] = {"Seno", "Cuadrada", "Triangular", "Sierra"}; uint8_t sigType = 0; uint8_t tabla[N_SAMPLES]; bool btnPrev = false; // ── Precalcula tabla de N muestras ────────────────────── void buildTable(uint8_t type) { for (int i = 0; i < N_SAMPLES; i++) { float t = (float)i / N_SAMPLES; float v = 0; switch (type) { case 0: v = sinf(2*M_PI*t); break; // Seno case 1: v = (t < 0.5f) ? 1.0f : -1.0f; break; // Cuadrada case 2: v = (t < 0.5f) ? (4*t-1) : (3-4*t); break; // Triangular case 3: v = 2*t - 1; break; // Sierra } tabla[i] = (uint8_t)((v + 1.0f) * 127.5f); } } // ── Dibuja forma de onda en la OLED ───────────────────── void drawOLED(float freqHz, int amp) { display.clearDisplay(); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); display.setCursor(0, 0); display.print(sigNames[sigType]); display.print(" "); display.print(freqHz, 1); display.print("Hz A:"); display.print(amp); display.print("%"); // Línea divisoria display.drawFastHLine(0, 10, OLED_W, SSD1306_WHITE); // Forma de onda (píxeles individuales) for (int x = 0; x < OLED_W; x++) { int idx = (x * N_SAMPLES) / OLED_W; int rawY = (int)(tabla[idx] * amp / 100); int y = 12 + (50 - rawY * 50 / 255); display.drawPixel(x, constrain(y, 12, 62), SSD1306_WHITE); } display.display(); } void setup() { pinMode(BTN_PIN, INPUT_PULLUP); dacWrite(DAC_PIN, 128); // Nivel medio al inicio display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay(); display.display(); buildTable(sigType); } void loop() { int rawFreq = analogRead(POT_FREQ); int rawAmp = analogRead(POT_AMP); float freqHz = map(rawFreq, 0, 4095, 1, 2000); int amp = map(rawAmp, 0, 4095, 0, 100); long stepUs = (long)(1000000.0f / (freqHz * N_SAMPLES)); // Botón: cicla entre señales bool btnNow = !digitalRead(BTN_PIN); if (btnNow && !btnPrev) { sigType = (sigType + 1) % 4; buildTable(sigType); } btnPrev = btnNow; // Emite un ciclo completo por el DAC for (int i = 0; i < N_SAMPLES; i++) { dacWrite(DAC_PIN, (tabla[i] * amp) / 100); delayMicroseconds(stepUs); } drawOLED(freqHz, amp); }
| Componente | Pin | ESP32 | Nota |
|---|---|---|---|
| OLED SSD1306 | SDA | GPIO 21 | I²C Data |
| OLED SSD1306 | SCL | GPIO 22 | I²C Clock |
| OLED SSD1306 | VCC / GND | 3.3 V / GND | No superar 3.3 V |
| Pot. Frecuencia | Pin central | GPIO 34 | ADC1_CH6, solo entrada |
| Pot. Amplitud | Pin central | GPIO 35 | ADC1_CH7, solo entrada |
| Ambos potenciómetros | Extremos | 3.3 V / GND | Divisor de tensión |
| Pulsador | Pin A | GPIO 32 | INPUT_PULLUP interno |
| Pulsador | Pin B | GND | — |
| Salida de señal | — | GPIO 25 | DAC Canal 1 (0–3.3 V) |
GPIO34 y GPIO35 son de entrada únicamente (sin pull-up interno). Los potenciómetros de 10 kΩ entre 3.3 V y GND mantienen el consumo dentro del límite de 12 mA por pin del ESP32.
