Sidereal Technology Servo Controller Command Set

Sidereal Technology Servo Controller Command Set

General notes

Axis Names

About speeds and rates

About ASCII Checksum (ACS) Mode

Entering and Leaving ACS mode

ASCII Commands

Definition of XBits and YBits

Send Configuration binary layout

Definition of Reported Motor Position

Tangent Protocol Emulation

PicServo Emulation

Binary commands

XXS / XXR / YXR Response Format

Sample XXS / XXR / YXR response

XXR Request Format

YXR Request Format

About base rates and rate adders

Known bugs with YXR commands

RateAdderTime never expires: fixed in V89

All motion stops on Y axis when RateAdderTime expires: fixed in V94

Wrong rate applied when RateAdderTime Expires: fixed in V94b

Sample YXY Request (in ACS mode)

Resyncing after communication error

Various communication stream details

Flash RAM and ROM

Accessing other SiTech modules

Conditions for entering Manual (“blinky”) mode

Servo II Communication Behavior when Powered Off

Firmware version history from Dan Gray

General notes

  1. All commands MUST BE IN ALL CAPS!
  2. The # character represents a decimal number that you must type
  3. Most commands are followed by a carriage return (‘\r’) character
  4. All Altitude/Dec commands begin with an "X". All Azimuth/RA commands begin with a "Y"

Axis Names

The X axis in the SiTech controller corresponds to the Declination axis (on an equatorial mount) or the Altitude axis on an Alt-Az mount.

The Y axis in the SiTech controller corresponds to the Right Ascension axis (on an equatorial mount) or the Azimuth axis on an Alt-Az mount.

Notice that if you were to take an equatorial mount and set the polar axis to 90 degrees, the RA axis would become the Azimuth axis and the Dec axis would become the Altitude axis. This is an intuitive way to remember this association.

About speeds and rates

The controller loops 1953 times per second. Fields that reference a speed/velocity/rate (e.g. the XS command) express this speed as a 32-bit number representing the number of ticks the motor encoder should advance per loop, multiplied by 2^16 (= 65,536) to express fractional values.

For example, if you want to advance the motor 1,000 counts per second, this corresponds to:

1,000 / 1953 ~= 0.512 counts per loop

which is expressed as the integer value:

        round(0.512 * 65,536) = 33,555

So you would send the command “XS33555\r” to set a max speed of 1,000 counts per second.

Note that 65,536 / 1,953 = 33.55657962109575, and 1,953 / 65,536 = 0.0298004150390625, so you can simply do:

        CountsPerSecToSpeedValue(cps): return round(cps * 33.55657962109575)

        SpeedValueToCountsPerSec(speed): return round(speed * 0.0298004150390625)

The SiTech Operations Manual describes the following “C++” functions (converted to something like Python here) to do similar conversions:

        def DegsPerSec2MotorSpeed(dps, ticksPerRev):

return round(ticksPerRev * dps * 0.09321272116971)

def MotorSpeed2DegsPerSec(speed, ticksPerRev):

        return round(speed / ticksPerRev * 10.7281494140625)

These coefficients can be derived as follows:

        10.7281494140625 = 0.0298004150390625 * 360 degs/rev

        0.09321272116971 = 33.55657962109575 / 360 degs/rev

About ASCII Checksum (ACS) Mode

The SiTech ASCII command set has a lot of commands that can be typed in from a terminal program.  But this was problematic when communications were not very good (noisy RS232 lines, etc).  Sometimes when SiTechExe sent a binary command, the controller did not receive it as a binary command.  Then, by chance, some of the binary data would equal an ASCII command, such as "Reset Controller", or other commands, and the controller would do unpredictable things.

To solve this, I devised an Ascii Checksum Mode (ACS).  If you are in the ACS mode, you send another byte after the <cr> byte, which is the 8 bit sum of all the bytes, inverted.

Entering and Leaving ACS mode

Command

Description

“YXY1\r”

Hex: 59 58 59 31 0D

Enter the ASCII Checksum mode (no response)

“YXY0\r\xb8”

Hex: 59 58 59 30 0D B8

Exit the ASCII Checksum mode (no response)

“YXY\r\xe8”

Hex: 59 58 59 0D E8

Returns:

    "Y0\r\n" if not in ASCII Checksunm mode

    "Y1\r\n" if in ASCII Checksum mode.

If controller is in the ACS mode, and it is receiving characters, if the character stream stops for more than 50 mSecs, the controller resets the serial stream, and the next character will be placed at the beginning of the receive buffer.

If the controller is not in the ACS mode, you can send characters with any time spacing, and it will always respond.

Example of a "YXS" command, in ACS mode:

59 58 53 0D EE

        0x59 = “Y”

        0x58 = “X”

        0x53 = “S”

        0x0D = <cr>

        0xEE = ~( (0x59 + 0x58 + 0x53 + 0x0D) % 256 )

One more oddity: If controller is in the ACS mode, and you want to "talk" to the focuser/rotator, then you replace the first 'X' with 'T', and the first 'Y' with 'U' (same as previously), but you calculate the checksum based on if it had been the 'X' or 'Y'.

