Satellite Sun Sensor Prototype Tutorial

Finland launches her first satellite in 2014. We're building sun sensor prototype with Arduino. Sun sensor is part of the navigation subsystem.


Four E910.86 sensors.

Please notice that this is an advanced project. After all, it IS rocket science. If you you are a beginner and want to quickly learn how to how to make prototypes with Arduino and use sensors, start with Make Arduino Bots & Gadgets.

Preliminary Requirements for the Final Product

  • 5mm x 5mm, height 6mm ( 3 mm thick), only the detector
  • I2C output
  • Maximum cost 500 EUR each
  • Actualized prototype costs < 100 EUR
  • Parts

  • Elmos E910.86 Integrated Solar Angle Sensor
  • 1 * Arduino UNO for sensor and i2c communications
  • 1 * Arduino UNO for simulating OBC
  • Breadboard
  • Chosen Sensor

  • E910.86
  • Manufacturer: Elmos
  • Integrated Solar Angle Sensor

    Official info sheet.

    Key Features

  • Supply voltage range 4.5V to 5.5V
  • Outputs angle of light incidence in XZ and YZ planes
  • Measurement range 15° to 165°
  • Resolution 2.7°
  • SPI interface
  • -40°C to +85°C

  • Microcontroller for Prototyping

  • Arduino Uno
  • Key Features

  • ATmega328
  • Operating Voltage 5V
  • Digital I/O Pins 14 (of which 6 provide PWM output)
  • Clock Speed 16 MHz
  • Protoboard for E910.86

    E910.86 is physically too small to be used with Arduino. Size makes connecting Arduino pins or additional components difficult. Protoboard with needed resistors, capasitators and pin header was made for easier prototyping. Protoboard is based on circuit diagram presented in E910.86 product preview document.


    E910.86 is very small. Using needle and multimeter to test connections.

    Please notice that darker ares in the board are nonconductive material. So large areas are conductive, small lines are not.


    Protoboard. Larger version.

    E910.86 pin descriptions and corresponding Arduino pins are marked in the image above. First Arduino pin is top left, when Aalto-1 text is horizontal.

    Protoboard pin connections:

    1 SCLK
    2 MOSI
    3 MISO
    4 CS
    5 RESET
    6 GND
    7 +5V
    8 Analog OUT

    Prototype Basic Setup for Reading Sensor Data


    Basic setup.

    Arduino Pin Connections

    ard11-mosi-e2 green
    ard12-miso-e3 yellow
    ard13-sck-e1 white
    ard10-cs-e4 brown

    ard5v-reset-e5 red
    ardGnd-gnd-e7 black
    ard5v-vcc-e8 red

    Hello Sun Sensor

    This "Hello sun sensor" test code reads X and Y data from E910.86. For a more full featured example, see the source tarball.

    Upload code to arduino and open serial monitor. You can find the latest version of the code in the tarball: sunSensorBotBookCom/e910.86-arduino/src/e910-86-arduino.ino.

    /* Read sun position with Elmos E910.86 SPI on Arduino.
    Copyright 2013 http://botbook.com/satellite Tero Karvinen & Kimmo Karvinen
    
    Connections for SPI:
    # Arduino-Purpose-E910.86
    ard13-sck-e1  white
    ard11-mosi-e2 green
    ard12-miso-e3 yellow
    ard10-cs-e4   brown
    ard5v-reset-e5	red
    ardGnd-gnd-e6	black
    ard5v-vcc-e7	red
    ardA3-analogSOUT-e8 blue 
    
    When the text is top up ("Aalto-1 Sun Sensor Proto V1")
    - pin one is top left.
    - x grows to left
    - y grows down
    - when sun is directly in front of the sensor, (x,y)==(0,0)
    The connector has 8 pins. 
    The protoboard is made excatly as descibed on E910.86 data sheet. 
    
    SPI functions start with 's'. 
    */
    
    #include <SPI.h>
    
    const int sSlaveSelectPin = 10;
    
    int xdeg = -273;
    int ydeg = -273;
     
    void setup() {
    	Serial.begin(115200); // bit/s	
        Serial.println("BotBook.com/satellite");
        sInit();
    	spiWrite(0b10010000, 0b00010000); // enable
    }
     
    void loop() {
    	spiWrite(0b00000000, 0b00011000);	// read xy-angle
    	delay(100);
    }
    
    /* spi */
    
    void sInit()
    {
    	Serial.println("sInit()");
    	SPI.begin(); 
    	Serial.println("SPI.begin() done. ");
    	pinMode (sSlaveSelectPin, OUTPUT);
    	SPI.setDataMode(SPI_MODE0);
    	SPI.setBitOrder(MSBFIRST);
    	SPI.setClockDivider(SPI_CLOCK_DIV4);
    	digitalWrite(sSlaveSelectPin, HIGH);
    	Serial.println("sInit() done. ");
    }
    
    int spiWrite(int byte1, int byte2) {
    	digitalWrite(sSlaveSelectPin, LOW);
    	delay(1);
    	unsigned int res1 = SPI.transfer(byte1);
    	delay(1);
    	unsigned int res2 = SPI.transfer(byte2);
    	delay(1);
    	digitalWrite(sSlaveSelectPin, HIGH); 
    	sSerExplainPacket(combine(res1, res2));
    }
    
    /* parsing */
    
    void sSerExplainPacket(unsigned long int p)
    {
    	if (p>>16-4 == 0b0100) {
    
    		int x = p & 0b0000111111000000;
    		x = x>>6;
    		const int xzero = 29;
    		const int xmax = 51; // at 75 deg
    		xdeg = (x-xzero) * 75/(xmax-xzero); 
    		int y = p & 0b0000000000111111;
    
    		const int yzero = 29;
    		const int ymax = 51; // at 75 deg
    		ydeg = (y-yzero) * 75/(ymax-yzero);
    
    		Serial.print("xy: ");
    		Serial.print("raw:(");
    		Serial.print(x);
    		Serial.print(",");
    		Serial.print(y);
    		Serial.print(")");
    
    		Serial.print(" deg:[");
    		Serial.print(xdeg);
    		Serial.print(",");
    		Serial.print(ydeg);
    		Serial.println("]");
    
    		if ((xdeg<-75) or (75<xdeg) or (ydeg<-75) or (75<ydeg)) {
    			Serial.print(" (angle out of range) ");
    		}
    	} else {
    		Serial.println("SPI Error: Unknown message ");
    		serBits(p);
    	}
    }
    
    /* end parsing */
    
    /* bit helpers */
    
    unsigned long int combine(unsigned int left, unsigned int right)
    { // combine two 8 bit words to one 16 bit word
    	return (left<<8)+right;
    }
    
    void serBits(unsigned long int x) 
    { // Print bits of x. x must be 16 bits.
    	for(int i=16; i>0; i--) {
    		unsigned int b = 0b1000000000000000 & x;
    		b = b>>(16-1);
    		Serial.print(b, DEC);
    		if ((i-1) % 4 == 0)
    			Serial.print(' '); 
    		x=x<<1;
    	}
    }
    
    /* end bit helpers */
    

    Sun Simulator Setup

    To verify that sensor readings are accurate we built a simple sun Simulator Setup. First tripod holds two line lasers and the sunsensor. Laser forms crosshairs to facing wall into center point of the sensor. Second tripod holds light source that simulates the sun. By moving the second tripod we can use the formula below to count the angle. Larger distance between the two tripods gives more accurate readings.


    Sun simulator. Larger version.


    I2C Communication

    When the sun sensor will be a part of the satellite, on board computer (OBC) will ask angle data from it. OBC is the master and sensor is the slave. Sensor is reading values all the time, but outputs them via I2C only when it receives a query from the master.


    Final prototype. Larger version.

    To simulate satellite's OBC we use another Arduino UNO. Upload codes from the tarball for both Arduinos (obc.ino, sunsensor.ino), connect master arduino to your computer and open serial monitor.

    Installing Command Line Development Environment

    This is the quickest and most effective way for advanced users. If this looks confusing, feel free to use vanilla Arduino IDE graphically.

    Burn xUbuntu 12.04 LTS live CD (burn image). Boot from the Live CD. Accessories: Terminal Emulator. Set your local keyboard map 'setxkbmap.fi'.

    $ sudo apt-get update
    $ sudo apt-get -y install arduino gedit python-serial gdebi make screen tree
    $ sudo gdebi -n http://botbook.com/satellite/download/python-ino_0.3.5-1_all.deb
    $ wget http://botbook.com/satellite/download/sunsensor-botbook-com-latest.tar.gz
    $ tar -xf sunsensor*.tar.gz
    $ cd sunSensor*
    

    Physically build the test setup with 2 Arduinos and E910.86 sun sensor. Connect USB wires. Connect master first, so it gets /dev/ttyACM0.

    $ make
    

    OBC and sun sensor code is compiled and uploaded to each Arduino. Serial monitor starts. You will see debug output of both the On Board Computer (obc, master) and Sun Sensor (slave).

    Make allows you to automate building tasks and simultaneously upload to both Arduinos, so it's the fastest way to develop. See README for more features.