David's Astronomy Pages
Notes - Session 601.2 (2017-02-07)

2017-02-07
Bullet Automated Guiding
Bullet PHD2 Connection and Control
Bullet PHD2 Methods
Bullet SharpCap Connection and Control
 
Bullet Images from 2017-01-23 >>

Automated Guiding

The addition of new equipment (TS 80mm APO scope and ZWO ASI178MC camera) at the start of 2017 brings three new  autoguiding possibilities:

G1) Use new TS 80mm APO + ZWO ASI178MC to guide existing 12" LX200 + ST-10XME
G2) Use existing 12" LX200 + ST-10XME to guide new TS 80mm APO + ZWO ASI178MC
G3) Use existing 12" LX200 + ST-10XME to guide Canon EOS Lens + ZWO ASI178MC

Note: For the purposes of this current discussion G2 and G3 can be considered to be equivalent.

Each of these setups brings the opportunity to produce images with sharper stars and longer exposure, a reduction in number of 'bad frames', and reduce/eliminate drift between frames (removing need to crop images to the area with full stacking).

Whilst manual intervention can obviously be used to initiate autoguiding and then start imaging there is a benefit from being able to fully automate the aquisition of a sequence of targets.  My existing Program (CCDApp2) already has target/image sequence control for slewing existing LX200 mount, for target centering and for taking images with SBIG ST-10XME camera.   But to provide the required control for the two cameras and the new guiding opportunities new code/subroutines are required.

G1) Guiding with TS 80mm APO + ZWO ASI178MC (using PHD2)

