Pyboard: Changing LED colour on USR button press - python

I got these this board Pyboard D-series which has internal LED diode with three different colours.
My goal is to make it change the LED colour on button press so basically if u press for the first time, red goes red, second time led goes green, third time led goes blue and at the fourth time I would love it to ("reset") and go back to red.
I tried making this fucntion based on stuff I found online, but it doest seem to be working.
I am new to IoT and micropython so I might be missing something important, but have no clue what.
Thanks for any advice
from pyb import Switch
from pyb import LED
led_R = LED(1)
led_G = LED(2)
led_B = LED(3)
# 1=red, 2=green, 3=blue
sw = pyb.Switch()
def cycle():
counter = 0
buttonState = ''
buttonState = sw.value()
print(buttonState)
if buttonState == True:
counter = counter + 1
print(counter)
elif counter == 0:
led_R.off()
led_G.off()
led_B.off()
elif counter == 1:
led_R.on()
led_G.off()
led_B.off()
elif counter == 2:
led_R.off()
led_G.on()
led_B.off()
elif counter == 3:
led_R.off()
led_G.off()
led_B.on()
else:
counter = 0
sw.callback(cycle())

Your callback cycle is called when button state transitions from off to on
In the callback sw.value() will always evalluate into true so it does not make sense to check it.
your counter should be initialized outside of callback
from pyb import Switch
from pyb import LED
led_R = LED(1)
led_G = LED(2)
led_B = LED(3)
# 1=red, 2=green, 3=blue
sw = pyb.Switch()
counter = 0
def cycle():
counter = counter + 1
if counter == 4:
counter = 0
print(counter)
if counter == 0:
led_R.off()
led_G.off()
led_B.off()
elif counter == 1:
led_R.on()
led_G.off()
led_B.off()
elif counter == 2:
led_R.off()
led_G.on()
led_B.off()
elif counter == 3:
led_R.off()
led_G.off()
led_B.on()
sw.callback(cycle())

Related

Resetting the count of variable in a while loop

from microbit import *
from ssd1306 import initialize, clear_oled
from ssd1306_stamp import draw_stamp
from ssd1306_img import create_stamp
from ssd1306_text import add_text
import utime as time
window = []
threshold = 550 # limit
count = 0
sample = 0
beat = False
start = False
good = create_stamp(Image.HAPPY)
bad = create_stamp(Image.SAD)
heart = create_stamp(Image.HEART)
values = []
def mean(datalist):
sum = 0
for i in datalist:
sum += i
if len(datalist) > 0:
return sum/len(datalist)
else:
return None
while True:
if button_a.was_pressed():
while True:
signal = pin1.read_analog()
window.append(signal)
avg = round(mean(window))
values.append(avg)
if len(window) == 11:
window.pop(0)
if beat is False and avg >= threshold+10:
beat = True
count += 1
display.show(Image.HEART, wait=False)
if count == 1:
t1 = time.ticks_ms()
if count == 11:
t2 = time.ticks_ms()
T = t2 - t1
bpm = round(600*1000/(T))
display.scroll(str(bpm))
initialize()
clear_oled()
add_text(0, 0, "Heart rate :")
add_text(0, 3, str(bpm) + " bpm")
if 60 <= bpm <= 100:
draw_stamp(38, 24, good, 1)
else :
draw_stamp(38, 24, bad, 1)
count = 0
sleep(2000)
if button_b.was_pressed():
break
count = 0
elif beat is True and avg <= threshold-10:
beat = False
display.clear()
sample += 1
if sample == 250:
threshold = mean(values)
values = []
sample = 0
sleep(20)
sleep(20)
This is the code connect to the microbit, and the function is about the heart rate sensor, which it will appear the average beat per minute when sensing 10 beats of the heart.
I am thinking of adding a function that if button b is pressed, the loop will pause, and press the button a to start again. I tried to add a break function in the loop, it worked when I click the button b, it pause the loop, however, the count of beat won't reset, and the time between the beat is also recorded although I break the loop.
Is there any way that I can break the loop and reset the count?
You should reset the counter before breaking. In your current code the line for the count is not executing since it breaks out before it reaches it.
if button_b.was_pressed():
count = 0
break

How to nest a function that responds to outside of function call?

