import pyaudio import random import time from math import sin import threading from Tkinter import * import tkMessageBox RATE = 44100 STEPS_PER_REV = 200 PULSES_PER_STEP = 8 SCREW_PITCH = 0.8 ## mm per revolution pulses_per_rev = STEPS_PER_REV * PULSES_PER_STEP steps_per_mm = STEPS_PER_REV/SCREW_PITCH class Stepper_gui: def __init__(self): self.window = Tk() self.window.title("Stepper Control") self.zero_button = Button(self.window, text="Zero Position", command=self.zero) self.zero_button.pack() self.zero_button = Button(self.window, text="Reverse", command=self.reverse) self.zero_button.pack() self.go_button = Button(self.window, text="Drive Syringe", command=self.run) self.go_button.pack() dl_lab = Label(self.window, text="Drive Length") dl_lab.pack() self.drive_length = StringVar() self.drive_length.set("1") self.drive_length_entry = Entry(self.window, textvariable=self.drive_length) self.drive_length_entry.pack() dd_lab = Label(self.window, text="Drive Duration") dd_lab.pack() self.drive_duration = StringVar() self.drive_duration.set("10") self.drive_duration_entry = Entry(self.window, textvariable=self.drive_duration) self.drive_duration_entry.pack() self.stepper = Stepper() def zero(self): self.stepper.zero() def reverse(self): tkMessageBox.showinfo("Careful", "Make sure you have the 'reverse' switch flicked. And don't set it to move too far.") self.stepper.set_reversing(True) self.stepper.set_mm_duration( float(self.drive_length.get()), float(self.drive_duration.get()) ) self.stepper.go() self.stepper.set_reversing(False) def run(self): if float(self.drive_length.get()) / float(self.drive_duration.get()) <= 4: if self.stepper.is_zeroed(): self.stepper.set_mm_duration( float(self.drive_length.get()), float(self.drive_duration.get()) ) self.stepper.go() else: tkMessageBox.showwarning("Warning", "Zero before use") else: tkMessageBox.showwarning("Warning", "Speed too fast") class Stepper: def __init__(self, mm=1, duration=10): self.running = False self.zeroed = False self.reversing = False self.mm = mm self.duration = duration self.start_pos = 0 #Only change when re-zeroing. To track that you don't run off end of track self.current_pos = 0 #Only change DURING stepping, to keep track of how many self.frequency, self.end_pos = self.get_frequency_and_end_pos() self.stream=pyaudio.PyAudio().open(format=pyaudio.paUInt8,channels=1,rate=RATE,frames_per_buffer=1,output=True) self.step_wave = self.get_wave() #one cycle at give freq def is_zeroed(self): return self.zeroed def set_reversing(self, boolRev): self.reversing = boolRev def set_mm_duration(self, mm, duration): self.mm = mm self.duration = duration def get_frequency_and_end_pos(self): # Calculate the frequency (Steps/per second) that have to be made num_steps = steps_per_mm * self.mm #pulses to make return (num_steps/float(self.duration), num_steps+self.current_pos) def get_wave(self): num_samples = int( 1/float(self.frequency * PULSES_PER_STEP) * RATE ) #wavetime * samples/second wave_kernal = [ int((sin((x/float(RATE)) * 2 * 3.1415 * self.frequency * PULSES_PER_STEP) + 1)*127.5) for x in range(0,num_samples)] wave = wave_kernal * PULSES_PER_STEP return wave def make_step(self): play_duration = len(self.step_wave)/float(RATE) bin_out=''.join(chr(x) for x in self.step_wave) #this transforms out into a binary string self.stream.write(bin_out) #which we can then write to the stream in one go. self.current_pos += 1 def set_params(self): self.frequency, self.end_pos = self.get_frequency_and_end_pos() self.step_wave = self.get_wave() #one cycle at give freq def zero(self): self.start_pos = 0 self.current_pos = 0 self.zeroed = True def go(self): if not self.running: self.set_params() if self.reversing: self.running = True t = threading.Thread(target=self.execute) t.daemon = True t.start() elif self.end_pos < 20000: self.running = True t = threading.Thread(target=self.execute) t.daemon = True t.start() else: tkMessageBox.showwarning("Warning", "Current settings will cause stepper to move off end. Reverse and Zero.") def execute(self): while self.current_pos < self.end_pos: self.make_step() self.running = False print self.current_pos def close(self): self.stream.close() pyaudio.PyAudio().terminate() if __name__ == '__main__': App = Stepper_gui() App.window.mainloop()