Friday, 10 January 2014

GY-80 orientation sensor on a Raspberry Pi

As I don't yet have a "Goto Mount" for my telescope, I've spent a frustrating amount of time trying and failing to find objects of interest by star hopping. Perhaps I just need more practice, but if accurate enough, an orientation sensor might give me a shortcut by telling me where my telescope is pointing? (Update - see next blog post.)

There are plenty of guides from people using I2C interface sensors from a Raspberry Pi, so this seemed worth a try. I bought a GY-80 on eBay for £7.50 shipped from China.
GY-80 sensor attached to Raspberry Pi
The GY-80 is tiny, only about 27x17mm in size, and has following I2C sensors:
  • HMC5883L (3-Axis Digital Compass), I2C Address 0x1E, datasheet
  • ADXL345 (3-Axis Digital Accelerometer), I2C Address 0x53, datasheet
  • L3G4200D (3-Axis Angular Rate Sensor / Gyro), I2C Address 0x69, datasheet
  • BMP085 (Barometric Pressure / Temperature Sensor), I2C Address 0x77, data sheet
Buying an all-in-one unit may allow a more accurate orientation sensor, but I was also intrigued if the digital compass would be helpful for polar alignment of my equatorial telescope mount?

Raspberry Pi I2C Setup

The Raspberry Pi's I2C interface is disabled by default - and also they switched things round a little in the B revision. See configuring I2C for Raspberry Pi (by Adafruit).

$ sudo emacs /etc/modules

Add the following lines (and reboot for it to take effect):

i2c-bcm2708 
i2c-dev

Check if the I2C modules have been disabled,

$ more /etc/modprobe.d/raspi-blacklist.conf
# blacklist spi and i2c by default (many users don't need them)

blacklist spi-bcm2708
blacklist i2c-bcm2708

If they have (as above), edit the file to comment out those blacklist entries by adding a leading hash.

$ sudo emacs /etc/modprobe.d/raspi-blacklist.conf

Install the I2C tools,

$ sudo apt-get install i2c-tools python-smbus

This checks the driver side of things - there are two potential I2C Linux devices:

$ sudo i2cdetect -l
i2c-0 i2c       bcm2708_i2c.0                   I2C adapter
i2c-1 i2c       bcm2708_i2c.1                   I2C adapter

Now let's check if there are any I2C devices detected - the exact command differs between the older Raspberry Pi model B with 256MB RAM and no holes,

$ sudo i2cdetect -y 0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --

Or the newer Raspberry Pi revisions with 512MB RAM and two mounting holes:

$ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- 

This says that there were no I2C devices found, on either of the possible Linux I2C devices (zero /dev/i2c-0 and one /dev/i2c-1). Which makes sense as I've not connected anything yet.

To avoid having to use sudo all the time to access the I2C device, I did this (log out and log in again for it to take effect):

$ sudo usermod -a -G i2c pi

Hat tip to David Grayson's documentation for his Raspberry C++ code for the MinIMU-9 sensor which is similar to the GY-80.

Hardware

I'm using four jumper cables (red, brown, green and yellow) to connect the GY-80 IMU to the Raspberry Pi GPIO pins (as in the photo above):
  • VCC_IN <--> Raspberry Pi GPIO pin 1, 3.3V
  • VCC_3.3V <--> Unused
  • GND <--> Raspberry Pi GPIO pin 6, Ground
  • SCL <--> Raspberry Pi GPIO pin 5, I2C serial clock (SCL)
  • SDA <--> Raspberry Pi GPIO pin 3, I2C serial data (SDA)
  • M_DRDY (interrupt from HMC5883L magnetometer) <--> Unused
  • A_INT1 (interrupt from ADXL345 accelerometer) <--> Unused
  • T_INT1 (interrupt from L3G4200 gyroscope) <--> Unused
  • P_XCLR (clear BMP085 barometer) <--> Unused
  • P_EOC (end of conversion for BMP085 barometer) <--> Unused
