from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
import math, utime
W = 128
H = 64
i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=200000)
oled = SSD1306_I2C(W, H, i2c)
oled.fill(0)
oled.text("Fourier e^-x", 0, 0)
oled.show()
gpio_pins = [2,3,4,5,6,7,8,9,10,11]
salidas = [Pin(p, Pin.OUT) for p in gpio_pins]
def dac_out(valor):
if valor < 0:
valor = 0
elif valor > 1023:
valor = 1023
mask = 1 << 9
for pin in salidas:
pin.value(1 if (valor & mask) else 0)
mask >>= 1
T = 0.5
w0 = 2 * math.pi / T # = 4π
x_min = 0.0
x_max = T
num_pts = W # ancho OLED
def f_original(x):
# Reducción al intervalo [0,T)
xr = ((x % T) + T) % T
# en 0<=xr<T es simplemente e^{-xr}
return math.exp(-xr)
N_MAX = 80
a_coeff = [0.0] * (N_MAX + 1)
b_coeff = [0.0] * (N_MAX + 1)
C = 2 * (1.0 - math.exp(-T)) / T
a0 = C
def compute_coeffs(Nmax):
for n in range(1, Nmax + 1):
k = (2.0 * math.pi * n) / T # k_n
denom = 1.0 + k * k
an = C / denom
bn = C * k / denom
a_coeff[n] = an
b_coeff[n] = bn
compute_coeffs(N_MAX)
def S_partial(x, N):
if N > N_MAX:
N = N_MAX
s = a0 / 2.0
for n in range(1, N+1):
s += a_coeff[n] * math.cos(n * w0 * x) + b_coeff[n] * math.sin(n * w0 * x)
return s
YMIN = math.exp(-T)
YMAX = 1.0
def dac_scale(y):
y_clamped = max(YMIN, min(y, YMAX))
return int((y_clamped - YMIN) / (YMAX - YMIN) * 1023.0)
def draw_once(N):
oled.fill(0)
oled.text("e^-x T={:.2f} N={}".format(T, N), 0, 0)
for i in range(num_pts):
px = i
x = x_min + (x_max - x_min) * i / (num_pts - 1)
y_true = f_original(x)
y_app = S_partial(x, N)
y_app_cl = max(YMIN, min(y_app, YMAX))
py_true = H - 1 - int((y_true - YMIN) / (YMAX - YMIN) * (H - 10)) # reservar top línea texto
py_app = H - 1 - int((y_app_cl - YMIN) / (YMAX - YMIN) * (H - 10))
if 0 <= py_true < H:
oled.pixel(px, py_true, 1)
if 0 <= py_app < H:
for dy in (-1, 0, 1):
p = py_app + dy
if 0 <= p < H:
oled.pixel(px, p, 1)
oled.show()
def main():
N = 10 # armónicos iniciales
samples = 32
sample_delay_ms = 50
print("Iniciando:")
try:
while True:
for j in range(samples):
x = x_min + (x_max - x_min) * j / (samples - 1)
y_true = f_original(x)
y_app = S_partial(x, N)
dac_val = dac_scale(y_app)
# escribir a R-2R
dac_out(dac_val)
if j % (samples // 8 if samples >= 8 else 1) == 0:
print("{:.4f}, {:.4f}".format(y_true, y_app))
utime.sleep_ms(sample_delay_ms)
draw_once(N)
utime.sleep(0.8)
# variar N para ver convergencia
N += 10
if N > 70:
N = 10
except KeyboardInterrupt:
print("Detenido por usuario — limpiando pines.")
for p in salidas:
p.value(0)
if __name__ == "__main__":
main()