#!/usr/bin/env python3
########### Position Camera Function#############
## This block of code opens up a user interface that allows the user to position the camera
## Warning: do NOT use the [x] to close the camera. use the 'Exit Program' button
from tkinter import *
import picamera
from time import sleep
# create a camera object
camera = picamera.PiCamera()
# Function to create a open the camera object
def CameraON():
camera.preview_fullscreen=False
camera.preview_window=(90,140, 320, 240)
camera.resolution=(640,480)
camera.rotation = 270
camera.start_preview()
# Function to stop camera preview
def CameraOFF():
camera.stop_preview()
# Function to destroy the UI correctly
def EXIT():
root.destroy()
camera.stop_preview()
camera.close()
# Create a root for the UI
root = Tk()
root.resizable(width=False, height=False)
root.geometry("320x300+89+50")
root.title("Camera Button Test")
root.buttonframe = Frame(root)
root.buttonframe.grid(row=5, column=3, columnspan=2)
# Create some buttons and the functions that are tied to the buttons
Button(root.buttonframe, text='Start Camera', command=CameraON).grid(row=1, column = 1)
Button(root.buttonframe, text='Kill Camera', command=CameraOFF).grid(row=1, column = 2)
Button(root.buttonframe, text='Exit Program', command=EXIT).grid(row=1, column = 3)
root.labelframe = Frame(root)
root.labelframe.grid(row=3, column=3, columnspan=1)
Label(root,text="Position the Camera").grid(row=3,column = 3)
root.mainloop()
###########End of Position Camera Function#######
########### Folder Select Function###############
# This block of code requires that the user select a folder where they want to save the photos
from tkinter.filedialog import askdirectory
def directoryBox(title=None, dirName=None):
options = {}
options['initialdir'] = dirName
options['title'] = title
options['mustexist'] = False
fileName =askdirectory(**options)
if fileName == "":
return None
else:
return fileName
root = Tk()
root.geometry(str(480)+"x"+str(320)+"+2+10")
root.title =('Where do you want to save the Photos')
folder = directoryBox('Where do you want to save the Photos','/media/pi')
root.destroy()
if folder != None:
# write to file
f=open('/home/pi/Desktop/FatigueTest/folderName.txt','w')
f.write(folder)
f.close()
while folder == None:
root = Tk()
root.geometry(str(480)+"x"+str(320)+"+50+50")
folder = directoryBox('Choose a valid location Hoe','/media/pi')
root.destroy()
if folder != None:
# write to file
f=open('/home/pi/Desktop/FatigueTest/folderName.txt','w')
f.write(folder)
f.close()
print(folder)
########### End of Folder Select Function########
############# Start of During Test Function##############
# This function creates a UI that controls the motor and camera during the test
# Warnings: Do not 'Show Camera' when the camera is about to take a photo -- the program will crash
# Warnings: The buttons will only activate after the end of the cycle. Be patient
# Warnings: The motor can only be move after 'Stop Cycle' has be clicked
# Warnings: Only press 'Goodbye' after you have stopped the cycle
# If you want to reset the cycle and runtime, edit the 'Data.txt file' First number is cycle and second is runtime
from time import time
import threading
from picamera import PiCamera
from time import time
import datetime as dt
from time import strftime
from Adafruit_MotorHAT import Adafruit_MotorHAT, Adafruit_DCMotor, Adafruit_StepperMotor
import atexit
import os
class App(threading.Thread):
def __init__(self,window,window_title):
# Create a root and give a title
self.root = window
self.root.title =(window_title)
threading.Thread.__init__(self)
self.width=480
self.height = 320
self.root.geometry(str(self.width)+"x"+str(self.height)+"+50+50")
self.isTesting = True
# Start the Thread
self.start()
def update(self):
pass
def close_window(self):
if not self.isTesting:
self.root.destroy()
def show_camera(self):
os.system('python3 /home/pi/Desktop/FatigueTest/PositionCameraUI.py')
def show_camera_thread(self):
threading.Thread(target=self.show_camera).start()
def start_cycle(self):
print('Resuming Test...')
self.isTesting = True
self.run()
def stop_cycle(self):
print('Stopping Test...')
self.isTesting = False
def motor_up(self):
if self.isTesting == False:
print('Motor going up...')
mh = Adafruit_MotorHAT()
myStepper = mh.getStepper(200, 2) # 200 steps/rev, motor port #2
myStepper.setSpeed(1000) # 30 RPM
myStepper.step(20, Adafruit_MotorHAT.BACKWARD, Adafruit_MotorHAT.MICROSTEP)
sleep(0.1)
mh.getMotor(1).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(2).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(3).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(4).run(Adafruit_MotorHAT.RELEASE)
def motor_down(self):
if self.isTesting == False:
print('Motor going down...')
mh = Adafruit_MotorHAT()
myStepper = mh.getStepper(200, 2) # 200 steps/rev, motor port #1
myStepper.setSpeed(1000) # 30 RPM
myStepper.step(20, Adafruit_MotorHAT.FORWARD, Adafruit_MotorHAT.MICROSTEP)
sleep(0.1)
mh.getMotor(1).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(2).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(3).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(4).run(Adafruit_MotorHAT.RELEASE)
def reset_count_thread(self):
threading.Thread(target=self.reset_count).start()
def reset_count(self):
pass
#f = open('/home/pi/Desktop/FatigueTest/Data.txt','w')
#if not self.isTesting:
# f = open('/home/pi/Desktop/FatigueTest/Data.txt','w')
# f.write('0\n0')
# f.close()
def run(self):
# Create loop to move motor, update label and update root
## Step 1: Set up the camera and motor, specify folder to save in
#camera = PiCamera()
#camera.vflip = True
#camera.hflip = True
mh = Adafruit_MotorHAT()
foldername = open('/home/pi/Desktop/FatigueTest/folderName.txt',"r").read()
Datafile = open('/home/pi/Desktop/FatigueTest/Data.txt',"r")
self.cycle = int(Datafile.readline())
self.runtime = int(Datafile.readline())
Datafile.close()
## Edit the following lines of code to change when the photo is taken and the maximum cycles
takePictureEvery = 50
self.maximumCycles = 10000
## Function Definitions
# recommended for auto-disabling motors on shutdown!
def turnOffMotors():
mh.getMotor(1).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(2).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(3).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(4).run(Adafruit_MotorHAT.RELEASE)
def savePic(counter,time_now):
cam=PiCamera()
cam.rotation = 270
cam.resolution=(640,480)
sleep(2)
cam.annotate_text = 'Cycle:{} Time:{}'.format(counter,time_now.strftime('%m-%d-%Y %H:%M:%S'))
cam.capture(foldername+'/'+'Cycle{}_'.format(counter)+time_now.strftime('%m_%d_%Y__%H_%M_%S.jpg'))
cam.close()
## Step 2: exit safely
#At exit - turn off the motors and the camera
atexit.register(turnOffMotors)
## Step 4: Move the Motor and take a photo of LCD Screen
myStepper = mh.getStepper(200, 2) # 200 steps/rev, motor port #2
myStepper.setSpeed(100) # 800 RPM
begin_time = time()
while self.isTesting and (self.cycle < self.maximumCycles):
self.root.update()
start_time = time()
foldername = open('/home/pi/Desktop/FatigueTest/folderName.txt','r').read()
Datafile = open('/home/pi/Desktop/FatigueTest/Data.txt',"r")
self.cycle = int(Datafile.readline())
self.runtime = int(Datafile.readline())
Datafile.close()
# Create some Labels to display buttons
Label(text='Cycle: {}/{}\nRun Time: {} s'.format(self.cycle,self.maximumCycles,str(dt.timedelta(seconds=int(self.runtime)))),
font=('Comic Sans MS',26)).place(anchor="center",x=int(self.width/2),y=int(self.height/2))
# Create some buttons
buttonwidth=int(self.width/5)
buttonheight = int(self.height/5)
Button(text = "Good-bye.", command = self.close_window).place(height = buttonheight,width=buttonwidth,x=self.width-buttonwidth,y=0)
#Button(text = "Reset Count", command = self.reset_count).place(height = buttonheight,width=buttonwidth,x=0,y=0)
Button(text = "Start Cycle", command = self.start_cycle).place(height = buttonheight,width=buttonwidth,x=0,y=self.height-buttonheight)
Button(text = "Stop Cycle", command = self.stop_cycle).place(height = buttonheight, width=buttonwidth,x=buttonwidth,y=self.height-buttonheight)
Button(text = "Motor Up", command = self.motor_up).place(height = buttonheight,width=buttonwidth,x=self.width-buttonwidth*2,y=self.height-buttonheight)
Button(text = "Motor Down", command = self.motor_down).place(height = buttonheight,width=buttonwidth,x=self.width-buttonwidth,y=self.height-buttonheight)
Button(text = "Show Camera", command = self.show_camera_thread).place(height = buttonheight,width=buttonwidth,x=buttonwidth*2,y=self.height-buttonheight)
# Move the gears
myStepper.step(250, Adafruit_MotorHAT.BACKWARD, Adafruit_MotorHAT.MICROSTEP)
sleep(5)
myStepper.step(251, Adafruit_MotorHAT.FORWARD, Adafruit_MotorHAT.MICROSTEP)
sleep(5)
# Save the photo in the file with the current time
if self.cycle%takePictureEvery == 0:
savePic(self.cycle, dt.datetime.now())
stop_time = time()-start_time
self.cycle = self.cycle + 1
self.runtime = int(self.runtime + stop_time)
# Write total time and cycle to file
Datafile = open('/home/pi/Desktop/FatigueTest/Data.txt','w')
Datafile.write(str(self.cycle)+'\n')
Datafile.write(str(self.runtime))
Datafile.close()
print('Time of cycle {0:6d} : {1:2.2f}'.format(self.cycle,stop_time))
self.root.update()
# when exit loop update labels and properly close camera
turnOffMotors()
# Change labels and update one last time
# Create some Labels to display buttons
if self.isTesting and (self.cycle >= self.maximumCycles):
Datafile = open('/home/pi/Desktop/FatigueTest/Data.txt','w')
Datafile.write('0\n0')
Datafile.close()
Label(text='DONE!!\nCycle: {}/{}\nRun Time: {} s'.format(self.cycle,self.maximumCycles,dt.timedelta(seconds=int(self.runtime))),
font=('Comic Sans MS',30)).place(anchor="center",x=int(self.width/2),y=int(self.height/2))
else:
Label(text='Cycle: {}/{}\nRun Time: {} s'.format(self.cycle,self.maximumCycles,dt.timedelta(seconds=int(self.runtime))),
font=('Comic Sans MS',26)).place(anchor="center",x=int(self.width/2),y=int(self.height/2))
# Create some buttons
buttonwidth=int(self.width/5)
buttonheight = int(self.height/5)
Button(text = "Good-bye.", command = self.close_window).place(height = buttonheight,width=buttonwidth,x=self.width-buttonwidth,y=0)
#Button(text = "Reset Count", command = self.reset_count_thread).place(height = buttonheight,width=buttonwidth,x=0,y=0)
Button(text = "Start Cycle", command = self.start_cycle).place(height = buttonheight,width=buttonwidth,x=0,y=self.height-buttonheight)
Button(text = "Stop Cycle", command = self.stop_cycle).place(height = buttonheight, width=buttonwidth,x=buttonwidth,y=self.height-buttonheight)
Button(text = "Motor Up", command = self.motor_up).place(height = buttonheight,width=buttonwidth,x=self.width-buttonwidth*2,y=self.height-buttonheight)
Button(text = "Motor Down", command = self.motor_down).place(height = buttonheight,width=buttonwidth,x=self.width-buttonwidth,y=self.height-buttonheight)
Button(text = "Show Camera", command = self.show_camera_thread).place(height = buttonheight,width=buttonwidth,x=buttonwidth*2,y=self.height-buttonheight)
self.root.update()
Window = Tk()
App(Window,"Testing in Progess")
Window.mainloop()
Comments