Objetivos de aprendizaje
Relacionar la tensión y la corriente de un condensador y de un inductor mediante y , y sus formas integrales.
Derivar e integrar numéricamente una señal muestreada y cuantificar el error.
Explicar por qué la derivada numérica amplifica el ruido y la integral acumula los errores de cero.
Calcular la energía almacenada en un condensador y aplicarla al orden de magnitud de un desfibrilador.
Teoría: Volumen I, Anexo C (la derivada, corriente en un condensador, tensión en un inductor, energía almacenada) (Miguel-Medina, 2026). Tiempo: ~2 h
import sys
if "google.colab" in sys.modules:
%pip install -q git+https://github.com/telmomm/math-tools-biomedical-electronicsimport matplotlib.pyplot as plt
import numpy as np
import sympy as sp
from scipy import integrate, signal
from circuitmath.plotting import use_style
use_style()
rng = np.random.default_rng(3) # semilla fija: el cuaderno da siempre el mismo resultadoIdea clave¶
En una resistencia, tensión y corriente son proporcionales en cada instante. En un condensador y en un inductor no: lo que cuenta es lo rápido que cambian (Anexo C del Volumen I).
| Componente | Forma diferencial | Forma integral | Energía almacenada |
|---|---|---|---|
| Condensador | |||
| Inductor |
Derivar e integrar son operaciones inversas, pero con señales medidas no se comportan igual. La derivada es «nerviosa»: exagera cualquier irregularidad. La integral es «tranquila», pero no olvida: acumula cualquier error pequeño que dure mucho. En este cuaderno vas a ver las dos cosas.
1. Predice¶
La tensión de un condensador sube en rampa, se mantiene constante y baja en rampa. Dibuja a mano la forma de su corriente.
Una tensión senoidal con un 0,5 % de ruido se deriva numéricamente. Si se muestrea diez veces más deprisa, ¿la derivada sale mejor, igual o peor?
Un desfibrilador almacena 200 J en un condensador de 100 µF. ¿A qué tensión hay que cargarlo: decenas, cientos o miles de voltios?
Tu predicción:
2. Ejecuta y explora¶
2.1 Con fórmulas¶
Si la tensión de un condensador es senoidal, SymPy deriva por nosotros. Es el ejemplo del Anexo C.
t, C, L, Vm, omega = sp.symbols("t C L V_m omega", positive=True)
v = Vm * sp.sin(omega * t)
i = C * sp.diff(v, t)
print("Corriente del condensador: i(t) =", i)
v_recuperada = sp.integrate(i, (t, 0, t)) / C # con v(0) = 0
print("Integrando la corriente: v(t) =", sp.simplify(v_recuperada))Corriente del condensador: i(t) = C*V_m*omega*cos(omega*t)
Integrando la corriente: v(t) = V_m*sin(omega*t)
La corriente es un coseno cuando la tensión es un seno: va adelantada 90°, y su amplitud crece con la frecuencia (). Integrar la corriente devuelve la tensión de partida.
2.2 Derivar una señal muestreada¶
Una señal medida es una lista de muestras separadas . La derivada se aproxima con la definición, sin llegar al límite:
Diferencia hacia delante: , la pendiente entre una muestra y la siguiente.
Diferencia centrada: , la pendiente entre las dos vecinas. Es la que usa
np.gradient.
Las probamos con una señal cuya derivada conocemos: un seno de 50 Hz.
F = 50.0 # hercios
OMEGA = 2 * np.pi * F
def derivada_adelante(y, dt):
"""Derivada aproximada con la diferencia hacia delante (devuelve una muestra menos)."""
return (y[1:] - y[:-1]) / dt
pasos = 1 / F / 2 ** np.arange(3, 13) # de 8 a 4096 muestras por periodo
error_adelante, error_centrada = [], []
for dt in pasos:
tiempo = np.arange(0, 2 / F, dt)
y = np.sin(OMEGA * tiempo)
exacta = OMEGA * np.cos(OMEGA * tiempo)
error_adelante.append(np.max(np.abs(derivada_adelante(y, dt) - exacta[:-1])))
error_centrada.append(np.max(np.abs(np.gradient(y, dt)[1:-1] - exacta[1:-1])))
fig, ax = plt.subplots()
ax.loglog(pasos * 1e3, np.array(error_adelante) / OMEGA, "o-", markersize=4, label="Hacia delante")
ax.loglog(pasos * 1e3, np.array(error_centrada) / OMEGA, "o-", markersize=4, label="Centrada")
ax.set(xlabel="Paso de muestreo, Δt (ms)", ylabel="Error relativo máximo")
ax.set_title("Error de la derivada")
ax.legend()
plt.show()
Igual que con las integrales del cuaderno C1, el error cae con el paso a un ritmo que depende de la regla: al dividir el paso por 10, el de la diferencia hacia delante se divide por 10 y el de la centrada, por 100.
Ahora un caso con sentido de circuito. A un condensador de 1 µF se le aplica una tensión trapezoidal: sube en rampa, se mantiene y baja.
C_CONDENSADOR = 1e-6 # faradios
FS = 100e3 # hercios, frecuencia de muestreo
DT = 1 / FS
tiempo = np.arange(0, 6e-3, DT)
v_trapecio = np.interp(tiempo, [0, 1e-3, 3e-3, 4e-3, 6e-3], [0, 5, 5, 0, 0]) # voltios
i_trapecio = C_CONDENSADOR * np.gradient(v_trapecio, DT)
fig, (ax_v, ax_i) = plt.subplots(2, 1, sharex=True, figsize=(6.4, 5.0))
ax_v.plot(tiempo * 1e3, v_trapecio)
ax_v.set(ylabel="Tensión (V)", title="Condensador de 1 µF con tensión trapezoidal")
ax_i.plot(tiempo * 1e3, i_trapecio * 1e3, color="C1")
ax_i.set(xlabel="Tiempo (ms)", ylabel="Corriente (mA)")
plt.show()
La corriente solo existe mientras la tensión cambia, y es proporcional a la pendiente: mA. En el tramo plano, con la tensión en su máximo, la corriente es nula.
2.3 Integrar una señal muestreada¶
El camino inverso: conocida la corriente, recuperar la tensión. integrate.cumulative_trapezoid aplica la regla de los trapecios de C1 y devuelve el área acumulada hasta cada instante.
v_integrada = integrate.cumulative_trapezoid(i_trapecio, tiempo, initial=0) / C_CONDENSADOR
diferencia = np.max(np.abs(v_integrada - v_trapecio))
print(f"Diferencia máxima con la tensión original: {diferencia * 1e3:.1f} mV")
fig, ax = plt.subplots()
ax.plot(tiempo * 1e3, v_trapecio, label="Tensión original")
ax.plot(tiempo * 1e3, v_integrada, "--", label="Integral de la corriente, $v(0) = 0$")
ax.plot(tiempo * 1e3, v_integrada + 2, ":", label="Integral de la corriente, $v(0) = 2$ V")
ax.set(xlabel="Tiempo (ms)", ylabel="Tensión (V)", title="De la corriente a la tensión")
ax.legend(loc="upper right", fontsize="small")
plt.show()Diferencia máxima con la tensión original: 12.5 mV

