StoRC
Autonomous Payload Delivery System
log.pde
Go to the documentation of this file.
00001 /***********************************************************
00002  * StoRC - Search to Rescue Craft
00003  * MEAM Senior Design 2011-2012
00004  * 
00005  * Authors:  Michael Posner (CIS, MEAM '12)
00006  * Timothy Hennelly (ESE '12)
00007  * Jacob Orloff (MEAM '12)
00008  * 
00009  * (some code from ArduPilot Mega project, found here:
00010  * http://code.google.com/p/ardupilot-mega/ )
00011  * 
00012  * Licensing:
00013  * 
00014  * This program is free software: you can redistribute it and/or modify 
00015  * it under the terms of the GNU General Public License as published by 
00016  * the Free Software Foundation, either version 3 of the License, or 
00017  * (at your option) any later version. 
00018  * 
00019  * This program is distributed in the hope that it will be useful, 
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
00022  * GNU General Public License for more details. 
00023  * 
00024  * You should have received a copy of the GNU General Public License 
00025  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00026  * 
00027  ***********************************************************/
00028 
00029 /**
00030 *  @file log.pde
00031 *  @brief Flash memory logging functions
00032 *  @author Michael Posner (CIS, MEAM '12)
00033 *  @author Timothy Hennelly (ESE '12)
00034 *  @author Jacob Orloff (MEAM '12)
00035 *  
00036 *  logging file, mostly copied from ArduPilot.  this allows us to write to
00037  the flash memory.  when a logging Write() function is changed here, make sure its
00038  appropriate Read() counterpart is changed in the default code you use to
00039  download the log. (it will give an Error Reading END_BYTE error if the 
00040  read() formate doesnt match the format that the data was written in below)
00041  Note:  Instead of modifying the DataFlash library to write floats (kinda hard), 
00042  instead a hack is to multiply the float value by 10^5 or whatever, then cast to long
00043  in the Write() function and write it using the long writing function.  Then, in the
00044  Read() function, cast back to float and divide by 10^5.
00045 */
00046 
00047 
00048 /**
00049 *  ArduPilot function.  figures out how many logs are currently in flash memory.
00050 *  @return the number of logs currently in flash memory
00051 */
00052 byte get_num_logs(void)
00053 {
00054         int page = 1;
00055         byte data;
00056         byte log_step = 0;
00057 
00058         DataFlash.StartRead(1);
00059 
00060         while (page == 1) {
00061                 data = DataFlash.ReadByte();
00062 
00063                 switch(log_step){                //This is a state machine to read the packets
00064                         case 0:
00065                                 if(data==HEAD_BYTE1)    // Head byte 1
00066                                         log_step++;
00067                                 break;
00068 
00069                         case 1:
00070                                 if(data==HEAD_BYTE2)    // Head byte 2
00071                                         log_step++;
00072                                 else
00073                                         log_step = 0;
00074                                 break;
00075 
00076                         case 2:
00077                                 if(data==LOG_INDEX_MSG){
00078                                         byte num_logs = DataFlash.ReadByte();
00079                                         return num_logs;
00080                                 }else{
00081                                                 log_step=0;      // Restart, we have a problem...
00082                                 }
00083                                 break;
00084                         }
00085                 page = DataFlash.GetPage();
00086         }
00087         return 0;
00088 }
00089 
00090 /**
00091 *  ArduPilot Mega function.  starts a new log file.
00092 *  @param num_existing_logs  the number of logs already in memory, as returned
00093 *    by @link{get_num_logs}
00094 *  @see get_num_logs
00095 */
00096 void start_new_log(byte num_existing_logs)
00097 {
00098         int start_pages[50] = {0,0,0};
00099         int end_pages[50]       = {0,0,0};
00100 
00101         if(num_existing_logs > 0) {
00102                 for(int i=0;i<num_existing_logs;i++) {
00103                         get_log_boundaries(i+1,start_pages[i],end_pages[i]);
00104                 }
00105                 end_pages[num_existing_logs - 1] = find_last_log_page(start_pages[num_existing_logs - 1]);
00106         }
00107 
00108         if(end_pages[num_existing_logs - 1] < 4095 && num_existing_logs < MAX_NUM_LOGS) {
00109                 if(num_existing_logs > 0)
00110                         start_pages[num_existing_logs] = end_pages[num_existing_logs - 1] + 1;
00111                 else
00112                         start_pages[0] = 2;
00113                 num_existing_logs++;
00114                 DataFlash.StartWrite(1);
00115                 DataFlash.WriteByte(HEAD_BYTE1);
00116                 DataFlash.WriteByte(HEAD_BYTE2);
00117                 DataFlash.WriteByte(LOG_INDEX_MSG);
00118                 DataFlash.WriteByte(num_existing_logs);
00119                 for(int i=0;i<MAX_NUM_LOGS;i++) {
00120                         DataFlash.WriteInt(start_pages[i]);
00121                         DataFlash.WriteInt(end_pages[i]);
00122                 }
00123                 DataFlash.WriteByte(END_BYTE);
00124                 DataFlash.FinishWrite();
00125                 DataFlash.StartWrite(start_pages[num_existing_logs-1]);
00126         }
00127         else{ //logs are full
00128           Serial.println("--LOGS ARE FULL--");
00129         }
00130 }
00131 
00132 /**
00133 *  ArduPilot Mega function.  figures out the boundaries of the log.  
00134 */
00135 void get_log_boundaries(byte log_num, int & start_page, int & end_page)
00136 {
00137         int page                = 1;
00138         byte data;
00139         byte log_step   = 0;
00140 
00141         DataFlash.StartRead(1);
00142         while (page == 1) {
00143                 data = DataFlash.ReadByte();
00144                 switch(log_step)                 //This is a state machine to read the packets
00145                         {
00146                         case 0:
00147                                 if(data==HEAD_BYTE1)    // Head byte 1
00148                                         log_step++;
00149                                 break;
00150                         case 1:
00151                                 if(data==HEAD_BYTE2)    // Head byte 2
00152                                         log_step++;
00153                                 else
00154                                         log_step = 0;
00155                                 break;
00156                         case 2:
00157                                 if(data==LOG_INDEX_MSG){
00158                                         byte num_logs = DataFlash.ReadByte();
00159                                         for(int i=0;i<log_num;i++) {
00160                                                 start_page = DataFlash.ReadInt();
00161                                                 end_page = DataFlash.ReadInt();
00162                                         }
00163                                         if(log_num==num_logs)
00164                                                 end_page = find_last_log_page(start_page);
00165 
00166                                         return;         // This is the normal exit point
00167                                 }else{
00168                                                 log_step=0;      // Restart, we have a problem...
00169                                 }
00170                                 break;
00171                         }
00172                 page = DataFlash.GetPage();
00173         }
00174         //  Error condition if we reach here with page = 2   TO DO - report condition
00175 }
00176 
00177 /**
00178 *  ArduPilot Mega function.  finds the last log page.
00179 */
00180 int find_last_log_page(int bottom_page)
00181 {
00182         int top_page = 4096;
00183         int look_page;
00184         long check;
00185 
00186         while((top_page - bottom_page) > 1) {
00187                 look_page = (top_page + bottom_page) / 2;
00188                 DataFlash.StartRead(look_page);
00189                 check = DataFlash.ReadLong();
00190                 if(check == (long)0xFFFFFFFF)
00191                         top_page = look_page;
00192                 else
00193                         bottom_page = look_page;
00194         }
00195         return top_page;
00196 }
00197 
00198 
00199 
00200 /**
00201 *  modified function from ArduPilot Mega.  Logs IMU data.  Be careful when casting from float to long!
00202 *  long is an integer type and cannot store decimals.  so this function takes in floats, but since the 
00203 *  flash library can't write floats (I looked into modifying it, but this hack is easier), I multiply
00204 *  the float by 10000 and then cast to a long.  Then the corresponding Read function divides by 10000
00205 *  before writing to the text file.
00206 */
00207 void Log_Write_IMU(float gyro_x, float gyro_y, float gyro_z, float accel_x, float accel_y, float accel_z)
00208 {
00209         
00210         DataFlash.WriteByte(HEAD_BYTE1);
00211         DataFlash.WriteByte(HEAD_BYTE2);
00212         DataFlash.WriteByte(LOG_IMU_MSG);
00213         DataFlash.WriteLong(millis());
00214         DataFlash.WriteLong((long)(gyro_x*10000.0));
00215         DataFlash.WriteLong((long)(gyro_y*10000.0));
00216         DataFlash.WriteLong((long)(gyro_z*10000.0));
00217         DataFlash.WriteLong((long)(accel_x*10000.0));
00218         DataFlash.WriteLong((long)(accel_y*10000.0));
00219         DataFlash.WriteLong((long)(accel_z*10000.0));
00220         DataFlash.WriteByte(END_BYTE);
00221         
00222 }
00223 
00224 /**
00225 * modified function from ArduPilot Mega.  Logs GPS data.  Note that the GPS library already returns
00226 * longitude and latitude as their actual values * 10^7, as well as the altitude, ground speed, and ground course 
00227 * as their actual values * 100, so there's no need to multiply before saving as longs.
00228 * @param log_day the number of the day of the week (0=Sun, 1=Mon, ... 6=Sat)
00229 * @param log_hour the hour of the current day (0 - 23)
00230 * @param log_minute the minute of the current hour (0 - 59)
00231 * @param log_second the second of the current minute (0-59)
00232 * @param log_latitude the GPS latitude, multiplied by 10^7 (this is necessary to log in long format while keeping significant digits)
00233 * @param log_longitude the GPS longitude, multiplied by 10^7 (this is necessary to log in long format while keeping significant digits)
00234 * @param log_altitude the altitude in cm (m * 100)
00235 * @param log_ground_speed the ground speed in cm/s (m/s * 100)
00236 * @param log_ground_course the ground course in hundredths of a degree (deg * 100)
00237 */
00238 void Log_Write_GPS(     long log_day, long log_hour, long log_minute, long log_second, long log_latitude, long log_longitude, long log_altitude,
00239                             long log_ground_speed, long log_ground_course)
00240 {
00241         DataFlash.WriteByte(HEAD_BYTE1);
00242         DataFlash.WriteByte(HEAD_BYTE2);
00243         DataFlash.WriteByte(LOG_GPS_MSG);
00244         DataFlash.WriteLong(millis());
00245         DataFlash.WriteLong(log_day);
00246         DataFlash.WriteLong(log_hour);
00247         DataFlash.WriteLong(log_minute);
00248         DataFlash.WriteLong(log_second);
00249         DataFlash.WriteLong(log_latitude);
00250         DataFlash.WriteLong(log_longitude);
00251         DataFlash.WriteLong(log_altitude);
00252         DataFlash.WriteLong(log_ground_speed);
00253         DataFlash.WriteLong(log_ground_course);
00254         DataFlash.WriteByte(END_BYTE);
00255 }
00256 
00257 /**
00258 *  Logs barometer data.
00259 */
00260 void Log_Write_Barometer(float temp, float press)
00261 {
00262         DataFlash.WriteByte(HEAD_BYTE1);
00263         DataFlash.WriteByte(HEAD_BYTE2);
00264         DataFlash.WriteByte(LOG_BAROMETER_MSG);
00265         DataFlash.WriteLong(millis());
00266         DataFlash.WriteLong((long)(temp*10000.0));
00267         DataFlash.WriteLong((long)(press*10000.0));
00268         DataFlash.WriteByte(END_BYTE);
00269 }
00270 
00271 /**
00272 *  Logs RC servo values.
00273 */
00274 void Log_Write_RC(int elevator, int rudder, int throttle, int ch4, int ch5, int ch6, int ch7, int ch8)
00275 {
00276         DataFlash.WriteByte(HEAD_BYTE1);
00277         DataFlash.WriteByte(HEAD_BYTE2);
00278         DataFlash.WriteByte(LOG_RC_MSG);
00279         DataFlash.WriteLong(millis());
00280         DataFlash.WriteLong((long)(elevator));
00281         DataFlash.WriteLong((long)(rudder));
00282         DataFlash.WriteLong((long)(throttle));
00283         DataFlash.WriteLong((long)(ch4));
00284         DataFlash.WriteLong((long)(ch5));
00285         DataFlash.WriteLong((long)(ch6));
00286         DataFlash.WriteLong((long)(ch7));
00287         DataFlash.WriteLong((long)(ch8));
00288         DataFlash.WriteByte(END_BYTE);
00289 }
00290 
00291 /**
00292 *  Logs Airspeed value
00293 */
00294 void Log_Write_Airspeed(float a)
00295 {
00296         DataFlash.WriteByte(HEAD_BYTE1);
00297         DataFlash.WriteByte(HEAD_BYTE2);
00298         DataFlash.WriteByte(LOG_AIRSPEED_MSG);
00299         DataFlash.WriteLong(millis());
00300         DataFlash.WriteLong((long)(a*10000.0));
00301         DataFlash.WriteByte(END_BYTE);
00302 }
00303 
00304 
00305 /**
00306 * Logs magnetometer values
00307 */
00308 void Log_Write_Magnetometer(float h, float r, float p, float y)
00309 {
00310         DataFlash.WriteByte(HEAD_BYTE1);
00311         DataFlash.WriteByte(HEAD_BYTE2);
00312         DataFlash.WriteByte(LOG_MAG_MSG);
00313         DataFlash.WriteLong(millis());
00314         DataFlash.WriteLong((long)(h*10000.0));
00315         DataFlash.WriteLong((long)(r*10000.0));
00316         DataFlash.WriteLong((long)(p*10000.0));
00317         DataFlash.WriteLong((long)(y*10000.0));
00318         DataFlash.WriteByte(END_BYTE);
00319 }
00320 
00321 
00322 /**
00323 *  Logs rudder controls values
00324 */
00325 void Log_Write_Controls_Rudder(float kpRud, float kpRudGm, float kdRud, float kdRudGm, float kiRud, float kiRudGm, float iRud, float delta)
00326 {
00327         DataFlash.WriteByte(HEAD_BYTE1);
00328         DataFlash.WriteByte(HEAD_BYTE2);
00329         DataFlash.WriteByte(LOG_CONTROLS_RUDDER_MSG);
00330         DataFlash.WriteLong(millis());
00331         DataFlash.WriteLong((long)(kpRud*10000.0));
00332         DataFlash.WriteLong((long)(kpRudGm*10000.0));
00333         DataFlash.WriteLong((long)(kdRud*10000.0));
00334         DataFlash.WriteLong((long)(kdRudGm*10000.0));
00335         DataFlash.WriteLong((long)(kiRud*10000.0));
00336         DataFlash.WriteLong((long)(kiRudGm*10000.0));
00337         DataFlash.WriteLong((long)(iRud*10000.0));
00338         DataFlash.WriteLong((long)(delta*10000.0));
00339         DataFlash.WriteByte(END_BYTE);
00340 }
00341 
00342 /**
00343 *  Logs elevator controls values
00344 */
00345 void Log_Write_Controls_Elevator(float kpEle, float kpEleGm, float kpRp, float kiEle, float kiEleGm, float iEle, float delta)
00346 {
00347         DataFlash.WriteByte(HEAD_BYTE1);
00348         DataFlash.WriteByte(HEAD_BYTE2);
00349         DataFlash.WriteByte(LOG_CONTROLS_ELEVATOR_MSG);
00350         DataFlash.WriteLong(millis());
00351         DataFlash.WriteLong((long)(kpEle*10000.0));
00352         DataFlash.WriteLong((long)(kpEleGm*10000.0));
00353         DataFlash.WriteLong((long)(kpRp*10000.0));
00354         DataFlash.WriteLong((long)(kiEle*10000.0));
00355         DataFlash.WriteLong((long)(kiEleGm*10000.0));
00356         DataFlash.WriteLong((long)(iEle*10000.0));
00357         DataFlash.WriteLong((long)(delta*10000.0));
00358         DataFlash.WriteByte(END_BYTE);
00359 }
00360 
00361 /**
00362 *  Logs throttle controls values
00363 */
00364 void Log_Write_Controls_Throttle(float kpThr, float kpThrGm, float kiThr, float kiThrGm, float iThr, float delAlt, float delta)
00365 {
00366         DataFlash.WriteByte(HEAD_BYTE1);
00367         DataFlash.WriteByte(HEAD_BYTE2);
00368         DataFlash.WriteByte(LOG_CONTROLS_THROTTLE_MSG);
00369         DataFlash.WriteLong(millis());
00370         DataFlash.WriteLong((long)(kpThr*10000.0));
00371         DataFlash.WriteLong((long)(kpThrGm*10000.0));
00372         DataFlash.WriteLong((long)(kiThr*10000.0));
00373         DataFlash.WriteLong((long)(kiThrGm*10000.0));
00374         DataFlash.WriteLong((long)(iThr*10000.0));
00375         DataFlash.WriteLong((long)(delAlt*10000.0));
00376         DataFlash.WriteLong((long)(delta*10000.0));
00377         DataFlash.WriteByte(END_BYTE);
00378 }
00379 
00380 /**
00381 *  Logs code state (drop status, logging switch)
00382 */
00383 void Log_Write_State(boolean drop_status, int logging_switch, boolean windProfile, float avgWindNS, float avgWindEW, float driftNS, float driftEW)
00384 {
00385         DataFlash.WriteByte(HEAD_BYTE1);
00386         DataFlash.WriteByte(HEAD_BYTE2);
00387         DataFlash.WriteByte(LOG_STATE_MSG);
00388         DataFlash.WriteLong(millis());
00389         
00390         if(drop_status) {
00391           DataFlash.WriteByte(1);
00392         }
00393         else {
00394           DataFlash.WriteByte(0);
00395         }
00396         DataFlash.WriteInt(logging_switch);
00397         if(windProfile) {
00398           DataFlash.WriteByte(1);
00399         }
00400         else {
00401           DataFlash.WriteByte(0);
00402         }
00403         DataFlash.WriteLong((long)(avgWindNS*10000.0));
00404         DataFlash.WriteLong((long)(avgWindEW*10000.0));
00405         DataFlash.WriteLong((long)(driftNS*10000.0));
00406         DataFlash.WriteLong((long)(driftEW*10000.0));
00407         DataFlash.WriteByte(END_BYTE);
00408 }
00409 
00410 
00411 /**
00412 *  Logs navigation values
00413 */
00414 void Log_Write_Navigation(long latc, long lonc, long delLat, long delLon, float psic, float psierror, float phic, long dropThresh)
00415 {
00416         DataFlash.WriteByte(HEAD_BYTE1);
00417         DataFlash.WriteByte(HEAD_BYTE2);
00418         DataFlash.WriteByte(LOG_NAVIGATION_MSG);
00419         DataFlash.WriteLong(millis());
00420         DataFlash.WriteLong(latc);
00421         DataFlash.WriteLong(lonc);
00422         DataFlash.WriteLong(delLat);
00423         DataFlash.WriteLong(delLon);
00424         DataFlash.WriteLong((long)(psic*10000.0));
00425         DataFlash.WriteLong((long)(psierror*10000.0));
00426         DataFlash.WriteLong((long)(phic*10000.0));
00427         DataFlash.WriteLong(dropThresh);
00428         DataFlash.WriteByte(END_BYTE);
00429 }
00430