From 1b94389e55734716c3ce46648454aad216586c27 Mon Sep 17 00:00:00 2001 From: "Hood, Jonathan D" Date: Mon, 8 Feb 2021 13:50:42 -0500 Subject: [PATCH] picomotor driver tested --- .../picomotor_driver.cpython-38.pyc | Bin 0 -> 3616 bytes Picomotor/picomotor_driver.py | 115 ++++++++++++------ Picomotor/test_driver.py | 30 +++++ Picomotor/testing.py | 64 +++++++--- 4 files changed, 149 insertions(+), 60 deletions(-) create mode 100644 Picomotor/__pycache__/picomotor_driver.cpython-38.pyc create mode 100644 Picomotor/test_driver.py diff --git a/Picomotor/__pycache__/picomotor_driver.cpython-38.pyc b/Picomotor/__pycache__/picomotor_driver.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..72d62ab466ffb9245c6ea9a60b103245cdb765ed GIT binary patch literal 3616 zcmZu!TW=J}6|SznOnW>t5Y}J}dnrheG6;EvO|r;K)+FY#C@^L*mJ`cLXWZ2`4Kv-d z)jinL8AmHY@(^i%K%!`69(l?C$X{sXA*+1}&w1OI&3CGM#vVvpbLw`g>eP46cdEQz zuU8qqyMMm$`_JEF>^o{4|4cM);+M=rNVdtOA$iBxG<3-~xh~C3>n@X~v|ci4z2KX+ zL@U_46Z`!{T>oToLG(gD?#5}XgjC`4K+RX* zU^mwCNgn?yXxzjv`353ju!0p9(B9IPj;#FM*)*jqr*^rV(y}V6sJ|;o(~{G&_L9Ng zx@@3y{^+H#S&=`M@5vd|T=^4uTAo2|O3uo&(5lKgc@E{YJTKozS(6{g4^h_T zM^d0{$O}0ArF?39uH3wObpc`lVquZQH4@afu&~f{a_7P7)BS~{;d z_NvJWaB#E5)m{*ZBv4_yLs1X~ej3J+*nz_*1ECC&PM~&SIKF=`H;ufKhTS0Ur{PzZ z7|ZO-_inY8v)W2KisDqnSbJU>&}}vAxl`XrD~@^ZuMf7<`${v(@79X z75D*yEw_6rjMCipJ8=@^l`!$NjwM4s&D|Xpcb^4=B(JvjF%-4CK?29dNk~UXnr3b# zL1!m-S5_Z*dJ9(tNe@H8Yo-Lu`u^U^($+fcO17TFvFvQ!Lg06UC{4ERhUw@1?X7!J zlB%-n;fM-bv>@mrk-~a3nynGnAI>`{Bfhot457G2Bgt2vs2^w^P@=< zVPa$MI81(p#t=a=%MRc;INC`0kV`JjuQ|d&hs>c_ga`$T4iamqDfcHn#|}`3t1H>! z8jyvLyWKWQke)_MQsiN_%^d!VC6Jr=L8@tF(~UkJ7LMy$?vw^t&>*Xz|=pLHfMiQ6HgSyQ2^n zsCgRVGJZ)7f?2LH0}yL~FFQRpdHz_ay!jVE^DR;?zbTXiq~_XRP?4HdLt~BsN=x#T zfHYqiF9=#2kebh!x+1LuCjxi}j&w*PHHmGdRt2zDX4%l5Wx8}Q(@m|R<{L3|=)Tg- zJFG}u(|r}{L(L^8$tgIantduB#Loi&-D#(YbP@Ht+kq1C4!D^1d&#^I56eInD;rn9 z#oa=2Wo09qUb@#>d%VoCT))4zbm!6SFN7vsRxi45-FqZxO6^#4 zV`9$A>Uv9L{8O>}hnaue{Wg2K+-gp#^8hS25&OBV;(jD^v%Q_DGw9W>$t~i2ZYP}} z=;igjHUb|h!|UQun5{i+5i6mR2E8PAp9h`T57R+zApovwxuE5ume7ZOc|rU%8o5!U(!4?(j6^>Pz)OX!mkNLHW8dEsGE91HFe(fZ?N21Lx}Jk1-Mjj51>CjNA`M<6L0L36 zafPCnIH^uhhf}Nq4hQ?`TPUcXLE{;IB>x(45eD$2c-jqe=e^jL3snF|s-F2zP~wM9Jkbl0rQoGl*?(xi_!v21lHy7wE{I zGe>A0S9!;|V{^zoWX_?XAD;Sc@)W_0D~^$Q4IuULK{pdkUx?SAzb5>an^8{^Mhl#=iGYrT(w@U zyH(e6ZP!+$i+>|3o+o49^9oQF(V5%0_3?7#QBNx!+eBbk=>T_c6i52ZKv&{ISSCFx GUF&}qs%Jj{ literal 0 HcmV?d00001 diff --git a/Picomotor/picomotor_driver.py b/Picomotor/picomotor_driver.py index 11c7630..de71f34 100644 --- a/Picomotor/picomotor_driver.py +++ b/Picomotor/picomotor_driver.py @@ -4,27 +4,35 @@ import serial import time import numpy as np +#import os class picomotor: - axis_names = { "MOTz_x": "112", "MOTz_y": "122"} - steps_in_turn = { "MOTz_x": [1000,1000], "MOTz_y": [1000,1000]} # [CW, CCW] number of steps for 1 turn + axis_names = { "MOTz_x": "112", "MOTz_y": "122", "MOTy_x": "232", "MOTy_y": "242", "MOTx_x": "212", "MOTx_y": "222"} + steps_in_turn = { "MOTz_x": [15000, 16000], "MOTz_y":[16000, 16000], "MOTy_x": [16000, 16000], "MOTy_y": [16000, 16000], + "MOTx_x": [16000, 16000], "MOTx_y": [16000, 16000]} # [CW, CCW] number of steps for 1 turn - def __init__(self, COM_port ) + def __init__(self, COM_port): """Open serial connection for NewFocus 8732 controller""" """COM_port: ie 'COM3' (check device manager) """ self.serial = serial.Serial(timeout = 0.5) #19200 baud didn't work. 8 bits, no parity, 1 stop bit. self.serial.baudrate = 9600 self.serial.port = COM_port #'COM3' - #print("Serial connection open: ", self.serial.open()) - response = self.sendreceive(self, "*IDN?") - print(response) - + try: + self.serial.open() + #print("Serial connection open: ", self.serial.open()) + response = self.sendreceive("*IDN?") + print(response) + #print(self.serial.is_open) + except: + self.serial.close() # don't know if this will help + print(self.serial.is_open) + print('Cannot open.') # Initialize positions - self.positions = dict.fromkeys(axis_names, 0) #{'MOTz_x': 0, 'MOTz_y': 0, ...} #units steps + self.positions = dict.fromkeys(self.axis_names, 0) #{'MOTz_x': 0, 'MOTz_y': 0, ...} #units steps # Turn on the slots? #self.sendreceive(':INST 1') #? not sure if I need this? @@ -37,62 +45,89 @@ def sendreceive(self, cmd): """ 8732 ends with carriage return \r. Does not echo command, but always responds. """ line = cmd + '\r' retval = self.serial.write(bytes(line, encoding='ascii')) - time.sleep(0.01) #not sure if need + self.serial.flush() # wait for outgoing serial data to complete + #time.sleep(0.01) #not sure if needed response = self.serial.read_until(b'\r') - #self.serial.flush() #what does this do? + response = response[:-1] # get rid of \r return response - - def move_abs(self, axis, position, velocity) - """ Move to absolute position, and if CCW (negative steps), then use correct cw/ccw disparities""" - cw ccw = steps_in_turn[axis] #number steps in turn - current_position = self.positions[axis] #get current position - steps = position - current_position - - if steps < 0: - steps = steps*(ccw/cw) - - self.move(axis, steps, velocity) - self.positions[axis] = position - - - def move(self, axis, steps, velocity) + + def move(self, axis, steps, velocity=1500): """ Move relative number of setups. Position CW, Negative CCW""" """ Returns before finished moving. """ - cmd1 = "INST:NSEL " + axis_names[axis] + cmd1 = ":INST:NSEL " + self.axis_names[axis] + + cmd2 = ":SOUR:PULS:FREQ "+ str(round(velocity)) # integer divider of 1500 if steps < 0: - cmd2 = ":SOUR:DIR CWW" + cmd3 = ":SOUR:DIR CCW" else: - cmd2 = ":SOUR:DIR CW" - - cmd3 = "SOUR:PULS:FREQ "+ str(round(velocity)) # integer divider of 1500 + cmd3 = ":SOUR:DIR CW" cmd4 = ":SOUR:PULS:COUN " + str(round(abs(steps))) - cmd = cmd1 + "; " + cmd2 + "; " + cmd3 + "; " + cmd4 + cmd = cmd1 + "; " + cmd2 + "; " + cmd3 #+ "; " + cmd4 + print(cmd) self.sendreceive(cmd) + time.sleep(0.01) + self.sendreceive(cmd4) + + self.wait_for_move() + # Update position in move_abs and move_rel + #self.positions[axis] = self.positions[axis] + steps - # Update position - self.positions[axis] = self.positions[axis] + steps + + def move_abs(self, axis, position, velocity=1500, ccw_correction=True): + """ Move to absolute position, and if CCW (negative steps), then use correct cw/ccw disparities""" + cw, ccw = self.steps_in_turn[axis] #number steps in turn + current_position = self.positions[axis] #get current position + steps = position - current_position + + if steps < 0: + steps = steps*(ccw/cw) + + self.move(axis, steps, velocity) + self.positions[axis] = position + return position + + def move_rel(self, axis, steps, velocity=1500, ccw_correction=True): + """ Move to absolute position, and if CCW (negative steps), then use correct cw/ccw disparities""" + cw, ccw = self.steps_in_turn[axis] #number steps in turn + + if steps < 0: + steps = steps*(ccw/cw) + + self.move(axis, steps, velocity) + self.positions[axis] = self.positions[axis] + steps #get current position + return self.positions[axis] + - def wait_for_move(self) + def wait_for_move(self): """ Wait for picomotor to finish moving """ timeout = 120 # timeout seconds - moving = 1 - while moving: #OPC returns 1 if all channels are finished + moving = 0 + while moving==0: #OPC returns 1 if all channels are finished time.sleep(0.2) text = self.sendreceive("*OPC?") moving = int(text)# get 1 or 0 from text - def zero_positions(self) + def zero_positions(self): """ Zero all positions """ - self.positions = dict.fromkeys(axis_names, 0) + self.positions = dict.fromkeys(self.axis_names, 0) - def zero_position(self, axis) + def zero_position(self, axis): """ Zero single axis """ self.positions[axis] = 0 - \ No newline at end of file + + + def get_position(self, axis): + """ Return current position """ + return self.positions[axis] + + + def close(self): + self.serial.close() + print(self.serial.is_open) \ No newline at end of file diff --git a/Picomotor/test_driver.py b/Picomotor/test_driver.py new file mode 100644 index 0000000..b86a13f --- /dev/null +++ b/Picomotor/test_driver.py @@ -0,0 +1,30 @@ + +""" +Created on Mon Feb 8 12:01:46 2021 + +@author: hoodl +""" +from picomotor_driver import picomotor +p = picomotor("COM4") +vel = 1500 + +p.move("MOTz_x", 15000, velocity=vel) +#p.wait_for_move() + + +p.move("MOTz_y", 1000, velocity=vel) +#p.wait_for_move() + +p.move("MOTy_x", 1000, velocity=vel) +#p.wait_for_move() + +p.move("MOTy_y", 1000, velocity=vel) +#p.wait_for_move() + +p.move("MOTx_x", 1000, velocity=vel) +#p.wait_for_move() + +p.move("MOTx_y", 1000, velocity=vel) +#p.wait_for_move() + +p.close() \ No newline at end of file diff --git a/Picomotor/testing.py b/Picomotor/testing.py index 9debbc6..7604d6e 100644 --- a/Picomotor/testing.py +++ b/Picomotor/testing.py @@ -1,13 +1,14 @@ import serial #import io +import time ser = serial.Serial(timeout = 1) #19200 baud didn't work. 8 bits, no parity, 1 stop bit. ser.baudrate = 9600 -ser.port = 'COM3' -ser.xonxoff=0 +ser.port = 'COM4' +#ser.xonxoff=0 #sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser)) @@ -15,44 +16,43 @@ ser.open() print(ser.is_open) -#ser.close() -#print(ser.is_open) +# Close +ser.close() +print(ser.is_open) ser.write(b'*IDN?\r') +ser.flush() txt = ser.read_until(b'\r') -print(txt) +print(txt[:-2]) + +# Turn on picomotor controller +# I don't think this is needed ser.write(b':INST 1\r') txt = ser.read_until(b'\r') print(txt) +ser.write(b':INST:STATE?\r') +print(ser.read_until(b'\r')) +ser.write(b':INST:STATE 1\r') # turns slot on +print(ser.read_until(b'\r')) -ser.write(b'INST:NSEL?\r') -txt = ser.read_until(b'\r') -print(txt) +# Move picomotor +# ser.write(b':INST:NSEL?\r') +# txt = ser.read_until(b'\r') +# print(txt) -ser.write(b'INST:NSEL 242\r') # slot (1-2), connector (1-4), channel (A,B). +ser.write(b':INST:NSEL 142\r') # slot (1-2), connector (1-4), channel (A,B). txt = ser.read_until(b'\r') print(txt) - - - -ser.write(b':INST:STATE 1\r') # turns slot on -print(ser.read_until(b'\r')) - -ser.write(b':INST:STATE?\r') -print(ser.read_until(b'\r')) - - - ser.write(b':SOUR:PULS:FREQ 1500\r') # freqs are integer dividens of 1500 Hz txt = ser.read_until(b'\r') print(txt) @@ -61,10 +61,28 @@ txt = ser.read_until(b'\r') print(txt) +ser.write(b':INST:NSEL 122; :SOUR:PULS:FREQ 1500; :SOUR:DIR CW; :SOUR:PULS:COUN 1000\r') +txt = ser.read_until(b'\r') +print(txt[:-2]) +## Testing +ser.write(b':INST:NSEL 112\r') # slot (1-2), connector (1-4), channel (A,B). +txt = ser.read_until(b'\r') +print(txt) +time.sleep(0.01) +ser.write(b':SOUR:PULS:FREQ 1500; :SOUR:DIR CW; :SOUR:PULS:COUN 1000\r') +txt = ser.read_until(b'\r') +print(txt[:-2]) +ser.write(b':INST:NSEL 122; :SOUR:PULS:FREQ 1500; :SOUR:DIR CW\r') # slot (1-2), connector (1-4), channel (A,B). +txt = ser.read_until(b'\r') +print(txt) +time.sleep(0.01) +ser.write(b':SOUR:PULS:COUN 1000\r') +txt = ser.read_until(b'\r') +print(txt[:-2]) @@ -93,3 +111,9 @@ print(txt) + +## Operation complet + +ser.write(b'*OPC?\r') +txt = ser.read_until(b'\r') +print(txt) \ No newline at end of file