I'm trying to figure out how I can solve this issue. I have a Raspberry Pi that is set up with a breadboard that consists of:
1 RGB light
2 buttons (left and right)
1 OLED screen
Each component works and I can run each one. What I'm trying to do is write a script that will allow me to select the "mode" with the left button (everything off vs lights vs screen on).
When a mode is selected, the right button then allows me to select between options within that mode. Below is the code as I have it:
def off():
lights = [red,green,blue]
for light in lights:
light.off()
def lightSelector():
off()
number = 0
while number < 5:
if rightButton.is_pressed:
if number == 0:
off()
red.on()
sleep(1)
number += 1
elif number == 1:
off()
green.on()
sleep(1)
number += 1
elif number == 2:
off()
blue.on()
sleep(1)
number += 1
elif number == 3:
off()
row()
sleep(1)
number+= 1
else:
number = 0
def picture():
image = Image.open('grant.jpeg')
image_r = image.resize((width,height), Image.BICUBIC)
image_bw = image_r.convert("1")
for x in range(width):
for y in range(height):
oled.pixel(x,y,bool(int(image_bw.getpixel((x,y)))))
oled.show()
def oledOff():
oled.fill(0)
oled.show()
def buttons():
x = 0
y = 0
while y is 0:
print('x = ' , x)
print('y = ' , y)
if leftButton.is_pressed:
if x == 0 :
oledOff()
off()
sleep(0.5)
x += 1
elif x == 1:
oledOff()
off()
lightSelector()
sleep(0.5)
x += 1
elif x == 2:
oledOff()
off()
picture()
sleep(0.5)
x += 1
else:
x = 0
oledOff()
off()
buttons()
The idea is that the buttons() function is the main overall function and will call the others as needed. My issue is that once I get to y == 1, or the lightSelector() function, it no longer registers that the leftButton is being pressed and won't switch to the next mode and I'm stuck in the lightSelector() function.
I know at baseline I can spell out lightSelector within the buttons function instead of calling another function but I'm trying to not be as verbose. I don't have any experience with threading or multprocessing and looked into it but couldn't see how that would help.

how can i make my script continuously run

I have made the connections in my board where I read the state of a reed switch. When the magnet nearby it shows "0" and I store the data at the "x" variable.
I'm using this to read the state of a fridge door so I can control some relays when the door is open (0) and then turn it off when closed (1).
When I use a while loop, I get the script running but it keeps counting when the variable is 1. I need this script to count when the door opens, (one) closes, and opens again (two).
Here is the code so far with the while loop.
import RPi.GPIO as GPIO
from time import sleep
GPIO.setmode(GPIO.BOARD)
inPin=15
outPin=12
GPIO.setup(inPin,GPIO.IN)
GPIO.setup(outPin,GPIO.OUT)
counter = 0
while True:
x = GPIO.input(inPin)
previousValue = 0
print(x)
if x==1:
GPIO.output(outPin,GPIO.LOW)
if x==0:
GPIO.output(outPin,GPIO.HIGH)
if x == 1 and previousValue == 0:
counter += 1
print(counter)
You could change the previous value
if x == 1 and previousValue == 0:
counter += 1
print(counter)
previousValue == 1
elif x == 0 and previousValue == 1:
previousValue == 0

brainfuck intepreter printing out wrong

