Rich's Wordpress

又一个WordPress站点

Digital Timer

This time I decided to make a timer that does the same job as the one we use on our phone or a stopwatch. As we all know, we can press two buttons: one controls the start and stop of the count, and the other resets the timer.

I’ve split it into two parts, firstly implementing a way to make it start and stop the timer, and then implementing a way to reset the timer. At first, I tried to write some functions to control it to start and stop the timer, the idea was that when I pressed the first button it would generate an interrupt and then I would let it execute the function to start the timer. When the second button is pressed, it will also generate an interrupt, then I will let it execute the function to pause the timer. In this way, the first part of it is done.

  1. Import all the libraries
  2. Initialize the 2 buttons and OLED
  3. Initialize two global variables, counter to 0 and bo (which stands for boolean) to False
  4. Create the first function to start the timer by using a while loop to count from 0 using the variable counter if bo is True
  5. Create the second function that turns bo to True and calls the start timer function
  6. Create the third function to stop the timer by using a while loop to display the counter if bo is False
  7. Create the last function that turns bo to False and calls the stop timer function
  8. Use the interrupt to check whether button 1 or button 2 is pressed and call the corresponding function.

Version 1:

from gpiozero import Button
from luma.core.render import canvas
from luma.oled.device import ssd1306
from time import sleep

key1 = Button(12)
key2 = Button(13)
device = ssd1306(port = 1, address = 0x3C)
counter = 0
bo = False
	
def start():
	global bo
	global counter
	while bo:
		with canvas(device) as draw:
			draw.text((0,0), str(counter), fill = "white")
		sleep(1)
		counter = counter + 1

def stop():
	global bo
	global counter
	while bo:
		with canvas(device) as draw:
			draw.text((0,0), str(counter), fill = "white")
		sleep(1)


def display_word():
	global bo
	bo = True
	start()

def stop_display():
	global bo
	bo = False
	stop()

		
key1.when_pressed = display_word
key2.when_pressed = stop_display

	
while True:
	pass
	

As you can imagine, my big piece of code didn’t succeed in achieving what I wanted. The OLED on the Raspberry Pi shows me that the timer has started, but it won’t stop. I can’t figure out why it won’t stop, and there doesn’t seem to be anything wrong with my logic. I went through some clues on the internet to see if anyone else was having the same problem as me, and I also went and asked my parents.

Eventually, the problem was discovered, my logic was fine, but the way I implemented it was wrong. When I used interrupts to start and pause the timer, I ignored the fact that both buttons had the same priority. So after I press the first button to start the timer, it won’t stop no matter how much I press the second button because it has to finish the task of the first interrupt before it can continue with the second interrupt of the same priority. It is impossible to finish the first task as there is a while loop that does stop until the variable bo becomes false.

So, after figuring out where my problem is, I immediately fix my code by keeping the task for the interrupt simple, it only needs to reverse the state of the boolean to indicate the computer to turn on and off. I also added the reset function which can allow the user to start the timer from 0 again.

Final Code

Version 2

from gpiozero import Button
from luma.core.render import canvas
from luma.oled.device import ssd1306
from time import sleep

key1 = Button(12)
key2 = Button(13)
device = ssd1306(port = 1, address = 0x3C)
counter = 0
bo = False
	

def display_word():
	global bo
	bo = not bo

def reset():
	global counter
	counter = 0

		
key1.when_pressed = display_word
key2.when_pressed = reset()

	
while True:
	if bo:
		with canvas(device) as draw:
			draw.text((0,0), str(counter), fill = "white")
		sleep(1)
		counter = counter + 1
	else:
		with canvas(device) as draw:
			draw.text((0,0), str(counter), fill = "white")
		sleep(1)
	

Final Result

Digital Timer
Scroll to top