import uos
import micropython
import time
import os
from machine import Pin
from machine import SPI
from machine import I2C
from lcd_api import LcdApi
# import sdcard
# from pzem_syg import PZEM_SYG
# from pico_i2c_lcd import I2cLcd
import mockup_sdcard as sdcard
from mockup_pzem_syg import PZEM_SYG
from pepe import I2cLcd
from ds1307 import DS1307
# PINOUT#---------------------------------------
# sda display---|1 GPIO 0 VBUS 40|
# scl display---|2 GPIO 1 VSYS 39|
# |3 GND GND 38|
# rele consumo --- |4 GPIO 2 3V3_EN 37|
# Buzzer --- |5 GPIO 3 3V3(OUT) 36|
# pzems tx --- |6 GPIO 4 ADC_VREF 35|
# pzems rx --- |7 GPIO 5 GPIO 28 34| --- rotary sw
# |8 GND GND 33|
# rele CN --- |9 GPIO 6 GPIO 27 32| --- rtc scl
# rele PAT --- |10 GPIO 7 GPIO 26 31| --- rtc sda
# LED verde --- |11 GPIO 8 RUN 30|
# LED rojo --- |12 GPIO 9 GPIO 22 29| --- rotary clk
# |13 GND GND 28|
# rele 1K --- |14 GPIO 10 GPIO 21 27|
# rele 2K5 --- |15 GPIO 11 GPIO 20 26| --- rotary dt
# sd miso --- |16 GPIO 12 GPIO 19 25|
# sd cs --- |17 GPIO 13 GPIO 18 24|
# |18 GND GND 23|
# sd sck --- |19 GPIO 14 GPIO 17 22|
# sd mosi --- |20 GPIO 15 GPIO 16 21|
#
# CONSTANTES ===================================================================
DEBUG = False
SETEAR_HORA = False
#[AÑO,DIA,MES,DIA_SEMANA(LUNES=1),HORA,MIN,SEG,0]
NUEVA_HORA = [2024,8,6,2,16,56,0]
PATH_SD = "/"
PATH_HISTORIAL = "/HISTORIAL.csv"
PATH_PRODUCTOS = "/PRODUCTOS.txt"
PATH_ULTIMOS_REGISTROS = "/ultimos_registros.json"
PIN_BUZZER = 3
PIN_RELE_CONSUMO = 2
PIN_LED_VERDE = 8
PIN_LED_ROJO = 9
PIN_RELE_CN = 6
PIN_RELE_PAT = 7
PIN_RELE_1K = 10
PIN_RELE_2K5 = 11
LCD_I2C_ADDR = 0x27
LCD_NUM_ROWS = 4
LCD_NUM_COLS = 20
LCD_PIN_SCL = 1
LCD_PIN_SDA = 0
LCD_FREQ = 400_000
SDCARD_CS = 13
SDCARD_SCK = 14
SDCARD_MOSI = 15
SDCARD_MISO = 12
SDCARD_FREQ = 10_000_000
RTC_PIN_SDA = 26
RTC_PIN_SCL = 27
ENCODER_PIN_DT = 20
ENCODER_PIN_CLK = 22
ENCODER_PIN_SW = 28
PZEM_CONS_ADDR = 0x01
PZEM_MD1_ADDR = 0x02
PZEM_MD2_ADDR = 0x03
NOMBRES_ENSAYOS = [
'consumo',
'fuga',
'corte_neutro',
'pat',
'tension_resistida'
]
# ==============================================================================
# VARIABLES GLOBALES ===========================================================
historial_json = []
listaProductos = []
primera_vez_comparando_hora = 1
id_prox_ensayo = 0
max_longitud_historial = 10
lcd = None
# Menu principal
previousValue = 1
posMenu = -1
# Menu Ensayos individuales
pos_ind = -1
prev_pos_ind = pos_ind
# Menu Productos
posProductos = -1
prev_pos_producto = posProductos
# Menu Historial
posHistorial = -1
prev_pos_historial = posHistorial
tipoMenu = 0
ensayototal = 0
banderita_producto = -1
producto_seleccionado = None
aprueba = [-1, -1, -1, -1, -1]
resultados_ensayos = {}
refresh_screen = False
# ==============================================================================
# -------- Funcion de Log ------------------------------------------------------
def escribir_log(topic, value):
with open(f"{PATH_SD}/log.txt", "a") as f:
# Si es un array se serializa
if isinstance(value, list):
value = ', '.join(map(str, value))
else:
value = str(value)
# Escribe el log en el archivo
f.write(f"{topic}: {value}\n")
# ------------------------------------------------------------------------------
# INICIALIZACIONES =============================================================
# -------- Inicialización LEDs -------------------------------------------------
buzzer = Pin(PIN_BUZZER, Pin.OUT, value=0)
led_verde = Pin(PIN_LED_VERDE, Pin.OUT, value=0)
led_rojo = Pin(PIN_LED_ROJO, Pin.OUT, value=0)
if DEBUG:
# Parpadeo de LED verde
led_verde.value(1)
time.sleep(0.5)
led_verde.value(0)
# Parpadeo de LED rojo
led_rojo.value(1)
time.sleep(0.5)
led_rojo.value(0)
# Pitido de buzzer
buzzer.value(1)
time.sleep(0.5)
buzzer.value(0)
# ------------------------------------------------------------------------------
# -------- Inicialización LCD --------------------------------------------------
def inicializar_display():
global lcd
try:
i2c = I2C(0, sda=Pin(LCD_PIN_SDA), scl=Pin(LCD_PIN_SCL), freq=LCD_FREQ)
lcd = I2cLcd(i2c, LCD_I2C_ADDR, LCD_NUM_ROWS, LCD_NUM_COLS)
if DEBUG:
lcd.clear()
lcd.move_to(0, 1)
lcd.putstr("INICIALIZANDO".center(LCD_NUM_COLS))
lcd.move_to(0, 2)
lcd.putstr("DISPOSITIVOS".center(LCD_NUM_COLS))
time.sleep(2)
except Exception as e:
print("Error al inicializar LCD:", e)
inicializar_display()
# ------------------------------------------------------------------------------
# -------- Inicialización SD ---------------------------------------------------
# Inicializar SPI a velocidad baja (400 kHz)
try:
spi = SPI(
id=1,
baudrate=400_000, # Baja velocidad para inicialización
polarity=0,
phase=0,
bits=8,
firstbit=SPI.MSB,
sck=Pin(SDCARD_SCK),
mosi=Pin(SDCARD_MOSI),
miso=Pin(SDCARD_MISO)
)
cs = Pin(SDCARD_CS, Pin.OUT, value=1)
sd = sdcard.SDCard(spi, cs)
# Montar sistema de archivos
vfs = uos.VfsFat(sd)
uos.mount(vfs, PATH_SD)
# Aumentar la velocidad del bus SPI después de montar
spi.init(baudrate=400_000)
if DEBUG:
# VALIDACIÓN DE TARJETA SD
lcd.clear()
lcd.putstr("PROBANDO SDCARD:".center(LCD_NUM_COLS))
path_test = f"{PATH_SD}/test.txt"
texto_test = "Texto de prueba\n"
lectura = ""
# Prueba de Escritura
lcd.putstr("Escritura:")
with open(path_test, "w") as f:
bytes_escritos = f.write(texto_test)
if bytes_escritos:
lcd.putstr("OK")
lcd.move_to(0, 2)
lcd.putstr("Lectura:")
# Prueba de Lectura
with open(path_test, "r") as f:
lectura = f.read()
if lectura == texto_test:
lcd.putstr("OK")
uos.remove(path_test)
else:
lcd.putstr("ERROR")
else:
lcd.putstr("ERROR")
time.sleep(2)
except Exception as e:
lcd.clear()
lcd.move_to(3, 1)
lcd.putstr(type(e).__name__)
time.sleep(5)
# ------------------------------------------------------------------------------
# -------- Inicialización RTC --------------------------------------------------
interfaz_i2c = I2C(
id=1,
scl=Pin(RTC_PIN_SCL),
sda=Pin(RTC_PIN_SDA),
freq=400_000
)
rtc = DS1307(interfaz_i2c)
if SETEAR_HORA:
rtc.datetime(NUEVA_HORA)
if DEBUG:
lcd.clear()
lcd.putstr("PROBANDO RTC:".center(LCD_NUM_COLS))
fh = rtc.datetime() # Tupla con la fecha y hora
fecha_formateada = '{:02}/{:02}/{} {:02}:{:02}:{:02}'.format(
fh[2],
fh[1],
fh[0],
fh[4],
fh[5],
fh[6]
)
lcd.putstr(fecha_formateada.center(LCD_NUM_COLS))
lcd.putstr("OK".center(LCD_NUM_COLS))
time.sleep(2)
# CONFIGURAR FECHA Y HORA: [año,mes,dia,dia_semana,hora,min,seg,dia_semana]
# rtc.datetime([2024,6,7,0,11,33,10,3])
# ------------------------------------------------------------------------------
# -------- Inicialización RTC --------------------------------------------------
if DEBUG:
lcd.clear()
lcd.putstr("ENCODER: ")
DT = Pin(ENCODER_PIN_DT, Pin.IN, Pin.PULL_UP)
CLK = Pin(ENCODER_PIN_CLK, Pin.IN, Pin.PULL_UP)
SW = Pin(ENCODER_PIN_SW, Pin.IN, Pin.PULL_UP)
if DEBUG:
lcd.putstr("OK")
time.sleep(2)
# ------------------------------------------------------------------------------
# -------- Inicialización Relés ------------------------------------------------
if DEBUG:
lcd.clear()
lcd.putstr("RELES: ")
rele_cons = Pin(PIN_RELE_CONSUMO, Pin.OUT, value=1)
rele_cn = Pin(PIN_RELE_CN, Pin.OUT, value=1)
rele_pat = Pin(PIN_RELE_PAT, Pin.OUT, value=1)
rele_tr1k = Pin(PIN_RELE_1K, Pin.OUT, value=1)
rele_tr2k5 = Pin(PIN_RELE_2K5, Pin.OUT, value=1)
if DEBUG:
lcd.putstr("OK")
time.sleep(2)
# ------------------------------------------------------------------------------
# -------- Inicialización PZEMs ------------------------------------------------
if DEBUG:
lcd.clear()
lcd.putstr("PZEM CONS: ")
pzem_consumo = PZEM_SYG(uart_id=1, addr=PZEM_CONS_ADDR)
if DEBUG:
lcd.putstr("OK")
lcd.move_to(0, 1)
lcd.putstr("PZEM MD1: ")
pzem_md1 = PZEM_SYG(uart_id=1, addr=PZEM_MD1_ADDR)
if DEBUG:
lcd.putstr("OK")
lcd.move_to(0, 2)
lcd.putstr("PZEM MD2: ")
pzem_md2 = PZEM_SYG(uart_id=1, addr=PZEM_MD2_ADDR)
if DEBUG:
lcd.putstr("OK")
time.sleep(2)
# ------------------------------------------------------------------------------
# -------- MENSAJE BIENVENIDA --------------------------------------------------
def MENSAJEBIENVENIDA():
lcd.clear()
lcd.move_to(0, 1)
lcd.putstr("LABORATORIO".center(20))
lcd.move_to(0, 2)
lcd.putstr("S&G LAB".center(20))
lcd.move_to(0, 3)
lcd.putstr("Version 1.1".center(20))
time.sleep(1)
# ------------------------------------------------------------------------------
# -------- MENÚ PRINCIPAL ------------------------------------------------------
def MENU():
global posMenu
if posMenu == -1:
lcd.clear()
lcd.move_to(0, 0)
lcd.putstr('~ENSAYAR TODO')
lcd.move_to(0, 1)
lcd.putstr(''' ENSAYO INDIVIDUAL''')
lcd.move_to(0, 2)
lcd.putstr(''' HISTORIAL''')
lcd.move_to(0, 3)
lcd.putstr(''' CAMBIAR DE PRODUCTO''')
posMenu = 0
if posMenu == 0:
lcd.move_to(0, 0)
lcd.putstr('''~''')
lcd.move_to(0, 1)
lcd.putstr(''' ''')
lcd.move_to(0, 2)
lcd.putstr(''' ''')
lcd.move_to(0, 3)
lcd.putstr(''' ''')
elif posMenu == 1:
lcd.move_to(0, 0)
lcd.putstr(''' ''')
lcd.move_to(0, 1)
lcd.putstr('''~''')
lcd.move_to(0, 2)
lcd.putstr(''' ''')
elif posMenu == 2:
lcd.move_to(0, 0)
lcd.putstr(''' ''')
lcd.move_to(0, 1)
lcd.putstr(''' ''')
lcd.move_to(0, 2)
lcd.putstr('''~''')
lcd.move_to(0, 3)
lcd.putstr(''' ''')
elif posMenu == 3:
lcd.move_to(0, 1)
lcd.putstr(''' ''')
lcd.move_to(0, 2)
lcd.putstr(''' ''')
lcd.move_to(0, 3)
lcd.putstr('''~''')
# ------------------------------------------------------------------------------
# -------- MENÚ INDIVIDUAL -----------------------------------------------------
def MENUINDIVIDUAL():
global prev_pos_ind, pos_ind, refresh_screen
lista_ensayos = [
"CONSUMO",
"FUGA",
"CORTE NEUTRO",
"PAT",
"TENSION RESISTIDA"
]
if pos_ind == -1:
# condicion inicial
refresh_screen = True
pos_ind = 0
prev_pos_ind = pos_ind
elif prev_pos_ind < pos_ind and pos_ind % 3 == 0:
# subimos de screen
refresh_screen = True
elif prev_pos_ind > pos_ind and pos_ind % 3 == 2:
# bajamos de screen
refresh_screen = True
elif prev_pos_ind == pos_ind:
# no hubo movimiento
return
if refresh_screen:
prev_pos_ind = pos_ind
lcd.clear()
lcd.putstr('Ensayos'.center(20))
if pos_ind < 3:
lcd.move_to(0, 1)
lcd.putstr(f"{'~' if pos_ind == 0 else ' '}Atras")
for i, nombre_ensayo in enumerate(lista_ensayos[:2]):
lcd.move_to(0, i+2)
lcd.putstr(f"{'~' if pos_ind == i + 1 else ' '}{nombre_ensayo}")
else:
for i, nombre_ensayo in enumerate(
lista_ensayos[pos_ind-pos_ind % 3-1:pos_ind-pos_ind % 3+2]):
lcd.move_to(0, i+1)
lcd.putstr(f"{'~' if pos_ind % 3 == i else ' '}{nombre_ensayo}")
else:
for i in range(1, 4):
lcd.move_to(0, i)
lcd.putstr('~' if pos_ind % 3+1 == i else ' ')
refresh_screen = False
# ------------------------------------------------------------------------------
# -------- MENÚ SELECCIÓN PRODUCTO ---------------------------------------------
def RECORRERPRODUCTO(listaProductos):
global prev_pos_producto, posProductos, refresh_screen
if posProductos == -1:
# condicion inicial
refresh_screen = True
posProductos = 0
prev_pos_producto = posProductos
elif prev_pos_producto < posProductos and posProductos % 3 == 0:
# subimos de screen
refresh_screen = True
elif prev_pos_producto > posProductos and posProductos % 3 == 2:
# bajamos de screen
refresh_screen = True
elif prev_pos_producto == posProductos:
# no hubo movimiento
return
if refresh_screen:
prev_pos_producto = posProductos
lcd.clear()
lcd.move_to(5, 0)
lcd.putstr('Productos')
if posProductos < 3:
lcd.move_to(0, 1)
lcd.putstr(f"{'~' if posProductos == 0 else ' '}Atras")
for i, producto in enumerate(listaProductos[:2]):
campos_producto = producto.split()
linea_menu = f"{campos_producto[0]} {campos_producto[1]}W C{campos_producto[8]}"
linea_menu = linea_menu[:19]
lcd.move_to(0, i+2)
lcd.putstr(f"{'~' if posProductos == i +
1 else ' '}{linea_menu}")
else:
for i, producto in enumerate(
listaProductos[posProductos-posProductos % 3-1:posProductos-posProductos % 3+2]):
campos_producto = producto.split()
linea_menu = f"{campos_producto[0]} {campos_producto[1]}W C{campos_producto[8]}"
linea_menu = linea_menu[:19]
lcd.move_to(0, i+1)
lcd.putstr(f"{'~' if posProductos %
3 == i else ' '}{linea_menu}")
else:
for i in range(1, 4):
lcd.move_to(0, i)
lcd.putstr('~' if posProductos % 3+1 == i else ' ')
refresh_screen = False
# ------------------------------------------------------------------------------
# -------- ADECUAR LINEA DE HISTORIAL A MENU -----------------------------------
def parsear_historial(hist):
linea_historial = f"{hist["id_ensayo"]} {hist["equipo"]}"
espacios_relleno = 19 - len(linea_historial) - 5
linea_historial += " " * espacios_relleno
for ensayo in NOMBRES_ENSAYOS:
linea_historial += hist[ensayo]["aprueba"]
return linea_historial[:19]
# ------------------------------------------------------------------------------
# -------- OBTENER HORA --------------------------------------------------------
def obtener_hora():
try:
fh = rtc.datetime()
time.sleep(1)
fecha_formateada = '{}-{:02}-{:02}T{:02}:{:02}:{:02}'.format(
fh[0],
fh[1],
fh[2],
fh[4],
fh[5],
fh[6]
)
except:
fecha_formateada = '2024-01-01T99:99:99'
return fecha_formateada
# ------------------------------------------------------------------------------
# -------- ESCRIBIR HISTORIAL --------------------------------------------------
def escribir_historial(nombre_producto, nuevos_ensayos):
import json
global id_prox_ensayo, lcd
lcd.clear()
lcd.putstr('GUARDANDO...'.center(LCD_NUM_COLS))
time.sleep(1)
fecha_formateada = obtener_hora()
# Se desempaquetan los resultados y se escriben defaults si están vacios
consumo = nuevos_ensayos["consumo"] if nuevos_ensayos["consumo"] else [-1, -1, -1, -1, "_"]
fuga = nuevos_ensayos["fuga"] if nuevos_ensayos["fuga"] else [-1, "_"]
corte_neutro = nuevos_ensayos["corte_neutro"] if nuevos_ensayos["corte_neutro"] else [-1, "_"]
pat = nuevos_ensayos["pat"] if nuevos_ensayos["pat"] else [-1, "_"]
tension_resistida = nuevos_ensayos["tension_resistida"] if nuevos_ensayos["tension_resistida"] else [-1, "_"]
nueva_entrada = {
"id_ensayo": id_prox_ensayo,
"equipo": nombre_producto,
"fecha": fecha_formateada,
"consumo": {
"potencia": consumo[0],
"fp": consumo[1],
"tension": consumo[2],
"corriente": consumo[3],
"aprueba": consumo[4]
},
"fuga": {
"corriente": fuga[0],
"aprueba": fuga[1]
},
"corte_neutro": {
"corriente": corte_neutro[0],
"aprueba": corte_neutro[1]
},
"pat": {
"resistencia": pat[0],
"aprueba": pat[1]
},
"tension_resistida": {
"tension": tension_resistida[0],
"aprueba": tension_resistida[1]
}
}
# Insertar la nueva entrada al principio del historial
historial_json.insert(0, nueva_entrada)
# Verificar si hay más entradas de las permitidas
if len(historial_json) > max_longitud_historial:
historial_json.pop() # Eliminar la entrada más antigua
# Se escribe en el archivo de buffer
with open(PATH_ULTIMOS_REGISTROS, 'w') as f:
json.dump(historial_json, f)
time.sleep(2)
# ESCRITURA A ARCHIVO HISTORIAL
nuevo_registro = [str(id_prox_ensayo), nombre_producto, fecha_formateada]
nuevo_registro += [str(campo) for campo in consumo]
nuevo_registro += [str(campo) for campo in fuga]
nuevo_registro += [str(campo) for campo in corte_neutro]
nuevo_registro += [str(campo) for campo in pat]
nuevo_registro += [str(campo) for campo in tension_resistida]
nuevo_registro = ",".join(nuevo_registro)
# Se verifica si el archivo de historial ya existe
file_exists = False
try:
with open(PATH_HISTORIAL, 'r') as f:
file_exists = True
except OSError:
pass
time.sleep(2)
# Si el archivo no existe, lo crea con los headers
if not file_exists:
with open(PATH_HISTORIAL, 'w') as f:
headers = "id_ensayo,equipo,fecha,consumo_potencia,consumo_fp,consumo_tension,consumo_corriente,consumo_aprueba,fuga_corriente,fuga_aprueba,corte_neutro_corriente,corte_neutro_aprueba,pat_resistencia,pat_aprueba,tension_resistida_tension,tension_resistida_aprueba\n"
f.write(headers)
# Escribe el nuevo registro en el archivo
time.sleep(2)
with open(PATH_HISTORIAL, 'a') as f:
f.write(nuevo_registro + "\n")
id_prox_ensayo += 1
time.sleep(1)
# ------------------------------------------------------------------------------
def MENUHISTORIAL():
global prev_pos_historial, posHistorial, refresh_screen
global historial_json, posMenu, tipoMenu
if posHistorial == -1:
# condicion inicial
refresh_screen = True
posHistorial = 0
prev_pos_historial = posHistorial
elif prev_pos_historial < posHistorial and posHistorial % 3 == 0:
# subimos de screen
refresh_screen = True
elif prev_pos_historial > posHistorial and posHistorial % 3 == 2:
# bajamos de screen
refresh_screen = True
elif prev_pos_historial == posHistorial:
# no hubo movimiento
return
if refresh_screen:
prev_pos_historial = posHistorial
lcd.clear()
lcd.move_to(5, 0)
lcd.putstr('Historial')
if len(historial_json) == 0:
lcd.move_to(2, 3)
lcd.putstr('Historial vacio')
time.sleep(2)
posHistorial = -1
posMenu = -1
tipoMenu = 0
MENU()
elif posHistorial < 3:
lcd.move_to(0, 1)
lcd.putstr(f"{'~' if posHistorial == 0 else ' '}Atras")
for i, hist in enumerate(historial_json[:2]):
i += 1
lcd.move_to(0, i+1)
lcd.putstr(f"{'~' if posHistorial == i else ' '}{
parsear_historial(hist)}")
else:
for i, hist in enumerate(
historial_json[posHistorial-posHistorial % 3-1:posHistorial-posHistorial % 3+2]):
lcd.move_to(0, i+1)
lcd.putstr(f"{'~' if posHistorial % 3 == i else ' '}{
parsear_historial(hist)}")
else:
for i in range(1, 4):
lcd.move_to(0, i)
lcd.putstr('~' if posHistorial % 3+1 == i else ' ')
refresh_screen = False
# ------------------------------------------------------------------------------
def POSICION(nro_ens, cond): # muestra en display si aprueba o no el ensayo
if (nro_ens == 0):
lcd.move_to(1, 2)
lcd.putchar(cond)
elif (nro_ens == 1):
lcd.move_to(6, 2)
lcd.putchar(cond)
elif (nro_ens == 2):
lcd.move_to(10, 2)
lcd.putchar(cond)
elif (nro_ens == 3):
lcd.move_to(14, 2)
lcd.putchar(cond)
elif (nro_ens == 4):
lcd.move_to(18, 2)
lcd.putchar(cond)
def mostrar_mensaje_lcd(mensaje):
time.sleep(.2)
lcd.clear()
lcd.putstr(mensaje)
time.sleep(.2)
# ------------------------------------------------------------------------------
def LECTURAPRODUCTO():
try:
with open(PATH_PRODUCTOS, "r") as file:
data = file.read().split("\r\n")
return data
except Exception as e:
print(e)
return ['ERROR']
# ------------------------------------------------------------------------------
def POTENCIAPRODUCTO(posProductos, listita):
global clase
pot_sin_split = listita[posProductos - 1]
spliteado = pot_sin_split.split()
potencia_asociada = spliteado[1]
clase = spliteado[8]
return potencia_asociada
# ------------------------------------------------------------------------------
def COTAS(posProductos, listita):
prod_selec = listita[posProductos - 1]
prod_selec = prod_selec.split()
for k in range(2, 8):
lista_cotas = prod_selec[k]
return lista_cotas
# ------------------------------------------------------------------------------
def CONTROLRELE(ensayo, clase, cerrado):
global rele_cons, rele_cn, rele_pat, rele_tr1k, rele_tr2k5
if cerrado == 1: # CERRAR RELE
# cierro rele CONSUMO para ensayar y abro los otros
if ensayo[0] == 1 and ensayo[1] != 1 and ensayo[2] != 1 and ensayo[3] != 1 and ensayo[4] != 1:
rele_cons.value(0)
rele_cn.value(1)
rele_pat.value(1)
rele_tr1k.value(1)
rele_tr2k5.value(1)
# ensayo = [-1,-1,-1,-1,-1,-1]
# cierro rele FUGA para ensayar y abro los otros
# elif ensayo[0] != 1 and ensayo[1] == 1 and ensayo[2] != 1 and ensayo[3] != 1 and ensayo[4] != 1:
# print("******************************************************************")
# rele_cons.value(1)
# rele_cn.value(1)
# rele_pat.value(1)
# rele_tr1k.value(1)
# rele_tr2k5.value(1)
# cierro rele CN para ensayar y abro los otros
elif ensayo[0] != 1 and ensayo[1] != 1 and ensayo[2] == 1 and ensayo[3] != 1 and ensayo[4] != 1:
rele_cons.value(0)
rele_cn.value(0)
rele_pat.value(1)
rele_tr1k.value(1)
rele_tr2k5.value(1)
# cierro rele PAT para ensayar y abro los otros
elif ensayo[0] != 1 and ensayo[1] != 1 and ensayo[2] != 1 and ensayo[3] == 1 and ensayo[4] != 1:
rele_cons.value(1)
rele_cn.value(1)
rele_pat.value(0)
rele_tr1k.value(1)
rele_tr2k5.value(1)
# cierro rele TR para ensayar y abro los otros
elif ensayo[0] != 1 and ensayo[1] != 1 and ensayo[2] != 1 and ensayo[3] != 1 and ensayo[4] == 1:
rele_cons.value(1)
rele_cn.value(1)
rele_pat.value(1)
if clase == 1:
rele_tr1k.value(0)
rele_tr2k5.value(1)
elif clase == 2:
rele_tr1k.value(1)
rele_tr2k5.value(0)
if cerrado == 0: # ABRIR RELE
rele_cons.value(1)
rele_cn.value(1)
rele_pat.value(1)
rele_tr1k.value(1)
rele_tr2k5.value(1)
return
# ------------------------------------------------------------------------------
# Llama a las funciones que ejecutan cada ensayo
def ENSAYOS(ensayo, aprueba, posProductos, lista_productos, ensayototal):
if ensayo[0] == 1:
res = CONSUMO(ensayo, aprueba)
mostrar_mensaje_lcd("Resultado: " + res[4])
if ensayo_habilitado(mostrar_mensaje=False):
if ensayo[1] == 1:
FUGA(aprueba)
if ensayo[2] == 1:
CN(ensayo, aprueba)
if ensayo[3] == 1:
PAT(ensayo, aprueba)
if ensayo[4] == 1:
TR(ensayo, aprueba)
time.sleep(0.5)
# ---------------------------------------#---------------------------------------#---------------------------------------#---------------------------------------
# -----ENSAYO CONSUMO----------------------------------#---------------------------------------#---------------------------------------#---------------------------------------
def CONSUMO(ensayo, aprueba):
global primera_vez_comparando_hora, producto_seleccionado
global led_verde, led_rojo, buzzer
pot = producto_seleccionado["potencia"]
clase = producto_seleccionado["clase"]
i_margen_bajo = producto_seleccionado["cotas"]["cons_min"]
i_margen_alto = producto_seleccionado["cotas"]["cons_max"]
pzem_consumo.read()
pasa_cons = "-"
lcd.move_to(0, 3)
lcd.putstr("Ensayando CONSUMO".center(20))
i_teorica = (pot/220)
cerrado = 1
CONTROLRELE(ensayo, clase, cerrado)
time.sleep(2.5)
# Tension, Corriente, Potencia, factor de potencia
lista_lecturas = MEDICION(pzem_consumo)
cerrado = 0
CONTROLRELE(ensayo, clase, cerrado)
voltaje = lista_lecturas[0]
corriente = lista_lecturas[1]
potencia_medida = lista_lecturas[2]
fdp = lista_lecturas[3]
if ((corriente > i_teorica*i_margen_alto) or (corriente < i_teorica*i_margen_bajo)):
aprueba[0] = 0 # No aprueba consumo
pasa_cons = "N"
led_verde.value(0)
led_rojo.value(1)
buzzer.value(1)
time.sleep(.3)
led_rojo.value(0)
buzzer.value(0)
elif ((corriente < i_teorica*i_margen_alto) and (corriente > i_teorica*i_margen_bajo)):
aprueba[0] = 1 # Aprueba consumo
pasa_cons = "A"
led_verde.value(1)
led_rojo.value(0)
buzzer.value(1)
time.sleep(.2)
buzzer.value(0)
led_verde.value(0)
time.sleep(.2)
buzzer.value(1)
led_verde.value(1)
time.sleep(.2)
buzzer.value(0)
led_verde.value(0)
return [potencia_medida, fdp, voltaje, corriente, pasa_cons]
# ------------------------------------------------------------------------------
def FUGA(aprueba):
global led_verde, led_rojo, buzzer
clase = producto_seleccionado["clase"]
cota_fuga = producto_seleccionado["cotas"]["fuga"]
pzem_md1.read()
lcd.move_to(0, 3)
lcd.putstr("Ensayando FUGA".center(20))
cerrado = 1
pasa_fuga = "-"
provisorio_fuga = [1, -1, -1, -1, -1]
CONTROLRELE(provisorio_fuga, clase, cerrado)
time.sleep(2.5)
lista_lecturas = MEDICION(pzem_md1) # Tension, Corriente
cerrado = 0
CONTROLRELE(provisorio_fuga, clase, cerrado)
corriente = lista_lecturas[1]*10 #se multiplica nomas para poner en escala, no es correccion
if (corriente > cota_fuga):
aprueba[1] = 0 # No aprueba fuga
pasa_fuga = "N"
led_verde.value(0)
led_rojo.value(1)
buzzer.value(1)
time.sleep(.3)
led_rojo.value(0)
buzzer.value(0)
elif (corriente < cota_fuga):
aprueba[1] = 1 # Aprueba fuga
pasa_fuga = "A"
led_verde.value(1)
led_rojo.value(0)
buzzer.value(1)
time.sleep(.2)
buzzer.value(0)
led_verde.value(0)
time.sleep(.2)
buzzer.value(1)
led_verde.value(1)
time.sleep(.2)
buzzer.value(0)
led_verde.value(0)
return [corriente, pasa_fuga]
# ------------------------------------------------------------------------------
def CN(ensayo, aprueba):
global led_verde, led_rojo, buzzer
clase = producto_seleccionado["clase"]
cota_fuga = producto_seleccionado["cotas"]["fuga"]*1000
pasa_CN = "-"
lcd.move_to(0, 3)
lcd.putstr("Ensayando CN".center(20))
cerrado = 1
CONTROLRELE(ensayo, clase, cerrado)
time.sleep(2)
lista_lecturas = MEDICION(pzem_md1) # Tension, Corriente
cerrado = 0
CONTROLRELE(ensayo, clase, cerrado)
corriente = lista_lecturas[1]*16
# if (corriente > lista_cotas[2]):
#TODO: Verificar si se usa cota de fuga!!!=================================================================
if (corriente > cota_fuga):
aprueba[2] = 0 # No aprueba CN
pasa_CN = "N" # este estaba invertido con el otro
led_verde.value(0)
led_rojo.value(1)
buzzer.value(1)
time.sleep(.3)
led_rojo.value(0)
buzzer.value(0)
elif (corriente < cota_fuga):
aprueba[2] = 1 # Aprueba CN
pasa_CN = "A"
led_verde.value(1)
led_rojo.value(0)
buzzer.value(1)
time.sleep(.2)
buzzer.value(0)
led_verde.value(0)
time.sleep(.2)
buzzer.value(1)
led_verde.value(1)
time.sleep(.2)
buzzer.value(0)
led_verde.value(0)
return [corriente, pasa_CN]
# ------------------------------------------------------------------------------
def PAT(ensayo, aprueba):
global led_verde, led_rojo, buzzer
clase = producto_seleccionado["clase"]
cota_pat = producto_seleccionado["cotas"]["pat"]
lcd.move_to(0, 3)
lcd.putstr("Ensayando PAT".center(20))
resistencia = -1
pasa_PAT = "-"
cerrado = 1
CONTROLRELE(ensayo, clase, cerrado)
time.sleep(1.5)
lista_lecturas = MEDICION(pzem_md2) # Tension, Corriente
time.sleep(.2)
cerrado = 0
CONTROLRELE(ensayo, clase, cerrado)
voltaje = (lista_lecturas[0])
corriente = ((lista_lecturas[1]*1000)+0.001)/1000
resistencia = (voltaje/corriente)
if resistencia>10000:
time.sleep(1)
cerrado = 1
CONTROLRELE(ensayo, clase, cerrado)
time.sleep(1.5)
lista_lecturas = MEDICION(pzem_md2) # Tension, Corriente
time.sleep(.2)
cerrado = 0
CONTROLRELE(ensayo, clase, cerrado)
voltaje = (lista_lecturas[0])
corriente = ((lista_lecturas[1]*1000)+0.001)/1000
resistencia = (voltaje/corriente)
if (resistencia >= cota_pat):
aprueba[3] = 0 # No aprueba PAT
pasa_PAT = "N"
led_verde.value(0)
led_rojo.value(1)
buzzer.value(1)
time.sleep(.3)
led_rojo.value(0)
buzzer.value(0)
elif (resistencia < cota_pat):
aprueba[3] = 1 # Aprueba PAT
pasa_PAT = "A"
led_verde.value(1)
led_rojo.value(0)
buzzer.value(1)
time.sleep(.2)
buzzer.value(0)
led_verde.value(0)
time.sleep(.2)
buzzer.value(1)
led_verde.value(1)
time.sleep(.2)
buzzer.value(0)
led_verde.value(0)
return [resistencia, pasa_PAT]
# ------------------------------------------------------------------------------
def TR(ensayo, aprueba):
global led_verde, led_rojo, buzzer
clase = producto_seleccionado["clase"]
v_margen_bajo = producto_seleccionado["cotas"]["tr_min"]
v_margen_alto = producto_seleccionado["cotas"]["tr_max"]
lcd.move_to(0, 3)
lcd.putstr("Ensayando TR".center(20))
pasa_TR = "-"
if (clase == 1):
v_teorica = 1000 # MEDICION DEL TRAFO
else:
v_teorica = 2500 # MEDICION DEL TRAFO
cerrado = 1
CONTROLRELE(ensayo, clase, cerrado)
time.sleep(2)
lista_lecturas = MEDICION(pzem_md1) # Tension, Corriente
time.sleep(.5)
cerrado = 0
CONTROLRELE(ensayo, clase, cerrado)
voltaje = round(lista_lecturas[0]*10)
if ((voltaje > v_teorica * v_margen_alto) or (voltaje < v_teorica * v_margen_bajo)):
aprueba[4] = 0 # No aprueba tr
pasa_TR = "N"
led_verde.value(0)
led_rojo.value(1)
buzzer.value(1)
time.sleep(.3)
led_rojo.value(0)
buzzer.value(0)
elif ((voltaje < v_teorica * v_margen_alto) and (voltaje > v_teorica * v_margen_bajo)):
aprueba[4] = 1 # Aprueba tr
pasa_TR = "A"
led_verde.value(1)
led_rojo.value(0)
buzzer.value(1)
time.sleep(.2)
buzzer.value(0)
led_verde.value(0)
time.sleep(.2)
buzzer.value(1)
led_verde.value(1)
time.sleep(.2)
buzzer.value(0)
led_verde.value(0)
return [voltaje, pasa_TR]
# ------------------------------------------------------------------------------
def GPIO_input_debounce_handler(pin_obj, retardo_debounce=0.001):
"""
Lee el estado de un pin usando `GPIO.input` considerando los efectos del bouncing.
"""
lectura = pin_obj.value()
time.sleep(retardo_debounce)
while pin_obj.value() != lectura:
lectura = pin_obj.value()
time.sleep(retardo_debounce)
return lectura
# ------------------------------------------------------------------------------
def ensayo_habilitado(mostrar_mensaje=True):
global lcd, tipoMenu, producto_seleccionado, pos_ind
ensayo_permitido = (producto_seleccionado["clase"] == 1)
if mostrar_mensaje and not ensayo_permitido:
lcd.clear()
lcd.putstr("Ensayo no disponible")
lcd.putstr(" para los productos ")
lcd.putstr(" de clase 2 ")
time.sleep(1)
tipoMenu = 1
pos_ind = -1
MENUINDIVIDUAL()
return False
return ensayo_permitido
# ------------------------------------------------------------------------------
def cambioEnRotor():
global previousValue, tipoMenu, posMenu, posHistorial, posProductos
global listaProductos, banderita_producto, pos_ind
global prev_pos_producto, prev_pos_historial
global aprueba, historial_json
# PANTALLA PPAL
if tipoMenu == 0:
clkState = CLK.value()
if clkState != previousValue:
if CLK.value() == 0:
if DT.value() == 0:
posMenu -= 1
if posMenu < 0:
posMenu = 0
else:
posMenu += 1
if posMenu > 3:
posMenu = 3
MENU()
previousValue = clkState
if GPIO_input_debounce_handler(SW) == 0:
# FDL
time.sleep(0.1)
if posMenu == 0:
if banderita_producto == -1:
lcd.clear()
lcd.putstr(" Por favor ")
lcd.putstr("seleccione producto")
lcd.putstr(" a ensayar")
time.sleep(1)
tipoMenu = 0
posMenu = -1
MENU()
else:
tipoMenu = 0
ensayototal = 1
ensayo = [-1, -1, -1, -1, -1]
aprueba = [-1, -1, -1, -1, -1]
mostrar_mensaje_lcd("Ensayando Todo")
for cont in range(0, 5):
ensayo[cont] = 1
mostrar_mensaje_lcd("Ensayo: " + str(cont))
ENSAYOS(
ensayo,
aprueba,
posProductos,
listaProductos,
ensayototal
)
ensayo = [-1, -1, -1, -1, -1]
aprueba = [-1, -1, -1, -1, -1]
posMenu = -1
MENU()
if posMenu == 1:
if banderita_producto == -1:
lcd.clear()
lcd.putstr(" Por favor ")
lcd.putstr("seleccione producto")
lcd.putstr(" a ensayar")
time.sleep(1)
tipoMenu = 0
posMenu = -1
MENU()
else:
tipoMenu = 1
aprueba = [-1, -1, -1, -1, -1]
ensayo = [-1, -1, -1, -1, -1]
pos_ind = -1
MENUINDIVIDUAL()
if posMenu == 2:
tipoMenu = 2
lcd.clear()
prev_pos_historial = -1
MENUHISTORIAL()
if posMenu == 3:
# listaProductos = LECTURAPRODUCTO()
tipoMenu = 3
lcd.clear()
prev_pos_producto = -1
posProductos = -1
banderita_producto = -1
RECORRERPRODUCTO(listaProductos)
# ENSAYO INDIVIDUAL
if tipoMenu == 1:
# listaProductos = LECTURAPRODUCTO()
clkState = CLK.value()
if clkState != previousValue:
if CLK.value() == 0:
if DT.value() == 0:
pos_ind = pos_ind - 1
if pos_ind <= 0:
pos_ind = 0
else:
pos_ind = pos_ind + 1
if pos_ind > 5:
pos_ind = 5
MENUINDIVIDUAL()
previousValue = CLK.value()
#
if SW.value() == 0:
time.sleep(0.1)
ensayototal = 0
# Atras
if pos_ind == 0:
ensayos = [-1, -1, -1, -1, -1]
pos_ind = -1
# Ensayo de CONSUMO
elif pos_ind == 1:
ensayos = [1, -1, -1, -1, -1]
mostrar_mensaje_lcd("Ensayando consumo")
ENSAYOS(ensayos, aprueba, posProductos, listaProductos, ensayototal)
mostrar_mensaje_lcd("Fin ensayo consumo")
# Ensayo de FUGA
elif pos_ind == 2:
if ensayo_habilitado(mostrar_mensaje=True):
ensayos = [-1, 1, -1, -1, -1]
mostrar_mensaje_lcd("Ensayando consumo")
ENSAYOS(ensayos, aprueba, posProductos, listaProductos, ensayototal)
mostrar_mensaje_lcd("Fin ensayo consumo")
else:
return
# Ensayo de CORTE NEUTRO
elif pos_ind == 3:
if ensayo_habilitado(mostrar_mensaje=True):
ensayos = [-1, -1, 1, -1, -1]
mostrar_mensaje_lcd("Ensayando consumo")
ENSAYOS(ensayos, aprueba, posProductos, listaProductos, ensayototal)
mostrar_mensaje_lcd("Fin ensayo consumo")
else:
return
# Ensayo de PAT
elif pos_ind == 4:
if ensayo_habilitado(mostrar_mensaje=True):
ensayos = [-1, -1, -1, 1, -1]
mostrar_mensaje_lcd("Ensayando consumo")
ENSAYOS(ensayos, aprueba, posProductos, listaProductos, ensayototal)
mostrar_mensaje_lcd("Fin ensayo consumo")
else:
return
# Ensayo de TR
elif pos_ind == 5:
ensayos = [-1, -1, -1, -1, 1]
mostrar_mensaje_lcd("Ensayando consumo")
ENSAYOS(ensayos, aprueba, posProductos, listaProductos, ensayototal)
mostrar_mensaje_lcd("Fin ensayo consumo")
tipoMenu = 0
posMenu = -1
pos_ind = 0
MENU()
# Historial
if tipoMenu == 2:
clkState = CLK.value()
if clkState != previousValue:
if CLK.value() == 0:
prev_pos_historial = posHistorial
if DT.value() == 0:
posHistorial = posHistorial - 1
if posHistorial <= 0:
posHistorial = 0
else:
posHistorial = posHistorial + 1
if posHistorial > len(historial_json):
posHistorial = len(historial_json)
MENUHISTORIAL()
previousValue = CLK.value()
if GPIO_input_debounce_handler(SW) == 0:
if posHistorial != 0:
registro_seleccionado = historial_json[posHistorial - 1]
mostrar_registro_historico(registro_seleccionado)
posHistorial = -1
MENUHISTORIAL()
else:
# Si se seleccinó 'Atras'
posMenu = -1
tipoMenu = 0
posHistorial = -1
MENU()
# Productos
if tipoMenu == 3:
clkState = CLK.value()
if clkState != previousValue:
if CLK.value() == 0:
prev_pos_producto = posProductos
if DT.value() == 0:
posProductos = posProductos - 1
if posProductos <= 0:
posProductos = 0
else:
posProductos = posProductos + 1
if posProductos > len(listaProductos):
posProductos = len(listaProductos)
RECORRERPRODUCTO(listaProductos)
previousValue = CLK.value()
if GPIO_input_debounce_handler(SW) == 0:
time.sleep(0.1)
if posProductos != 0:
seleccionar_producto(posProductos, listaProductos)
tipoMenu = 0
posMenu = -1
banderita_producto = 0
MENU()
else:
lcd.clear()
tipoMenu = 0
posMenu = 0
print("Entro a else,vuelve a menu")
posMenu = -1
MENU()
# ------------------------------------------------------------------------------
# ------------------ MEDICIONES ------------------------------------------------
def MEDICION(placa):
global voltaje
global corriente
voltaje = 0
corriente = 0
potencia = 0
fdp = 0
x = 0
tensiones = [0, 0, 0, 0]
corrientes = [0, 0, 0, 0]
potencias = [0, 0, 0, 0]
fp = [0, 0, 0, 0]
if (placa.read()):
lecturas = placa.getValuesDictionary()
tensiones[0] = lecturas["voltage"] # Tension
corrientes[0] = lecturas["current"] # Corriente
potencias[0] = lecturas["active_power"] # Potencia
fp[0] = lecturas["power_factor"] # factor de potencia
for x in range(3): # armo arreglo con 3 lecturas estables
lecturas = placa.getValuesDictionary()
tensiones[x] = lecturas["voltage"] # Tension
corrientes[x] = lecturas["current"] # Corriente
potencias[x] = lecturas["active_power"] # Potencia
fp[x] = lecturas["power_factor"] # factor de potencia
voltaje = voltaje + tensiones[x]
corriente = corriente + corrientes[x]
potencia = potencia + potencias[x]
fdp = fdp + fp[x]
# obtengo tension y corriente promedio
voltaje = voltaje / 3
corriente = corriente / 3
potencia = potencia / 3
fdp = fdp / 3
return voltaje, corriente, potencia, fdp
# ------------------------------------------------------------------------------
def alinear_texto(titulo, numero, unidad, ancho=20):
espacio_disponible = ancho - len(titulo) - len(str(numero)) - len(unidad)
if espacio_disponible < 0:
raise ValueError("El ancho total es menor que la suma de los largos del título y el número.")
return titulo + ' ' * espacio_disponible + str(numero) + unidad
# ------------------------------------------------------------------------------
def seleccionar_producto(posProductos, lista_productos):
"""
Carg el producto seleccionado en una variable global
"""
global producto_seleccionado
campos_producto = lista_productos[posProductos-1].split()
producto_seleccionado = {
"nombre": campos_producto[0],
"potencia": int(campos_producto[1]),
"clase": int(campos_producto[8]),
"cotas": {
"cons_min": float(campos_producto[2]),
"cons_max": float(campos_producto[3]),
"fuga": float(campos_producto[4]),
"pat": float(campos_producto[5]),
"tr_min": float(campos_producto[6]),
"tr_max": float(campos_producto[7]),
}
}
mostrar_producto_seleccionado()
# ------------------------------------------------------------------------------
def mostrar_producto_seleccionado():
"""
Muestra el producto seleccionado en el display
"""
global lcd
cols_lcd = 20
ps = producto_seleccionado
nombre = "_" + ps["nombre"] + "_"
titulo = nombre.center(cols_lcd)
titulo = titulo.replace(" ", "-").replace("_", " ")
pot_nominal = ps["potencia"]
pot_nominal = alinear_texto("Potencia", pot_nominal, " W", cols_lcd)
clase = ps["clase"]
clase = alinear_texto("Clase", clase, " ", cols_lcd)
lcd.clear()
lcd.putstr(titulo)
lcd.move_to(0, 1)
lcd.putstr(pot_nominal)
lcd.move_to(0, 2)
lcd.putstr(clase)
time.sleep(3)
# ------------------------------------------------------------------------------
def mostrar_registro_historico(registro_historico):
"""
Muestra el registro seleccionado en el display
"""
global lcd
cols_lcd = 20
id_ensayo = str(registro_historico["id_ensayo"])
equipo = registro_historico["equipo"]
titulo = id_ensayo + "_" + equipo.upper().replace(" ", "_") + "_"
titulo = titulo.center(cols_lcd)
titulo = titulo.replace(" ", "-").replace("_", " ")
fecha = registro_historico["fecha"].replace("T", " ")
headers = "CON FUG CN PAT TR "
aprobaciones = []
for ensayo in NOMBRES_ENSAYOS:
aprobaciones.append(" " + registro_historico[ensayo]["aprueba"] + " ")
linea_aprobados = " ".join(aprobaciones)
lcd.clear()
lcd.putstr(titulo)
lcd.move_to(0, 1)
lcd.putstr(fecha)
lcd.move_to(0, 2)
lcd.putstr(headers)
lcd.move_to(0, 3)
lcd.putstr(linea_aprobados)
time.sleep(3)
# ------------------------------------------------------------------------------
def cargar_historial():
import json
try:
with open(PATH_ULTIMOS_REGISTROS, 'r') as f:
historial_json = json.loads(f.read())
id_prox_ensayo = historial_json[0].get('id_ensayo', 0) + 1
except Exception as err:
print(repr(err))
historial_json = []
with open(PATH_ULTIMOS_REGISTROS, 'w') as f:
json.dump(historial_json, f)
id_prox_ensayo = 1
return id_prox_ensayo, historial_json
# ------------------------------------------------------------------------------
def main():
global historial_json, listaProductos, posMenu, id_prox_ensayo
listaProductos = LECTURAPRODUCTO()
id_prox_ensayo, historial_json = cargar_historial()
MENSAJEBIENVENIDA()
posMenu = -1
MENU()
while 1:
cambioEnRotor()
# ------------------------------------------------------------------------------
if __name__ == "__main__":
main()