La integral recupera la tensión original, salvo unos milivoltios en las esquinas, donde la derivada numérica redondea. Pero la corriente dice cuánto cambia la tensión, no cuánto vale: para recuperarla hace falta saber de dónde partía. Es la constante de integración del Anexo C, y físicamente es la tensión inicial del condensador.
2.4 Con ruido, derivar e integrar no se parecen¶
Hasta aquí las señales eran perfectas. Medimos ahora una tensión senoidal de 1 V con un ruido de 5 mV, un 0,5 %: casi invisible. Y calculamos la corriente del condensador derivando, con dos frecuencias de muestreo.
RUIDO = 5e-3 # voltios, desviación típica del ruido de medida
fig, axes = plt.subplots(1, 2, figsize=(9, 3.6), sharey=True)
for ax, fs in zip(axes, (10e3, 100e3), strict=True):
dt = 1 / fs
tiempo = np.arange(0, 2 / F, dt)
v_medida = np.sin(OMEGA * tiempo) + RUIDO * rng.standard_normal(len(tiempo))
i_medida = C_CONDENSADOR * np.gradient(v_medida, dt)
i_ideal = C_CONDENSADOR * OMEGA * np.cos(OMEGA * tiempo)
ax.plot(tiempo * 1e3, i_medida * 1e3, linewidth=0.6, label="Derivada de la medida")
ax.plot(tiempo * 1e3, i_ideal * 1e3, "k--", linewidth=1, label="Corriente real")
ax.set(xlabel="Tiempo (ms)", title=f"Muestreo a {fs / 1e3:.0f} kHz")
error = np.std(i_medida - i_ideal) / (C_CONDENSADOR * OMEGA)
print(f"Muestreo a {fs / 1e3:5.0f} kHz: ruido de la corriente = {error:.0%} de su amplitud")
axes[0].set_ylabel("Corriente (mA)")
axes[0].legend(fontsize="small")
fig.tight_layout()
plt.show()Muestreo a 10 kHz: ruido de la corriente = 12% de su amplitud
Muestreo a 100 kHz: ruido de la corriente = 114% de su amplitud

