UNIVERSIDAD ANÁHUAC MAYAB
Facultad de ingeniería
Ingeniería Biomédica
Octavo semestre
Transformadas integrales
Irving Sifuentes
Proyecto Aplicativo de Investigación
Carlos Javier Rodriguez Ortiz | 483283
Diego Luna Montalvo| 470096
Darian Cuellar Jimenez| 472174
14/05/2026
Introducción
El presente proyecto consiste en el diseño e implementación de un sistema basado en el
microcontrolador ESP32 capaz de generar señales analógicas periódicas (cuadrada, diente de
sierra y senoidal). La particularidad del sistema es que permite aproximar dichas señales
mediante el uso de Series de Fourier, permitiendo al usuario manipular tanto la frecuencia de
salida como el número de armónicos calculados en tiempo real.
Procedimiento
1. Revisión de requisitos del proyecto
○ Se identificaron las funciones principales solicitadas: generar señales
cuadradas, diente de sierra y senoidal usando el DAC del ESP32.
○ También se consideró el uso de 3 botones, un potenciómetro para variar la
frecuencia de 1 a 20 Hz, y otro potenciómetro para cambiar la cantidad de
coeficientes de Fourier de 1 a 30.
2. Asignación de pines del ESP32
○ Se seleccionaron los pines del lado donde se encuentran GPIO25 y GPIO26.
○ La distribución utilizada fue:
Función
Pin
Salida DAC
GPIO25
Lectura de salida DAC
GPIO34
Potenciómetro de frecuencia
GPIO32
Potenciómetro de coeficientes GPIO33
Botón señal cuadrada
GPIO27
Botón señal diente de sierra
GPIO14
Botón señal senoidal
GPIO13
3. Conexión de la salida DAC
○ El pin GPIO25 se utilizó como salida analógica.
○ Para leer la señal generada, se conectó el GPIO25 al GPIO34 mediante una
resistencia de 1 kΩ.
4. Conexión de los botones
○ Cada botón se conectó entre su pin correspondiente y GND.
○ Se usaron resistencias internas pull-up desde el código.
5. Conexión de los potenciómetros
○ Los potenciómetros se conectaron como divisores de voltaje entre 3.3 V y
GND.
○ La terminal central de cada potenciómetro se conectó al pin analógico
correspondiente.
6. Programación del ESP32
○ Se programó el ESP32 en Arduino IDE.
○ El programa lee los botones y selecciona la señal correspondiente.
○ La señal seleccionada se convierte a un valor de 0 a 255 para enviarse por el
DAC.
7. Control de frecuencia
○ El potenciómetro conectado al GPIO32 controla la frecuencia.
○ La lectura analógica se convierte al rango de 1 Hz a 20 Hz.
8. Control de coeficientes de Fourier
○ El potenciómetro conectado al GPIO33 controla el número de coeficientes.
○ La lectura se convierte al rango de 1 a 30 coeficientes.
9. Visualización en Serial Plotter
○ Se enviaron valores numéricos al Serial Plotter.
○ Se graficaron al mismo tiempo:
■ señal real enviada al DAC,
■ aproximación por Fourier,
■ lectura del DAC en GPIO34,
■ frecuencia,
■ número de coeficientes.
10.Verificación final
● Se probó cada botón para confirmar el cambio de señal.
● Se giró el potenciómetro de frecuencia para comprobar el rango de 1 a 20 Hz.
● Se giró el potenciómetro de coeficientes para observar cómo cambia la aproximación
de Fourier.
Descripción del sistema
El sistema integra hardware y software para la síntesis de señales:
● Interfaz de usuario: Tres botones para la selección de la forma de onda y dos
potenciómetros para el control de parámetros (Frecuencia de 1-20 Hz y Número de
coeficientes de 1-30).
● Procesamiento: El ESP32 calcula la aproximación de Fourier sumando armónicos de
forma iterativa.
● Salida Analógica: Se utiliza el convertidor Digital-Analógico (DAC) interno del
ESP32 (pin 25) para la salida física de la señal.
● Monitoreo: El sistema envía por puerto serie el valor de la señal original vs. la
aproximación de Fourier para su visualización en el Serial Plotter.
Fundamento Matemático (Series de Fourier)
Para cada señal, se calcularon los coeficientes de la serie trigonométrica de Fourier bajo la forma:
Código
#include <math.h>
#define DAC_PIN 25
#define DAC_READ_PIN 34
#define POT_FREQ 32
#define POT_COEFF 33
#define BTN_SQUARE 27
#define BTN_SAW 14
#define BTN_SINE 13
enum WaveType {
SQUARE,
SAWTOOTH,
SINE
};
WaveType selectedWave = SINE;
const int sampleRate = 1000;
const int plotRate = 200;
const unsigned long samplePeriodUs = 1000000UL / sampleRate;
const unsigned long plotPeriodUs = 1000000UL / plotRate;
unsigned long lastSampleMicros = 0;
unsigned long lastPlotMicros = 0;
float phase = 0.0;
float realSignal = 0.0;
float fourierSignal = 0.0;
int dacValue = 0;
void setup() {
Serial.begin(115200);
pinMode(BTN_SQUARE, INPUT_PULLUP);
pinMode(BTN_SAW, INPUT_PULLUP);
pinMode(BTN_SINE, INPUT_PULLUP);
analogReadResolution(12);
analogSetPinAttenuation(POT_FREQ, ADC_11db);
analogSetPinAttenuation(POT_COEFF, ADC_11db);
analogSetPinAttenuation(DAC_READ_PIN, ADC_11db);
}
void loop() {
readButtons();
int freqADC = analogRead(POT_FREQ);
int coeffADC = analogRead(POT_COEFF);
float frequency = mapFloat(freqADC, 0, 4095, 1.0, 20.0);
int harmonics = map(coeffADC, 0, 4095, 1, 30);
unsigned long nowMicros = micros();
if (nowMicros - lastSampleMicros >= samplePeriodUs) {
lastSampleMicros += samplePeriodUs;
phase += 2.0 * PI * frequency / sampleRate;
if (phase >= 2.0 * PI) {
phase -= 2.0 * PI;
}
realSignal = generateOriginalWave(selectedWave, phase);
dacValue = signalToDACCode(realSignal);
dacWrite(DAC_PIN, dacValue);
}
if (nowMicros - lastPlotMicros >= plotPeriodUs) {
lastPlotMicros += plotPeriodUs;
fourierSignal = fourierApproximation(selectedWave, phase, harmonics);
int adcReadback = analogRead(DAC_READ_PIN);
float realDACScale = dacValue;
float fourierDACScale = signalToDACFloat(fourierSignal);
float readbackDACScale = adcReadback * 255.0 / 4095.0;
Serial.print(realDACScale, 2);
Serial.print('\t');
Serial.print(fourierDACScale, 2);
Serial.print('\t');
Serial.print(readbackDACScale, 2);
Serial.print('\t');
Serial.print(harmonics);
Serial.print('\t');
Serial.println(frequency, 2);
}
}
void readButtons() {
static unsigned long lastButtonTime = 0;
if (millis() - lastButtonTime < 120) {
return;
}
if (digitalRead(BTN_SQUARE) == LOW) {
selectedWave = SQUARE;
lastButtonTime = millis();
}
if (digitalRead(BTN_SAW) == LOW) {
selectedWave = SAWTOOTH;
lastButtonTime = millis();
}
if (digitalRead(BTN_SINE) == LOW) {
selectedWave = SINE;
lastButtonTime = millis();
}
}
float generateOriginalWave(WaveType wave, float x) {
switch (wave) {
case SQUARE:
if (sin(x) >= 0) {
return 1.0;
} else {
return -1.0;
}
case SAWTOOTH:
return (x / PI) - 1.0;
case SINE:
return sin(x);
}
return 0.0;
}
float fourierApproximation(WaveType wave, float x, int N) {
float sum = 0.0;
switch (wave) {
case SQUARE:
for (int k = 1; k <= N; k++) {
int n = 2 * k - 1;
sum += sin(n * x) / n;
}
return (4.0 / PI) * sum;
case SAWTOOTH:
for (int n = 1; n <= N; n++) {
sum += sin(n * x) / n;
}
return (-2.0 / PI) * sum;
case SINE:
return sin(x);
}
return 0.0;
}
int signalToDACCode(float signal) {
// Converts -1 to 1 into 0 to 255
float dacFloat = (signal + 1.0) * 127.5;
if (dacFloat < 0) dacFloat = 0;
if (dacFloat > 255) dacFloat = 255;
return (int)dacFloat;
}
float signalToDACFloat(float signal) {
return (signal + 1.0) * 127.5;
}
float mapFloat(float x, float in_min, float in_max, float out_min, float out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
Cálculos
Resultados
Armado del proyecto:
Conclusiones
En conclusión, el desarrollo de este sistema de generación de señales mediante el
microcontrolador ESP32 permite validar de manera empírica la convergencia de las series de
Fourier y su aplicación práctica en la síntesis de formas de onda complejas. A través de la
implementación algorítmica de las sumatorias de armónicos y la manipulación de parámetros
en tiempo real como la frecuencia y el número de coeficientes, se evidencia cómo la adición
sucesiva de funciones senoidales ortogonales permite aproximar con precisión señales no
senoidales, tales como la cuadrada y la diente de sierra. Este proyecto no solo demuestra la
capacidad de procesamiento de punto flotante del ESP32 para aplicaciones de procesamiento
digital de señales (DSP), sino que también subraya la importancia de la reconstrucción de
señales analógicas mediante convertidores DAC, consolidando así los conceptos teóricos de
análisis de frecuencias y sistemas de control embebidos en una solución técnica funcional y
versátil.