import math
import time
import micropython
import dht
from machine import Pin, ADC, I2C, Timer
from ssd1306 import SSD1306_I2C
# =========================================================
# MEMORIA ISR
# =========================================================
micropython.alloc_emergency_exception_buf(100)
# =========================================================
# OLED
# =========================================================
i2c = I2C(
0,
scl=Pin(1),
sda=Pin(0),
freq=1000000
)
oled = SSD1306_I2C(128, 64, i2c)
# =========================================================
# BOTONES
# =========================================================
btn1 = Pin(13, Pin.IN, Pin.PULL_UP)
btn2 = Pin(14, Pin.IN, Pin.PULL_UP)
btn3 = Pin(15, Pin.IN, Pin.PULL_UP)
btn4 = Pin(16, Pin.IN, Pin.PULL_UP)
btn5 = Pin(17, Pin.IN, Pin.PULL_UP)
# =========================================================
# DAC R2R
# =========================================================
gpio_pins = [11,10,9,8,7,6,5,4,3,2]
pins_obj = [Pin(i, Pin.OUT) for i in gpio_pins]
def salp(datos):
ii = 512
for pin in pins_obj:
pin.value(1 if (datos & ii) else 0)
ii >>= 1
def dac(valor):
salida = int((valor + 1) * 511)
return max(0, min(1023, salida))
# =========================================================
# FOURIER EJERCICIO 1
# =========================================================
def f_fourier(x, N=15):
suma = (math.pi / 4 + 1 / 4)
n = 1
while n <= N:
a_n = (1 / (2 * math.pi)) * (
(-2 / n) * math.sin(n * math.pi / 2) +
(4 / (n * n)) * (
1 +
math.cos(n * math.pi) -
2 * math.cos(n * math.pi / 2)
)
)
b_n = (1 / (2 * math.pi)) * (
(2 / n) * (
-math.cos(n * math.pi / 2) +
math.cos(n * math.pi) +
math.pi -
math.pi * math.cos(n * math.pi)
)
-
(8 / (n * n)) *
math.sin(n * math.pi / 2)
)
suma += (
a_n * math.cos(n * x / 2)
)
suma += (
b_n * math.sin(n * x / 2)
)
n += 1
return suma
# =========================================================
# GRAFICA OLED
# =========================================================
XMIN = -2 * math.pi
XMAX = 2 * math.pi
ALTO_GRAF = 48
OFFSET_Y = 16
def calcular_amp(func, xmin, xmax, pasos=128):
max_val = 0
for i in range(pasos):
x = xmin + (
i * (xmax - xmin)
/ (pasos - 1)
)
y = func(x)
if abs(y) > max_val:
max_val = abs(y)
return max_val
AMP = calcular_amp(
f_fourier,
XMIN,
XMAX
)
def dibujar_fourier():
oled.fill_rect(0,16,128,48,0)
segs = []
paso = (
XMAX - XMIN
) / 64
x_prev = None
y_prev = None
x = XMIN
while x <= XMAX:
y = f_fourier(x)
xp = int(
(x - XMIN)
/
(XMAX - XMIN)
*
127
)
centro = OFFSET_Y + (ALTO_GRAF // 2)
mitad = ALTO_GRAF // 2 - 2
yp = int(
centro -
(y / AMP) * mitad
)
yp = max(
OFFSET_Y,
min(
OFFSET_Y + ALTO_GRAF - 1,
yp
)
)
if x_prev is not None:
segs.append(
(
x_prev,
y_prev,
xp,
yp
)
)
x_prev = xp
y_prev = yp
x += paso
eje_x = int(
(0 - XMIN)
/
(XMAX - XMIN)
*
127
)
oled.vline(
eje_x,
OFFSET_Y,
ALTO_GRAF,
1
)
eje_y = OFFSET_Y + (ALTO_GRAF // 2)
oled.hline(
0,
eje_y,
128,
1
)
for s in segs:
oled.line(
s[0],
s[1],
s[2],
s[3],
1
)
oled.text("FOURIER",0,16)
# =========================================================
# ADC
# =========================================================
adc_volt = ADC(26)
adc_amp = ADC(27)
adc_ohm = ADC(28)
factor = 3.3 / 65535
# =========================================================
# DHT22
# =========================================================
dht_sensor = dht.DHT22(
Pin(22)
)
# =========================================================
# VARIABLES
# =========================================================
modo = 1
modo_anterior = 0
voltaje = 0
corriente_ma = 0
resistencia = 0
temp_dht = 0
hum_dht = 0
# =========================================================
# RELOJ TIMER
# =========================================================
hora = 10
minuto = 47
segundo = 0
# =========================================================
# VSYS SIMULADO
# =========================================================
vsys_v = 4.1
# =========================================================
# PROMEDIOS
# =========================================================
cont_v = 0
suma_v = 0
prom_v = 0
cont_i = 0
suma_i = 0
prom_i = 0
cont_r = 0
suma_r = 0
prom_r = 0
cont_t = 0
suma_t = 0
prom_t = 0
# =========================================================
# TIMER ISR
# =========================================================
def reloj_isr(timer):
global segundo
global minuto
global hora
segundo += 1
if segundo >= 60:
segundo = 0
minuto += 1
if minuto >= 60:
minuto = 0
hora += 1
if hora >= 24:
hora = 0
# =========================================================
# TIMER
# =========================================================
timer = Timer()
timer.init(
period=1000,
mode=Timer.PERIODIC,
callback=reloj_isr
)
# =========================================================
# DEBOUNCE
# =========================================================
ultimo_1 = 0
ultimo_2 = 0
ultimo_3 = 0
ultimo_4 = 0
ultimo_5 = 0
DEBOUNCE = 200
# =========================================================
# ISR BOTONES
# =========================================================
def isr_btn1(pin):
global modo
global ultimo_1
ahora = time.ticks_ms()
if time.ticks_diff(
ahora,
ultimo_1
) > DEBOUNCE:
modo = 1
ultimo_1 = ahora
def isr_btn2(pin):
global modo
global ultimo_2
ahora = time.ticks_ms()
if time.ticks_diff(
ahora,
ultimo_2
) > DEBOUNCE:
modo = 2
ultimo_2 = ahora
def isr_btn3(pin):
global modo
global ultimo_3
ahora = time.ticks_ms()
if time.ticks_diff(
ahora,
ultimo_3
) > DEBOUNCE:
modo = 3
ultimo_3 = ahora
def isr_btn4(pin):
global modo
global ultimo_4
ahora = time.ticks_ms()
if time.ticks_diff(
ahora,
ultimo_4
) > DEBOUNCE:
modo = 4
ultimo_4 = ahora
def isr_btn5(pin):
global modo
global ultimo_5
ahora = time.ticks_ms()
if time.ticks_diff(
ahora,
ultimo_5
) > DEBOUNCE:
modo = 5
ultimo_5 = ahora
# =========================================================
# ACTIVAR IRQ
# =========================================================
btn1.irq(
trigger=Pin.IRQ_FALLING,
handler=isr_btn1
)
btn2.irq(
trigger=Pin.IRQ_FALLING,
handler=isr_btn2
)
btn3.irq(
trigger=Pin.IRQ_FALLING,
handler=isr_btn3
)
btn4.irq(
trigger=Pin.IRQ_FALLING,
handler=isr_btn4
)
btn5.irq(
trigger=Pin.IRQ_FALLING,
handler=isr_btn5
)
# =========================================================
# BARRA SUPERIOR
# =========================================================
def dibujar_barra():
oled.fill_rect(0,0,128,16,0)
if hora < 10:
htxt = "0" + str(hora)
else:
htxt = str(hora)
if minuto < 10:
mtxt = "0" + str(minuto)
else:
mtxt = str(minuto)
if segundo < 10:
stxt = "0" + str(segundo)
else:
stxt = str(segundo)
reloj = htxt + ":" + mtxt + ":" + stxt
oled.text(
reloj,
0,
0
)
oled.text(
str(vsys_v) + "V",
80,
0
)
oled.hline(
0,
15,
128,
1
)
# =========================================================
# FOURIER
# =========================================================
PASO = (XMAX - XMIN) / 256
x = XMIN
# =========================================================
# LOOP PRINCIPAL
# =========================================================
while True:
dibujar_barra()
if modo != modo_anterior:
oled.fill_rect(
0,
16,
128,
48,
0
)
modo_anterior = modo
# =====================================================
# MODO 1
# =====================================================
if modo == 1:
dibujar_fourier()
y = f_fourier(x)
y_norm = y / AMP
y_norm = max(
-1,
min(1, y_norm)
)
salp(
dac(y_norm)
)
print(y_norm)
x += PASO
if x >= XMAX:
x = XMIN
# MAS RAPIDO PARA SCOPPY
time.sleep_us(25)
# =====================================================
# MODO 2
# =====================================================
elif modo == 2:
lectura_v = adc_volt.read_u16()
voltaje = lectura_v * factor
suma_v += voltaje
cont_v += 1
if cont_v >= 10:
prom_v = suma_v / 10
suma_v = 0
cont_v = 0
oled.fill_rect(0,16,128,48,0)
oled.text("VOLTIMETRO",0,16)
oled.text(
"V:"
+ str(round(voltaje,4)),
0,
32
)
oled.text(
"P:"
+ str(round(prom_v,4)),
0,
48
)
print(
"Volt:",
round(voltaje,4)
)
time.sleep_ms(200)
# =====================================================
# MODO 3
# =====================================================
elif modo == 3:
lectura_r = adc_ohm.read_u16()
vr = lectura_r * factor
if vr < 0.001:
resistencia = 0.0
else:
Ramp = 10.0
R7 = 1000.0
corriente = vr / Ramp
if corriente <= 0:
resistencia = 0.0
else:
resistencia = (
3.3 / corriente
) - R7 - Ramp
if resistencia < 0:
resistencia = 0.0
suma_r += resistencia
cont_r += 1
if cont_r >= 10:
prom_r = suma_r / 10.0
suma_r = 0.0
cont_r = 0
oled.fill_rect(0,16,128,48,0)
oled.text("OHMETRO",0,16)
oled.text(
"R:" + str(int(resistencia)),
0,
32
)
oled.text(
"P:" + str(int(prom_r)),
0,
48
)
print("Ohm:", resistencia)
time.sleep_ms(300)
# =====================================================
# MODO 4
# =====================================================
elif modo == 4:
lectura_i = adc_amp.read_u16()
vshunt = lectura_i * factor
if vshunt < 0.001:
corriente_ma = 0
else:
Rshunt = 10
corriente_ma = (
vshunt /
Rshunt
) * 1000
suma_i += corriente_ma
cont_i += 1
if cont_i >= 10:
prom_i = suma_i / 10
suma_i = 0
cont_i = 0
oled.fill_rect(0,16,128,48,0)
oled.text("AMPERIMETRO",0,16)
oled.text(
"I:"
+ str(round(corriente_ma,3)),
0,
32
)
oled.text(
"P:"
+ str(round(prom_i,3)),
0,
48
)
print(
"mA:",
round(corriente_ma,3)
)
time.sleep_ms(200)
# =====================================================
# MODO 5
# =====================================================
elif modo == 5:
oled.fill_rect(0,16,128,48,0)
try:
dht_sensor.measure()
temp_dht = (
dht_sensor.temperature()
)
hum_dht = (
dht_sensor.humidity()
)
suma_t += temp_dht
cont_t += 1
if cont_t >= 10:
prom_t = suma_t / 10
suma_t = 0
cont_t = 0
oled.text("DHT22",0,16)
oled.text(
"T:"
+ str(round(temp_dht,1)),
0,
32
)
oled.text(
"P:"
+ str(round(prom_t,1)),
0,
48
)
oled.text(
"H:"
+ str(round(hum_dht,1)),
70,
32
)
print(
temp_dht,
hum_dht
)
except:
oled.text(
"ERROR DHT",
0,
32
)
print("Error DHT")
time.sleep(1)
oled.show()