StoRC
Autonomous Payload Delivery System
|
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