Sunday, 26 January 2014

Instrumented Telescope with Raspberry Pi and orientation sensor

A "Push To" telescope mount is like a fully automated "Go To" telescope mount, but without the motors. You must manually move the telescope, but because the telescope knows where it is pointed, you get live tracking telling you where it needs to go.

I'm using a Raspberry Pi with a GY-80 orientation sensor to turn my basic SkyWatcher EQ2 mount into a computer assisted "Push To" telescope - which can pass this information to planetarium software like SkySafari on my iPad/iPhone. To do this I've written a little Python script ( which runs on the Raspberry Pi, and translates the orientation sensor information into RA/Dec angles. The Raspberry Pi listens to Meade LX200 (or Nexstar) serial protocol commands received over TCP/IP, and responds with the orientation information.
SkySafari Plus v4, showing telescope direction from a Raspberry Pi

Indoor testing has gone well so far... I can rotate the Raspberry Pi and watch the blue cross-hairs on SkySafari change position. The locations look sensible (and drift naturally due to sidereal rotation). There is a bit of jitter which may need some smoothing.

Part of the idea came from reading how easy it is to have SkySafari talking to telescope via a Raspberry Pi running a WiFi to serial port bridge (similar blog post), mimicking SkySafari's expensive but neat SkyFi box. I was also impressed with Simon Box's instrumented Dobsonian telescope (measuring altitude-azimuth angles directly) connected to Stellarium (Update: and this similar instrumented telescope project called scopebox), and Leon Rozengarten's project building an Arduino telescope controller using the HMC6352 and ADXL345 sensors (videocode).

This project meant integrating lots of different stuff - serial communication protocols, I2C sensor chips, Inertial measurement unit (IMU) / Attitude and heading reference system (AHRS) calculations, quaternion mathematics for rotations, sidereal time, angle conversions, etc. Here are a few notes... my Python script is on GitHub.

Mounting the Raspberry Pi

Because I wanted a case with some form of external mounting, I went for the Cyntech "BerryBlack" Raspberry Pi case - plus the optional SD card cover.  The red and green logo RPi stands out nicely, and the light pipe for the LEDs is very well done. I was able to mount this quite stably to the telescope tube via a piece of wood attached to the camera screw thread on the O-rings.

Two screws ready to hang the Raspberry Pi onRaspbery Pi attached to SkyWatcher telescope tube

However, for outdoor use, note the Cyntech case is not air or water tight - for a start the slot for the GPIO cable is wide open. Also the two screw slots on the back are not fully enclosed - there is an air/water gap to the back of the board. I may have to do something about this to avoid dew getting inside...

Meade LX200 Protocol

This is a well established and widely used protocol for communicating with a computerised telescope using serial commands. It is also well documented, see Meade Telescope Serial Command Protocol (2010), see also Meade Telescope Serial Command Protocol (2002) and this alternative page (sometimes clearer).

The commercial SkySafari SkyFi box seems to use a standard approach (RFC 2217) for transmitting serial connection data via TCP/IP (i.e. a normal network connection), which can be done in software using ser2net on Linux. This means writing code to listen on a network port for Meade LX200 commands was actually quite straightforward. In my code I focussed on implementing enough of the commands for Sky Safari Plus v4 to connect, set the time and location, get the orientation - and behave nicely if any of the goto or slew commands are sent. SkySafari also handles alignment by sending a sync command to the (Raspberry Pi pretending to be a) telescope.

Celestron Nexstar Protocol

Celestron have released the Nexstar Protocol documentation. It is a similar serial protocol, and works over TCP/IP in the same way. In some ways it seems better designed than the Meade LX200 protocol - for example the RA/Dec angles are always sent as pairs.

Since Sky Safari Plus v4 can also connect using this protocol, I tried this too. Surprisingly SkySafari only uses a small handful of the commands and interestingly does not send sync commands to the telescope - it seems to do a local calibration itself instead. I'm sticking with the Meade LX200 protocol instead (see below for more details).

Measuring the Celestial Angles

The telescope communication protocols use two important celestial angles: the right ascension (equatorial axis) paired with the declination, which must be calculated from the local altitude and azimuth angles taking into account the latitude, longitude and time. See for example for how this works.

I'm using a combined gyroscope/accelerometer/magnetometer orientation sensor. Without caring about the telescope mount type etc, this can give me the altitude and azimuth angles - although most relevant documentation instead talks about yaw, pitch and roll angles.

IMU and AHRS code

Using the axis terminology for planes there are three rotational axes: roll (rotation about X-axis, direction of flight), pitch (lateral rotation about Y-axis), and yaw (rotation about Z-axis). In general planes fly horizontally, so the yaw is typically a compass bearing and maps to the telescope's azimuth. Similar the roll can be interpreted as the rotation of the eyepiece/camera, while pitch would be the  telescope's elevation (i.e. the altitude angle).

For the yaw, the accelerometer is useless (the values don't change, gravity is just down) so we must combine the gyroscope and compass data. For the most part the Earth's magnetic field is nearly horizontal, but I suppose in principle the compass data is also of some limited use for the pitch when pointing roughly North or South. However, for the pitch and roll, it is normal to just combine the accelerometer and gyroscope data.

See for example this page on how a quadcopter can get its orientationRaspberry Pi AHRS by David Grayson (core code in minimu9-ahrs.cpp), and FireTail AHRS software (for Arduino) based on this (core core in ahrs.cppFireTail is an autopilot for RC aircraft). There are lots of cool hobby projects out there using these kinds of sensors!

For the angle calculations I decided to play with quaternions, this page on IMU maths with quarternions was very helpful - as was Christoph Gohlke's Python quarternions code. I'm currently using a simple complementary filter putting 98% of the weighting on the gyroscope, and 2% on the accelerometer and compass. There are more advanced IMU approaches including Sebastian Madgwick's IMU/AHRS sensor fusion algorithm.

Using SkySafari Plus

Here's my SkySafari v4.0.1 telescope setup on the iPad or iPhone:
  • Scope Type: Meade LX-200 GPS (see note below)
  • Mount Type: Equatorial Push-To (see note below)
  • Auto-Detect SkyFi: Off (I'm currently testing via ethernet)
  • IP Address: The Raspberry Pi's IP address, or helpfully just the host name
  • Port Number: 4030 (default, but must match the Raspberry Pi setting)
  • Set Time & Location: On (see note below)
  • Readout Rate: 4 per second (default)
  • Save Log File: Off

SkySafari Plus v4 on iPad, telescope connection settingsSkySafari Plus v4 on iPad, connected as "Push To" telescope

SkySafari Plus v4 on iPhone,
telescope connection settings
SkySafari Plus v4 on iPhone,
connected as a "Push To" telescope
SkySafari Plus v4 on iPhone,
connected as a "GoTo" telescope

The exact mount type does not seem important, only if it is "Push-To" or "GoTo". If you select "Push-To" then the "GoTo" button and rate control are inactive. If you select "GoTo" these controls are live, and additional Left/Right and Up/Down buttons appear on the side of the screen. Since the iPad/iPhone is multi-touch, you can use these together at the same time. If you did have motors on the telescope connected to the Raspberry Pi, it should be possible to extend to control the telescope this way.

In order to do the angle conversion, the Raspberry Pi needs to know the location (latitude and longitude) and time zone. If running a Raspberry Pi offline (e.g. from batteries away from the house) it won't know the date and time. Connecting a GPS to the Raspberry Pi is one solution, but from a usability point of view it seems simplest to just set this via SkySafari (especially if using an iPad or iPhone with a GPS).

However, if you configure the Scope Type as "Meade LX-200 Classic" then SkySafari v4 takes an extra 15 seconds or so for the connection. Using one of the other Meade settings like "Meade LX-200 GPS" avoids this and connects really quickly while setting the location and time information. Here's a  sample of the output seen during connection (location redacted) when running my Python script on a Raspberry Pi:

$ ./ 
Connecting to sensors...
Connected to GY-80 sensor
Opening network port...
Starting up on port 4030
Local site now latitude XX.XXXd, longitude X.XXXd
Local site timezone now -0.0
Local site timezone now -0.0
Requested site time 14:42:20 (TZ -0.0), new offset 1s, total offset 1s
Effective site date/time is 2014-01-25 14:42:20.964108 (local/GMT/UTC)
Requested site date 01/25/14 (MM/DD/YY) gives offset of 0 days
Effective site date/time is 2014-01-25 14:42:21.090983 (local/GMT/UTC)

Oddly, if the Scope Type is set to one of the Celestron NexStar models, then SkySafari v4 doesn't actually seem to try to set the location or time. This is one reason why I'm sticking with the Meade LX200 protocol instead.

With a target selected in SkySafari, pressing the align button should update the telescope mount tracking to be centred there. With the NexStar protocol SkySafari seems to do this itself (and only allow relatively small offsets to be used). With the Meade LX-200 protocol, SkySafari sends the revised orientation to the telescope with a sync command, and the telescope mount itself recalculates the calibration. This seems like a really neat user interface, which Simon Box uses on his project.

The Meade LX200 protocol includes commands for controlling a motorised focuser - but as far as I can see, SkySafari doesn't support this. If it did, I might be tempted to connect my Tasco 1603EF focuser to the Raspberry Pi as well.

To Do List

Improve the Raspberry Pi mounting. It currently has some give, so may need bracing to prevent any knocks while in use throwing off the calibration by a few degrees. Also this is too far away from the eyepiece to connect the Raspberry Pi add-on camera via its ribbon cable, but a USB cable to a web camera or DSLR should be fine...

Sensor calibration, see for example AndrewBirkett's post on calibrating the HMC5883L compass, another interesting post on compass calibration (from a group working on DIY robot lawn mowers), and these maths heavy posts on Gauss-Newton for sphere fitting (part 2part 3mcUSense on GitHub).

A refinement (or alternative) would be to capture photos from a webcam or DLSR on the telescope and run a plate solver (e.g. using's software), to report exactly where the telescope is pointed. Plate solvers can be sped up by providing an approximate orientation, so this orientation sensor could help there.

Multi-star calibration, probably with SkySafari as the front end using the Meade LX200 protocol's sync commands. This will be important if the sensor chip's X-axis isn't perfectly aligned with the telescope's line of sight. Initially I'm just use one-star alignment to correct the azimuth angle which depends on the offset between true North and the compass bearing.

Reduce cable clutter by switching from ethernet to wifi, ideally freeing me from the house wifi network (Update: done, using a mini USB WiFi dongle which supports use as an Access Point).

Further reduce cable clutter by tapping a 5V supply for the Raspberry Pi from the 6V supply for the SkyWatcher EQ2 sidereal motor?

And of course, test this outdoors for real... ;)

Update - Code Feedback

Can people check for or report any problems with the code on the issue tracker on the GitHub page please?


  1. I've not had time to tinker with this lately - and we're into summer already. In early outdoor testing, accuracy wasn't as good as I was hoping - frankly the red dot finder was more effective - so this is very much a prototype for now. Also my Python code on still isn't very portable yet (due to the I2C dependencies etc).

    1. Hello,
      I'm trying to get it works. Could you tell me how can I check what's wrong or missing?
      I'v got this message:
      Ensure,, and are present and importable

      See the following links, tweak the i2cutils import inside etc:

    2. I'm not sure - if this is triggered by my code can you open an issue on with the full traceback error please?

  2. In theory you could use any I2C orientation sensor, but each needs its own code written to get the data (and scale it to the same units). Right now there isn't a nice uniform Python library for doing this :(

  3. Would Stellarium work?
    I have a GY-80 sensor ready to hook up
    Will do it all
    do I have to setup I2C stuff
    Looking forward to getting it up and running


    1. Last time I checked Stellarium you have to also configure a virtual serial port for this to work, see

  4. I have GY80 hooked up and working with some code
    Temp, barometer, accelerometers
    Can't read gyros with code suggested

    Will code allow connection to wifi other than iphone.
    Laptop running planetarium program.
    How do I change the code to use stellarium on a laptop.
    or to use laptop to Raspi usb?

    1. It might be best to discuss the code over on GitHub (you can file issues etc). I didn't really finish the I2C integration nicely, and probably my instructions were too short.

      The code acts as a virtual serial port accessed over TCP/IP, so you can use wifi or an ethernet cable assuming there is no firewall blocking this.

      From memory, when I tested Stellarium on my laptop, the laptop was running a virtual serial port which connected over the network to the Raspberry Pi attached to the telescope, which was running the Python code using the I2C code. I did not take any detailed notes on this.

  5. So you never finished the project?
    Anyone else take it up?
    Everybody gets to a point then drops
    Leon Rosengarten had a great start then nothing
    You should get back to it
    Nothing out there using IMU for scope!


  6. I have a GY80 and a Merlin/Orion head which I am trying to use for a very similar project. I am trying to use the GY80 to tell me the angle and direction which my head is pointed so I can turn it into a GOTO mount.

    I can't seem to get your code to run though, it complains that I don't have an astrophysics module. Python and coding on the Raspberry Pi are both new to me, so I am completely lost...

    Any help or guidance would be appreciated.


    1. Yeah, it uses astropy from for things like calculating Greenwich sidereal time, so you need to install that too. I should add some more detailed instructions to the GitHub page for this project:

  7. Hello Peter,

    Excellent project! Could you take a picture of mounted GY-80 sensor with Raspberry Pi in "Pi case" and show it? :) Thanks!

    Best regards!

    1. Do you mean try to show how the GY-80 sensor is squeezed inside the case?

    2. Yes :) I bought GY-80 too. Now I'm watching for proper case to mount on my Sky Watchers Synta 8" tepescope.

  8. May I ask you how is real precision (tenth of degrees) of your device under sky ?

    1. I suspect it was measured in degrees rather than tenths of a degree... I didn't manage to measure it directly/systematically.

  9. Hello Peter . Congratulations on your work .
    Sorry to steal the time due to the fact that not Riec to run python code . I think the problem is that " In addition to install and activate all you need for the I2C port , a setup or missing files or libraries ." Use the GY - 80 and a banana more . I read the addresses of the sensors , and the hardware is ok . I think the problem is that specified above . I visato page on IL - 80 and also they can not read any data. Using other test code for the barometer can read your data .
    Perfevore you tell me the raspberry version used by you? Or if you have missed some installation of python library ? Thank you for your time.
    PS : I'm Italian , I apologize for my English

    1. As described on I was using the (old) Raspberry Pi B which only has two USB ports,

      The method to enable I2C has changed for the Raspberry Pi 2 (the new version with four USB ports). I have not tried the GY-80 sensor with the Raspberry Pi 2. Sorry.

  10. Dear Peter,
    I have tried your Code and eveything works like a Charme (I have added some functionality for GPIO Output for GOTO), how ever the GY80 is giving me some trouble and I hoped you may help me here...

    I get a signal which I can read from SkySafari/Server everything works fine, but the GY80 is giving me a wrong direction/Location... If I Point directly to the sun - the sun is always quite far away, directions (NWES too)...
    If I move the sensor - Skysafari moves too, but not in the given direction.
    I also tried every possible "Installation" of the sensor (XYZ Label pointing up, pointing down, 90° ....).

    Any clue where I could start digging? Alignment I already tried...
    Thanks in advance,

    1. I'd start by double checking the GPS information has worked and gives a sensible time and latitude and longitude for your location, as that's one obvious way things could be breaking. You can turn off the GPS bit in SkySafari and try setting the location via telescope_server.ini instead - and hopefully your Raspberry PI can getting the time from your network?

    2. Long/Lat is manually set (it was a bit wrong with Skysafari: LAT was correct,LONG was 344 instead of 16 (N48/E16 should be Vienna). Time is also set correct (GMT-1).
      Neither Skysafari nor Stellarium Shows correct view :( so goto doesnt work either as positions are wrong - sometimes Position jumps completly random and after 5sec wrong Position is fixed :/