# ENV: micropython-20231005-v1.21.0
# DOCS: https://docs.micropython.org/en/v1.21.0/index.html
import re
from machine import Pin, I2C
# Tutorials:
# https://newbiely.com/tutorials/esp32-micropython/esp32-micropython-lcd-i2c
# https://newbiely.com/tutorials/esp32-micropython/esp32-micropython-keypad-4x4
from DIYables_MicroPython_LCD_I2C import LCD_I2C
from DIYables_MicroPython_Keypad import Keypad
# I2C LCD Init
I2C_ADDR = 0x27
LCD_ROWS = 4
LCD_COLS = 20
i2c = I2C(0, scl=Pin(22), sda=Pin(21))
lcd = LCD_I2C(i2c, I2C_ADDR, LCD_ROWS, LCD_COLS)
lcd.backlight_on()
lcd.clear()
# Keypad Init
NUM_ROWS = 4
NUM_COLS = 4
ROW_PINS = [19, 18, 5, 17]
COL_PINS = [16, 4, 0, 2]
KEYMAP = ['1', '2', '3', '+',
'4', '5', '6', '-',
'7', '8', '9', '*',
'C', '0', '=', '/']
keypad = Keypad(KEYMAP, ROW_PINS, COL_PINS, NUM_ROWS, NUM_COLS)
keypad.set_debounce_time(400) # 400ms, addjust it if it detects twice for single press
# State Init
state = 0 # 0 - ready; 1 - digit; 2 - operator; 3 - result
result = 0 # compute result
seq = [] # number and operatots sequence
dgt = re.compile('[0123456789]')
opr = re.compile('[\+\-\*\/]')
lcd.clear()
lcd.print('0')
"""
#
def calc(sq):
for op in ['*', '/', '+', '-']:
while sq.count(op):
pos = sq.index(op)
sq.pop(pos)
a = int(sq[pos - 1])
b = int(sq.pop(pos))
if op == '*': с = a * b
elif op == '/': с = a / b
elif op == '+': с = a + b
elif op == '-': с = a - b
sq[pos - 1] = с
return sq[0]
assert calc([]) == 0
assert calc(['123']) == 123
assert calc(['2', '-', '1']) == 1
assert calc(['1', '+', '2', '+', '3', '*', '4', '/', '2']) == 9
assert calc(['1', '/', '0']) == 'error'
assert calc(['xyz']) == 'error'
assert calc(['5', '/', '2']) == 2.5
assert calc(['10', '/', '3']) == 3.3333333333333335
"""
while True:
# C — clear
# 0-9 — digit
# A-D — operator
# # — compute
key = keypad.get_key()
if key:
if (key == 'C'):
state = 0
result = 0
seq.clear()
lcd.clear()
lcd.print('0')
elif (key == '='):
if state == 2:
seq.pop()
state = 1
if state == 1:
try: result = '=' + str(eval(''.join(seq)))
except: result = 'error'
lcd.set_cursor(0, 1)
lcd.print(result)
elif (opr.match(key)):
if state < 2:
if state == 0:
seq.append('0')
seq.append(key)
state = 2
elif state == 2:
seq[len(seq) - 1] = key
elif (dgt.match(key)):
if state == 1:
num = seq.pop()
if num == '0':
num = ''
seq.append(num + key)
elif state == 0 or state == 2:
seq.append(key)
state = 1
lcd.set_cursor(0, 0)
lcd.print(''.join(seq))