Labelled back of GY-80 boardChips on the front of the GY-80 board
I soldered the pins I was using on the GY-80 board (without this you don't get any connection), and then my Raspberry Pi could detect the four I2C sensors:

$ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1e -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- 53 -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- 69 -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- 77

As expected, four I2C devices found, with the published hex identifiers :)
  • HMC5883L (3-Axis Digital Compass), I2C Address 0x1E
  • ADXL345 (3-Axis Digital Accelerometer), I2C Address 0×53
  • L3G4200D (3-Axis Angular Rate Sensor), I2C Address 0×69
  • BMP085 (Barometric Pressure / Temperature Sensor), I2C Address 0×77

Data Access

From the very nice Adafruit tutorial for using BMP085 with Raspberry Pi, let's download and run their example Python code:

$ git clone https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code.git
Cloning into 'Adafruit-Raspberry-Pi-Python-Code'...
remote: Reusing existing pack: 461, done.
remote: Total 461 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (461/461), 155.96 KiB, done.
Resolving deltas: 100% (196/196), done.
$ cd Adafruit-Raspberry-Pi-Python-Code/Adafruit_BMP085/

And now use Adafruit_BMP085_example.py to access the BMP085 chip's temperature/pressure sensor:

$ python Adafruit_BMP085_example.py 
Temperature: 14.60 C
Pressure:    999.04 hPa
Altitude:    118.99

Those numbers look about right - it is quite cold in this room (thus my wish for a kotatsu in Scotland), atmospheric pressure is about 1000 hPa and my analogue barometer says 997 millibars or hPa, while the altitude isn't far off either.

Adafruit also have example code for the ADXL345 (3-Axis Digital Accelerometer), Adafruit_ADXL345.py on GitHub, I moved the sensor while this was running and the numbers changed:

$ cd ../Adafruit_ADXL345/
$ python Adafruit_ADXL345.py 
[Accelerometer X, Y, Z]
[0, 0, 0]
[42, -31, -269]
[41, -31, -272]
[41, -30, -271]
[41, -31, -273]
[35, -32, -257]
[40, -43, -282]
[28, -27, -253]
[15, -25, -273]
[14, -24, -273]
[16, -26, -274]
^C
Traceback (most recent call last):
  File "Adafruit_ADXL345.py", line 114, in <module>
    sleep(1) # Output is fun to watch if this is commented out
KeyboardInterrupt

I briefly tested the gyroscope using a little test script gyro.py from bashardawood on Github, which gave small numbers at rest, and big numbers when I moved the sensor:

$ python gyro.py 
         7          6         -6
        11          2         -4
         8          4         -5
         9          3         -5
         6          2         -1
        11       -252         -7
         7          1         -3
         7          0         -3
         5          2          1
         6          4         -3
         6         -1         -2
         6          0         -3
         9          0         -5
         6          1          1
        11          4         -3
       114        202        -97
     -3180      -3039        740
     -2965      -4777       1272
       874      -2551        601
      -188      -2221        101
      -833      -1531         93
       363        774       -347
       758       1450      -1096
^C
Traceback (most recent call last):
  File "gyro.py", line 56, in <module>
    sleep(0.02)
KeyboardInterrupt

I also gave the compass a quick test by following Andrew Birkett's blog post on using the HMC5883L. He has some other nice posts on the MPU-6050 gyro and accelerometer and HMC5883L compass, including combining the MPU6050 and HMC5883L for pitch, roll and yaw where he says he hopes to expand this code (on GitHub) to also cover the ADXL345 (accelerometer), the L3G4200D (gyroscope) and the BMP085 (pressure sensor) (Update - Andrew has bought a GY-80 for his Raspberry Pi too.).

Update:
My next blog post talks about using the GY-80 to measure telescope orientation.