ASCII Commands

Cmd

Description

Sample requests

Sample responses

Q

Send scope encoder data in Tangent format

(note: no CR following Q)

Q

+00000\t+00000\r

SB#

Set Baud Rate

   1 = 9600

   2 = 19200

Changes all controllers on serial bus

Firmware version 1.5 or later

Change takes effect immediately. Value is reset when controller reboots (unless written to flash?)

SB19200\r

(none)

\r

Return controller status in the form:

X# Y# XZ# YZ# XC# YC# V# T# X[AM] Y[AM] K#

where:

X: Alt/Dec motor encoder position

Y: Az/RA motor encoder position

XZ: Alt/Dec scope axis encoder position

YZ: Az/RA scope axis encoder position

XC: Alt/Dec motor current * 100.0

YC: Az/RA motor current * 100.0

V: Controller power supply voltage * 10.0

T: Controller CPU temperature (Degs F)

XA (or XM): Alt/Dec motor mode

     (Auto or Manual)

YA (or YM): Az/RA motor mode

     (Auto or Manual)

K: Handpaddle status bits

\r

(carriage return)

X1234 Y-1234

XZ0 YZ0

XC3 YC3

V121 T74

XA YA

K0\r\n

For the following commands, an “X” prefix affects the Altitude/Dec axis and a “Y” prefix affects the Azimuth/RA axis:

Cmd

Description

Sample requests

Sample responses

X

Y

Return the position of the X or Y motor

X\r

Y\r

X874795\r\n

Y10769092\r\n

X#

Y#

