In this article, I will document the coding part of my TWHPFS.
It’s just a python script. I am a newbie to python, hope you won’t laugh about my messy code, hahaha.
Talk about the logic:
Ok, firstly we need variables representing the physical units, which are, LCD, button, led, servo,
# pin for hardwares lcd = Adafruit_CharLCD(rs=26, en=19, d4=13, d5=6, d6=5, d7=11, cols=16, lines=2) led = PWMLED(17) servo = Servo(22) button = Button(4) # setup servo.max()
We need a timer, which contains start time and time now. We don’t need to hold time now because it constantly changing, and we can get it from the system at any time. So:
time_start = time() seconds = 0 minutes = 0 lcdTime = ""
To calculate the RPM, my solution is using a Hall effect sensor. Whenever the sensor triggers, I store the timestamp into an array. So, the last timestamp minus the first time stamp, divided by the intervals, I can have the RPM!
pulsesStamps =  rpmStartTime = time() currentRpm = 0
And here is the most important part, the workflow:
- Wait to be triggered –
- Spinning –
- showing message1
- Showing message2
- Wait to be triggered.
We use stages to represent each part so the program would know where it is.
# stage: # 0 = begining, wait for pushing button # 1 = spinning, wait for stop # 2 = is stoped, showing time # 3 = is stoped, showing message # 4 = ending, auto matically go to begining stage = 0
Then, based on the variables needed, let’s import the libraries.
from gpiozero import Button, PWMLED, Servo from Adafruit_CharLCD import Adafruit_CharLCD from time import time, sleep import decimal import RPi.GPIO as GPIO
Then the functions.
To get the servo triggered, I need two callback functions, one of which being called whenever the button is pressed, another one released.
# what to do when pressing button def triggerServo1(): global stage stage = 1 servo.mid() lcd.clear() led.value = 0.8 print("pressed") def triggerServo2(): sleep(0.05) servo.max() led.value = 0.2 recordStartTime()
Moreover, when I release the button, the start time got reset.
def recordStartTime(): global time_start, minutes time_start = time() minutes = 0 print("startTimeRefreshed")
When it is spinning, we need to:
- Run the timer and RPM calculator
- Show it on the LCD.
Let’s wrap it inside a function:
# stage 1, spining def Spin (): global currentRpm, stage, pulsesStamps, seconds, minutes, rpmStartTime, time_start, lcdTime if stage == 1 : if (time() - rpmStartTime) >= 2 and len(pulsesStamps) >= 2 : currentRpm = 60 / ((pulsesStamps[-1] - pulsesStamps) / (len(pulsesStamps)-1)) rpmStartTime = time() del pulsesStamps[0: (len(pulsesStamps)-2)] print(currentRpm) if currentRpm <= 30 : print("RPM < 30, Stopped") stage = 2 seconds = int(time() - time_start) - minutes * 60 try: if (time() - pulsesStamps[-1]) >= 5: print("Not detect spin for 5 second, Stopped") stage = 2 except: pass if seconds >= 60: minutes += 1 seconds = 0 if seconds < 10 : lcdTime = str(minutes)+ "'0" +str(seconds)+ '" RPM ' + str(currentRpm) else: lcdTime = str(minutes)+ "'" +str(seconds)+ '" RPM ' + str(currentRpm) lcd.clear() lcd.message(lcdTime) if currentRpm >= 400: lcd.message("\n" + "Are You Cheating?")
When it stops:
- Blink the timer and RPM 4 times.
- Show the equality;
- Show the description;
- If user press the button now, break.
#stage 2,3,4, stopping def Stop (): global currentRpm, pulsesStamps, stage if stage == 2 : pulsesStamps =  for i in range (0,4): lcd.clear() sleep(0.2) lcd.message(lcdTime) sleep(0.2) stage = 3 if stage == 3 : congrat1 = str(minutes)+ "'" +str(seconds)+ '"' + " = " + "$" + str(0.07 * (minutes*60 + seconds)) congrat2 = " $1766/Credit in ITP is $0.7/second, and you just wasted "+ str(minutes)+ "'" +str(seconds)+ '"' +" here. " lcd.clear() lcd.message(congrat1) for i in range(0,len(congrat2)-16): lcd.message("\n" + congrat2[i:i+16]) sleep(0.5) if stage == 1: break if stage == 3: sleep (3) stage = 0
Callback function to save the timestamp in the list.
# setup call back event GPIO.setmode(GPIO.BCM) print("Setup GPIO pin as input on GPIO27") GPIO.setup(27 , GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.add_event_detect(27, GPIO.BOTH, callback=sensorCallback,bouncetime=10)
# call this to record the time stamp when hall effect sensor activated def sensorCallback(channel): timestamp = time() if stage == 1 and GPIO.input(channel): pulsesStamps.append(timestamp)
Set the loop
It’s just like Arduino, but we better wrap it inside a try to deal with errors.
# loop try: while True: sleep(0.1) button.when_pressed = triggerServo1 button.when_released = triggerServo2 WaifForStart() Spin() Stop() print(stage) except KeyboardInterrupt: GPIO.cleanup()
That’s pretty much it.