Finland launches her first satellite in 2014. We're building sun sensor prototype with Arduino. Sun sensor is part of the navigation subsystem.
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.
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.
Please notice that darker ares in the board are nonconductive material. So large areas are conductive, small lines are not.
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
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
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 */
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.
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.
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.
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.