diff --git a/site_ansto/instrument/sans/config/goniometer/sct_goniometer.tcl b/site_ansto/instrument/sans/config/goniometer/sct_goniometer.tcl
new file mode 100644
index 00000000..a7162f14
--- /dev/null
+++ b/site_ansto/instrument/sans/config/goniometer/sct_goniometer.tcl
@@ -0,0 +1,183 @@
+##
+# @file Goniometer controller
+#
+# Author: Jing Chen (jgn@ansto.gov.au) June 2010
+#
+# The Goniometer controller can be installed with the following command,
+# ::scobj::goniometer::mkGoniometer {
+# name "goniometer"
+# IP localhost
+# PORT 62944
+# tuning 1
+# interval 1
+# }
+#
+# NOTE:
+# If tuning=1 this will generate gom/set_gom, gchi/set_gchi and gphi/set_gphi
+# nodes for the instrument scientists.
+# The tuning parameter should be set to 0 for the users.
+#
+
+namespace eval ::scobj::goniometer {
+}
+
+proc ::scobj::goniometer::set_gom {basePath} {
+ set newGOM [sct target]
+ hsetprop $basePath targetGom $newGOM
+ return idle
+}
+
+proc ::scobj::goniometer::set_gchi {basePath} {
+ set newGCHI [sct target]
+ hsetprop $basePath targetGchi $newGCHI
+ return idle
+}
+
+proc ::scobj::goniometer::set_gphi {basePath} {
+ set newGPHI [sct target]
+ hsetprop $basePath targetGphi $newGPHI
+ return idle
+}
+
+##
+# @brief Request a state report from the PLC controller by sending a get_prop command
+proc ::scobj::goniometer::rqStatFunc {} {
+ set comm "gom,gchi,gphi\n"
+ sct send $comm
+ return rdState
+}
+
+##
+# @brief Read and record the state report from the PLC server
+proc ::scobj::goniometer::rdStatFunc {basePath} {
+ set replyStr [sct result]
+ #broadcast $replyStr
+ if {[string first "err" $replyStr] != -1} {
+ broadcast "ERROR: cannot get the value to the PLC server, check again!"
+ } else {
+ set s1 [string map { | gom: | gchi: | gphi: | |} $replyStr]
+ set s2 [string trim $s1 "|\n"]
+ set s3 [split $s2 "|:"]
+
+ array set stateArr $s3
+
+ hset $basePath/gom $stateArr(gom)
+ hset $basePath/gchi $stateArr(gchi)
+ hset $basePath/gphi $stateArr(gphi)
+
+ hsetprop $basePath currGom $stateArr(gom)
+ hsetprop $basePath currGchi $stateArr(gchi)
+ hsetprop $basePath currGphi $stateArr(gphi)
+
+ #sct update $s3
+ sct utime readtime
+ }
+ return idle
+}
+
+##
+# @Check if any of gom/gchi/gphi has been changed by client
+proc ::scobj::goniometer::checkStatusFunc {basePath} {
+ set targetGom [hgetpropval $basePath targetGom]
+ set targetGchi [hgetpropval $basePath targetGchi]
+ set targetGphi [hgetpropval $basePath targetGphi]
+
+ set currGom [hgetpropval $basePath currGom]
+ set currGchi [hgetpropval $basePath currGchi]
+ set currGphi [hgetpropval $basePath currGphi]
+
+ if {$targetGom != $currGom} {
+ set comm "gom$targetGom\n"
+ } elseif {$targetGchi != $currGchi} {
+ set comm "gchi$targetGchi\n"
+ } elseif {$targetGphi != $currGphi} {
+ set comm "gphi$targetGphi\n"
+ } else {
+ return idle
+ }
+
+ sct send $comm
+ return CheckReply
+}
+
+proc ::scobj::goniometer::checkReplyFunc {} {
+ set replyStr [sct result]
+ broadcast $replyStr
+
+ if {[string first "var" $replyStr] != -1} {
+ broadcast "ERROR: the varaible does not exist!"
+ } elseif {[string first "set" $replyStr] != -1} {
+ broadcast "ERROR: PLC cannot write new values for variable due to internal reason!"
+ } else {
+ sct utime readtime
+ }
+
+ return idle
+}
+
+##
+# @brief Make a Goniometer controller
+#
+# @param argList, {name "goniometer" IP localhost PORT 62944 tuning 1 interval 1}
+#
+# name: name of goniometer controller object
+# IP: IP address of RF generator moxa box
+# PORT: Port number assigned to the generator on the moxa-box
+# tuning: boolean, set tuning=1 to allow instrument scientists to set the axe positions
+# interval: polling and ramping interval in seconds.
+proc ::scobj::goniometer::mkGoniometer {argList} {
+# Generate parameter array from the argument list
+ foreach {k v} $argList {
+ set KEY [string toupper $k]
+ set pa($KEY) $v
+ }
+
+ MakeSICSObj $pa(NAME) SCT_OBJECT
+ sicslist setatt $pa(NAME) klass instrument
+ sicslist setatt $pa(NAME) long_name $pa(NAME)
+
+ hfactory /sics/$pa(NAME)/gom plain internal int
+ hfactory /sics/$pa(NAME)/gchi plain internal int
+ hfactory /sics/$pa(NAME)/gphi plain internal int
+
+ hfactory /sics/$pa(NAME)/set_gom plain user int
+ hfactory /sics/$pa(NAME)/set_gchi plain user int
+ hfactory /sics/$pa(NAME)/set_gphi plain user int
+
+ makesctcontroller sct_goniometer std $pa(IP):$pa(PORT)
+
+ hset /sics/$pa(NAME)/gom 0
+ hset /sics/$pa(NAME)/gchi 0
+ hset /sics/$pa(NAME)/gphi 0
+
+ hsetprop /sics/$pa(NAME) currGom 0
+ hsetprop /sics/$pa(NAME) currGchi 0
+ hsetprop /sics/$pa(NAME) currGphi 0
+
+ hsetprop /sics/$pa(NAME) targetGom 10
+ hsetprop /sics/$pa(NAME) targetGchi 15
+ hsetprop /sics/$pa(NAME) targetGphi 20
+
+ hsetprop /sics/$pa(NAME)/gom read ::scobj::goniometer::rqStatFunc
+ hsetprop /sics/$pa(NAME)/gom rdState ::scobj::goniometer::rdStatFunc /sics/$pa(NAME)
+
+ hsetprop /sics/$pa(NAME)/gchi read ::scobj::goniometer::checkStatusFunc /sics/$pa(NAME)
+ hsetprop /sics/$pa(NAME)/gchi CheckReply ::scobj::goniometer::checkReplyFunc
+
+ # Initialise properties required for generating the API for GumTree and to save data
+ ::scobj::hinitprops $pa(NAME) gom gchi gphi
+
+ sct_goniometer poll /sics/$pa(NAME)/gom $pa(INTERVAL)
+ sct_goniometer poll /sics/$pa(NAME)/gchi $pa(INTERVAL)
+
+ if {$pa(TUNING)} {
+ hsetprop /sics/$pa(NAME)/set_gom write ::scobj::goniometer::set_gom /sics/$pa(NAME)
+ hsetprop /sics/$pa(NAME)/set_gchi write ::scobj::goniometer::set_gchi /sics/$pa(NAME)
+ hsetprop /sics/$pa(NAME)/set_gphi write ::scobj::goniometer::set_gphi /sics/$pa(NAME)
+
+ sct_goniometer write /sics/$pa(NAME)/set_gom
+ sct_goniometer write /sics/$pa(NAME)/set_gchi
+ sct_goniometer write /sics/$pa(NAME)/set_gphi
+ }
+}
+