"""
Villafaña Oliva César Omar
Mosqueda Hernández Josué Mosqueda
Arellano Fuentes Cristian Yael
Objective: Implement menu navigation with joystick, interrupt execution,
and change option upon receiving and decoding IR remote signals.
"""
from machine import Pin, ADC
import time
import ir_rx
from menu import Menu
remoteOption = 0x00 # The IR remote reading
position = 1 # The current option where the line is positioned
changeOption = [False] # Indicate that an immediate change must be made if another option was pressed on the remote
joyPressed = 1 # Indicate that the joystick is not pressed (0-pressed, 1-not pressed)
codeDict = {0x68:0, 0x30:1, 0x18:2, 0x7a:3, 0x10:4, 0x38:5, 0x5a:6, 0x42:7,
0x4a:8, 0x52:9, 0x2:"up", 0x90:"right", 0x98:"down", 0xe0:"left", 0x1c:"OK",
0x22:"asterisk", 0xc2:"hashtag"}
# IR receiver interrupt function
def callback(data, addr, ctrl):
global remoteOption, joyPressed
# If the user is not in the menu because a signal was received or the joystick was pressed
if remoteOption > 0x00 or not joyPressed:
changeOption[0] = True # Indicate that it is necessary to change to another option
joyPressed = True # Indicate that the joystick is not pressed (1) to not show the menu
if data > 0x00: # If the reading was not a button release
remoteOption = data # Register the hexadecimal number of the read button
print("Code pattern detected: ", hex(remoteOption))
# Show the menu and a line below the current option.
def showMenu():
menu.mostrar_texto(message, 0, 10) # Show menu at (0, 10)
menu.oled.pintar_linea(18 + position*10, 1) # Below option 1 is at x=18; each subsequent option moves down by 10.
# Update the line of the current option; displacement indicates how many options it went up or down
def moveLine(displacement):
global position
menu.oled.pintar_linea(18 + position*10, 0) # Paint a black line at the current position (erase).
position += displacement # Update line position
menu.oled.pintar_linea(18 + position*10, 1) # White line underneath; Below option 1 is at x=18; each subsequent option moves down by 10.
# Configure the pin to connect the IR receiver
pin_ir_rx = Pin(26, Pin.IN)
# Create an instance of the IR receiver with the NEC_16 protocol
ir = ir_rx.NEC_16(pin_ir_rx, callback)
# Joystick
vry = ADC(Pin(12, Pin.IN)) # vertical movement
vry.atten(ADC.ATTN_11DB) # attenuation adjustment
button = Pin(14, Pin.IN, Pin.PULL_UP) # joystick press; 1 when not pressed
if __name__ == '__main__':
menu = Menu(pin_scl=21, pin_sda=22, pin_ldr=34, pin_dht=2, cambiarOpcion=changeOption) # Used pins and change state
message = ("Show:",
"1.- Luminosity.",
"2.- Temperature.",
"3.- Humidity.",
"4.- Names.") # Menu options
showMenu() # Show the menu for the first time
def readJoystick():
global joyPressed, position
valueY = vry.read() # read vertical point
joyPressed = button.value() # read button state
if joyPressed == False: # If the button was pressed (0 - pressed, 1 - not pressed)
menu.opciones(position) # Execute the option at the current position
if valueY < 200: # If moved upwards (close to 0 for lower sensitivity)
if position != 1: # If not at the upper limit
moveLine(-1) # Move the line 1 position back
elif valueY > 3700: # If moved downwards (close to 4096 for lower sensitivity)
if position != 4: # If not at the lower limit
moveLine(1) # Move the line 1 position forward
def readRemote():
global remoteOption, position, changeOption
if remoteOption > 0x00: # Detect if it wasn't held down
option = codeDict[remoteOption] # Get the corresponding button
print(remoteOption, option)
if option == "up":
if position != 1: # If not at the upper limit
position -= 1 # Go up
menu.opciones(position) # Execute the option at the current position
elif option == "down":
if position != 4: # If not at the lower limit
position += 1 # Go down
menu.opciones(position) # Execute the option at the current position
elif option == "OK":
menu.opciones(position) # Execute the option at the current position
else:
menu.opciones(option) # Execute the option
if option in range(1,5): # If the option is valid (1-4)
position = option # Update the current line position
if changeOption[0] == False: # If it has not been indicated to change the option
remoteOption = 0x00 # Reset the option received by the receiver
showMenu() # Show the menu again
changeOption[0] = False # The option change has already been made for this cycle
# Infinite loop to detect and decode IR signals
while True:
# Read joystick
readJoystick()
# Wait for remote control signal
readRemote()
if joyPressed == False: # If the joystick was pressed in this cycle
showMenu() # Show the menu again