most functionality to splashdwon, find neutral and start mission. short timeouts still in code for testing, will adjust to go directly to sit_idle after splashdown
Dependencies: mbed MODSERIAL FATFileSystem
IMU.cpp
00001 #include "IMU.h" 00002 00003 IMU::IMU(PinName Tx, PinName Rx): 00004 _rs232(Tx,Rx) 00005 { 00006 } 00007 00008 void IMU::initialize() { 00009 //set up the spi bus and frequency 00010 _rs232.baud(115200); 00011 00012 // initialize the processing state machine 00013 state = SYNC0; 00014 00015 // initialize to zeros 00016 euler[0] = 0.0; 00017 euler[1] = 0.0; 00018 euler[2] = 0.0; 00019 00020 // initialize to zeros 00021 latLonAlt[0] = 0.0; 00022 latLonAlt[1] = 0.0; 00023 latLonAlt[2] = 0.0; 00024 00025 // initialize to no GNSS fix 00026 is2dFixValid = false; 00027 is3dFixValid = false; 00028 numSV = 0; 00029 } 00030 00031 // this stops an interval timer trigger of the IMU update function 00032 void IMU::start() { 00033 interval.attach(this, &IMU::update, .05); //this should be a 1 Hz sample rate 00034 } 00035 00036 // this stops the interval timer trigger of the IMU update function 00037 void IMU::stop() { 00038 interval.detach(); 00039 } 00040 00041 void IMU::runIMU() { 00042 update(); 00043 } 00044 00045 // updated the imu update function with a state machine that doesn't hang if no data is present 00046 void IMU::update() { 00047 00048 // // DEBUGGING an example packet 00049 // Serial pc(USBTX, USBRX); 00050 // //char data[20] = {0x75,0x65,0x80,0x0E,0x0E,0x04,0x3E,0x7A,0x63,0xA0,0xBB,0x8E,0x3B,0x29,0x7F,0xE5,0xBF,0x7F,0x84,0xEE}; // 3d accel 00051 // char data[20] = {0x75,0x65,0x80,0x0E,0x0E,0x0C,0xBA,0xE3,0xED,0x9B,0x3C,0x7D,0x6D,0xDF,0xBF,0x85,0x5C,0xF5,0x41,0xBB}; // euler cf 00052 // for (int j=0; j<20; j++) { 00053 //byte = data[j]; 00054 00055 while (_rs232.readable()) { 00056 // read a single byte 00057 byte = _rs232.getc(); 00058 00059 // state machine to process byte-by-byte 00060 switch (state) { 00061 case SYNC0 : 00062 if (byte == 0x75) { 00063 packet[0] = byte; // save into the packet 00064 state = SYNC1; 00065 } 00066 break; 00067 00068 case SYNC1 : 00069 if (byte == 0x65) { 00070 packet[1] = byte; // save into the packet 00071 state = SET; 00072 } 00073 else { 00074 state = SYNC0; 00075 } 00076 break; 00077 00078 case SET : 00079 descriptor = byte; // save descriptor set 00080 packet[2] = byte; // save into the packet 00081 state = LEN; 00082 break; 00083 00084 case LEN : 00085 len = byte; // save payload length 00086 packet[3] = byte; // save into the packet 00087 state = PAY; 00088 i = 0; // reset payload field length counter 00089 break; 00090 00091 case PAY : 00092 if (i < len) { // keep adding until get all the payload length 00093 packet[4+i] = byte; // add byte to the packet, skipping over the header 4-bytes 00094 i++; // increment payload counter 00095 } 00096 else { 00097 state = CRC0; 00098 } 00099 if (i >= len) { // not an elseif, since we want to escape when i==len 00100 state = CRC0; 00101 } 00102 break; 00103 00104 case CRC0 : 00105 crc0 = byte; // save the msb of the checksum 00106 state = CRC1; 00107 break; 00108 00109 case CRC1 : 00110 crc1 = byte; // save the lsb of the checksum 00111 checksum = ((unsigned int)crc0 << 8) + (unsigned int)crc1; // make checksum into a uint16 00112 if (checksum == calcChecksum(packet, len+4)) { // passed checksum, wahoo! 00113 processPayload(descriptor, packet[4], &packet[4]); // process the payload part of the packet, starting at byte 4 00114 } 00115 state = SYNC0; // reset to SYNC0 state 00116 break; 00117 00118 default : 00119 state = SYNC0; 00120 } 00121 } 00122 return; 00123 } 00124 00125 void IMU::processPayload(char descriptor, char length, unsigned char * payload) { 00126 if (descriptor == IMU_DATA_SET) { // find an IMU data descriptor set 00127 if (length > 2) { // make sure there are at least two bytes to see the field descriptor 00128 if (payload[1] == EULER_CF_DESCRIPTOR) { // find an euler CF field descriptor 00129 processEulerCfPacket(length, payload); 00130 } 00131 } 00132 } 00133 else if (descriptor == GNSS_DATA_SET) { // find a GNSS data descriptor set 00134 if (length > 2) { // make sure there are at least two bytes to see the field descriptor 00135 if (payload[1] == LLH_POSITION_DESCRIPTOR) { // find a lat-lon-alt field descriptor 00136 processLatLonAltPacket(length, payload); 00137 } 00138 else if (payload[1] == GNSS_FIX_INFO_DESCRIPTOR) { // find a gnss fix field descriptor 00139 processGnssFixInformation(length, payload); 00140 } 00141 } 00142 } 00143 } 00144 00145 void IMU::processEulerCfPacket(char length, unsigned char * payload) { 00146 if (length >= EULER_CF_LENGTH) { // make sure correct field length 00147 if (payload[0] == EULER_CF_LENGTH) { // make sure field length is as expected 00148 euler[0] = floatFromChar(&payload[ROLL_OFFSET+2])*180/_PI; // roll Euler angle convert in degrees 00149 euler[1] = floatFromChar(&payload[PITCH_OFFSET+2])*180/_PI; // pitch Euler angle convert in degrees 00150 euler[2] = floatFromChar(&payload[YAW_OFFSET+2])*180/_PI; // yaw Euler angle convert in degrees 00151 } 00152 } 00153 } 00154 00155 void IMU::processLatLonAltPacket(char length, unsigned char * payload) { 00156 if (length >= LLH_POSITION_LENGTH) { // make sure correct field length 00157 if (payload[0] == LLH_POSITION_LENGTH) { // make sure field length is as expected 00158 latLonAlt[0] = doubleFromChar(&payload[LATITUDE_OFFSET+2]); // latitude in decimal degrees 00159 latLonAlt[1] = doubleFromChar(&payload[LONGITUDE_OFFSET+2]); // longitude in decimal degrees 00160 latLonAlt[2] = doubleFromChar(&payload[HEIGHT_MSL_OFFSET+2]); // altitude above mean sea level in meters 00161 } 00162 } 00163 } 00164 00165 void IMU::processGnssFixInformation(char length, unsigned char * payload) { 00166 if (length >= GNSS_FIX_INFO_LENGTH) { // make sure field length is as expected 00167 if (payload[0] == GNSS_FIX_INFO_LENGTH) { // make sure field length is as expected 00168 is2dFixValid = char(payload[FIX_TYPE_OFFSET+2]) & 0x01; // bitand on LSB to see 2d fix flag 00169 is3dFixValid = char(payload[FIX_TYPE_OFFSET+2]) & 0x02; // bitand on LSB to see 3d fix flag 00170 numSV = char(payload[NUM_SV_OFFSET+2]); // number of GNSS satellite vehicles 00171 } 00172 } 00173 } 00174 00175 float IMU::floatFromChar(unsigned char * value) { 00176 unsigned char temp[4]; 00177 temp[0] = value[3]; 00178 temp[1] = value[2]; 00179 temp[2] = value[1]; 00180 temp[3] = value[0]; 00181 return *(float *) temp; 00182 } 00183 00184 double IMU::doubleFromChar(unsigned char * value) { 00185 unsigned char temp[8]; 00186 temp[0] = value[7]; 00187 temp[1] = value[6]; 00188 temp[2] = value[5]; 00189 temp[3] = value[4]; 00190 temp[4] = value[3]; 00191 temp[5] = value[2]; 00192 temp[6] = value[1]; 00193 temp[7] = value[0]; 00194 return *(double *) temp; 00195 } 00196 00197 float IMU::getRoll() { 00198 return euler[0]; 00199 } 00200 00201 float IMU::getPitch() { 00202 return euler[1]; 00203 } 00204 00205 float IMU::getHeading() { 00206 return euler[2]; // 00207 } 00208 00209 bool IMU::getIsValid2dFix() { 00210 return is2dFixValid; 00211 } 00212 00213 bool IMU::getIsValid3dFix() { 00214 return is3dFixValid; 00215 } 00216 00217 char IMU::getNumSV() { 00218 return numSV; 00219 } 00220 00221 double IMU::getLatitude() { 00222 return latLonAlt[0]; 00223 } 00224 00225 double IMU::getLongitude() { 00226 return latLonAlt[1]; 00227 } 00228 00229 double IMU::getAltitudeMSL() { 00230 return latLonAlt[2]; 00231 } 00232 00233 unsigned int IMU::calcChecksum(unsigned char * mip_packet, char checksum_range) { 00234 unsigned char checksum_byte1 = 0; 00235 unsigned char checksum_byte2 = 0; 00236 unsigned int myChecksum = 0; 00237 00238 for (int i=0; i<checksum_range; i++) { 00239 checksum_byte1 += mip_packet[i]; 00240 checksum_byte2 += checksum_byte1; 00241 } 00242 myChecksum = ((unsigned int)checksum_byte1 << 8) + (unsigned int)checksum_byte2; 00243 return myChecksum; 00244 }
Generated on Thu Jul 14 2022 10:54:35 by 1.7.2