- Use OpenPHD / Event Monitoring to connect to PHD2 to control guiding operations and to actively monitor guiding status
  More on PHD2 Event Monitoring (https://github.com/OpenPHDGuiding/phd2/wiki/EventMonitoring)

- Add user option to specify the use PHD2 Guiding using Secondary Camera/GuideScope
- Add function to open PHD2 Guiding software from Main Control software
- Add function to open a TCP Client Connection to PHD2 Server on Port 4400
- Add function(s) to initiate PHD2 Guiding for each target, including Begin Looping, Auto-Select Star, Begin Guiding
- Add function(s) / display for summarising Guiding statistics
- Add function to stop PHD2 Looping/Guiding

OpenPHD / Event Monitoring can be used to connect to PHD2 to control the guiding operation and to actively monitor guiding status
More on PHD2 Event Monitoring (https://github.com/OpenPHDGuiding/phd2/wiki/EventMonitoring)

Detailed description of these new functions is contained in later section "PHD2 Connection and Control"

G2) Guiding with 12" LX200 APO + ST-10XME (using CCDSoft). Imaging using ZWO ASI178MC

- Use CCDSoft to autoguide mount using ST-10XME's Imager (i.e. the larger 'Imager' CCD rather than the small 'Autoguider' CCD)
- Add new 'Job' type and associated functionality that
   - slews to target (or continues on same target)
   - commences autoguiding using ST-10XME
   - triggers Image Capturing software to commence image capture using ZWO ASI178MC camera
- Modify existing guiding function(s) to utilise ST-10XME's Imager CCD
- Use SharpCap for taking images with ZWO ASI178MC, utilising scripts where possible.

SharpCap has a Scripting Object Model than can be accessed via Python scripts executed by SharpCap's IronPython Console.
This provides the opportunity for providing a certain level of automated control on image capture in SharpCap using ZWO ASI178MC camera.   The User may or may not be needed to be present to intervene at some points to perform to certain manual actions (e.g. starting Live Stacking).   More on SharpCap Scripting (http://www.sharpcap.co.uk/sharpcap/sharpcap-scripting).

Detailed description of these new functions is contained in later section "SharpCap Connection and Control"

Back to Top


PHD2 Connection and Control

OpenPHD / Event Monitoring can be used to connect to PHD2 to control the guiding operation and to actively monitor guiding status.
from a third party program.  Some details on Connection, Event Notification Messages and Server Method Invocation is given at PHD2 Event Monitoring (https://github.com/OpenPHDGuiding/phd2/wiki/EventMonitoring), but a degree of trial and error was required to create methods/functions that provided the level of control required.

Clients connect to PHD on TCP port 4400.  Messages sent to/from the PHD2 server are formatted as JSON objects. Each message is a single line of text terminated by CR LF , with a format like
 {"method": "guide", "params": [{"pixels": 1.5, "time": 8, "timeout": 40}, false], "id": 42}

Whilst there are libraries/source code for reading/writing JSON objects, I've elected so far to use fit for purpose methods for reading/writing the particular messages required.

The following VB.Net Code illustrates the key functionality that I've added to my Observatory Control Software for controlling PHD2.    The code refers to certain routines/variables (e.g. AddComment, ReportComment) that aren't included here, however there is enough information given for another programmer to gain a reasonable idea on how they might incorporate PHD2 control into their own software.   The output generated by an example session is also shown.

 

classPhd2 (New Class for PHD2 control)

Imports System.Net.Sockets
Imports System.IO
Imports System.Net
Imports System.Text

Public Phd2 As New classPhd2
Public PHD2GuidingMonitorFlag as boolean

Public Class classPhd2

  Dim Phd2Socket As TcpClient
  Dim Phd2ServerStream As NetworkStream

  Dim ServerAddress As String = "127.0.0.1" ' Set the IP address of the server to local machine
  Dim PortNumber As Integer = 4400 ' Set the port number used by the server

  Dim Connected As Boolean ' flag indicating if we're connected to PHD2 or not
  Dim Phd2SocketOpen As Boolean
  Dim IdNum As Integer
 
  Sub SendRequest()...
  Sub GetMessage()...
  Sub ParseResponse()...
 
Sub ConnectPHD2()...
  Sub StartPHD2Guiding()...
  Sub WaitForGuidingToSettle()...

End Class

Sub StartPHD2GuidingMonitor()...
Sub RunPHD2GuidingMonitor()...
Sub StopPHD2GuidingMonitor()...

SendRequest  (Sends request to Invocate a PHD2 Method)

Sub SendRequest _
    (ByVal Request As String, _
     ByRef Response As String, _
     ByVal RequiredItem As String, _
     ByRef Result As String)

 
  IdNum = IdNum + 1
  Request = Request.Replace("#ID", CStr(IdNum))

  LogFile.WriteLine(">> Request=" + Request)        ' debugging

  Dim data As [Byte]() = System.Text.Encoding.ASCII.GetBytes(Request + vbCrLf)

  GetMessage(Response)
  Phd2ServerStream.Write(data, 0, data.Length)
  Sleep(0.5)

  GetMessage(Response)
  LogFile.WriteLine("<< Len = " + CStr(Len(Response)))  ' debugging
  LogFile.WriteLine("<< Message In=" + Response)        ' debugging

  ParseResponse(Response, RequiredItem, Result)
End Sub
 

GetMessage (Fetches Message or Response from PHD2 Server)

Sub GetMessage (ByRef Message As String)
  Dim PacketLen As Integer

  PacketLen = Phd2Socket.Available
  If PacketLen > 0 Then
    Dim bytes(PacketLen) As Byte
    Phd2ServerStream.Read(bytes, 0, CInt(PacketLen))
    Message = Encoding.ASCII.GetString(bytes)
  Else
    Message = ""
  End If
End Sub

ParseResponse (Parses a Response from PHD2 Server and extracts the principle result)

Sub ParseResponse _
    (ByVal Response As String, _
     ByVal RequiredItem As String, _
     ByRef Result As String)


  Dim j1
  Dim S As String
  Dim C As Integer

  Result = ""

  j1 = Response.IndexOf("{""jsonrpc""")

  If j1 >= 0 Then
    S = Right(Response, Len(Response) - j1)

    j1 = S.IndexOf(RequiredItem)

    If j1 >= 0 Then
      j1 = j1 + Len(RequiredItem) + 2
      C = 0

      While C = 1 Or (C = 0 And S(j1) <> "," And S(j1) <> "}" And S(j1) <> "]")
        If S(j1) <> """" And S(j1) <> "[" Then
          Result = Result + S(j1)
        End If
        If S(j1) = "[" Then
          C = 1
        End If
        If S(j1) = "," Then
          C = 0
        End If
        j1 = j1 + 1
      End While
    Else
      j1 = S.IndexOf("error")
      If j1 >= 0 Then
        Result = "Error: "

        j1 = S.IndexOf("message")
        If j1 >= 0 Then
          j1 = j1 + Len("message") + 2
          While S(j1) <> "," And S(j1) <> "}"
            If S(j1) <> """" Then
              Result = Result + S(j1)
            End If

            j1 = j1 + 1
          End While
        End If
      Else
        Result = "null"
      End If
    End If
  Else
    Result = "null"
  End If
End Sub

ConnectPHD2 (Create Connection to PHD2 Server)

Sub ConnectPHD2()

  Dim T As Integer
  Dim Response As String
  Dim Result As String

  ReportComment("Connect PHD2 Guiding software")

  ' Check that PHD2 Software is running
  ' -----------------------------------
  If IsProcessRunning("phd2") = False Then

    ' Open PHD2 program since it is not already running
    OpenApplicationAndWait("PHD2", "phd2.exe", "C:\Program Files (x86)\PHDGuiding2")

    ReportComment(Tab2 + "Waiting for PHD2 to open and initialise ...")
    ReportComment("")
    Sleep(3)

    If IsProcessRunning("phd2") = False Then
      ReportComment(Tab2 + "PHD2 doesn't appear to have opened - no connection possible.")
      Connected = False
      Exit Sub
    End If
  End If

  AddComment(Tab2 + "Connecting PHD2 ...")

  T = 0
  Connected = False
  IdNum = 0

  Do While T < 15 And Connected = False
    Try
      Phd2Socket = New TcpClient

      Phd2Socket.Connect(ServerAddress, PortNumber)
      ReportComment(LAlign2("Ok", 10) + "Connected" + _
      " (IP: " + ServerAddress + " Port: " + CStr(PortNumber) + ")")
      Connected = True
    Catch ex As Exception
      Connected = False
      T = T + 1
      Sleep(1)
    End Try
  Loop

  If Connected = False Then
    ReportComment(LAlign2("Fail", 10) + "Problem connecting to PHD2 " + _
    " (IP: " + ServerAddress + " Port: " + CStr(PortNumber) + ")")
    Exit Sub

  Else
    Try
      AddComment(Tab2 + "Checking datastream ...")
      Phd2ServerStream = Phd2Socket.GetStream()
      GetMessage(Response)
      ReportComment(LAlign2("Ok", 10))

    Catch ex As Exception
      ReportComment(LAlign2("Fail", 10) + "Problem accessing datastream")
      Exit Sub
    End Try

    ' Check Profile Profile
    ' ---------------------
    AddComment(Tab2 + "- Profile")
    SendRequest("{""method"": ""get_profile"", ""id"": #ID}", Response, "name", Result)
    If Result <> "" Then
      ReportComment(LAlign2("Yes", 10) + "(" + Result + ")")
    Else
      ReportComment(LAlign2("No", 10) + "** profile is required **")
    End If

    ' Check Equipment  ' not recognised
    ' ---------------
    AddComment(Tab2 + "- Current Equipment")
    SendRequest("{""method"": ""get_current_equipment"", ""id"": #ID}", Response, "result", Result)
    ReportComment(LAlign2("-", 10)) ' + Result)

    ' Check Equipment Connection
    ' --------------------------
    AddComment(Tab2 + "- Equipment Connected")
    SendRequest("{""method"": ""get_connected"", ""id"": #ID}", Response, "result", Result)
    If Result = "true" Then
      ReportComment(LAlign2("Yes", 10))
    Else
      ReportComment(LAlign2("No", 10) + "** equipment requires connection **")
    End If

    ' Check Calibration Status
    ' -------------------------
    AddComment(Tab2 + "- Calibration")
    SendRequest("{""method"": ""get_calibrated"", ""id"": #ID}", Response, "result", Result)
    If Result = "true" Then
      ReportComment(LAlign2("Yes", 10))
    Else
      ReportComment(LAlign2("No", 10) + "** calibration is required **")
    End If

    ' Get Binning
    ' -----------
    AddComment(Tab2 + "- Binning")
    SendRequest("{""method"": ""get_camera_binning"", ""id"": #ID}", Response, "result", Result)
    ReportComment(LAlign2("Ok", 10) + Result)

    ' Get Pixel Scale
    ' ---------------
    AddComment(Tab2 + "- Pixel Scale")
    SendRequest("{""method"": ""get_pixel_scale"", ""id"": #ID}", Response, "result", Result)
    ReportComment(LAlign2("Ok", 10) + Result + " arc sec/px")

    ReportLine()
  End If
End Sub

StartPHD2Guiding (Activates autoguiding)

Sub StartPHD2Guiding()
  Dim response As String
  Dim Result As String
  Dim SNR As String
  Dim Exposure As String
  Dim Profile As String

  ' Check that we're connected to PHD2
  ' ----------------------------------
  ReportComment(Tab2 + "Activate Guidescope Guiding")

  If Phd2.Connected = False Then
    Phd2.ConnectPHD2() ' Try connecting to PHD2 if not already connected
    Sleep(1)
  End If

  AddComment(Tab2 + Tab2 + "Check Connection")
  If Phd2.Connected Then
    ' Get Profile
    ' -----------
    Phd2.SendRequest("{""method"": ""get_profile"", ""id"": #ID}", response, "name", Profile)
    ReportComment(LAlign2("Ok", 10) + "Using PHD2 (" + Profile + ")")
  Else
    ReportComment(LAlign2("Fail", 10) + "Unable to connect to PHD2")
    Exit Sub
  End If

  ' Get Exposure
  ' ------------
  SendRequest("{""method"": ""get_exposure"", ""id"": #ID}", response, "result", Exposure)

  ' Begin Looping
  ' -------------
  AddComment(Tab2 + Tab2 + "Start Looping ...")
  SendRequest("{""method"": ""loop"", ""id"": #ID}", response, "result", Result)
  If Result = "0" Then
    ReportComment(LAlign2("Ok", 10) + "Exposure " + Exposure + " ms")
  Else
    ReportComment(LAlign2("?", 10) + "Uncertain result (" + Result + ")")
  End If
  Sleep(3)


  ' Find Guide Star
  ' -------------
  AddComment(Tab2 + Tab2 + "Select Guide Star ...")
  SendRequest("{""method"": ""find_star"", ""id"": #ID}", response, "result", Result)
  ReportComment(LAlign2("Ok", 10) + Result)
  Sleep(1)

  AddComment(Tab2 + Tab2 + "Check App State ...")
  SendRequest("{""method"": ""get_app_state"", ""id"": #ID}", response, "result", Result)
  ReportComment(LAlign2("Ok", 10) + Result)

  ' Begin Guiding
  ' -------------
  AddComment(Tab2 + Tab2 + "Start Guiding ...")
  SendRequest("{""method"": ""guide"", ""params"": [{""pixels"": 1.5, ""time"": 5, _
      ""timeout"": 20}, false], ""id"": #ID}", response, "result", Result)

  If Result = "0" Then
    ReportComment(LAlign2("Ok", 10))
  Else
    ReportComment(LAlign2("?", 10) + "Uncertain result (" + Result + ")")
  End If

  ' Check Guiding
  ' -------------
  AddComment(Tab2 + Tab2 + "Review Guiding ...")
  WaitForSettleDone(Result, SNR)
  If Result = "0" Then
    ReportComment(LAlign2("Ok", 10) + "Guiding is stable, SNR " + SNR)
  Else
    ReportComment(LAlign2("Fail", 10) + Result)
  End If

  StartPHD2GuidingMonitor()
End Sub

WaitForGuidingToSettle (Wait for Guiding To Settle)

Sub WaitForGuidingToSettle(ByRef Result As String, ByRef SNR As String)
  Dim Response As String
  Dim SettleDoneFlag As Boolean
  Dim j1 As Integer

  SettleDoneFlag = False

  SNR = "---"

  Do While SettleDoneFlag = False
    GetMessage(Response)

    j1 = Response.IndexOf("GuideStep")
    If j1 >= 0 Then
      ParseEvent(Response, "SNR", SNR)
      objConsole.txtCurrentResult.Text = "Autoguiding On, SNR=" + SNR
    End If

    j1 = Response.IndexOf("SettleDone")
    If j1 >= 0 Then
      SettleDoneFlag = True
      ParseEvent(Response, "Status", Result)
    End If
  Loop

End Sub

StopPHD2Guiding (Stop Guiding)

Sub StopPHD2Guiding()
  Dim response As String
  Dim Result As String

  ' Check PHD2 App State
  ' --------------------
  SendRequest("{""method"": ""get_app_state"", ""id"": #ID}", response, "result", Result)
  LogFile.WriteLine("Checking PHD2 App State (Result=" + Result + ")")

  If Result <> "Stopped" Then
    ' Stop PHD2 Looping/Guiding
    ' -------------------------
    LogFile.WriteLine("Stopping PHD2 Looping/Guiding")
    SendRequest("{""method"": ""stop_capture"", ""id"": #ID}", response, "result", Result)
    Sleep(0.2)

    ' Recheck PHD2 App State
    ' -----------------------
    SendRequest("{""method"": ""get_app_state"", ""id"": #ID}", response, "result", Result)
    LogFile.WriteLine("Checking PHD2 App State (Result=" + Result + ")")
  End If
End Sub

 

StartPHD2GuidingMonitor (Starts Guiding Monitor)

Sub StartPHD2GuidingMonitor()
  ' Check Existing Active Thread
  ' ----------------------------
  If Not (PHD2MonitorThread Is Nothing) Then
    If PHD2MonitorThread.IsAlive Then
      MsgBox("Sorry - You can not run another job whilst one is still active")
      ScrollLogBox()
      Exit Sub
    End If
  End If

  ' Start Monitor
  ' -------------
  PHD2GuidingMonitorFlag = True
  PHD2MonitorThread = New Thread(AddressOf RunPHD2GuidingMonitor)
  PHD2MonitorThread.IsBackground = True
  PHD2MonitorThread.Start()
End Sub

RunPHD2GuidingMonitor (Guiding Monitor (Thread))

Sub RunPHD2GuidingMonitor() ' Threaded Process
  Dim Response As String
  Dim j1 As Integer
  Dim SNR As String

  SNR = "---"
  LogFile.WriteLine("Start PHD2 Guide Monitor")

  Do While PHD2GuidingMonitorFlag = True

    Phd2.GetMessage(Response)

    j1 = Response.IndexOf("GuideStep")
    If j1 >= 0 Then

      Phd2.ParseEvent(Response, "SNR", SNR)
      objConsole.txtCurrentResult.Text = "Autoguiding On, SNR=" + SNR
      LogFile.WriteLine(Response)
    End If
    Sleep(0.1)
  Loop

  ' Clean-up
  ' --------
  objConsole.txtCurrentResult.Text = ""
End Sub

StopPHD2GuidingMonitor (Stop Guiding Monitor)

Sub StopPHD2GuidingMonitor()
  LogFile.WriteLine("Stop PHD2 Guide Monitor")
  PHD2GuidingMonitorFlag = False  ' Trigger end of Monitoring
End Sub

Example Session

----------------------------------------------------------------------------------------
Connect PHD2 Guiding software
  Starting C:\Program Files (x86)\PHDGuiding2\phd2.exe ... (delay may occur)
  Waiting for PHD2 to open and initialise ...

  Connecting PHD2 ...      Ok     Connected (IP: 127.0.0.1 Port: 4400)
  Checking datastream ...  Ok
  - Profile                Yes    (Simulator)
  - Current Equipment      ??     ** method doesn't work in PHD2 2.6.2
  - Equipment Connected    No     ** equipment requires connection **
  - Calibration            No     ** calibration is required **
  - Binning                Ok     ** Error: camera not connected **
  - Pixel Scale            Ok     0.378965 arc sec/px
----------------------------------------------------------------------------------------

** User currently needed to manually Connect Equipment in PHD2, Perform/Check Calibration
   at the commencement of the session

----------------------------------------------------------------------------------------
Take Frame Jobs - Live MODE
  AutoSave Folder...             C:\Data\CCD Imaging\New\2017-02-04 TEST
  AutoSave Start Num...          10300
  Date/Time (TheSky6)... Ok      2017-02-07 16:26:32 (Local)
                                 2017-02-07 16:26:32 (UT)
  Lat/Long (TheSky6)...  Ok   
  CCD Regulation ...     Ok      Regulation is ON (Setpoint: -25.0 °C)
  Airmass Cutoff...      Ok      Airmass 3.3
  Checking Targets ...   Ok      1 targets selected
----------------------------------------------------------------------------------------
  Checking Folder Names and Parameters ...
  Reading Reference File ...
  Estimated Duration...          7.0 mins
----------------------------------------------------------------------------------------
TRI / M33 (1/1)
  Checking Airmass ...     Ok    Airmass 1.12
  Slewing ...              Ok    M33
  Checking position ...    Ok    2.0s
  Delay (1s) ...           Ok
  Checking CCD Temp...     OK    -24.8 °C
  Checking Focuser ...     OK
  Activate Guidescope Guiding
    Check Connection       Ok    Using PHD2 (Simulator)
    Start Looping ...      Ok    Exposure 1000 ms
    Select Guide Star ...  Ok    148.86,255.46
    Check App State ...    Ok    Selected
    Start Guiding ...      Ok
    Review Guiding ...     Ok    Guiding is stable, SNR 25.73

  Taking 120s image (C)... Ok    [00010300] 16:26:55 (UT) Full 3x3 120s C
  Taking 120s image (C)... Ok    [00010301] 16:27:06 (UT) Full 3x3 120s C
  Taking 120s image (C)... Ok    [00010302] 16:27:17 (UT) Full 3x3 120s C
Doing Post Job Tasks :
Operation... Completed
----------------------------------------------------------------------------------------

Currently the Guiding Monitor simply updates SNR value on the bottom of the program's console,
but in due course its function will be expanded to capture and summarise Guiding Statistics.
This is with the idea of supplementing and complementing the functions of PHD2 own monitoring
(History, Target, Guide Stats) and those of PhdLogView.

Image

Back to Top


PHD2 Methods

The table of available methods on the PHD2 Event Monitoring wiki page (https://github.com/OpenPHDGuiding/phd2/wiki/EventMonitoring) doesn't display correctly on my web browser (result and description columns are either partially or fully hidden. I've therefore redisplayed the table below in its entirety for convenience.

Method Params Result Description
capture_single_frame exposure: exposure duration milliseconds (optional), subframe: array [x,y,width,height] (optional) integer(0) captures a singe frame; guiding and looping must be stopped first
clear_calibration string: "mount" or "ao" or "both" integer (0) if parameter is omitted, will clear both mount and AO. Clearing calibration causes PHD2 to recalibrate next time guiding starts.
dither PIXELS (float), RA_ONLY (boolean), SETTLE (object) integer (0) See below
find_star none on success: returns the lock position of the selected star, otherwise returns an error object Auto-select a star
flip_calibration none integer (0)
get_algo_param_names string: axis ("ra","x","dec", or "y") array of guide algorithm param names (strings)
get_algo_param string: axis, string: name float: the value of the named parameter get the value of a guide algorithm parameter on an axis
get_app_state none string: current app state same value that came in the last AppState notification
get_calibrated none boolean: true if calibrated
get_calibration_data string: which ("AO" or "Mount") optional, default = "Mount" example output: {"calibrated":true,"xAngle":-167.1,"xRate":39.124,"xParity":"-","yAngle":106.1,"yRate":39.330,"yParity":"+"}
get_connected none boolean: true if all equipment is connected
get_cooler_status none "temperature": sensor temperature in degrees C (number), "coolerOn": boolean, "setpoint": cooler set-point temperature (number, degrees C), "power": cooler power (number, percent) returns a JSONRPC error if the camera does not have a cooler
get_current_equipment none example: {"camera":{"name":"Simulator","connected":true},"mount":{"name":"On Camera","connected":true},"aux_mount":{"name":"Simulator","connected":true},"AO":{"name":"AO-Simulator","connected":false},"rotator":{"name":"Rotator Simulator .NET (ASCOM)","connected":false}} get the devices selected in the current equipment profile
get_dec_guide_mode none string: "Off"/"Auto"/"North"/"South"
get_exposure none integer: exposure time in milliseconds
get_exposure_durations none array of integers: the list of valid exposure times in milliseconds
get_lock_position none array: [x, y] coordinates of lock position, or null if lock position is not set
get_lock_shift_enabled none boolean: true if lock shift enabled
get_lock_shift_params none example: {"enabled":true,"rate":[1.10,4.50],"units":"arcsec/hr","axes":"RA/Dec"}
get_paused none boolean: true if paused
get_pixel_scale none number: guider image scale in arc-sec/pixel.
get_profile none {"id":profile_id,"name":"profile_name"}
get_profiles none array of {"id":profile_id,"name":"profile_name"}
get_search_region none integer: search region radius
get_sensor_temperature none "temperature": sensor temperature in degrees C (number)
get_star_image integer: size (optional) frame: the frame number, width: the width of the image (pixels), height: height of the image (pixels), star_pos: the star centroid position within the image, pixels: the image data, 16 bits per pixel, row-major order, base64 encoded Returns an error if a star is not currently selected; The size parameter, if given, must be >= 15.The actual image size returned may be smaller than the requested image size (but will never be larger). The default image size is 15 pixels.
get_use_subframes none boolean:subframes_in_use
guide SETTLE (object), RECALIBRATE (boolean) integer (0) See below
guide_pulse integer: amount (pulse duration in milliseconds, or ao step count), string: direction ("N"/"S"/"E"/"W"/"Up"/"Down"/"Left"/"Right"), string (optional): which ("AO" or "Mount" [default]) integer (0) Returns an error if PHD2 is currently calibrating or guiding
loop none integer (0) start capturing, or, if guiding, stop guiding but continue capturing
save_image none {"filename":"full_path_to_FITS_image_file"} save the current image. The client should remove the file when done with it.
set_algo_param string: axis, string: name, float: value integer(0) set a guide algorithm parameter on an axis
set_connected boolean: connect integer (0) connect or disconnect all equipment
set_dec_guide_mode string: mode ("Off"/"Auto"/"North"/"South") integer(0)
set_exposure integer: exposure time in milliseconds integer (0)
set_lock_position X: float, Y: float, EXACT: boolean (optional, default = true) integer (0) When EXACT is true, the lock position is moved to the exact given coordinates. When false, the current position is moved to the given coordinates and if a guide star is in range, the lock position is set to the coordinates of the guide star.
set_lock_shift_enabled boolean: enable lock shift integer (0)
set_lock_shift_params {"rate":[XRATE,YRATE],"units":UNITS,"axes":AXES} integer (0) UNITS = "arcsec/hr" or "pixels/hr"; AXES = "RA/Dec" or "X/Y"
set_paused PAUSED: boolean, FULL: string (optional) integer (0) When setting paused to true, an optional second parameter with value "full" can be provided to fully pause phd, including pausing looping exposures. Otherwise, exposures continue to loop, and only guide output is paused. Example: {"method":"set_paused","params":[true,"full"],"id":42}
set_profile integer: profile id integer (0) Select an equipment profile. All equipment must be disconnected before switching profiles.
shutdown integer (0) Close PHD2
stop_capture none integer (0) Stop capturing (and stop guiding)

 

Back to Top


SharpCap Connection and Control

SharpCap has a Scripting Object Model than can be accessed via Python scripts executed by SharpCap's IronPython Console.
This provides the opportunity for providing a certain level of automated control on image capture in SharpCap using ZWO ASI178MC camera.   The User may or may not be needed to be present to intervene at some points to perform certain manual actions (e.g. starting Live Stacking).   More on SharpCap Scripting (http://www.sharpcap.co.uk/sharpcap/sharpcap-scripting).

The requirements for the Python Script are as follows


Python commands like 'dir(SharpCap)', 'dir(SharpCap.SelectedCamera)' were used to dig into the SharpCap object model in an attempt to identify methods and properties. Applying the results involved a bit of trial and error. 

Eventually a server script was built.  Once started the script opens Port 4000 (localhost), and waits/listens for a connection from the CCDApp2 program running on the same machine. After connection is made the server than waits for request messages from CCDApp2's job queue, such as 'take_image_set' request to record a set of Live Stacked Images for a specified Target Object.   Progress during image capture is communicated through 'get_appstate' and 'get_lastresult' requests.   When the job queue slews the Telescope to a new target or Positions the Scope onto the target using Locate Images

The server would normally run entirely in 'Auto' mode. But either by clicking stop capture or unchecking the 'Auto' checkbox, the server can be placed in 'Manual' mode. From this state the image set can be re-done or certain other imaging tasks can be conducted using extra buttons that appear when in this Manual state, or any other function can be accessed by manually going to main SharpCap window.  To return to 'Auto' mode check the 'Auto' button and click 'Continue' button.

If the CCDApp2 program closes the server stops, but can be restarted by clicking on 'Restart Server' button.

Overall Program Flow based on AppStates, key client requests and direct user input are illustrated in the attached diagram

Server Script - Diagram illustrating Program Flow.
(shows AppStates, key client requests and direct user inputs)
Image
 

 

Screen captures of the Server Form are show below:

Server Script - Listening (Waiting for Client Connection
Image
 
Server Script - Ready (Client Connected)
Image
 
Server Script - Imaging
(Imaging under Client Control)
Imaging
 
Server Script - Manual
(Imaging Stopped / Control switched to Manual)
Image
 

 

List of Methods

Method Description Parameters Results  
         
get_appstate Get Application/Server State none string ("Listening", "Ready",
"Imaging", "Manual", "Stopped" )

if "Imaging" then also
iFrame (int), nFrames (int)
 
notify_session Notification of Client Session sessionname (string) int (0)  
notify_slew Notification that a slew is taking place objectname (string) int (0)  
notify_positioning Notification that positioning is taking place objectname (string) int (0)  
take_image_set Take Image Set objectname (string), count (int),
exposure (float), gain (int)
int (0)  
abort Aborts capture of current image set, and sets AppState to Ready none
int(0)  
get_lastresult Get Last Result none
string (description of the result of the last run)  
notify_eof Notification that job sequence has finished none int (0)  
shutdown Closes Server and script
(doesn't close Sharpcap program)
none int (0)  


Notes:

During initial development of the Server Script the Telnet applet was used as the Client to test the Server Connectivity.  
Telnet wasn't initially available on my Windows 7 machine but was enabled as follows

To enable Telnet command line utilities:

Back to Top