Un ruido del 0,5 % en la tensión se ha convertido en uno de más del 10 % en la corriente, y al muestrear más deprisa empeora: supera a la propia señal. La explicación está en la fórmula: la diferencia entre dos muestras vecinas contiene el ruido de las dos, que no depende del paso, y se divide por un cada vez menor.
Es un resultado general: derivar amplifica el ruido, tanto más cuanto más rápido es el ruido comparado con la señal. El remedio es suavizar antes de derivar. Un método habitual es el filtro de Savitzky-Golay, que ajusta un polinomio por mínimos cuadrados (cuaderno B6) a las muestras de una ventana y deriva el polinomio.
fs = 100e3
dt = 1 / fs
tiempo = np.arange(0, 2 / F, dt)
v_medida = np.sin(OMEGA * tiempo) + RUIDO * rng.standard_normal(len(tiempo))
i_ideal = C_CONDENSADOR * OMEGA * np.cos(OMEGA * tiempo)
# Polinomio de grado 3 ajustado a una ventana de 201 muestras (2 ms)
derivada_suave = signal.savgol_filter(v_medida, window_length=201, polyorder=3, deriv=1, delta=dt)
i_suave = C_CONDENSADOR * derivada_suave
error = np.std(i_suave - i_ideal) / (C_CONDENSADOR * OMEGA)
print(f"Ruido de la corriente con suavizado: {error:.1%} de su amplitud")
fig, ax = plt.subplots()
ax.plot(tiempo * 1e3, i_suave * 1e3, label="Derivada suavizada")
ax.plot(tiempo * 1e3, i_ideal * 1e3, "k--", linewidth=1, label="Corriente real")
ax.set(xlabel="Tiempo (ms)", ylabel="Corriente (mA)", title="Derivar después de suavizar")
ax.legend()
plt.show()Ruido de la corriente con suavizado: 0.5% de su amplitud