Set servo motor target. An optional speed command (S#) may be appended.

Range: -2,147,483,648 - 2,147,483,647

X-1000\r

X1000S100\r

Y2000\r

(none)

(none)

(none)

XF#

YF#

Reset the current motor position to equal the supplied number. This stops the controller if moving.

Range: -2,147,483,648 - 2,147,483,647

XF15000\r

YF-7500\r

(none)

(none)

XS

YS

Return the max velocity of the servo based on the current movement command

XS\r

YS\r

S3500000\r\n

s3500000\r\n

XS#

YS#

Set the max velocity of the servo

Range: 0 - 2,147,483,647

XS99999\r

(none)

XR

YR

Returns the ramping speed (acceleration)

Defined as the maximum amount the rate can increase per each servo loop

Range: 0 - 3,900

XR\r

YR\r

R1000\r\n

r2000\r\n

XR#

YR#

Set the ramping speed (acceleration)

Range: 0 - 3,900

XR2000\r

YR3000\r

(none)

(none)

XP

YP

Return the Proportional coefficient of the PID control

Range: 0 - 32,767

XP\r

YP\r

P5000\r\n

P15000\r\n

XP#

YP#

Set the Proportional coefficient of the PID control

Range: 0 - 32,767

XP1234\r

YP5678\r

(none)

(none)

XI

YI

Return the Integral coefficient of the PID control

Range: 0 - 32,767

XI\r

YI\r

I2500\r\n

I2500\r\n

XI#

YI#

Set the Integral coefficient of the PID control

Range: 0 - 32,767

XI5000\r

YI5000\r

(none)

(none)

XL

YL

Return the Integral limit for PID control

Range: 0 - 24,000

XL\r

YL\r

L22000\r\n

L22000\r\n

XL#

YL#

Set the Integral limit for PID control

Range: 0 - 24,000

(NOTE - doesn’t seem to work??)

XL5000\r

YL5000\r

(none)

(none)

XD

YD

Return the Derivative for PID control

Range: 0 - 32,767

XD\r

YD\r

D4000\r\n

D4000\r\n

XD#

YD#

Set the Derivative for PID control

Range: 0 - 32,767

XD8000\r

YD8000\r

(none)

(none)

XE

YE

Return the current position error of the servo

Range: 0 - 32,767

XE\r

YE\r

E0\r\n

E0\r\n

XE#

YE#

Set the maximum position error limit before the servo turns off

Range: 0 - 32,767

XE8000\r

YE8000\r

(none)

(none)

XEL

YEL

Return the maximum position error limit

Range: 0 - 32,767

XEL\r

YEL\r

E12800\r\n

e12800\r\n

XO

YO

Return the current PWM output of the servo

Range: 0 - 255

XO\r

YO\r

O1\r\n

O1\r\n

XO#

YO#

Set the PWM output limit

Range: 0 - 255

XO100\r

YO100\r

(none)

(none)

XC

YC

Return the motor current * 100

Range: 0 - 240 (= 0.00 - 2.40 amps)

XC\r

YC\r

C3\r\n

C3\r\n

XC#

YC#

Set the motor current limit * 100

Range: 0 - 240 (= 0.00 - 2.40 amps)

XC200\r

YC200\r

(none)

(none)

XM#

YM#

Change axis to Manual mode and set the PWM output to the specified value

Range: -255 to 255

XM100\r

YM100\r

(none)

(none)

XA

YA

Change axis to Auto mode

XA\r

YA\r

(none)

(none)

XN

YN

Normal stop -- ramps down, then stops.

Automatically clears when new position is given.

XN\r

YN\r

(none)

(none)

XNT

YNT

Normal stop, transitioning to Drag and Track or Slew and Track mode once the speed is slow enough

XNT\r

YNT\r

(none)

(none)

XG

YG

Emergency stop (stops immediately)

XG\r

YG\r

(none)

(none)

XB

YB

Return the current XBits (or YBits) value

XB\r

YB\r

B107\r\n

b0\r\n

XB#

YB#

Set the current XBits (or YBits) value

XB107\r

YB1\r

(none)

(none)

XZ

YZ

Return the current scope encoder position

Range: -2,147,483,648 to +2,147,483,647

XZ\r

YZ\r

Z0\r\n

z0\r\n

XZ#

YZ#

Reset the current scope encoder position to the supplied value

Range: -2,147,483,648 to +2,147,483,647

XZ-10000\r

YZ15000\r

(none)

(none)

The following  commands affect both servos, and only have an X command

(no Y command variant):

Cmd

Description

Sample requests

Sample responses

XK

Return the handpaddle button status in decimal

XK\r

K0\r\n

XH

Return the temperature of the CPU, in degrees F

XH\r

H81\r\n

XV

Return the firmware version * 10

e.g. 31 = version 3.1

XV\r

V37\r\n

XJ

Return the motor power supply voltage * 10

e.g. 121 = 12.1 volts

XJ\r

J121\r\n

XY

Return the current CPU clock, in milliseconds

Range: -2,147,483,648 to 2,147,483,647

XY\r

Y123456\r\n

XY#

Set the current CPU clock, in milliseconds

Range: 0 to 4,294,967,295

(does not accept negative numbers)

XY1234567\r

(none)

XQ

Reset/reboot the servo system (both axes)

XQ\r

(none)

XU

Program factory defaults into flash ROM

XU\r

XW

Save the configuration currently in working RAM to the flash ROM (both axes)

XW\r

XT

Read the configuration from the flash ROM into working RAM

XT\r

FC

Flash Configure. 128 bytes should follow this command, plus 2 bytes of checksum (simple addition of the 128 bytes). This configuration will be written to Flash, and read into working RAM.

FC\r

SC

Send Configuration. The controller sends 128 bytes, followed by two bytes of checksum (simple addition of the 128 bytes). This data represents the contents of flash ROM (but not necessarily the contents of working RAM). See “Send Configuration Layout” table for more info.

SC\r

[128 bytes of binary data plus 2 byte checksum]

YV

Get Serial Number

YV\r

S56245\r\n

XX Extended read/write commands:

Cmd

Description

Sample requests

Sample responses

XXL

XXL#

Get/Set the latitude

4500 = 45 degrees north

-4500 = 45 degrees south

XXL\r

XXL1000\r

L-4500\r\n

(none)

XXT

XXT#

Get/Set the X (Altitude) scope encoder ticks per revolution

XXT\r

XXT1234\r

T14351984\r\n

(none)

XXZ

XXZ#

Get/Set the Y (Azimuth) scope encoder ticks per revolution

XXZ\r

XXZ14352714\r

Z14352714\r\n

(none)

XXU

XXU#

Get/Set the X (Altitude) motor encoder ticks per revolution

XXU\r

XXU1234\r

U28307692\r\n

(none)

XXV

XXV#

Get/Set the Y (Azimuth) motor encoder ticks per revolution

XXV\r

XXV1234\r

V28307692\r\n

(none)

XXA

XXA#

Get/Set the X (Altitude) Slew Rate.

See “Note about SlewRate and GuideRate”

XXA\r

XXA1234\r

A7256252\r\n

(none)

XXB

XXB#

Get/Set the Y (Azimuth) Slew Rate

See “Note about SlewRate and GuideRate”

XXB

XXB1234\r

B7256252\r\n

(none)

XXC

XXC#

Get/Set the X (Altitude) Pan Rate

XXC\r

XXC1234\r

C219886\r\n

(none)

XXD

XXD#

Get/Set the Y (Azimuth) Pan Rate

XXD\r

XXD1234\r

D219886\r\n

(none)

XXE

XXE#

Get/Set the Platform tracking rate

XXE\r

XXE1234\r

E11025\r\n

(none)

XXF

XXF#

Get/Set the Platform up/down adjuster

XXF\r

XXF1234\r

F200\r\n

(none)

XXG

XXG#

Get/Set the Platform Goal

XXG\r

XXG1234\r

G10000000\r\n

(none)

XXH

XXH#

Get/Set the X (Altitude) Guide Rate

See “Note about SlewRate and GuideRate”

XXH\r

XXH1234\r

H5131\r\n

(none)

XXI

XXI#

Get/Set the Y (Azimuth) Guide Rate

See “Note about SlewRate and GuideRate”

XXI\r

XXI1234\r

I5131\r\n

(none)

XXJ

XXJ#

Get/Set the PicServo timeout value, in seconds. More recently, sets whether RA PEC Auto Sync is enabled (value = 1) or disabled (value = 0).

XXJ\r

XXJ1\r

J1\r\n

(none)

XXQ

XXQ#

Get/Set digital outputs on the radio handpad receiver

XXQ\r

XXQ1\r

Q0\r\n

(none)

XXN

XXN#

Get/Set Argo Navis mode

1 = Argo Navis mode, 0 = Off

XXN\r

XXN1\r

N0\r\n

(none)

XXK

XXK#

Get/Set X (Altitude) local search distance

(version 1.6 and later)

XXK\r

XXK1\r

K0\r\n

(none)

XXM

XXM#

Get/Set Y (Azimuth) local search distance

(version 1.6 and later)

XXM\r

XXM1\r

M0\r\n

(none)

XXO

XXO#

Get/Set X (Altitude) backlash

(version 1.6 and later)

XXO\r

XXO1\r

O0\r\n

(none)

XXP

XXP#

Get/Set Y (Azimuth) backlash

(version 1.6 and later)

XXP\r

XXP1\r

P0\r\n

(none)

YX Extended read/write commands (for PEC control):

Cmd

Description

Sample requests

Sample responses

YXA

YXA#

Get/Set Y (Azm/RA) ticks per worm rev

YXA\r

YXA40000\r

A36000\r\n

(none)

YXB

YXB#

Get/Set X (Alt/Dec) ticks per worm rev

(not yet implemented)

YXC

Start reading Y (Azm/RA) PEC table.

Responses are in the form:

  YXE,[index],[value]\r\n

where [index] increases from 0 thru 255, and [value] is the offset at that PEC index.

After first response, send 255 more ‘\r’ characters to retrieve each remaining table entry. Sending any character aborts the loop (without response), and after the final ‘\r’ the controller goes back to responding normally.

YXC\r

\r

\r

\r

YXE,0,-6\r\n

YXE,1,-8\r\n

YXE,2,-10\r\n

YXE,255,-3\r\n

YXD

Start reading X (Alt/Dec) PEC table

(not yet implemented)

YXE

Set Y (Azm/RA) PEC table value.

Full form:

YXE,index,value

YXE,0,-10\r

(none)

YXF

Set X (Alt/Dec) PEC table value

(not yet implemented)

YXG

Save current PEC table for Y (Azm/RA) axis to Flash

YXG\r

G\n

YXH

Save current PEC table for Y (Azm/RA) axis to Flash

(not yet implemented)

YXI

Arm PEC Record using manual PEC sync

YXI\r

I\n

YXJ

???

YXJ\r

J\n

YXK

Arm PEC Playback

YXK\r

K\n

YXL

Arm PEC Record using auto PEC sync

YXL\r

L\n

YXM

Clear PEC table

YXM\r

M\n

YXN

???

YXN\r

N\n

YXO

???

YXO\r

O0\r\n

YXP

???

YXP\r

P0\r\n

YXQ

???

YXQ\r

Q0\r\n

YXR

Binary motion request (see below)

YXR\r

(none)

Definition of XBits and YBits

XBits is for the X axis

YBits is for the Y axis

Bit

Definition

0

If 1, the motor encoder is incremented in the opposite direction

1

If 1, the motor polarity is reversed

2

If 1, the axis encoder is reversed

3

(XBits) If 1, we are in computerless Drag and Track mode

(YBits) If 1, we are in computerless Slew and Track mode (no clutches; use handpad to slew; must be in Drag and Track mode too)

4

(XBits) If 1, we are in the tracking platform mode

(YBits) Digital input from radio handpad receiver, or RA PEC Sensor sync

5

(XBits) If 1, hand paddle is enabled

(YBits) Digital input from radio handpad receiver

6

(XBits) If 1, hand paddle is compatible with New hand paddle, which allows slewing in two directions and guiding

(YBits) Digital input from radio handpad receiver

7

(XBits) If 1, we are in guide mode. The pan rate is added or subtracted from the current tracking rate

(YBits) Digital input from radio handpad receiver

Note about the Guide Mode: If PC software puts the controller in the guide mode, and you are controlling an Equatorial mount, you must give the declination motor a destination, even if you want it to be stopped.  If you want the declination axis to be normally stopped, give the declination a far far away goal, and set the speed to zero.  This is because the controller adds or subtracts from the current speed and direction, and the controller gets confused if the axis is at its destination.  This is changed in servo version 1.6, and this is automatically done for you in the controller.

Note about SlewRate and GuideRate

SiTechExe flips SlewRate and GuideRate to negative values to indicate that the mount is “through the pole” (e.g. beyond zenith in an Alt-Az, or through the celestial pole on a GEM) and the handpad directions should be inverted.

Send Configuration binary layout

# All fields LSB first unless otherwise noted

0 0 0 0 # Alt/Dec Default Acceleration

0 0 0 0 # Alt/Dec Backlash

0 0 # Alt/Dec Error Limit

0 0 # Alt/Dec Proportional Gain

0 0 # Alt/Dec Integral Gain

0 0 # Alt/Dec Derivative Gain

0 0 # Alt/Dec Output Limit, 0xFF = 100.0

0 0 # Alt/Dec Current Limit * 100

0 0 # Alt/Dec Integral Limit

0 # XBits

FF # Unused / Padding??

0 0 0 0 # Azm/RA Default Acceleration

0 0 0 0 # Azm/RA Backlash

0 0 # Azm/RA Error Limit

0 0 # Azm/RA Proportional Gain

0 0 # Azm/RA Integral Gain

0 0 # Azm/RA Derivative Gain

0 0 # Azm/RA Output Limit, 0xFF = 100.0

0 0 # Azm/RA Current Limit * 100

0 0 # Azm/RA Integral Limit

0 # YBits

FF # Unused / Padding??

0 # Address

FF # Unused / padding??

0 0 0 0 # Equatorial Rate

0 0 0 0 # Equatorial UpDown adjust

0 0 0 0 # Tracking Platform Goal

0 0 # Latitude * 100, MSB FIRST!!

0 0 0 0 # Azm Scope Encoder Ticks Per Rev, MSB FIRST!!

0 0 0 0 # Alt Scope Encoder Ticks Per Rev, MSB FIRST!!

0 0 0 0 # Azm Motor Ticks Per Rev, MSB FIRST!!

0 0 0 0 # Alt Motor Ticks Per Rev, MSB FIRST!!

0 0 0 0 # Alt/Dec Slew Rate

0 0 0 0 # Azm/RA Slew Rate

0 0 0 0 # Alt/Dec Pan Rate

0 0 0 0 # Azm/RA Pan Rate

0 0 0 0 # Alt/Dec Guide Rate

0 0 0 0 # Azm/RA Guide Rate

FF # R/A PEC Auto Sync Enable (if low bit = 1), or PicServo Comm Timeout??

FF # Unused / Padding??

FF # Baud Rate??

FF # Unused / Padding??

0 # 1 = Enable Argo Navis, 2 = Enable Sky Commander

FF # Unused / Padding??

0 0 0 0 # Local Search Degrees * 100

0 0 0 0 # Local Search Speed, arcsec per sec

0 0 0 0 # Backlash speed

0 0 0 0 # RA/Azm PEC Ticks

FF # Unused / Padding??

FF # Unused / Padding??

Definition of Reported Motor Position

The motor position reported by (for example) the YXR command needs a bit of explanation. Each axis has a motor setpoint, which is the position where the controller wants the motor to be at a given instant. The difference between the actual motor encoder position and the setpoint is the error, provided by the XE and YE commands.

If the position error is less than 7 ticks, the reported “motor position” is actually the motor setpoint. If the position error is more than 7 ticks, the reported position is the actual current encoder position of the motor. The plot below shows the motor position (in red) and position error (in blue) when trying to move 1 tick per second back and forth with P, I, and D set to 0. Notice that the motor position appears to increase at first (even though it is physically not moving), and then jumps back to 0 (the actual position) when the error gets too large. It also switches back to reporting the setpoint when the error drops down again.

As another example, if the motor is stopped (but still in Auto mode) and an external force is applied to the motor, the reported position and error changes as follows:

Notice that the reported motor position remains 0 (the setpoint) until the motor has been forced out of position by more than 7 counts.

In pseudocode, the behavior seems to be as follows:

error = motor_encoder_position - motor_setpoint

if abs(error) <= 7:

    motor_reported_position = motor_setpoint

else:

    motor_reported_position = motor_encoder_position

Or, from the point of view of a client who wants to retrieve the actual motor position:

if abs(error) <= 7:

    motor_encoder_position = motor_reported_position + error

else:

    motor_encoder_position = motor_reported_position

This has been tested on firmwares V89 and V94.

Tangent Protocol Emulation

When the controller receives a 'Q' as the first character in a line, it responds emulating the Tangent “Q” protocol.  The encoder resolution is always 18000 (the controller uses the configured values for encoder ticks per revolution for the Scope Encoders, and converts it to 18000).

PicServo Emulation

0AAh Puts the servo into the PicServo Emulation mode (no CR required).  See http://www.jrkerr.com/psdata.pdf for a description.  There are some items different, all motion control is the same.  The differences are descibed below.

Binary commands

The controller supports a few ASCII commands that combine with binary data to allow reading and controlling the servo in a very efficient manner.

When packing binary data, all multi-byte values (ints and longs) are encoded LSB first. For example:

        12,345,678 = 0x00BC614E = [0x4E, 0x61, 0xBC, 0x00]

Checksums are calculated as the 16-bit sum of the bytes in the binary payload (not including the checksum bytes themselves), with the high-order byte inverted. The low-order byte comes first in the data stream. For example, the (artificially short) payload:

        [0xAA, 0xBB, 0xCC, 0xDD]

would have a checksum of:

        0xAA + 0xBB + 0xCC + 0xDD = 0x030E

        0x030E ^ 0xFF00 = 0xFC0E

        LSB first = [0x0E, 0xFC]

Cmd

Description

XXS\r

Controller responds with 41 bytes (as of firmware 3.6C) of status info

XXR\r

Sets some parameters, encoded as 21 bytes of binary data following the ASCII command. Response is the same as XXS

YXR\r

Sets some parameters, encoded as 34 bytes of binary data following the ASCII command. Response is the same as XXS

XXS / XXR / YXR Response Format

Bytes

Description

0

0xA8 + controller address (1, 3, or 5)

1 - 4

Alt/Dec motor position (LSB first)

5 - 8

Az/RA motor position (LSB first)

9 - 12

Alt/Dec scope encoder position (LSB first)

13 - 16

Az/RA scope encoder position (LSB first)

17

Keypad status

  Bit 1: Left button pressed (0x01)

  Bit 2: Right button pressed (0x02)

  Bit 3: Up button pressed (0x04)

  Bit 4: Down button pressed (0x08)

  Bit 5: Pan mode toggled (see note below) (0x10 = 16)

  Bit 6: RTN button pressed (0x20 = 32)

  Bit 7: ESC button pressed (0x40 = 64)

  Bit 8: Any directional button pressed (since last speed command?)

SPD button note:

By holding the SPD button for > 0.25 second, you toggle the speed at which the telescope slews when using the directional buttons. You can currently toggle between 3 speeds:

  Slew mode
 Pan mode (indicated by Keypad status bit 5)

  Guide mode (indicated by XBits bit 7)

18

XBits (see XBits table for description)

19

YBits (see YBits table for description)

20

ExtraBits

  Bit 1: If set, X axis is stopped

  Bit 2: If set, X axis is in Manual (blinking?) mode

  Bit 3: Digital In 0 (RA/Azm Home Mask). Different from DigIn0 on YBits

  Bit 4: Digital In 1 (Dec/Alt Home Mask). Different from DigIn1 on YBits

  Bit 5: If set, Y axis is stopped

  Bit 6: If set, Y axis is in Manual (blinking?) mode

  Bit 7: Y PEC Recording

  Bit 8: Y PEC Playing

21 - 22

Analog input 1

23 - 24

Analog input 2

25 - 28

Millisecond clock

29

Temperature, Degs F (may be changed to Alt/Dec Worm Phase)

30

Az/RA Worm Phase

31-34

Alt/Dec motor location at last Alt/Dec scope encoder location change

35-38

Az/RA motor location at last Az/RA scope encoder location change

39

Checksum (low byte)

40

Checksum (inverted high byte)

Sample XXS / XXR / YXR response

A9                         ; A8 + controller address

1D 5C 00 00                 ; Alt/Dec motor position: 23,581

5E 67 04 00                 ; Az/RA motor position: 288,606

00 00 00 00                ; Alt/Dec encoder location: 0

1D 19 00 00                ; Az/RA encoder location: 6,429

00                         ; Keypad status: 0

60                        ; XBits

0                         ; YBits

80                        ; Various bits

0                         ; Analog input 1: 0

0                         ; Analog input 2: 0

5E 96 0E 00                 ; Millisecond Clock: 955,998

50                         ; Temperature in degrees F: 80 (may change to Alt/Dec Worm Phase)

99                         ; Az/RA Worm phase (0-255): 153 (153/256 = 59.7 percent)

00 00 00 00                 ; Alt/Dec motor location at last Alt/Dec encoder location change

2D 67 04 00                 ; Az/RA motor location at last Az/RA encoder location change

84 FA                         ; Checksum (= (A9 + 1D + … + 67 + 04 + 00) ^ 0xFF00, LSB first)

XXR Request Format

The following 21 bytes follow the XXR\r ASCII command (which may have included an ASCII checksum if ACS mode is enabled)

Bytes

Description

0 - 3

Alt/Dec motor destination, in motor counts

4 - 7

Alt/Dec speed, in counts per servo loop (see “About speeds and rates”)

8 - 11

Az/RA motor destination, in motor counts

12 - 15

Az/RA motor speed, in counts per servo loop (see “About speeds and rates”)

16

If bit 0 is set, use the following XBits and YBits values. If not set, ignore.

17

XBits (ignored if Byte 16 bit 0 is 0)

18

YBits (ignored if Byte 16 bit 0 is 0)

19

Checksum (low byte)

20

Checksum (inverted high byte)

YXR Request Format

The following 34 bytes follow the YXR\r ASCII command (which may have included an ASCII checksum if ACS mode is enabled)

Bytes

Description

0 - 3

Alt/Dec motor destination, in motor counts

4 - 7

Alt/Dec speed (base rate), in counts per servo loop (see “About speeds and rates”)

8 - 11

Az/RA motor destination, in motor counts

12 - 15

Az/RA speed (base rate), in counts per servo loop (see “About speeds and rates”)

16 - 19

Alt/Dec Rate Adder (see “About base rates and rate adders”)

20 - 23

Az/RA Rate Adder

24 - 27

Alt/Dec Rate Adder time (in servo loops; 1953 would be 1 second)

28 - 31

Az/RA Rate Adder time (in servo loops; 1953 would be 1 second)

32

Checksum (low byte)

33

Checksum (inverted high byte)

About base rates and rate adders

The Rate Adder is added to the base rate for the number of servo loops specified.  For instance if the base rate is 2000 and the rate adder is -2100, then the rate will be -100 for 66 servo loops.  This in effect will change the direction of the motor for 66 servo loops.  Note that in SiTechExe, the total rate is truncated to 0 so it never actually changes motor directions, because, if the controller has backlash enabled, it will toggle back and forth.

Known bugs with YXR commands

RateAdderTime never expires: fixed in V89

Prior to firmware V89, the Rate Adder time appears to be ignored, and both the base rate and rate adder will be applied indefinitely.

All motion stops on Y axis when RateAdderTime expires: fixed in V94

With firmware V89, there have been cases where the controller stops all motion on an axis (both base rate and rate adder) when a non-zero Rate Adder time expires. If the Rate Adder time is 0, then the Base Rate applies indefinitely. It is not yet known how the controller enters this state, but it likely applies to controllers prior to V94.

The problem usually manifests when homing the telescope. SiTechExe reports “Slewing First Slew” but the axis does not move. In contrast to tracking and directional controls (which continuously send new commands at intervals roughly equal to the RateAdderTime), the Home command sends a single command to send the axis towards the home sensor transition point. When the RateAdderTime on that command expires (normally 60-80 msec later), the axis stops.

This problem may also result in the tracking error spikes seen below. This could happen if the RateAdderTime expires just before the next command is sent, causing the axis to briefly fall behind.

Only the Y axis seems to be affected by this bug. When the bug occurs, a negative rate is returned by the YS command. (Normally YS returns the absolute value of the currently applied rate.)

Wrong rate applied when RateAdderTime Expires: fixed in V94b

In cases where BaseRate+RateAdder is negative, an incorrect rate will take effect when RateAdderTime expires.

Sample YXY Request (in ACS mode)

59 58 52 0D                ; YXY\r

EF                         ; ASCII Checksum: 239  = ~(0x59 + 0x58 + 0x52 + 0x0D) & 0xFF

F7 25 CF FF                 ; Alt/Dec destination: -3,201,545

D0 07 00 00                 ; Alt/Dec base rate: 2,000

0B CF BA 58                 ; Az/RA destination: 1,488,637,707

EB 15 00 00                 ; Az/RA base rate: 5,611

00 00 00 00                 ; Alt/Dec rate adder: 0

16 EA FF FF                 ; Az/RA rate adder: -5,610

42 00 00 00                 ; Alt/Dec rate adder in effect for 66 servo loops

42 00 00 00                 ; Az/RA rate adder in effect for 66 servo loops

2F                         ; Checksum (low byte)

F5                         ; Checksum (high byte, inverted)

Note that the checksum is calculated as:

        F7 + 25 + CF + … +42 + 00 + 00 + 00 = 2607 = 0x0A2F

        0x0A2F ^ 0xFF00 = 0xF52F

        swap(0xF52F) = 2F, F5

Resyncing after communication error

If you use the above binary command to control the servo controller, be sure to have a way to restart communication if the command gets out of sync by a communication fault.  If you receive a bad checksum, you should resync communication by sending a few of XXS commands.

Various communication stream details

In non-ACS mode, a standalone carriage return generates a one-line status:

   \r → (one line status)

and a command followed by a carriage return generates an appropriate response:

   YXY\r → Y0\r\n

It seems that any non-uppercase characters are ignored, so this still generates a valid response:

   aaaYbbbXcccYddd\r → Y0\r

More generally, it seems that all characters are thrown away except for:

        A-Z

        0-9

        :;<=>?@,-

Also, the input buffer on the controller seems to take the first 3 uppercase letters, and will ignore anything after that (up until the final \r) unless a numeric argument follows. For example:

   XXL\r → L4300\r\n           # get latitude

   XXLASDF\r → L4300\r\n   # interpreted as XXL\r

   XXL-1000\r → (none)

   XXL\r → L-1000\r\n

   XXLASDF2000\r → L-1000\r\n  # interpreted as XXL\r

Suppose the controller’s ACS state is unknown. Is it safe to always send a checksum even if it is not needed? NO, not in general. For example, “XA\rY” has a checksum byte ‘Y’. If you were to send two back-to-back XA commands:

XA\rYXA\rY

the second command would be interpreted as “YXA” instead!

However, it is ok to send YXY\r\xe8 (Get ACS mode, with checksum appended) in either ACS or non-ACS mode since the \xe8 character will be ignored in non-ACS mode. Of course, this may not work if you are in the middle of sending an XXR or YXR payload, or if you are in the middle of receiving a PEC table (the first non-\r character will abort the table command/response loop), so you may need to send some extra bytes first to re-sync the command stream.

Note that it is possible to send commands to quickly if you don’t do strict request/response alternation. For example:

   X\r → X-1202663\r\n   # get X motor position

   X\rX\r → X-1202663\r\n  # second command was dropped

   X\rX\rX\rX\rX\rX\rX\r → X-1202663\r\nX-1202663\r\n   # only 2 of 7 responses

In ACS mode, "end of command" is signified by "\r" plus one byte. So:

X\r\rX\r\x9A -> X0\r\n

The first X\r would be a "return short status" command, but the second \r is treated as an invalid checksum. At this point we start with a fresh slate. X\r\x9A has a valid checksum, and returns the position of the X axis

Flash RAM and ROM

The flash RAM values are loaded from the flash ROM to RAM on reset. Both the X and Y parameters are stored to the flash ROM.

Accessing other SiTech modules

Use X and Y for module address 1.  

If the module address is 3, use 'T' and 'U', for address 5, it's 'V' and 'W'.

Conditions for entering Manual (“blinky”) mode

XEL / YEL / XE# / YE# can be used to get/set the error threshold, but these are only applied if the motor is moving “fast enough”.

According to Dan Gray:

The ServoII firmware will keep a motor moving if it’s already moving fast enough, and in the proper direction, and it will hold the error at the error limit. The threshold for this is 6 ticks in 1/1953 of a second… that is, if the motor has moved more than 6 ticks in the past ~512 usec, it will not trip. (This corresponds to an average speed of 11718 ticks/sec)

Also, if the output goes high for a long period of time, but the motor does not move, then it is sensing a jam up and will go to manual.

Kevin’s pseudocode interpretation (assuming X axis and positive movement):

NewSetpoint = [calculation based on destination, current speed, max speed, acceleration]

MaxError = [output of XEL command]

CurrentError = SetPoint - CurrentPosition // Tends to peak near MaxError if moving fast enough

if ([Movement in last 512 usec] > 6 ticks) {

        // Advance setpoint no more than MaxError ticks away

        SetPoint = Min(CurrentPosition + MaxError, NewSetpoint);

}

else if (CurrentError > MaxError) {

        [Go to Manual/Blinky Mode]

}

else if (PWM output > 127 for more than 2 seconds) {

        [Go to Manual/Blinky Mode]

}

Servo II Communication Behavior when Powered Off

When the Servo II controller is connected to the computer via USB but the unit itself is powered off, it is possible to get garbage data back from the controller (perhaps because the serial pins are floating internally). For example, sending \r\n might result in the following response (including pin change events):

SerialPinChange: CTS → True

SerialPinChange: Break

SerialPinChange: Break

SerialPinChange: CTS → False

SerialPinChange: DSR

SerialPinChange: CD

SerialPinChange: Ring

RECV: 00

Firmware version history from Dan Gray

http://siderealtechnology.com/V81A.BIN

http://siderealtechnology.com/V83.BIN

http://siderealtechnology.com/V84.BIN

http://siderealtechnology.com/V84.BIN

http://siderealtechnology.com/V86A.BIN

http://siderealtechnology.com/V86B.BIN

http://siderealtechnology.com/V87.BIN

http://siderealtechnology.com/V88.BIN

http://siderealtechnology.com/V89.BIN

http://siderealtechnology.com/V90.BIN

http://siderealtechnology.com/V91.BIN

http://siderealtechnology.com/V92.BIN

http://siderealtechnology.com/V93.BIN

http://siderealtechnology.com/V94.BIN

;Version History

;******************************

;Version 9.4

;Again worked with Kevin Ivarsen to fix the Rate Adders, so offset works properly.

;He even figured out the code, all I had to do was re-compile!

;

;Version 9.3

;added the BiSS Interface

;made the routine ResetCPU: really reset the cpu.  (added the load sfrpage, #0 instruction)

;Version 9.2

;Added flash safety, with block 0 copy, and block checksums.

;Version 9.1

;PEC only collects data when guide buttons are pressed.

;Version 9.0:

;Made safety provisions for CEMF.

;moved pwm frequency to 15KHz (TH0 = E8 instead of E0)

;Version 8.9:

;increased the tracking settings for runaway on bad encoder settings.  

;This started at the yerkes telescope. THat one was increased to maximum almost.

;Checked that the offset tracking rates actually stop.  Kevin I. noticed this.

;Fixed the problem, it was in IFZERODptr

;Version 8.8:

;added the voltage stabilized detection on startup, so if you spin the servomotors,

          ;and they backfeed into the controller, it won't erase the flash.

;******************************

;8.7:

; Fixed bug in using CalcNewOffsetYScpEnc instead of CalcNewOffsetXScpEnc, so forcing the X scope encoder forced Y instead.

;******************************

;8.6B:

;in

//          lcall UpdateAzMultiplier  Taken out in 8.6B

;Version 8.6

;fixed the FC function in interpret

;fixed the disable / enable the wrong interrupt when using the non-usb serial port (interpret)

;******************************

;Version 8.5

;hardened for flash erases

;******************************

;Version 8.3

;Added Load PSBank from Loader, to make sure in bottom code space 32K block.

;******************************

;Version 8.1:

;Added longer delay for the encoder chips to initialize.

;Added 2nd serial port

;******************************