22 comments:

  1. Peter,

    Thanks for the kind words about my blog and I shall follow your work with a telescope with interest, I used to have a decent scope and would have loved a goto system on it.

    If you need some code for your sensors just look on the 'dev' branch on my git hub account ( https://github.com/bitify/raspi/tree/dev/i2c-sensors/bitify/python/sensors ), it has code for ADXL345 and L3G4200D already and a new version of the IMU class using these sensors.

    ReplyDelete
    Replies
    1. Thanks Andrew - I had stumbled over your dev branch (I thought I'd commented about this on your blog or GitHub), and will give it a try. The telescope side of my software is going well, doing coordinate transformation etc. Linking in the sensor data is next... and I'll write another blog post with details.

      Delete
  2. The VCC_IN must be supplied with 5v, as you are using 3.3v supply from raspberry pi, should use the pin VCC_3.3V in the GY-80.

    ReplyDelete
    Replies
    1. I'd have to open up the Pi's case to check, but you may be right. I suspect it works either way.

      Delete
  3. Looking forward to your goto blog
    William
    AYR

    ReplyDelete
    Replies
    1. Do you mean http://astrobeano.blogspot.co.uk/2014/01/instrumented-telescope-with-raspberry.html where I've used this with a Telescope?

      Delete
    2. That looks like what I'm after, thanks. I have a 10" LX200 gps but the main board has packed up twice and at £200+ a time I've decided to take a different route. Started with the arduino and have the motors under full control, but at 75 I no longer am capable of writing the goto software. I like the idea of the push to using my Pi and then switching to motor tracking. I've managed to get as far as the Pi detecting the components on the GY 80 but can't get into github with your link in your testing section.
      Many thanks for your good blogs.
      William

      Delete
    3. I've not had time to tinker with this lately, my Python code on http://github.com/peterjc/longsight isn't very portable yet (due to the I2C dependencies etc). In early testing, accuracy wasn't as good as I was hoping - this is very much a prototype for now.

      Delete
  4. Good post , question , i was trying using two brushless dc motor , which seems working but does not track correctly .Any suggestions ?

    ReplyDelete
    Replies
    1. I've not tried anything combining an orientation sensor with motors, so no ideas from me - sorry.

      Delete
  5. Hi Peter, what was the orientation of the sensor with regards to the X/Y/Z axis as represented on the sensor board and the telescope axis ?
    In other words, was it upside down in any way ?
    Thanks
    Regards
    Mathieu

    ReplyDelete
    Replies
    1. There's a little x/y/z axis labelled on the circuit board, but I'm not sure now which way up it was.

      Delete
    2. Yes, but in relation to the position of your Pi as from your photo, how was the sensor oriented ?

      Delete
    3. Someone else asked me to take a photo of the Pi and the sensor board inside the case for http://astrobeano.blogspot.co.uk/2014/01/instrumented-telescope-with-raspberry.html - from memory it was upside down in the corner of the case, with the two PCBs roughly parallel. I thought the exact orientation didn't matter as the offset was calculated when running the telescope calibration sync commands.

      Delete
  6. Also, what should we change in your code if we are observing from the southern hemisphere ?
    Thanks !

    ReplyDelete
    Replies
    1. If you mean http://astrobeano.blogspot.co.uk/2014/01/instrumented-telescope-with-raspberry.html and https://github.com/peterjc/longsight/blob/master/telescope_server.py then I'm not sure. It needs updating from using https://github.com/eteq/astropysics/ to https://github.com/astropy/astropy which would probably handle the southern hemisphere.

      Delete
    2. I'm gonna give this a god. Already changed most of your code to be Python classes. Also I have the sensor connected to an Arduino not to the Pi directly, so the whole setup is a bit different. Motors and sensors are on the arduino.

      Delete
    3. Good luck - my initial code was very much a proof of principle, and I've sadly not had time to work on this for ages. I hope you'll blog about your setup one day :)

      Delete
  7. Hello. Good work but for RPI version 1. I have version 3, where the code is wrong. Probably the error is in i2cutils.py. What has changed since the time when the code was created? You advise me or do you updated code? Thank you for answer

    ReplyDelete
    Replies
    1. I don't lnow what might have changed with the RPi v3, but I'd start with ensuring i2cdetect works. Perhaps you have to try a different bus number?

      In any case it looks like there's been some changes to the Ada Fruit Python libraries so a lot of this blog post would need to be updated for that too.

      Delete
    2. Here is the mistake. The program does not continue and will end on the first error. http://1url.cz/Ot1SA

      Delete