¿Y la integral? Medimos la corriente trapezoidal del apartado 2.2 con mucho ruido (0,5 mA, un 10 % de su amplitud) y, además, con un pequeño error de cero del instrumento de 0,2 mA.
tiempo = np.arange(0, 6e-3, DT)
ruido_i = 0.5e-3 * rng.standard_normal(len(tiempo))
ERROR_CERO = 0.2e-3 # amperios
casos = {
"Solo ruido": i_trapecio + ruido_i,
"Ruido y error de cero": i_trapecio + ruido_i + ERROR_CERO,
}
fig, (ax_i, ax_v) = plt.subplots(2, 1, sharex=True, figsize=(6.4, 5.6))
ax_i.plot(tiempo * 1e3, casos["Ruido y error de cero"] * 1e3, linewidth=0.5)
ax_i.set(ylabel="Corriente medida (mA)", title="Integrar una corriente con ruido")
ax_v.plot(tiempo * 1e3, v_trapecio, "k--", linewidth=1, label="Tensión real")
for nombre, corriente in casos.items():
v_caso = integrate.cumulative_trapezoid(corriente, tiempo, initial=0) / C_CONDENSADOR
ax_v.plot(tiempo * 1e3, v_caso, label=nombre)
ax_v.set(xlabel="Tiempo (ms)", ylabel="Tensión integrada (V)")
ax_v.legend()
plt.show()
El ruido, aun siendo grande, apenas deja huella: sus valores positivos y negativos se compensan al sumar. Integrar atenúa el ruido. En cambio, el error de cero, veinticinco veces menor que la corriente, no se compensa nunca: se acumula y la tensión calculada se aleja cada vez más de la real. Es la deriva, el problema característico de todo lo que integra, desde un integrador analógico hasta un sensor inercial.
2.5 Energía almacenada¶
La potencia que entra en un componente es , y la energía, su integral. Para el condensador con tensión trapezoidal:
potencia = v_trapecio * i_trapecio
energia = integrate.cumulative_trapezoid(potencia, tiempo, initial=0)
fig, ax = plt.subplots()
ax.plot(tiempo * 1e3, energia * 1e6, label="$\\int v\\,i\\,dt$")
energia_formula = 0.5 * C_CONDENSADOR * v_trapecio**2
ax.plot(tiempo * 1e3, energia_formula * 1e6, "k--", linewidth=1, label="$\\frac{1}{2}Cv^2$")
ax.set(xlabel="Tiempo (ms)", ylabel="Energía (µJ)", title="Energía en el condensador")
ax.legend()
plt.show()
La integral de la potencia coincide en todo momento con : la energía depende solo de la tensión que tiene el condensador en ese instante, no de cómo se llegó a ella. Y al final vuelve a cero. El condensador almacena la energía y la devuelve entera; una resistencia la habría disipado.
2.6 Hilo biomédico: la energía de un desfibrilador¶
Un desfibrilador externo entrega al tórax una descarga de unos 200 J en pocos milisegundos. Ninguna batería portátil puede dar esa potencia, así que la energía se acumula antes, durante unos segundos, en un condensador. Los valores siguientes son típicos, y el modelo (un condensador que se descarga sobre una resistencia) es el más simple posible.
C_DESFIB = 100e-6 # faradios
ENERGIA = 200.0 # julios
R_PACIENTE = 50.0 # ohmios, impedancia transtorácica típica
v_carga = np.sqrt(2 * ENERGIA / C_DESFIB)
tau = R_PACIENTE * C_DESFIB
print(f"Tensión de carga: {v_carga:.0f} V")
print(f"Corriente inicial: {v_carga / R_PACIENTE:.0f} A")
print(f"Potencia inicial: {v_carga**2 / R_PACIENTE / 1e3:.0f} kW")
print(f"Constante de tiempo de la descarga: {tau * 1e3:.1f} ms")
tiempo_d = np.linspace(0, 5 * tau, 1001)
i_paciente = v_carga / R_PACIENTE * np.exp(-tiempo_d / tau)
entregada = integrate.cumulative_trapezoid(i_paciente**2 * R_PACIENTE, tiempo_d, initial=0)
fig, (ax_i, ax_w) = plt.subplots(2, 1, sharex=True, figsize=(6.4, 5.0))
ax_i.plot(tiempo_d * 1e3, i_paciente)
ax_i.set(ylabel="Corriente (A)", title="Descarga de un desfibrilador sobre el paciente")
ax_w.plot(tiempo_d * 1e3, entregada, color="C1")
ax_w.axhline(ENERGIA, color="k", linestyle="--", linewidth=1)
ax_w.set(xlabel="Tiempo (ms)", ylabel="Energía entregada (J)")
plt.show()
t_90 = tiempo_d[np.searchsorted(entregada, 0.9 * ENERGIA)]
print(f"El 90 % de la energía se entrega en {t_90 * 1e3:.1f} ms")Tensión de carga: 2000 V
Corriente inicial: 40 A
Potencia inicial: 80 kW
Constante de tiempo de la descarga: 5.0 ms

