changecom(`;',` ') ; APT PMAC software ; ; Michael Ashley / 20-Mar-2001 / UNSW ; ; PMAC error codes: ; ; ERR001 Command not allow during program execution ; ERR002 Password error ; ERR003 Data error or unrecognized command ; ERR004 Illegal character (> 127 ASCII, or serial parity/framing error) ; ERR005 Command not allowed unless buffer is open ; ERR006 No room in buffer for command ; ERR007 Buffer already in use ; ERR008 ------------ ; ERR009 Program structural error (e.g., ENDIF without IF) ; ERR010 Both overtravel limits set for a motor in the coordinate system ; ERR011 Previous move not completed ; ERR012 A motor in the coordinate system is open-loop ; ERR013 A motor in the coordinate system is not activated ; ERR014 No motors in the coordinate system ; ERR015 Not pointing to valid program buffer ; ERR016 Running improperly structured program (e.g., missing ENDWHILE) ; ERR017 Trying to resume after / or \ with motors out of stopped position ; ; Improvements: ; - all pvt moves to go through one routine, which can check for ; position in bounds. ; - hitting a limit should result in the telescope being driven ; slightly off the limit, and a flag being set, which requires ; external action to reset ; - pixel-coverage (drift in dec, raster in ra) ; NOTE: tabs are fatal to the PMAC!  close delete gather disable plc 0..31  &1 a &2 a ; Programming constructs: define(`PLC', `open plc $1 clear') define(`PROG', `open prog $1 clear') ; M variables: define(`M0_ServoLoops', `m0') ; P variables: ; The defines labelled "External" are used by the THI interface to PTCS, and ; so must not be changed. define(`ServoLoopOverflow', `p20') define(`ServoClockPeriod', `p21') define(`ServoLoops', `p19') define(`PrevServoLoops', `p22') define(`TimeInSecs', `p23') define(`PrevTime', `p24') define(`DeltaTime', `p25') define(`Hours', `p26') define(`Minutes', `p27') define(`Seconds', `p28') define(`TimeOffset', `p29') ; External define(`RA', `p30') define(`RAMult', `p31') define(`HAZero', `p32') define(`Dec', `p33') define(`DecMult', `p34') define(`DecZero', `p35') define(`TimeMult', `p36') define(`xVelocityCounts', `p37') define(`yVelocityCounts', `p38') define(`Aerr', `p47') define(`gA', `p48') define(`gAerr', `p61') define(`Adiff', `p50') define(`gAint', `p51') define(`Av', `p52') define(`Berr', `p53') define(`gB', `p54') define(`gBerr', `p62') define(`Bdiff', `p56') define(`gBint', `p57') define(`Bv', `p58') define(`gTai', `p59') define(`gMjd', `p60') ; External define(`xOffset', `p39') define(`yOffset', `p40') define(`saveA', `p63') define(`saveB', `p64') define(`FirstTime', `p70') define(`xHomeFlags', `p79') define(`yHomeFlags', `p80') define(`xHomed', `p81') define(`yHomed', `p82') define(`xDeltaT', `p86') define(`yDeltaT', `p87') define(`xUpdate', `p100') ; External define(`TaiDemand', `p101') ; External define(`ADemand', `p102') ; External define(`AVDemand', `p103') ; External define(`BDemand', `p104') ; External define(`BVDemand', `p105') ; External define(`yUpdate', `p106') ; External define(`xTaiDemand1', `p84') define(`yTaiDemand1', `p85') define(`TaiDemand0', `p65') define(`ADemand0', `p66') define(`AVDemand0', `p67') define(`BDemand0', `p68') define(`BVDemand0', `p69') define(`temp1', `p72') define(`temp2', `p73') define(`xPosition', `p76') define(`xActual', `p107') define(`xSlewTime', `p109') define(`yPosition', `p77') define(`yActual', `p108') define(`ySlewTime', `p110') define(`xstep', `p112') define(`ystep', `p113') define(`radius', `p114') ; External define(`maxstep', `p115') ; External define(`xVel', `p116') define(`yVel', `p117') define(`Time', `p78') define(`Tracking', `p88') define(`xsign', `p118') define(`decLimit', `p119') define(`xMin', `p120') define(`xMax', `p121') define(`yMin', `p122') define(`yMax', `p123') define(`RadiansPerPixel', `p124') define(`PixelsWiggle', `p125') ; External define(`xTest', `p126') decLimit = 0 radius = 0.00015 radius = 0 xstep = 0 ystep = 0 xsign = 1 maxstep = 100 xOffset = 0 yOffset = 0 Tracking = 0 PixelsWiggle = 2 ; Immutable constants: define(`Pi', `3.14159265359') define(`DegToRad', `(Pi/180)') define(`SecondsOfTimeToRad', `(Pi/43200)') define(`SiderealRate', `1.0027379093') define(`SecondsInADay', `(3600*24)') define(`TrackingVelocity', `(SiderealRate*2*Pi/SecondsInADay)') ; Properties of the telescope and CCD: define(`RAEncoderResolution', `(10000*4)') define(`RAGearRatio', `5760') define(`DecEncoderResolution', `(10000*4)') define(`DecGearRatio', `14400') define(`ArcsecsPerPixel', `(9.43)') define(`maxXEncoderFreq', `400000') define(`maxXCountsPerSec', `(maxXEncoderFreq*4)') ; DANGER are the following the right way around? define(`xMinDeg', `(-64)') define(`xMaxDeg', `(67)') define(`yMinDeg', `(-74.5)') define(`yMaxDeg', `(39.0)') ; Properties of the PMAC: define(`PmacCrystalRate', `1.0000353') ; the PMAC is slow ; Derived constants: RAMult = 2*Pi/(RAGearRatio*RAEncoderResolution) DecMult = 2*Pi/(DecGearRatio*DecEncoderResolution) TimeMult = SiderealRate * SecondsOfTimeToRad HAZero = +0.0765 ; HA zero in radians, must agree with thi_main.c DecZero = -0.595 ; Dec zero in radians, also must agree with thi_main.c ServoClockPeriod = 640*(2*I992+3)*(I997+1)*(I998+1)/(9000*8388608) ServoClockPeriod = ServoClockPeriod * PmacCrystalRate xMin = DegToRad*xMinDeg/RAMult xMax = DegToRad*xMaxDeg/RAMult yMin = (DecZero + DegToRad*yMinDeg)/DecMult yMax = (DecZero + DegToRad*yMaxDeg)/DecMult RadiansPerPixel = DegToRad*ArcsecsPerPixel/3600.0 ; These values are used if the motor numbers are changed on the ; macro station: ; I102 = $C0A0 ; I103=$721 ; I104=$721 ; I105=$721 ; I125 = $140F70 ; I202 = $C0A4 ; I203=$723 ; I204=$723 ; I205=$723 ; I225 = $140F71 ; M120->X:`$'0F70,16 ; Motor #1 home flag ; M220->X:`$'0F71,16 ; Motor #2 home flag define(`SetupMVariables', `m0->X:`$'0,0,24,U M120->X:`$'0F74,16 ; Motor #1 home flag M131->x:`$'003D,21,1 ; Motor #1 positive end limit set M132->x:`$'003D,22,1 ; Motor #1 negative end limit set M133->X:`$'0003,5,1 ; MACRO auxilliary communications error M161->D:`$'0028 ; Motor #1 commanded position (1/(i108*32) counts) M162->D:`$'002B ; Motor #1 actual position (1/(i108*32) counts) M220->X:`$'0F75,16 ; Motor #2 home flag M231->x:`$'0079,21,1 M232->x:`$'0079,22,1 M261->D:`$'0064 ; Motor #2 commanded position (1/(i208*32) counts) M262->D:`$'0067 ; Motor #2 actual position (1/(i208*32) counts) ') ; Note carefully: ; i123 (the homing velocity) must be low enough that the motors ; follow the demand position, or else homing causes big problems ; i169 (the maximum DAC output) therefore must be sufficient to ; support a rate of i123. i169 limits the velocity in PVT mode. ; Ergo, the homing velocity must be less than the slewing velocity. ; define(`SetupXAxis', `&1 #1->X a #1 k I100=0 ; deactivate RA motor I101=0 ; no commutation I102=`$'C0A8 ; DAC adddress I103=`$'725 ; position loop feedback address I104=`$'725 ; velocity loop feedback address I105=`$'725 ; master handwheel address I111=0 ; disable RA fatal following limit I112=0 ; disable RA warning following I113=0 ; positive software position limit I114=0 ; negative software position limit I116=30000 ; maximum velocity in counts/msec for LINEAR moves I117=30000 ; maximum acceleration in counts/msec^2 for LINEAR moves I125=`$'140F74 ; motor flag address I128=160 ; motor in-position band I130=6000 ; PID proportional gain; increasing it makes the motor buzz I131=6200 ; PID derivative gain I132=6560 ; PID velocity feedforward gain I133=42600 ; PID integral gain I134=1 ; PID integration mode I135=0 ; PID acceleration feedforward gain I164=0 ; deadband gain factor (0 = off) I165=16 ; deadband size I168=0 ; friction feedforward I169=5000 ; maximum DAC output in RA (this limits PVT moves) I100=1 ; activate RA motor j/ %100') define(`SetupYAxis', `&2 #2->Y a #2 k I200=0 ; deactivate Dec motor I201=0 ; no commutation I202=`$'C0AC ; DAC adddress I203=`$'727 ; position loop feedback address I204=`$'727 ; velocity loop feedback address I205=`$'727 ; master handwheel address I211=1000000 ; set Dec fatal following limit I212=0 ; disable Dec warning following I213=0 ; positive software position limit I214=0 ; negative software position limit I216=400 ; maximum velocity in counts/msec for LINEAR moves I225=`$'140F75 ; motor flag address I228=160 ; motor in-position band I230=6000 ; PID proportional gain; increasing it makes the motor buzz I231=6200 ; PID derivative gain I232=6560 ; PID velocity feedforward gain I233=42600 ; PID integral gain I234=1 ; PID integration mode I235=0 ; PID acceleration feedforward gain ; Integrated power protection. If I257 and I258 are set to 2000, 1000 ; respectively, then the motor will cut-out if stalled for more than ; 22 seconds. I257=2000 ; continuous current limit I258=5000 ; integrated current limit ; I257=0 ; continuous current limit ; I258=0 ; integrated current limit I263=4194304 ; maximum integrated error (default = 4194304, no limit) I264=0 ; deadband gain factor (0 = off) I265=16 ; deadband size I268=0 ; friction feedforward I269=5000 ; maximum DAC output in RA (this limits PVT moves) I200=1 ; activate Dec motor j/ %100') define(`SetupPMAC', `a undefine all i10 = 3713991 i5 = 3 ; Enable all PLC programs &1') define(`NoCR', `i3 = 0 i62 = 1') define(`CR', `i3 = 1 i62 = 0') define(`xDisableAmpFault', `i125 = i125 | `$'100000') define(`xEnableAmpFault', `i125 = i125 & `$'0FFFFF') define(`xDisableOvertravelLimits', `i125 = i125 | `$'020000') define(`xEnableOvertravelLimits', `i125 = i125 & `$'1DFFFF') define(`yDisableAmpFault', `i225 = i225 | `$'100000') define(`yEnableAmpFault', `i225 = i225 & `$'0FFFFF') define(`yDisableOvertravelLimits', `i225 = i225 | `$'020000') define(`yEnableOvertravelLimits', `i225 = i225 & `$'1DFFFF') define(`RATracking', `Tracking = Tracking | `$'0001') define(`RASlewing', `Tracking = Tracking | `$'0002') define(`RANotSlewing', `Tracking = Tracking & `$'FFFD') define(`RALimit', `Tracking = Tracking | `$'0004') define(`RANotLimit', `Tracking = Tracking & `$'FFFB') define(`DecTracking', `Tracking = Tracking | `$'0010') define(`DecSlewing', `Tracking = Tracking | `$'0020') define(`DecNotSlewing', `Tracking = Tracking & `$'FFDF') define(`DecLimit', `Tracking = Tracking | `$'0040') define(`DecNotLimit', `Tracking = Tracking & `$'FFBF') define(`MacroError', `Tracking = Tracking | `$'0080') define(`MacroOK', `Tracking = Tracking & `$'FF7F') ; PLC names: define(`Timer', `1') define(`ReportPosition', `3') define(`Servo', `4') define(`MacroSet', `5') ; PROG names: define(`xTrack', `1') define(`yTrack', `2') define(`xStop', `3') define(`yStop', `4') define(`xKnifeEdge', `5') define(`yKnifeEdge', `6') ; Constants for the servo simulation: define(`AGAIN', `1.5') define(`AIGAIN', `0.2') define(`ADGAIN', `-3.0') define(`BGAIN', `1.5') define(`BIGAIN', `0.2') define(`BDGAIN', `-3.0') NoCR SetupPMAC SetupMVariables SetupXAxis SetupYAxis xDisableAmpFault ;xDisableOvertravelLimits xEnableOvertravelLimits yDisableAmpFault ;yDisableOvertravelLimits yEnableOvertravelLimits gAint = 0 gBint = 0 gMjd = 0.0 RA = 0 Dec = 0 xHomeFlags = 0 yHomeFlags = 0 xHomed = 0 yHomed = 0 Av = TrackingVelocity xVelocityCounts = Av / RAMult Bv = 0 yVelocityCounts = Bv / DecMult TaiDemand = 0 xTaiDemand1 = 0 yTaiDemand1 = 0 ADemand = 0 AVDemand = Av BDemand = 0 BVDemand = Bv TaiDemand0 = TaiDemand ADemand0 = ADemand AVDemand0 = AVDemand BDemand0 = BDemand BVDemand0 = BVDemand ;-------------------------------------------------------------- PLC(Servo) ; ; A servo simulator, for use when the hardware is not available. ; Aerr = gA - ADemand Adiff = Aerr - gAerr if (abs(Aerr) > 0.005) gAint = 0.0 else gAint = gAint + Aerr endif Av = AGAIN * Aerr + AIGAIN * gAint + ADGAIN * Adiff if (Av > 0.05) Av = 0.05 endif if (Av < -0.05) Av = -0.05 endif gA = gA - Av * ServoClockPeriod gAerr = Aerr Berr = gB - BDemand Bdiff = Berr - gBerr if (abs(Berr) > 0.005) gBint = 0.0 else gBint = gBint + Berr endif Bv = BGAIN * Berr + BIGAIN * gBint + BDGAIN * Bdiff if (Bv > 0.05) Bv = 0.05 endif if (Bv < -0.05) Bv = -0.05 endif gB = gB - Bv * ServoClockPeriod gBerr = Berr close ;-------------------------------------------------------------- ServoLoops = 0 PrevServoLoops = 0 ServoLoopOverflow = 0 PLC(Timer) ; ; The fundamental timing mechanism in the PMAC is the number of ; servo clock cycles. Each cycle is of length "ServoClockPeriod" ; seconds (about 0.00044s by default). The PMAC variable "m0" ; points to the servo cycle counter, but is only 24 bits in ; length, so we have to worry about overflow (after about 2 hours). ; This PLC routine simply counts the number of overflows. ; ServoLoops = M0_ServoLoops if (ServoLoops < PrevServoLoops) ServoLoopOverflow = ServoLoopOverflow + 1 endif PrevServoLoops = ServoLoops close ;-------------------------------------------------------------- Time = 0 PrevTime = 0 TimeOffset = 0 FirstTime = 1 ; TimeInSecs is the number of seconds that have elapsed since the ; program was started. ; TimeOffset is the number of seconds to add to "TimeInSecs" to ; get the current TAI. ; Time after tracking is underway, this should be ; about 0.2 sec greater than "TimeInSecs". It is the time ; at which the tracking calculations are done. ; ; PLC(ReportPosition) ; ; This routine reports back to the host computer the PMAC time ; and the motor positions. ; ; Begin by calculating the time; we then quickly grab a copy of the ; motor positions. ; saveA = M162 saveB = M262 TimeInSecs = (ServoLoopOverflow * 16777216 + ServoLoops) * ServoClockPeriod ; ; If more than one second has elapsed since we last reported, do it ; again. ; DeltaTime = TimeInSecs - PrevTime if (DeltaTime < 0.0 OR DeltaTime > 0.95) PrevTime = TimeInSecs gTai = TimeInSecs + TimeOffset if (FirstTime != 0 AND Time != 0) FirstTime = 0 Time = TimeInSecs + 0.25 endif ; ; Output the following information: ; ; gMjd the modified Julian Date at which the program started ; gTai the TAI in seconds, to be added to gMjd ; M162 the RA motor position ; M262 the Dec motor position ; ; Note that we enclose the output in angle brackets, since the PMAC ; device driver traps everything between such brackets. ; p130=yPosition*i108*32-saveB ;cmd"p102" ;send" " ;cmd"p103" send"<" cmd"gMjd" send" " cmd"gTai" send" " cmd"saveA" send" " cmd"saveB" gAerr = Time - TimeInSecs send" " cmd"gAerr" send" " cmd"xHomed" send" " cmd"yHomed" send" " cmd"Tracking" ; send" " ;cmd"M133" send">" send^J if (m131 = 1 OR m132 = 1) RALimit else RANotLimit endif if (m231 = 1 OR m232 = 1) DecLimit else DecNotLimit endif ; if (m133 = 1) ; MacroError ; else ; MacroOK ; endif endif close ;-------------------------------------------------------------- PLC(MacroSet) if (xHomeFlags != 0) msw0,mi912,xHomeFlags msw4,mi912,xHomeFlags xHomeFlags = 0 endif if (yHomeFlags != 0) msw1,mi912,yHomeFlags msw5,mi912,yHomeFlags yHomeFlags = 0 endif close ;-------------------------------------------------------------- ; The Right Ascension tracking routine. ; ; Limit switch behaviour: ; ; The outer limits directly cut the power to the servo amplifiers. ; ; The inner limits cause the PMAC to maintain the motor position ; at its commanded value, and to stop any motion programs in that ; coordinate system. This is not ideal, since the commanded position ; may be far away from the limit, and since we are disabling the ; following error, we can get into trouble. The PMAC manual describes ; this situation in some detail. ; ; To recover from an inner limit: manually move the telescope ; away from the limit, and reload this file into the PMAC. PROG(xTrack) ; Idle until the axis is calibrated. while (xHomed != 1) endwhile abs(x) xPosition = m162 / (i108 * 32) x(xPosition) pvt100 xUpdate = 0 I113=xMax I114=xMin while (0 < 1) RATracking ; If either inner limit is hit, set the motor demand position to its current ; actual position, and set the velocity to zero. ; DANGER: why not go to zenith, or a point close to the limit? if (m131 = 1 OR m132 = 1) xPosition = m162 / (i108 * 32) xVelocityCounts = 0 endif ; If the THI program has requested a change in position (which it does ; about once per second), process the request. if (xUpdate != 0) xUpdate = 0 xTaiDemand1 = TaiDemand - TimeOffset ; If the difference between the actual time and the demand time exceeds ; 60 seconds, we set the difference to zero, on the assumption that this ; is probably due to a time setting event. xDeltaT = Time - xTaiDemand1 if (abs(xDeltaT) > 60.0) xDeltaT = 0.0 endif ; Calculate the new demand position, and then ensure it lies between ; +/-Pi radians. xPosition = (ADemand - HAZero + xDeltaT * AVDemand) while (xPosition < -Pi) xPosition = xPosition + 2*Pi endwhile while (xPosition > Pi) xPosition = xPosition - 2*Pi endwhile ; We should now check that the position is within the inner limits, and ; if not, signal a limit. ; Convert from radians and radians/sec to encoder counts and counts/sec. xPosition = xPosition / RAMult xVelocityCounts = AVDemand / RAMult ; xActual = m162 / (i108 * 32) ; If the position change is so large that we can't cope with it with ; our normal 100ms adjustment, then we go into slew mode. if (abs(xPosition - xActual) > abs(0.5*xVelocityCounts)) RASlewing ; Calculate the slew time in milliseconds. This is slightly longer than ; the best the telescope is capable of, to ensure that we have a zero ; following error throughout the move. For slews than take less than 2 or ; 3 seconds, we substitute a minimum slew time. ; How long would it take to slew at half the maximum slew rate? xSlewTime = 2000 * abs(xPosition - xActual) / maxXCountsPerSec ; If this is greater than 8 seconds, we have time to reach maximum velocity, ; so we adjust the slew time accordingly. ; send^J ; send"xSlewTime=" ; cmd"xSlewTime" ; send^J ; if (xSlewTime > 8000) ; send^J ; send"xPosition=" ; cmd"xPosition" ; send^J ; send^J ; send"xActual=" ; cmd"xActual" ; send^J ;;linear ; xSlewTime = 8000 + (xSlewTime - 8000) * 0.5 ;;tm(xSlewTime) ;;ts(2000) ;;ta(4000) ;;x(xPosition) ; pvt(4000) ; if (xPosition > xActual) ; xVel = maxXCountsPerSec ; else ; xVel = -maxXCountsPerSec ; endif ; xTest = xActual + xVel * (4000/1000) * (2/3) ; send^J ; send"pvt(4000)x(" ; cmd"xTest" ; send":" ; cmd"xVel" ; send^J ; x(xTest):(xVel) ;; xTest = xSlewTime - 8000 ; send^J ; send"pvt(" ; cmd"xTest" ; send")x(" ;; pvt(xSlewTime - 8000) ;;; xTest = xPosition - xVel * (4000/1000) ;; xTest = xTest + xVel * ((xSlewTime-8000)/1000) ; cmd"xTest" ; send":" ; cmd"xVel" ; send^J ;; x(xTest):(xVel) ; pvt(xSlewTime-4000) ; else if (xSlewTime < 3000) if (xSlewTime < 2000) xSlewTime = 2000 else xSlewTime = 3000 endif endif ; Prepare for the slew. pvt(xSlewTime) ; endif ; Calculate the desired position, taking into account the time required for ; the slew. xPosition = xPosition + xVelocityCounts * xSlewTime * 0.001 ; Slew. send^J send"pvt(4000)x(" cmd"xPosition" send":" cmd"xVelocityCounts" send^J x(xPosition):(xVelocityCounts) ; Update the time, and return to 100 millisecond PVT moves. Time = Time + PmacCrystalRate * xSlewTime * 0.001 pvt100 else RANotSlewing endif ; if (abs(xPosition - xActual) < abs(20 * xVelocityCounts)) ; ;I130=7000 ;I131=3000 ;I132=3200 ;I133=40000 ;I164=0 ;I165=16 ;else ; if (abs(xPosition - xActual) < abs(200 * xVelocityCounts)) ;I130=2000 ;I131=0 ;I132=0 ;I133=0 ;I164=128 ;I165=1000 ;else ;I130=50 ;I131=0 ;I132=0 ;I133=0 ;I164=128 ;I165=1000 ;endif ;endif ; if (abs(xPosition - xActual) > abs(0.5 * xVelocityCounts)) ; linear ; x(xPosition) ; pvt100 ; endif endif ; Now adjust the desired position for any special effects (such as small ; circles or raster patterns). if (radius = 0) xActual = xPosition xVel = xVelocityCounts else if (radius < 0) xVel = xVelocityCounts + xsign * PixelsWiggle * RadiansPerPixel / (7.5 * RAMult * cos(BDemand)) xActual = xPosition + xsign * (xVel - xVelocityCounts) * xstep * 0.1 xstep = xstep + xsign if (xstep > 37.5) xstep = 37 xsign = - xsign xVel = xVelocityCounts endif if (xstep < -37.5) xstep = -37 xsign = - xsign xVel = xVelocityCounts endif else ; Guard against ridiculous radii. if (abs(radius) > 0.01) radius = 0.01 endif xActual = xPosition + cos(6.283185307 * xstep / maxstep) * (radius / RAMult) xVel = xVelocityCounts - (62.83185307 / maxstep) * sin(6.283185307 * xstep / maxstep) * (radius / RAMult) xstep = xstep + 1 if (xstep > (maxstep - 0.5)) xstep = 0 endif endif endif x(xActual):(xVel) xActual = xPosition xPosition = xPosition + xVelocityCounts * 0.1 Time = Time + 0.1 * PmacCrystalRate endwhile close ;-------------------------------------------------------------- ; The Declination tracking routine. PROG(yTrack) while (yHomed != 1) endwhile abs(y) yPosition = m262 / (i208 * 32) y(yPosition) pvt100 yUpdate = 0 ; I213=yMax ;I214=yMin while (0 < 1) ; Limit the motor current during tracking, to prevent burn-out of the ; old Dec motor. if (radius = 0) i269=1000 else i269=1000 endif DecTracking if (m231 = 1 OR m232 = 1) decLimit=1 DecLimit pvt(60000) yPosition = -DecZero/DecMult ; yPosition = m262 / (i208 * 32) yVelocityCounts = 0 i269=5000 y(yPosition):(yVelocityCounts) i269=1000 endif if (decLimit = 0) if (yUpdate != 0) ; Allow higher current during slews. i269=5000 yUpdate = 0 yTaiDemand1 = TaiDemand - TimeOffset yDeltaT = Time - yTaiDemand1 if (abs(yDeltaT) > 60.0) yDeltaT = 0.0 endif yPosition = (BDemand - DecZero + yDeltaT * BVDemand) yPosition = yPosition / DecMult yVelocityCounts = BVDemand / DecMult ; If the Dec change is more than one pixel, treat it as a slew. if ((abs(yPosition - yActual) * DecMult) > RadiansPerPixel) ystep =0 DecSlewing ySlewTime = abs(yPosition - yActual) * DecMult ySlewTime = int(90000 * ySlewTime) if (ySlewTime < 5000) if (ySlewTime < 3000) ySlewTime = 3000 else ySlewTime = 5000 endif endif ;ySlewTime = ySlewTime * 0.5 pvt(ySlewTime) yPosition = yPosition + yVelocityCounts * ySlewTime * 0.001 ; if (yPosition > yMin AND yPosition < yMax) y(yPosition):(yVelocityCounts) ; else ; decLimit=1 ; DecLimit ; endif pvt100 else DecNotSlewing endif endif if (radius = 0) ystep = 0 yActual = yPosition yVel = yVelocityCounts else if (radius < 0) yVel = yVelocityCounts + PixelsWiggle * RadiansPerPixel / (- radius * DecMult) yActual = yPosition + (yVel - yVelocityCounts) * ystep * 0.1 ystep = ystep + 1 else if (radius > 0.01) radius = 0.01 endif yActual = yPosition + sin(6.283185307 * ystep / maxstep) * (radius / DecMult) yVel = yVelocityCounts + (62.83185307 / maxstep) *cos(6.283185307 * ystep / maxstep) * (radius / DecMult) ystep = ystep + 1 if (ystep > (maxstep - 0.5)) ; DANGER: is it a good idea to zero x as well? xstep = 0 ystep = 0 endif endif endif y(yActual):(yVel) yActual = yPosition yPosition = yPosition + yVelocityCounts * 0.1 endif endwhile close ;-------------------------------------------------------------- ; The routines for initial mount calibration using the tilt sensor. ; ; Set the "Capture n Flag Select Control" so that the home flag ; is used for position capture for nodes 0,1,4,5 (motors 1,2,3,4). ; ; The RA tilt-sensor gives a high output and illuminates the red LED when ; the telescope is west of the nominal zenith. This high output is converted ; to 0 V at TB4 pin 4 of the compact macro station. ; ; The Dec tilt-sensor gives a high output and illuminates the orange LED when ; the telescope is south of the nominal zenith. This high output is converted ; to 0 V at TB6 pin 4. p111=0 msw0,mi913,p111 msw1,mi913,p111 msw4,mi913,p111 msw5,mi913,p111 PROG(xKnifeEdge) ; send"RA start" xHomed = 0 if (M120 = 0) i123=-1000 ; Use -ve if west of the switch xHomeFlags = 2 while (xHomeFlags != 0) endwhile else i123=+1000 ; Use +ve if east of the switch xHomeFlags = 10 while (xHomeFlags != 0) endwhile endif i126=1000000 ; Offset from home, so that we now approach from ; the same direction each time. home1 ; send"RA intermediate" delay 2000 if (M120 = 0) i123=-500 ; Use -ve if west of the switch xHomeFlags = 2 while (xHomeFlags != 0) endwhile else i123=+500 ; Use +ve if east of the switch xHomeFlags = 10 while (xHomeFlags != 0) endwhile endif i126=1000000 ; Offset from home, so that we now approach from ; the same direction each time. home1 ; send"RA intermediate" delay 2000 ; Now find home again, this time slowly. if (M120 = 0) i123=-15 ; Use -ve if west of the switch xHomeFlags = 2 while (xHomeFlags != 0) endwhile else i123=+15 ; Use +ve if east of the switch xHomeFlags = 10 while (xHomeFlags != 0) endwhile endif i126=0 home1 ; send"RA complete" xHomed = 1 close PROG(yKnifeEdge) yHomed = 0 ; If the Dec limit has been hit, drive towards the zenith. if (m231 = 1 OR m232 = 1) pvt(60000) yPosition = -DecZero/DecMult yVelocityCounts = 0 i269=5000 y(yPosition):(yVelocityCounts) endif i269=5000 send"DecOne" if (M220 = 0) send"NORTH" i223=+1000 ; Use +ve if north of the switch yHomeFlags = 2 while (yHomeFlags != 0) endwhile else send"SOUTH" i223=-1000 ; Use -ve if south of the switch yHomeFlags = 10 while (yHomeFlags != 0) endwhile endif i226=2000000 home2 delay 1000 send"DecTwo" if (M220 = 0) send"NORTH" i223=+400 ; Use +ve if north of the switch yHomeFlags = 2 while (yHomeFlags != 0) endwhile else send"SOUTH" i223=-400 ; Use -ve if south of the switch yHomeFlags = 10 while (yHomeFlags != 0) endwhile endif i226=2000000 home2 delay 1000 send"Decintermediate" if (M220 = 0) i223=+30 ; Use +ve if north of the switch yHomeFlags = 2 while (yHomeFlags != 0) endwhile else i223=-30 ; Use -ve if south of the switch yHomeFlags = 10 while (yHomeFlags != 0) endwhile endif i226=0 home2 send"DecComplete" yHomed = 1 i269=1000 close enable plc Timer ;enable plc Servo enable plc ReportPosition enable plc MacroSet ;