Project Home
H1 Prototype
Mechanicals
Software
|
Heliostat Software
SoftwareArduino uses a special extension of the Processing language, which is based in C and has a few special functions useful for embedded microprocessor programming. This avoids requiring assembly level knowledge to access digital i/o, pwm, and other MCU functions. One button from the Arduino UI invokes the compilation process, which actually uses the Gnu C compiler in the background. The many layers of Open Source software involved are truly amazing. The Arduino community is an invaluable resource for those interested in learning how to use the Arduino platform for ATMEL ATMega family programming.For those new to the Arduino platform, they like to call its programs Sketches, as if they were short and quick. If you've written enough to code to fill a 168 or 328 you've written a lot more than a sketch, and filling more than half of a ATMEGA 1280 takes thousands of lines of code. My code mantra is modularity and lots of testing. Debugging a huge main program using untested libraries makes for huge head aches given the primitive state of Arduino debugging. There is no provision for setting break points and checking and altering variables during run time. So called instrumenting the code with Serial.print statements is the most effective way of deducing the cause of strange run-time behavior, besides and always in conjunction with careful study of the code base.
SketchesHelioEEPROMHelioEEPROM was created for managing the EEPROM configuration. It was instrumented with print statements to output the text for a suitable header file for use by the main program. The actual header file is created by running the program with the Serial monitor window open and then using Copy and Paste to create the actual file using your favorite text editor.
The HelioCom program expects to find certain configuration information in EEPROM in order to work properly, thus HelioEEPROM is essential for creating the default EEPROM data.
MotorTestCalThe MotorTestCal program was created for just focusing on motor testing and calibration routines. It of course needs access to the configuration structure created in EEPROM by that program.
HelioComHelioCom is the main heliostat program. It incorporates a main loop that checks for Serial input as well as user inputs, allowing manual and serial control, and also checks for scheduled events and invokes the proper control routines during tracking operation.
LibrariesClockThe clock is currently based on the DS1307 chip, and the clock library is based on code originally written by Maurice Ribble.DBThe DB library provides a very simple database model for data stored in EEPROM. This is very useful for such things as heliostat target, and scheduled event records. It requires use of the EEPROM library.Here's the library header code: struct DB_Header { byte n_recs; byte rec_size; byte head; // points to first record in sort order byte tail; // last record in sort, but sort is not implemented in the library // because you need to know the key and that gets complicated! }; #define DB_HEAD_SIZE 4 // DB_error values #define DB_OK 0 #define DB_RECNO_OUT_OF_RANGE 1 #define DB_REC (byte*)(void*)&& typedef byte* DB_Rec; class DB { public: void create(int head_ptr, byte recsize); void open(int head_ptr); boolean write(byte recno, const DB_Rec rec); boolean read(byte recno, DB_Rec rec); boolean deleteRec(byte recno); // delete is a reserved word boolean insert(byte recno, const DB_Rec rec); byte append(DB_Rec rec); byte nRecs(); byte head(); void head(byte h); void tail(byte t); byte tail(); DB_Header DB_head; byte DB_error; private: int writeHead(); int readHead(); int EEPROM_dbWrite(int ee, const byte* p); int EEPROM_dbRead(int ee, byte* p); int DB_head_ptr; int DB_tbl_ptr; }; extern DB db;...and here is a sample Arduino sketch demonstrating usage: // DB library test/example sketch #include <EEPROM.h> #include <DB.h> #define TEST_TBL_PTR 3072 DB db; struct Test_Rec { short id; int x,y; char product[8]; } test_rec; void listRecords() { for (int i=0;i<db.DB_head.n_recs;i++) { db.read(i+1, DB_REC test_rec); Serial.print("id: "); Serial.println(test_rec.id,DEC); Serial.print("x,y: "); Serial.print(test_rec.x,DEC); Serial.print(','); Serial.println(test_rec.y,DEC); Serial.print("product = "); Serial.println(test_rec.product); Serial.println(); } } void setup() { char buf[8]; int i; Serial.begin(9600); db.create(TEST_TBL_PTR, sizeof(test_rec)); // no need to call db.open after a create for (i=0;i<5;i++) { test_rec.id = i; test_rec.x = i*2; test_rec.y = i*3; itoa(test_rec.x*test_rec.y,test_rec.product,10); db.append(DB_REC test_rec); } listRecords(); Serial.print("NRecs = "); Serial.println(db.DB_head.n_recs,DEC); Serial.println("---------------"); db.deleteRec(2, DB_REC test_rec); Serial.println("Deleted rec 2"); Serial.print("NRecs = "); Serial.println(db.DB_head.n_recs,DEC); Serial.println("---------------"); listRecords(); Serial.println("---------------"); test_rec.id=99; test_rec.x=99; test_rec.y=99; db.insert(2,DB_REC test_rec); Serial.println("Inserted new #2=99"); Serial.print("NRecs = "); Serial.println(db.DB_head.n_recs,DEC); Serial.println("---------------"); listRecords(); } void loop() { } FLIntFLInt stands for Float, Long, and Integer types. This is basically a set of routines for formating numbers to strings.
LCDShieldThis is a useful library for human I/O using the popular LCD shield for Arduinos.
MotorThis has a few kludges in the code to account for differences in the Azimuth and Altitude angle calculations, but the rest is pretty generic and all intended to work with most H-bridge style motor drivers.
SolPosThe SolPos algorithm was developed by Martin Rymes with the NREL. I hacked it up fairly severely to save memory space on the Arduino, but it retains most of the original's functionality.TriadHere's some bona fide rocket science. The so called Triad algorithm was developed by NASA scientists as a means of determining attitude based on two measurements of another frame of reference. Applied to the issue of heliostat mount alignment and the Triad algorithm allows deduction of the Euler pitch and roll angles for the azimuth axis of rotation which allows the MCU to compensate for these alignment errors while tracking.
The Triad algorithm requires two vectors in the body (i.e. rocket/heliostat) frame of reference, and two corresponding vectors expressed in the inertial (earth) frame of reference. The cross product is used to create a third and orthogonal vector for each input vector pair. Things are normalized and the resulting pair of vector triads represents a frames of reference for the body and inertial systems. By some magic of matrix math, the attitude matrix relating these two systems is found by summing the dot products of each vector with its corresponding transposed vector pair, but I bet you already knew that.
The Triad algorithm is part of a general vector library. /* example usage Matrix3x3 Rbi; Vector v1b,v2b,v1i,v2i; v1b = ... v2b = ... v1i = ... v2i = ... useTriad(v1b,v2b,v1i,v2i,Rbi); Roll = atan2(-Rbi.b2,Rbi.b1); Pitch = asin(Rbi.b0); Yaw = atan2(-Rbi.c0,Rbi.a0); */ |