El 90 % de la energía se entrega en 5.8 ms
Dos mil voltios, cuarenta amperios y decenas de kilovatios, durante unos milisegundos. Una batería que cargue el condensador con 20 W necesita diez segundos para reunir esos 200 J: el condensador hace de depósito que se llena despacio y se vacía de golpe.
Los desfibriladores reales no usan esta descarga exponencial tal cual. Los clásicos añadían un inductor en serie para dar forma al pulso, que es el circuito RLC del cuaderno C4; los actuales cortan la descarga e invierten su polaridad (onda bifásica).
3. Explica¶
En el tramo plano de la tensión trapezoidal, el condensador tiene 5 V y almacena su energía máxima, pero la corriente es nula. Explica por qué no hay contradicción.
En la figura del error de la derivada, ¿qué pendiente tiene cada recta? ¿Por qué la diferencia centrada es mejor si usa la misma información?
Explica con tus palabras por qué muestrear más deprisa empeora la derivada de una señal con ruido. ¿Qué precio se paga al suavizar con una ventana más larga?
La integral atenúa el ruido pero acumula el error de cero. ¿Qué tendría que cumplir un error para que la integral lo eliminara? ¿Cómo corregirías la deriva si supieras que la tensión debe volver a cero al final?
La curva de energía del condensador vuelve a cero. ¿Cómo sería la curva de una resistencia sometida a la misma tensión trapezoidal?
En el desfibrilador, la potencia inicial es de decenas de kilovatios. ¿De dónde sale esa potencia, si la batería solo da unos vatios?
4. Ejercicios¶
Básico. Por un inductor de 10 mH circula una corriente triangular de 1 kHz que oscila entre −1 A y +1 A.
Genera la corriente muestreada (pista:
signal.sawtoothconwidth=0.5) y calcula la tensión con .Comprueba la forma y la amplitud de la tensión con un cálculo a mano.
Calcula la energía almacenada en cada instante. ¿Cuánto vale su máximo y con qué frecuencia oscila?
Aplicación. Quieres medir la capacidad de un condensador a partir de registros con ruido de su tensión y su corriente. Genera datos sintéticos con una tensión senoidal, µF y un 1 % de ruido en las dos señales.
Estima derivando la tensión y ajustando por mínimos cuadrados (cuaderno B6).
Estímala integrando la corriente y ajustando .
Repite cada estimación cien veces. ¿Qué método es más preciso y por qué?
Reto biomédico. Un marcapasos estimula el corazón 70 veces por minuto con pulsos de 2,5 V y 0,4 ms sobre una carga de 500 Ω (electrodo y tejido).
Calcula la energía de un pulso y la que se gasta en estimular durante un día.
El pulso se toma de un condensador de salida de 10 µF. ¿Cuánto cae su tensión durante el pulso?
La electrónica del marcapasos consume además 15 µA de forma continua. Con una batería de 2,8 V y 1 Ah, estima la vida del dispositivo. ¿Qué gasta más: estimular o mantener la electrónica encendida?
Resumen¶
En un condensador, la corriente es proporcional a la derivada de la tensión; en un inductor, la tensión es proporcional a la derivada de la corriente. Las formas integrales necesitan una condición inicial.
La derivada numérica es una diferencia dividida por el paso; su error cae con el paso (orden 1 hacia delante, orden 2 centrada).
Derivar amplifica el ruido, y más cuanto más deprisa se muestrea: hay que suavizar antes. Integrar atenúa el ruido, pero acumula los errores de cero en forma de deriva.
Un condensador almacena y la devuelve entera. Eso permite acumular energía despacio y entregarla de golpe, como en un desfibrilador.
→ Siguiente: C3 · Transitorios de primer orden
- Miguel-Medina, T. (2026). Electrónica en Ingeniería Biomédica — Volumen I. Autopublicación. 10.5281/zenodo.22913382