ISISComputingGroup / IBEX

Top level repository for IBEX stories
5 stars 2 forks source link

SXD: Solution for AttoCube #6056

Open kjwoodsISIS opened 3 years ago

kjwoodsISIS commented 3 years ago

As a scientist I want to be able to control the AttoCube, so that I can control the orientation of the sample in my experiments.

Acceptance Criteria

Notes

  1. The OPI must offer functionality equivalent to the existing SXD AttoCube positioner VI (located here: C:\LabVIEW Modules\Instruments\SXD\AttoCube).
    1. The AttoCube is driven by a Galil.
    2. Controlled via a Galil using direct commands, so not via standard motor record

Time in Planning

00:15:15 02/05/24

KathrynBaker commented 4 months ago

The front panel of the existing VI is: image

KathrynBaker commented 4 months ago

The Galil code for this is proving hard to track down at present, but it is important to note that is not run as a motor by LabVIEW, and as such, it may be best to treat this as a specific piece of equipment using the data set below.

On initialisation the following commands should be sent (in this order):

VERBOSE=0
AB0
MO
XQ #SXD
MG "stop 1" {P2}

BUSY is determined by comparing the response to BUSY= with \s0.0000\r\n:, if they match the system is not busy. ATANGLE= returns the Angle Postion Y= returns the Arc Position If setting the angle send ATTO= with a double between +170 and -170, followed by ATGO=1 If setting the arc send ARK= with a double between -19 and +19, followed by ARGO=1 If stop has been requested send the same set of commands as on initialisation, AB0, MO, XQ #SXD, MG "stop 1" {P2}

In summary there are three values to send, and three values to read.

davidkeymer commented 4 months ago

Galil code extracted from AttoCube controller:

