00001 /*!@file Devices/BeeStem3.C Simple interface to beestem */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Devices/BeeStem3.C $ 00035 // $Id: BeeStem3.C 13312 2010-04-26 02:16:07Z beobot $ 00036 // 00037 00038 #include "Devices/BeeStem3.H" 00039 00040 #include "Component/OptionManager.H" 00041 #include <string> 00042 00043 #define BS_CMD_DELAY 5000000 00044 00045 // ###################################################################### 00046 BeeStem3::BeeStem3(OptionManager& mgr, const std::string& descrName, 00047 const std::string& tagName, const char *defdev) : 00048 ModelComponent(mgr, descrName, tagName), 00049 itsPort(new Serial(mgr)) 00050 { 00051 // set a default config for our serial port: 00052 itsPort->configure(defdev, 57600, "8N1", false, false, 1); 00053 // itsPort->setBlocking(true); 00054 00055 // attach our port as a subcomponent: 00056 addSubComponent(itsPort); 00057 00058 mMotorControllerState.resize(NUM_MOTOR_CONTROLLERS); 00059 00060 for(int i = 0; i < mMotorControllerState.size(); i ++) 00061 { 00062 mMotorControllerState[i] = 0; 00063 } 00064 00065 pthread_mutex_init(&itsSerialLock, NULL); 00066 } 00067 00068 // ###################################################################### 00069 BeeStem3::~BeeStem3() 00070 { 00071 pthread_mutex_destroy(&itsSerialLock); 00072 } 00073 00074 // ###################################################################### 00075 bool BeeStem3::getSensors(int &accelX,int &accelY,int &accelZ, 00076 int &compassHeading, int &compassPitch, int &compassRoll, 00077 int &internalPressure, int &externalPressure, 00078 int &desiredHeading, int &desiredDepth, int &desiredSpeed, 00079 int &headingK, int &headingP, int &headingD, int &headingI, int &headingOutput, 00080 int &depthK, int &depthP, int &depthD, int &depthI, int &depthOutput, char &killSwitch)//, 00081 // int &thruster1, int &thruster2,int &thruster3, 00082 //int &thruster4,int &thruster5,int &thruster6) 00083 { 00084 char readCmd = 0x00; 00085 char accel_data[3]; 00086 unsigned char adc_data[32]; 00087 char desired_heading[2]; 00088 char desired_depth[2]; 00089 char desired_speed; 00090 char marker_drop[2]; 00091 char comp_accel[6]; 00092 char comp_mag[6]; 00093 char comp_heading[6]; 00094 char comp_tilt[6]; 00095 char battery[4]; 00096 char pid[12]; 00097 char kill_switch; 00098 char temp; 00099 00100 00101 //clear serial buffer 00102 while(itsPort->read(&temp,1)); 00103 00104 // send read command to Propeller 00105 itsPort->write(&readCmd, 1); 00106 usleep(40000); 00107 00108 //read accelerometer 00109 int size = itsPort->read(&accel_data, 3); 00110 00111 if(size <= 0) 00112 { 00113 LERROR("Couldn't read accel_data."); 00114 return false; 00115 } 00116 00117 accelX = accel_data[0]; 00118 accelY = accel_data[1]; 00119 accelZ = accel_data[2]; 00120 00121 //read adc data 00122 size = itsPort->read(&adc_data, 32); 00123 00124 if(size <= 0) 00125 { 00126 LERROR("Couldn't read adc_data."); 00127 return false; 00128 } 00129 00130 internalPressure = adc_data[14]; 00131 internalPressure += adc_data[15]<<8; 00132 00133 externalPressure = adc_data[12]; 00134 externalPressure += adc_data[13]<<8; 00135 00136 /* thruster1 = adc_data[16]; 00137 thruster1 += adc_data[17]<<8; 00138 00139 thruster2 = adc_data[18]; 00140 thruster2 += adc_data[19]<<8; 00141 00142 thruster3 = adc_data[20]; 00143 thruster3 += adc_data[21]<<8; 00144 00145 thruster4 = adc_data[22]; 00146 thruster4 += adc_data[23]<<8; 00147 00148 thruster5 = adc_data[24]; 00149 thruster5 += adc_data[25]<<8; 00150 00151 thruster6 = adc_data[26]; 00152 thruster6 += adc_data[27]<<8;*/ 00153 00154 //read desired heading 00155 size = itsPort->read(&desired_heading, 2); 00156 00157 if(size <= 0) 00158 { 00159 LERROR("Couldn't read desired_heading."); 00160 return false; 00161 } 00162 00163 desiredHeading = desired_heading[0]; 00164 desiredHeading += desired_heading[1]<<8; 00165 00166 //read desired depth 00167 size = itsPort->read(&desired_depth, 2); 00168 00169 if(size <= 0) 00170 { 00171 LERROR("Couldn't read desired_depth."); 00172 return false; 00173 } 00174 00175 desiredDepth = (255 & desired_depth[0]); 00176 desiredDepth |= (255 & desired_depth[1]<<8) & 65280; 00177 00178 //read desired speed 00179 size = itsPort->read(&desired_speed, 1); 00180 00181 if(size <= 0) 00182 { 00183 LERROR("Couldn't read desired_speed."); 00184 return false; 00185 } 00186 00187 desiredSpeed = desired_speed; 00188 00189 //read marker droppers 00190 size = itsPort->read(&marker_drop, 2); 00191 00192 if(size <= 0) 00193 { 00194 LERROR("Couldn't read marker_drop."); 00195 return false; 00196 } 00197 00198 //read compass acceleration 00199 size = itsPort->read(&comp_accel, 6); 00200 00201 if(size <= 0) 00202 { 00203 LERROR("Couldn't read comp_accel."); 00204 return false; 00205 } 00206 00207 //read compass magnetic field 00208 size = itsPort->read(&comp_mag, 6); 00209 00210 if(size <= 0) 00211 { 00212 LERROR("Couldn't read comp_mag."); 00213 return false; 00214 } 00215 00216 //read compass heading 00217 size = itsPort->read(&comp_heading, 6); 00218 00219 if(size <= 0) 00220 { 00221 LERROR("Couldn't read comp_heading."); 00222 return false; 00223 } 00224 00225 00226 compassHeading = (unsigned char) comp_heading[0]; 00227 compassHeading += (unsigned char) (comp_heading[1])<<8; 00228 00229 compassPitch = comp_heading[2]; 00230 compassPitch += comp_heading[3]<<8; 00231 00232 compassRoll = comp_heading[4]; 00233 compassRoll += comp_heading[5]<<8; 00234 00235 //read compass tilt 00236 size = itsPort->read(&comp_tilt, 6); 00237 00238 if(size <= 0) 00239 { 00240 LERROR("Couldn't read comp_tilt."); 00241 return false; 00242 } 00243 00244 //read battery values 00245 size = itsPort->read(&battery,4); 00246 00247 if(size <= 0) 00248 { 00249 LERROR("Couldn't read battery."); 00250 return false; 00251 } 00252 00253 //read pid values 00254 size = itsPort->read(&pid,12); 00255 00256 if(size <= 0) 00257 { 00258 LERROR("Couldn't read pid."); 00259 return false; 00260 } 00261 00262 headingK = pid[0]; 00263 headingP = pid[1]; 00264 headingD = pid[2]; 00265 headingI = pid[3]; 00266 00267 headingOutput = (0x00ff & pid[4]); 00268 headingOutput |= pid[5] << 8; 00269 00270 depthK = pid[6]; 00271 depthP = pid[7]; 00272 depthD = pid[8]; 00273 depthI = pid[9]; 00274 depthOutput = (0x00ff & pid[10]); 00275 depthOutput |= pid[11] << 8; 00276 00277 //read killswitch value 00278 size = itsPort->read(&kill_switch,1); 00279 00280 if(size <= 0) 00281 { 00282 LERROR("Couldn't read kill switch."); 00283 return false; 00284 } 00285 00286 killSwitch = kill_switch; 00287 00288 /* LINFO("desired_depth[0] = %x, desired_depth[1] = %x, depthOutput= %x", 00289 (0x00ff & pid[10]), 00290 ((0x00ff & pid[11]) << 8) & 0x0ff00, 00291 depthOutput); */ 00292 00293 return true; 00294 } 00295 00296 bool BeeStem3::setPID(int pidMode, float k, float p, float i, float d) 00297 { 00298 LINFO("pidMode: %d, k %f, p %f, i %f, %f",pidMode,k,p,i,d); 00299 00300 char pidCmdK; 00301 char pidCmdP; 00302 char pidCmdI; 00303 char pidCmdD; 00304 char pidDepthEn = 0x61; 00305 char pidHeadingEn = 0x60; 00306 char en = 0x01; 00307 char dis = 0x00; 00308 00309 int16 kv, pv, iv, dv; 00310 kv = k*100; 00311 pv = p*100; 00312 iv = i*100; 00313 dv = d*100; 00314 00315 char temp; 00316 00317 //clear serial buffer 00318 while(itsPort->read(&temp,1)); 00319 00320 switch(pidMode) 00321 { 00322 case PID_DEPTH: 00323 pidCmdK = 0x20; 00324 pidCmdP = 0x21; 00325 pidCmdI = 0x22; 00326 pidCmdD = 0x23; 00327 break; 00328 case PID_HEADING: 00329 pidCmdK = 0x30; 00330 pidCmdP = 0x31; 00331 pidCmdI = 0x32; 00332 pidCmdD = 0x33; 00333 break; 00334 case PID_DISABLE: 00335 LINFO("Disable PID."); 00336 itsPort->write(&pidDepthEn, 1); 00337 itsPort->write(&dis, 1); 00338 itsPort->write(&pidHeadingEn, 1); 00339 itsPort->write(&dis, 1); 00340 return true; 00341 break; 00342 case PID_ENABLE: 00343 LINFO("Enable PID."); 00344 itsPort->write(&pidDepthEn, 1); 00345 itsPort->write(&en, 1); 00346 //itsPort->write(&pidHeadingEn, 1); 00347 //itsPort->write(&en, 1); 00348 return true; 00349 break; 00350 default: 00351 LERROR("Invalid PID mode specified."); 00352 return false; 00353 } 00354 00355 00356 // send set update K cmd upper lower 00357 itsPort->write(&pidCmdK, 1); 00358 00359 temp =(kv & 0xff00) >> 8; 00360 itsPort->write(&temp,1); 00361 temp =(kv & 0x00ff); 00362 itsPort->write(&temp,1); 00363 00364 // send set update P cmd 00365 itsPort->write(&pidCmdP, 1); 00366 temp =(pv & 0xff00) >> 8; 00367 itsPort->write(&temp,1); 00368 temp =(pv & 0x00ff); 00369 itsPort->write(&temp,1); 00370 00371 // send set update K cmd 00372 itsPort->write(&pidCmdI, 1); 00373 temp =(iv & 0xff00) >> 8; 00374 itsPort->write(&temp,1); 00375 temp =(iv & 0x00ff); 00376 itsPort->write(&temp,1); 00377 00378 // send set update K cmd 00379 itsPort->write(&pidCmdD, 1); 00380 temp =(dv & 0xff00) >> 8; 00381 itsPort->write(&temp,1); 00382 temp =(dv & 0x00ff); 00383 itsPort->write(&temp,1); 00384 00385 return true; 00386 } 00387 00388 void BeeStem3::setThruster(int num, int val) 00389 { 00390 if(val == mMotorControllerState[num]) //don't bother setting it if it's already at this value 00391 { 00392 return; 00393 } 00394 mMotorControllerState[num] = val; //save the new state 00395 printf("Set thruster [%d]:%d\n", num, val); 00396 char thrusterCmd = 0xff; 00397 //char temp; 00398 00399 //clear serial buffer 00400 // while(itsPort->read(&temp,1)); 00401 00402 // send set thruster command to Propeller 00403 itsPort->write(&thrusterCmd, 1); 00404 00405 // while(itsPort->read(&temp, 1) != 0) 00406 // std::cout << temp; 00407 // std::cout << std::endl; 00408 00409 // send set thruster command to Propeller 00410 itsPort->write(&num, 1); 00411 //while(itsPort->read(&temp, 1) != 0) 00412 // printf("%c", temp); 00413 //std::cout << std::endl; 00414 00415 // send set thruster command to Propeller 00416 itsPort->write(&val, 1); 00417 } 00418 00419 /*bool BeeStem3::setDesiredValues(int16 heading, int16 depth, char speed, 00420 char markerDropper) 00421 { 00422 char setDesiredHeadingCmd = 0x0b; 00423 char setDesiredDepthCmd = 0x0c; 00424 char temp; 00425 00426 //clear serial buffer 00427 while(itsPort->read(&temp,1)); 00428 00429 // send set desired values command to Propeller 00430 itsPort->write(&setDesiredHeadingCmd, 1); 00431 00432 char headingUpper = ((0x00ff00 & heading) >> 8) & 0x00ff; 00433 char headingLower = (heading & 0x00ff); 00434 00435 char depthUpper = ((0x00ff00 &depth) >> 8) & 0x00ff; 00436 char depthLower = (depth & 0x00ff); 00437 00438 LINFO("Writing Heading Upper %x", headingUpper); 00439 itsPort->write(&headingUpper,1); 00440 LINFO("Writing Heading Lower %x", headingLower); 00441 itsPort->write(&headingLower,1); 00442 00443 itsPort->write(&setDesiredDepthCmd, 1); 00444 00445 itsPort->write(&depthUpper,1); 00446 itsPort->write(&depthLower,1); 00447 00448 itsPort->write(&speed,1); 00449 itsPort->write(&markerDropper,1); 00450 itsPort->write(&markerDropper,1); 00451 00452 return true; 00453 }*/ 00454 00455 bool BeeStem3::setDesiredHeading(int16 heading) 00456 { 00457 char setDesiredHeadingCmd = 0x0b; 00458 char temp; 00459 00460 //clear serial buffer 00461 while(itsPort->read(&temp,1)); 00462 00463 // send set desired values command to Propeller 00464 itsPort->write(&setDesiredHeadingCmd, 1); 00465 00466 char headingUpper = ((0x00ff00 & heading) >> 8) & 0x00ff; 00467 char headingLower = (heading & 0x00ff); 00468 00469 LINFO("Writing Heading Upper %x", headingUpper); 00470 itsPort->write(&headingUpper,1); 00471 LINFO("Writing Heading Lower %x", headingLower); 00472 itsPort->write(&headingLower,1); 00473 00474 return true; 00475 } 00476 00477 bool BeeStem3::setDesiredDepth(int16 depth) 00478 { 00479 char setDesiredDepthCmd = 0x0c; 00480 char temp; 00481 00482 //clear serial buffer 00483 while(itsPort->read(&temp,1)); 00484 00485 // send set desired values command to Propeller 00486 itsPort->write(&setDesiredDepthCmd, 1); 00487 00488 char depthUpper = ((0x00ff00 & depth) >> 8) & 0x00ff; 00489 char depthLower = (depth & 0x00ff); 00490 00491 LINFO("Writing Depth Upper %x", depthUpper); 00492 itsPort->write(&depthUpper,1); 00493 LINFO("Writing Depth Lower %x", depthLower); 00494 itsPort->write(&depthLower,1); 00495 00496 return true; 00497 } 00498 00499 bool BeeStem3::setDesiredSpeed(char speed) 00500 { 00501 char setDesiredSpeedCmd = 0x0d; 00502 char temp; 00503 00504 //clear serial buffer 00505 while(itsPort->read(&temp,1)); 00506 00507 // send set desired values command to Propeller 00508 itsPort->write(&setDesiredSpeedCmd, 1); 00509 00510 LINFO("Setting speed: %d\n",speed); 00511 itsPort->write(&speed,1); 00512 00513 return true; 00514 } 00515 00516 void BeeStem3::startCompassCalibration() 00517 { 00518 char startCalibCmd = 0xe0; 00519 char temp; 00520 00521 //clear serial buffer 00522 while(itsPort->read(&temp,1)); 00523 00524 // send set desired values command to Propeller 00525 itsPort->write(&startCalibCmd, 1); 00526 } 00527 00528 void BeeStem3::endCompassCalibration() 00529 { 00530 char endCalibCmd = 0xe1; 00531 char temp; 00532 00533 //clear serial buffer 00534 while(itsPort->read(&temp,1)); 00535 00536 // send set desired values command to Propeller 00537 itsPort->write(&endCalibCmd, 1); 00538 } 00539 00540 // ###################################################################### 00541 /* So things look consistent in everyone's emacs... */ 00542 /* Local Variables: */ 00543 /* indent-tabs-mode: nil */ 00544 /* End: */