# Simple Calculator using Keypad & I2C LCD with Raspberry Pi Pico
from machine import Pin, I2C
import utime
from pico_i2c_lcd import I2cLcd
debug = True
# I2C setup
i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=200000)
I2C_ADDR = i2c.scan()[0]
lcd = I2cLcd(i2c, I2C_ADDR, 2, 16)
# Keypad layout
keyName = [['1','2','3','+'],
['4','5','6','-'],
['7','8','9','*'],
['c','0','=','/']]
keypadRowPins = [13,12,11,10]
keypadColPins = [9,8,7,6]
row = []
col = []
keypadState = []
for i in keypadRowPins:
row.append(Pin(i, Pin.IN, Pin.PULL_UP))
keypadState.append([0,0,0,0])
for i in keypadColPins:
col.append(Pin(i, Pin.OUT))
# ---------------- CALCULATOR LOGIC ---------------- #
def solve(oprt, oprdA, oprdB):
if oprt == "+":
return oprdA + oprdB
elif oprt == "-":
return oprdA - oprdB
elif oprt == "*":
return oprdA * oprdB
elif oprt == "/":
return round(oprdA / oprdB, 6)
def calc(lst):
operand = []
operator = []
for i in lst:
if debug:
print(i)
if i == '+':
while (len(operator)!=0 and
(operator[-1] in ['*','/','-','+'])):
b = operand.pop(-1)
a = operand.pop(-1)
c = operator.pop(-1)
operand.append(solve(c,a,b))
operator.append(i)
elif i == '-':
while (len(operator)!=0 and
(operator[-1] in ['*','/','-','+'])):
b = operand.pop(-1)
a = operand.pop(-1)
c = operator.pop(-1)
operand.append(solve(c,a,b))
operator.append(i)
elif i == '*':
while (len(operator)!=0 and
(operator[-1] in ['*','/'])):
b = operand.pop(-1)
a = operand.pop(-1)
c = operator.pop(-1)
operand.append(solve(c,a,b))
operator.append(i)
elif i == '/':
while (len(operator)!=0 and
(operator[-1] in ['*','/'])):
b = operand.pop(-1)
a = operand.pop(-1)
c = operator.pop(-1)
operand.append(solve(c,a,b))
operator.append(i)
elif i == '(':
operator.append(i)
elif i == ')':
while operator[-1] != '(':
b = operand.pop(-1)
a = operand.pop(-1)
c = operator.pop(-1)
operand.append(solve(c,a,b))
operator.pop(-1)
else:
operand.append(i)
while len(operator) != 0:
b = operand.pop(-1)
a = operand.pop(-1)
c = operator.pop(-1)
operand.append(solve(c,a,b))
return operand[0]
# ---------------- KEYPAD READING ---------------- #
def keypadRead():
global row
j_ifPressed = -1
i_ifPressed = -1
for i in range(len(col)):
col[i].low()
utime.sleep(0.005)
for j in range(len(row)):
pressed = not row[j].value()
if pressed and (keypadState[j][i] != pressed):
keypadState[j][i] = pressed
elif not pressed and (keypadState[j][i] != pressed):
keypadState[j][i] = pressed
j_ifPressed = j
i_ifPressed = i
col[i].high()
if j_ifPressed != -1 and i_ifPressed != -1:
return keyName[j_ifPressed][i_ifPressed]
else:
return -1
# ---------------- LCD DISPLAY ---------------- #
def printLCD(lst):
lcd.clear()
string = ""
for i in lst:
string += str(i)
lcd.move_to(0,0)
lcd.putstr(string[:16])
lcd.move_to(0,1)
lcd.putstr(string[16:32])
# ---------------- START SCREEN ---------------- #
lcd.clear()
lcd.move_to(0,0)
lcd.putstr("Simple")
lcd.move_to(0,1)
lcd.putstr("Calculator")
utime.sleep(2)
lcd.clear()
# ---------------- MAIN PROGRAM ---------------- #
shiftFlag = False
signFlag = False
inputList = ['']
if __name__ == '__main__':
while True:
key = keypadRead()
if key != -1:
if ((key <= '9' and key >= '0') or key == '.'):
inputList[-1] = inputList[-1] + key
elif key in ['+','-','*','/']:
if inputList != ['']:
if (inputList[-1] == '' and
inputList[-2] in ['+','-','*','/']):
inputList[-2] = key
elif inputList[-1] == '':
inputList[-1] = key
inputList.append('')
else:
inputList[-1] = float(inputList[-1])
inputList.append(key)
inputList.append('')
elif key == 'c':
if inputList == ["error"]:
inputList = ['']
if inputList != ['']:
if inputList[-1] == '':
inputList.pop()
inputList[-1] = str(inputList[-1])[:-1]
else:
inputList[-1] = str(inputList[-1])[:-1]
elif key == '=':
if inputList[-1] == '':
inputList.pop(-1)
elif inputList[-1] != ')':
inputList[-1] = float(inputList[-1])
try:
ans = calc(inputList)
inputList = [str(ans)]
except:
inputList = ["error"]
printLCD(inputList)
print(inputList)