I recently decided to try to code "yet another" brainfuck interpreter, but I have a problem. It prints out the wrong numbers, when it should put our hello,world!. Does anyone know why this is happening? Thanks in advance! I cannot figure out why it's doing this. Please help! I am only a beginner. Sorry for the bad coding style, but please don't change the whole thing. I would rather recieve tips.
from copy import copy
import sys
def brainfuckintepreter(program):
# find pairs of brackets
brackets = {}
bbrackets = {}
def findmatchingclosingbracket(ctr):
level = 0
if program[ctr] == '[':
while True:
if program[ctr] == '[':
level += 1
elif program[ctr] == ']':
level -= 1
if level == 0:
return ctr
break
ctr += 1
def findmatchingopeningbracket(ctr):
level = 0
if program[ctr] == ']':
while True:
if program[ctr] == '[':
level -= 1
elif program[ctr] == ']':
level += 1
if level == 0:
return ctr
break
ctr -= 1
"""
ctr = 0
for a in program:
if a == '[':
f = copy(findmatchingclosingbracket(ctr))
brackets[ctr] = f
bbrackets[f] = ctr
ctr += 1
print(brackets)
print(bbrackets)
"""
# running the program
tape = [0] * 3000
pointer = 1500
counter = 0
results = ""
valid = True
while counter != len(program) and valid:
a = program[counter]
# move right
if a == '>':
if pointer == len(tape) - 1:
tape.append(0)
pointer += 1
# move left
elif a == '<':
if pointer == 0:
raise ValueError("On index ", counter, ", the program tried to move to -1 on the tape")
valid = False
return valid
else:
pointer -= 1
# increment
elif a == '+':
if tape[pointer] == 255:
tape[pointer] = 0
else:
tape[pointer] += 1
# decrement
elif a == '-':
if tape[pointer] == 0:
tape[pointer] = 255
else:
tape[pointer] -= 1
# output character
elif a == '.':
t = chr(tape[pointer])
results += t
print(t, end='')
# input character
elif a == ',':
tape[pointer] = ord(sys.stdin.read(1))
# opening bracket
elif a == '[':
if tape[pointer] == 0:
pointer = findmatchingclosingbracket(pointer)
# closing bracket
elif a == ']':
if tape[pointer] != 0:
pointer = findmatchingopeningbracket(counter)
counter += 1
"""
for b in tape:
if b != 0:
print(b)
"""
brainfuckintepreter('++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.')
Edit:
I changed my code after some revisions, but same problem.
Your loops are the problem.
level = 0
while level > 0:
...
That loop will never be entered. The condition is immediately false (you're setting level to 0, right before checking if it is greater than 0).
You could change that to a do..while loop instead of a while loop (make a while true loop and check the condition at the end to decide whether to break out of the loop or not) and start checking at the current pointer position (include the current [ or ]), not at the next character after it.
Also here:
if tape[pointer] == 0:
pointer = findmatchingclosingbracket(pointer)
you should be passing and updating the program counter, not the tape pointer on the second line. And likewise for the other one just below it.

IndexError in unused conditional

def menurender():
global pos
global menulist
line1=menulist[pos]
if pos == len(menulist):
line2="back"
else:
line2=menulist[pos+1]
lcd.clear()
lcd.message(str(pos)+' ' +line1+ "\n"+str(pos+1)+' '+ line2)
In my block of code, I have a conditional in the menurender() function that checks to make sure that the list menulist has a valid index before referencing it, but i receive IndexError: list index out of range. I understand that the else statement is causing it, but I am confused because python shouldn't be executing it.
Full code
#!/usr/bin/python
#################################################
#IMPORTS#########################################
#################################################
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
from Adafruit_I2C import Adafruit_I2C
#################################################
#OBJECTS#########################################
#################################################
lcd = Adafruit_CharLCDPlate()
#################################################
#VARIABLES#######################################
#################################################
#current button value
prevbutton = "NULL"
#for SELECT key and determining clicks
action = False
#variable for menu position
pos = 0
#on screen cursor 0 for top line, 1 for bottom line
cursor = 0
#Handles list structure and action when clicked
menulist= []
menulist.append("CPU")
menulist.append("RAM")
menulist.append("STORAGE")
menulist.append("NETWORK")
#get input from keys and return the currently pressed key
def buttonstatus():
bstatus = "Null"
if lcd.buttonPressed(lcd.SELECT) == True:
bstatus="SELECT"
elif lcd.buttonPressed(lcd.UP) == True:
bstatus="UP"
elif lcd.buttonPressed(lcd.DOWN) == True:
bstatus="DOWN"
elif lcd.buttonPressed(lcd.LEFT) == True:
bstatus="LEFT"
elif lcd.buttonPressed(lcd.RIGHT) == True:
bstatus="RIGHT"
return bstatus
#checks buttons pressed and converts that into action for top menu
def getinput():
global prevbutton
global pos
if buttonstatus() != prevbutton:
prevbutton = buttonstatus()
if buttonstatus() == "SELECT":
print "select"
elif buttonstatus() == "DOWN":
pos = pos + 1
elif buttonstatus() == "UP":
pos = pos -1
#elif buttonstatus() == "LEFT":
#print "left"
#elif buttonstatus() == "RIGHT":
#print "right"
#defines bounds for the position of the cursor
def posbounds():
global pos
global menulist
if pos < 0:
pos = 0
if pos == len(menulist):
pos = len(menulist)
#code renders the menu on the LCD
def menurender():
global pos
global menulist
line1=menulist[pos]
if pos == len(menulist):
line2="back"
else:
line2=menulist[pos+1]
lcd.clear()
lcd.message(str(pos)+' ' +line1+ "\n"+str(pos+1)+' '+ line2)
while True:
getinput()
posbounds()
menurender()
There are lots if values for pos != len(menulist) for which menulist[pos+1] gives an IndexError (including pos == len(menulist) - 1). You should check
if pos > (len(menulist) - 2):
You should probably change if pos == len(menulist): to if pos == len(menulist) - 1: if you want to check if pos is the index of the last element, or to if pos == len(menulist) - 2: if you want to check for the second to last element.
A better way of doing this may be by using a try ... except block.
try:
line2 = menulist[pos+1]
except IndexError:
# Out of range -> pos is greater than len(menulist)-1
line2 = 'back'
However - this doesn't seem lika a Pythonic way of doing anything at all in Python. Maybe you could tell us what you are trying to achieve, and someone here may propose a better way of doing it.

Categories

Resources