'SXD CENTER STICK GALIL CONTROL PROGRAM
'26/03/09
'RICHARD BLIGHT
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''MAIN TASK''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#SXD
'MG "MAIN TASK RUNNING";NO                 TEST
JS #ARINIT;NO                             INITIALISE ARRAYS
JS #INIT;NO                               INITIALISE
XQ #ARTASK,1;NO                           ARK TASK
XQ #ATTASK,2;NO                           ATTO TASK
XQ #ANTASK,3;NO                           ANALOGUE INPUT TASK
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
#COMMS;NO              COMMS LOOP
JS #REPLY,REP = 1;NO                      PROCESS REPLIES
'JS #TELL,RESPON = 1;NO                    SEND STORED REPLIES
JP #RESCHK,BUSY = 1;NO                    LOOP IF BUSY
JS #ARKGO,ARGO = 1;NO                     IF ARK GO IS RECEIVED
JP #COMMS,ARGO = 1
JS #ATTOGO,ATGO = 1;NO                    IF ATTO GO IS RECEIVED
JP #COMMS;NO                              LOOP
'
#RESCHK;NO             RESET CHECK
JP #COMMS,((ARDONE = 0)|(ATDONE = 0));NO  LOOP IF EITHER TASK IS RUNNING
JS #INIT;NO                               RESET
JP #COMMS;NO                              LOOP
EN
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
#ARKGO;NO              ARK GO
BUSY = 1;NO                               SET BUSY FLAG
ARSTART = 1'NO                            START ATTO MOVEMENT
EN
'
#ATTOGO;NO             ATTO GO
BUSY = 1;NO                               SET BUSY FLAG
ATSTART = 1'NO                            START ARK MOVEMENT
EN
'
#REPLY;NO              PROCESS REPLIES
'MG "REPLY ROUTINE"
JP #STORE,VERBOSE = 0;NO                  STORE IF VERBOSE IS 0
#SEND;NO                                  SEND IF VERBOSE = 1
IF (TYPE = 1);NO                          IF MESSAGE IS A STRING
MG "",TEMP {S6};NO                        SEND AS A STRING
ELSE
MG "",TEMP {F3.2};NO                      ELSE SEND AS A NUMBER
ENDIF
REP = 0;NO                                CLEAR THE REPLY FLAG
EN
#STORE;NO                                 TO STORE THE MESSAGE
TELLAR[N] = TEMP;NO                       SAVE MESSAGE IN ONE ARRAY
TYPEAR[N] = TYPE;NO                       AND THE TYPE IN ANOTHER
N = N + 1;NO                              INCREMENT THE ARRAYS
REP = 0;NO                                CLEAR THE REPLY FLAG
EN
'
#TELL;NO               SEND ALL SAVED MESSAGES
N = N - 1;NO                              NEXT HIGHEST MESSAGE
JP #EXIT,N < 0;NO                         EXIT AFTER 0
IF (TYPEAR[N] = 1);NO                     IF MESSAGE IS A STRING
MG "",TELLAR[N] {S6};NO                   SEND AS A STRING
ELSE
MG "",TELLAR[N] {F3.2};NO                 ELSE SEND AS A NUMBER
ENDIF
JP #TELL;NO                               LOOP
#EXIT
N=0;NO                                    CLEAR N AS IT ENDS THE LOOP AT -1
RESPON = 0;NO                             CLEAR THE RESPOND FLAG
EN
'
#INIT;NO               SET UP ALL VARIABLES
BUSY = 0
ARGO = 0
ATGO = 0
ARSTART = 0
ATSTART = 0
ARK = 0
ATTO = 0
EN
'
#ARINIT;NO             SET UP ARRAYS
VERBOSE = 1
RESPON = 0
REP = 0
DM TELLAR[10]
DM TYPEAR[10]
N = 0
TYPE = 0
ATAERR = 0;NO                             ATTO ANGLE ERROR FLAG
ATMERR = 0;NO                             ATTO MOVE ERROR FLAG
ARAERR = 0;NO                             ARC ANGLE ERROR FLAG
ARMERR = 0;NO                             ARC MOVE ERROR FLAG
EN
'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''ARK TASK''''''''''''''''''''''''''''''''''
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#ARTASK
WT 500
'MG "ARC TASK RUNNING";NO                  TEST
JS #VTOA
'MG "**ARPN",Y{F2.2}
#WAITLP5;NO                                WAIT UNTIL READY FOR REPLY
JP #WAITLP5,REP = 1
TEMP = "**ARPN"
TYPE = 1
REP = 1
#WAITLP;NO                                WAIT UNTIL READY FOR REPLY
JP #WAITLP,REP = 1
TEMPINV = Y
JS #INVERT
Y = TEMPINV
TEMP = Y{F2.2}
TYPE = 2
REP = 1
JS #ARKINIT;NO                            INITIALISE
'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
#ARKLOOP;NO                               LOOP WHILE START = 0
MO A
JP #ARKLOOP,ARSTART=0
'
ARMERR = 0;NO                             CLEAR MOVE ERROR FLAG
ARDONE = 0
IF ((ARK < -20) | (ARK > 20));NO          CHECK VALUE IS ACCEPTABLE
'MG "ARC ANGLE MUST BE BETWEEN +-20"
'MG "**ARAE";NO                            ARC ANGLE ERROR MESSAGE
TEMP = "**ARAE"
TYPE = 1
REP = 1
ARAERR = 1;NO                             ANGLE ERROR FLAG
JP #ARKDONE
ENDIF
ARAERR = 0;NO                             CLEAR ANGLE ERROR FLAG
JS #AR_INV;NO                             INVERTS THE ENTERED VALUE
'
#AR_REST;NO             ARK RESTART
JS #VTOA;NO                               FIND CURRENT ANGLE
'MG ""
'MG "ARC ANGLE IS: ",Y{F2.2}
'MG "DESIRED ARC ANGLE IS: ",ARK{F2.2}
JS #ATOV;NO                               FIND ENDVOLT
JS #DONE1;NO                              IS THE ARK WHERE IT SHOULD BE?
'
'FIRST MOVE
SH A;NO                                   ENERGISE MOTOR
IF (PARK > ENDVOLT);NO                    IF START POSITION > END POSITION
IF (PARK > -5.8);NO                       AND NOT TOO NEAR THE END STOP
JS #NEG_ABL;NO                            TAKE UP BACKLASH
PR -30000;NO                              FIRST MOVE VALUE
BG A;NO                                   MOVE
ELSE;NO                                   GO UP IF TOO NEAR END STOP
PR 10000
BG A
ENDIF
ELSE;NO                                   IF START < END POSITION
IF (PARK < 6.8);NO                        AND NOT TOO NEAR THE END STOP
JS #POS_ABL;NO                            TAKE UP BACKLASH
PR 30000;NO                               FIRST MOVE VALUE
BG A;NO                                   MOVE
ELSE;NO                                   GO DOWN IF TOO NEAR END STOP
PR -10000
BG A
ENDIF
ENDIF
'
#LOOP3
JS #AFT_MOV
'MG "VOLTS =",PARK;NO              TEST
JS #DONE1;NO                              IS THE ARK WHERE IT SHOULD BE
VDIFF1 = ENDVOLT - PARK
'MG "NEW DISTANCE =",VDIFF1;NO     TEST
JP #CHANGE,(((_PR A > 0) & (VDIFF1 < 0)) | (((_PR A < 0) & (VDIFF1 > 0)))
JS #SPERV1
MOVEVAL = VDIFF1 * SPERV1
IF (@ABS[MOVEVAL] > 1000)
MOVEVAL = MOVEVAL - (MOVEVAL / 5);NO      TAKE OFF 20%
ENDIF
'MG "NEW STEPS - 20% =",MOVEVAL;NO TEST
PR MOVEVAL
'MG "PR = ",_PR A
BG A
JP #LOOP3
EN
'
#CHANGE
'MG "CHANGE"
JP #NEG,_PR A < 0
#POS
IF (PARK < 6.5);NO                          
PR 100000;NO                              
BG A;NO                                   MOVE
JS #AFT_MOV
JS #NEG_ABL
PR -30000
BG A
ELSE;NO                                   GO UP IF TOO NEAR END STOP
PR -150000
BG A
JS #AFT_MOV
JS #POS_ABL
PR 30000
BG A
ENDIF
JP #LOOP3
#NEG
IF (PARK > -5.5)
PR -100000
BG A
JS #AFT_MOV
JS #POS_ABL
PR 30000
BG A
ELSE
PR 150000
BG A
JS #AFT_MOV
JS #NEG_ABL
PR -30000
BG A
ENDIF
JP #LOOP3
EN
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
#ARKINIT
MT 2;NO                                   SET UP STEPPER AXIS
AC 5000
DC 5000
SP 5000
ERR1 = 0
ARDONE = 1
EN
'
#AR_INV;NO                                THIS ROUTINE INVERTS THE 
IF (ARK < 0);NO                           ENTERED VALUE TO MATCH
ARK = @ABS[ARK];NO                        THE ORIENTATION OF THE CONTROL
ELSE;NO                                   SIDE.  THIS IS EASIER THAN 
ARK = 0 - ARK;NO                          CHANGING EVERY SIGN IN THE
ENDIF;NO                                  PROGRAM.
'MG "ARK =",ARK;NO   TEST
EN
'
#VTOA
Y = PARK + 7.6;NO                         GET INPUT AND MAKE IT +VE
Y = (Y / 0.4034) - 20;NO                  CONVERT TO ANGLE
EN
'
#INVERT
IF (TEMPINV < 0);NO                       INVERT SENT VALUE 
TEMPINV = @ABS[TEMPINV]
ELSE
TEMPINV = 0 - TEMPINV 
ENDIF
EN
'
#ATOV
Z = ARK + 20;NO                           MAKE THE VALUES POSITIVE
ENDVOLT = (Z * 0.4034) - 7.6;NO           CONVERT TO VOLTAGE
EN
'
#SPERV1
ARMOVE = @ABS[PARK - OLDPARK];NO          FIND VOLT CHANGE
OLDPARK = PARK;NO                         SAVE LAST POSITION
IF (ARMOVE<0.05);NO                       HAS IT MOVED?
'MG "ARC IS NOT MOVING!"
ERR1 = ERR1 + 1
JP #AR_REST,ERR1 < 3
'MG "ARC MOVE ERROR"
'MG "**ARME";NO                            ARK MOVE ERROR MESSAGE
TEMP = "**ARME"
TYPE = 1
REP = 1
ARMERR = 1;NO                             ARK MOVE ERROR FLAG
JP #ARKDONE
ENDIF
'MG "SPERV =",_PR A;NO          TEST
'MG "DIVIDED BY",ARMOVE;NO      TEST
SPERV1 = @ABS[_PR A] / ARMOVE;NO          FIND STEPS PER VOLT
'MG "SPERV =",SPERV1;NO         TEST
EN
'
#NEG_ABL;NO                               NEGATIVE ANTI-BACKLASH
'MG "NEGATIVE ANTI-BACKLASH";NO TEST
PR -50000
BG A
JS #AFT_MOV
OLDPARK = PARK;NO                         SAVE OLD POSITION
'MG "VOLTS =",PARK;NO           TEST
EN
'
#POS_ABL;NO                               POSITIVE ANTI-BACKLASH
'MG "POSATIVE ANTI-BACKLASH";NO TEST
PR 50000
BG A
JS #AFT_MOV
OLDPARK = PARK;NO                         SAVE OLD POSITION
'MG "VOLTS =",PARK;NO           TEST
EN
#AFT_MOV
AM A
WT 200
JS #VTOA
'MG ""
'MG "ARC ANGLE IS: ",Y{F2.2}
EN
'
#DONE1;NO                                 CHECKS TO SEE IF THE ARK IS THERE
IF (@ABS[Y - ARK] < 0.05);NO              WITHIN TOLERANCE
'MG "ARC IN POSITION"
'MG "**ARDN"
TEMP = "**ARDN"
TYPE = 1
REP = 1
JS #VTOA
'MG "**ARPN",Y{F2.2}
TEMP = "**ARPN"
TYPE = 1
REP = 1
#WAITLP1
JP #WAITLP1,REP = 1
TEMPINV = Y
JS #INVERT
Y = TEMPINV
TEMP = Y{F2.2}
TYPE = 2
REP = 1
JP #ARKDONE
ENDIF
EN
'
#ARKDONE;NO                               CLOSE DOWN TASK
ARDONE = 1
ARSTART = 0
ERR1 = 0
JP #ARKLOOP
EN
'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''ATTO TASK'''''''''''''''''''''''''''''''''
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#ATTASK
WT 1000
'MG "ATTO TASK RUNNING";NO                 TEST
ATANGLE = PATTO / 0.0556
'MG "ATANGLE",ATANGLE
'MG "**ATPN",ATANGLE{F3.2};NO              SEND FIRST POSITION
#WAITLP4
JP #WAITLP4,REP = 1
TEMP = "**ATPN"
TYPE = 1
REP = 1
#WAITLP2
JP #WAITLP2,REP = 1
TEMINV = ATANGLE
JS #INVERT1
ATANGLE = TEMINV
TEMP = ATANGLE{F3.2}
TYPE = 2
REP = 1
JS #ATINIT;NO                             INITIALISE ATTO
'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
#ATLOOP;NO                                LOOP WHILE START = 0
JP #ATLOOP,ATSTART=0
'
ATMERR = 0;NO                             CLEAR MOVE ERROR FLAG
ATDONE = 0
IF ((ATTO < -170) | (ATTO > 170));NO      CHECK VALUE IS ACCEPTABLE
'MG "ATTO ANGLE MUST BE BETWEEN +-170 DEGREES!"
'MG "**ATAE";NO                            ATTO ANGLE ERROR MESSAGE
TEMP = "**ATAE"
TYPE = 1
REP = 1
ATAERR = 1;NO                             ATTO ANGLE ERROR FLAG
JP #ATDONE
ENDIF
ATAERR = 0;NO                             CLEAR ANGLE ERROR FLAG
JS #AT_INV
#AT_REST
'
S = 5000;NO                               FIRST MOVE
PEND = ATTO * 0.0556;NO                   DESIRED VOLTAGE
PSTART = PATTO;NO                         START VOLTAGE
VDIFF = PEND - PSTART
'MG ""
'MG "ATTO ANGLE IS: ",PSTART{F1.4}
'MG "DESIRED ATTO ANGLE IS: ",PEND{F1.4}
'
'INITIAL MOVE
JS #DONE;NO                               IS MOVE NECESSARY?
IF (PSTART > PEND);NO                     IF START > END POSITION
IF (PSTART < -9);NO                       AND START POSITION < 1V
MG "STEPD 1" {P2},@ABS[S]{F5.0} {P2};NO   MOVE DOWN (INC V)
ELSE
MG "STEPU 1" {P2},@ABS[S]{F5.0} {P2};NO   ELSE MOVE UP (DEC V)
ENDIF
ELSE;NO                                   IF START < END POSITION
IF (PSTART > 9);NO                        AND START POSITION > 9V
MG "STEPU 1" {P2},@ABS[S]{F5.0} {P2};NO   MOVE UP
ELSE
MG "STEPD 1" {P2},@ABS[S]{F5.0} {P2};NO   ELSE MOVE DOWN
ENDIF
ENDIF
JS #AFTER;NO                              WAIT FOR MOVE
'
'CLEVER BIT
#LOOP2
PTEST = PATTO;NO                          FIND POSITION
'MG "NEW ATTO ANGLE = ",PTEST{F1.4}
VDIFF = PEND - PTEST;NO                   FIND NEW DIFFERENCE
JS #DONE;NO                               IS MOVE DONE?
JS #SPERV;NO                              FIND SPERV
IF (@ABS[VDIFF] > 12);NO                  IF THE MOVE IS TOO HIGH
VDIFF = VDIFF - (VDIFF/10);NO             REDUCE IT
'MG "REDUCED DISTANCE = ",VDIFF{F1.4}
ENDIF
'
S = VDIFF * SPERV;NO                      FIND NO OF STEPS
IF (S < 0);NO                             IF POSITIVE
MG "STEPU 1" {P2},@ABS[S]{F5.0} {P2};NO   MOVE UP
ELSE
MG "STEPD 1" {P2},@ABS[S]{F5.0} {P2};NO   ELSE MOVE DOWN
ENDIF
JS #AFTER;NO                              WAIT FOR MOVE
JP #LOOP2
EN
'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
#ATINIT
CC 38400,0,0,0;NO                         SET UP AUX COMMS
MG "SETF 1 1000" {P2};NO                  SET UP ATTOCUBE CONTROLLER
MG "SETV 1 70" {P2}
MG "SETM 1 STP" {P2}
ATDONE = 1
ERR2 = 0
EN
'
#AT_INV;NO                                THIS ROUTINE INVERTS THE 
IF (ATTO < 0);NO                          ENTERED VALUE TO MATCH
ATTO = @ABS[ATTO];NO                      THE ORIENTATION OF THE CONTROL
ELSE;NO                                   SIDE.  THIS IS EASIER THAN 
ATTO = 0 - ATTO;NO                        CHANGING EVERY SIGN IN THE
ENDIF;NO                                  PROGRAM.
'MG "ATTO = ",ATTO;NO   TEST
EN
'
#INVERT1
IF (TEMINV < 0);NO                       INVERT SENT VALUE 
TEMINV = @ABS[TEMINV]
ELSE
TEMINV = 0 - TEMINV 
ENDIF
EN
'
#DONE
WT 100
IF (@ABS[VDIFF] < 0.004);NO               ARE WE THERE YET?
'MG "ATTO IN POSITION"
'MG "**ATDN"
TEMP = "**ATDN"
TYPE = 1
REP = 1
ATANGLE = PATTO / 0.0556
'MG "**ATPN",ATANGLE{F3.2}
TEMP = "**ATPN"
TYPE = 1
REP = 1
#WAITLP3
JP #WAITLP3,REP = 1
TEMINV = ATANGLE
JS #INVERT1
ATANGLE = TEMINV
TEMP = ATANGLE{F3.2}
TYPE = 2
REP = 1
JP #ATDONE
ENDIF
EN
'
#ATDONE;NO                                CLOSE DOWN TASK
ATDONE = 1
ATSTART = 0
ERR2 = 0
JP #ATLOOP
EN
'
#AFTER;NO                                 WAIT FOR MOVE FINISHED
X=@ABS[S]/1000
X=X+(X/10);NO                              WAIT STEPS/FREQ + 20%
IF (X < 0.5);NO                           EXTRA TIME FOR DIGITAL FILTER
X = X + 0.5
ENDIF
WT X*1000;NO                              *1000 FOR MS
SSAVE=S;NO                                KEEP FOR SPERV
EN
'
#SPERV
MOVE=@ABS[PTEST-PSTART];NO                FIND VOLT CHANGE
IF (MOVE<0.02);NO                         HAS IT MOVED?
ERR2 = ERR2 + 1
JP #AT_REST,ERR2 < 3
'MG "ATTOCUBE IS NOT MOVING!"
'MG "**ATME";NO                            ATTO MOVE ERROR MESSAGE
TEMP = "**ATME"
TYPE = 1
REP = 1
ATMERR = 1;NO                             ATTO MOVE ERROR FLAG
JP #ATDONE
ENDIF
SPERV=@ABS[SSAVE]/MOVE;NO                 FIND STEPS PER VOLT
PSTART = PTEST
EN
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''ANALOGUE INPUT TASK'''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#ANTASK
'MG "ANALOGUE INPUT TASK RUNNING";NO       TEST
PATTO = 0;NO                              INITIALISE
PARK = 0
ATOLD3 = 0
AROLD3 = 0
ATOLD2 = 0
AROLD2 = 0
ATOLD1 = 0
AROLD1 = 0
ATVAL = 0
ARVAL = 0
'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
#ANLOOP
ATOLD3 = ATOLD2;NO                        MOVE NEW VALUES IN
AROLD3 = AROLD2
ATOLD2 = ATOLD1
AROLD2 = AROLD1
ATOLD1 = ATVAL
AROLD1 = ARVAL
ATVAL = @AN[1]
ARVAL = @AN[2]
PATTO = ((ATVAL * 0.5) + (ATOLD1 * 0.25) + (ATOLD2 * 0.15) + (ATOLD3 * 0.1))
PARK = ((ARVAL * 0.5) + (AROLD1 * 0.25) + (AROLD2 * 0.15) + (AROLD3 * 0.1))
WT 100;NO                                 FIND AVERAGE VALUE THEN WAIT 100MS
JP #ANLOOP
EN
'