# -*- coding: utf-8 -*-
import math
import time
import framebuf
from machine import Pin, I2C, ADC
from ssd1306 import SSD1306_I2C
from LibDecTarjeta import Board
WIDTH, HEIGHT = 128, 64
i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000)
oled = SSD1306_I2C(WIDTH, HEIGHT, i2c)
adc_x = ADC(26)
adc_y = ADC(27)
class Parser:
def __init__(self, expression):
self.expr = expression.replace(" ", "")
self.pos = 0
self.x_val = 0
self.y_val = 0
self.z_val = 0
def parse(self, x_val=0, y_val=0, z_val=0):
self.x_val = x_val
self.y_val = y_val
self.z_val = z_val
self.pos = 0
result = self.parse_expression()
if self.pos < len(self.expr):
raise ValueError("Caracter inesperado: {}".format(self.expr[self.pos]))
return result
def parse_expression(self):
result = self.parse_term()
while self.pos < len(self.expr) and self.expr[self.pos] in "+-":
op = self.expr[self.pos]
self.pos += 1
term = self.parse_term()
result = result + term if op == '+' else result - term
return result
def parse_term(self):
result = self.parse_factor()
while self.pos < len(self.expr) and self.expr[self.pos] in "*/":
op = self.expr[self.pos]
self.pos += 1
factor = self.parse_factor()
result = result * factor if op == '*' else result / factor
return result
def parse_factor(self):
if self.expr[self.pos] == '(':
self.pos += 1
result = self.parse_expression()
if self.pos >= len(self.expr) or self.expr[self.pos] != ')':
raise ValueError("Falta )")
self.pos += 1
return result
func_names = ['sin', 'cos', 'tan', 'exp', 'log', 'sqrt']
for fn in func_names:
ln = len(fn)
if self.expr[self.pos:self.pos+ln] == fn:
self.pos += ln
if self.pos >= len(self.expr) or self.expr[self.pos] != '(':
raise ValueError("Falta ( despues de {}".format(fn))
self.pos += 1
val = self.parse_expression()
if self.pos >= len(self.expr) or self.expr[self.pos] != ')':
raise ValueError("Falta ) despues de {}".format(fn))
self.pos += 1
f = getattr(math, fn)
return f(val)
if self.expr[self.pos] == 'x':
self.pos += 1
return self.x_val
if self.expr[self.pos] == 'y':
self.pos += 1
return self.y_val
if self.expr[self.pos] == 'z':
self.pos += 1
return self.z_val
start = self.pos
if self.expr[self.pos] in '+-':
self.pos += 1
while self.pos < len(self.expr) and (self.expr[self.pos].isdigit() or self.expr[self.pos] == '.'):
self.pos += 1
if start == self.pos or (self.expr[start:self.pos] in ['+', '-']):
raise ValueError("Numero esperado")
return float(self.expr[start:self.pos])
def map_adc_to_range(val, min_val, max_val):
return min_val + (val / 65535) * (max_val - min_val)
def draw_axes(xmin, xmax, ymin, ymax):
oled.fill(0)
y0 = int(HEIGHT * ymax / (ymax - ymin))
if 0 <= y0 < HEIGHT:
oled.hline(0, y0, WIDTH, 1)
x0 = int(-xmin * WIDTH / (xmax - xmin))
if 0 <= x0 < WIDTH:
oled.vline(x0, 0, HEIGHT, 1)
def mostrar_pantalla_inicio():
agumon = bytearray([
0xf8, 0x1f, 0xf7, 0xef, 0x8f, 0x37, 0x7f, 0x97,
0x7f, 0x17, 0x79, 0xf7, 0x87, 0xf7, 0xbf, 0x2f,
0xc0, 0xef, 0xe7, 0x37, 0xd6, 0xe7, 0xc6, 0x38,
0xf3, 0xa2, 0xcc, 0x39, 0xad, 0x55, 0x81, 0x01
])
fb = framebuf.FrameBuffer(agumon, 16, 16, framebuf.MONO_HLSB)
oled.fill(0)
oled.blit(fb, 56, 24)
oled.show()
time.sleep(2)
oled.fill(0)
oled.text("Calculadora", 28, 0)
oled.text("cientifica", 30, 10)
oled.text("Pi Pico W", 32, 20)
oled.text("SSD1306", 40, 30)
oled.text("Edwin Luis", 30, 45)
oled.text("Garavito Omoya", 13, 55)
oled.show()
time.sleep(4)
oled.fill(0)
oled.show()
def mostrar_resultado(expr, result):
oled.fill(0)
oled.text("Expresion:", 0, 0)
oled.text(expr[:15], 0, 10)
oled.text("Resultado:", 0, 30)
oled.text(str(result)[:15], 0, 40)
oled.show()
time.sleep(3)
def graficador(expr, valores):
parser = Parser(expr)
while True:
x_range = map_adc_to_range(adc_x.read_u16(), 5, 15)
y_range = map_adc_to_range(adc_y.read_u16(), 1, 6)
xmin = -x_range
xmax = x_range
ymin = -y_range
ymax = y_range
draw_axes(xmin, xmax, ymin, ymax)
dx = (xmax - xmin) / WIDTH
for pixel_x in range(WIDTH):
x = xmin + pixel_x * dx
try:
y = parser.parse(
x_val=x,
y_val=valores.get('y', 0),
z_val=valores.get('z', 0)
)
except Exception:
y = 0
pixel_y = int(HEIGHT - ((y - ymin) * HEIGHT / (ymax - ymin)))
if 0 <= pixel_y < HEIGHT:
oled.pixel(pixel_x, pixel_y, 1)
oled.show()
time.sleep(0.1)
def validar_expr(expr):
permitidos = "0123456789+-*/().xyzsincoetagplr"
for c in expr:
if c.lower() not in permitidos:
return False
return True
def detectar_variables(expr):
expr = expr.lower()
variables = set()
if 'x' in expr:
variables.add('x')
if 'y' in expr:
variables.add('y')
if 'z' in expr:
variables.add('z')
return variables
def main():
mostrar_pantalla_inicio()
try:
board = Board()
print("Microcontrolador detectado:", board.type)
except Exception as e:
oled.fill(0)
oled.text("Error detectando", 0, 10)
oled.text("la placa", 0, 20)
oled.text(str(e)[:15], 0, 40)
oled.show()
return
while True:
oled.fill(0)
oled.text("Ingrese funcion:", 0, 10)
oled.text("Ej: sin(x)+x*y", 0, 30)
oled.show()
expr = input("Ingrese funcion f(x,y,z): ")
if not validar_expr(expr):
print("Expresion contiene caracteres invalidos")
continue
variables = detectar_variables(expr)
valores = {}
try:
for var in sorted(variables):
val = float(input(f"Valor para {var}: "))
valores[var] = val
except Exception:
print("Error: ingrese solo numeros válidos.")
continue
try:
parser = Parser(expr)
result = parser.parse(
x_val=valores.get('x', 0),
y_val=valores.get('y', 0),
z_val=valores.get('z', 0)
)
mostrar_resultado(expr, result)
print("Funcion valida, graficando...")
except Exception as e:
print("Error en expresion:", e)
continue
graficador(expr, valores)
main()