00001 /*!@file Devices/Pololu.C Interface to poloau Serial Servo Controller */ 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/Pololu.C $ 00035 // $Id: Pololu.C 8524 2007-06-28 20:37:05Z rjpeters $ 00036 // 00037 00038 #include "Devices/Pololu.H" 00039 00040 #include "Component/OptionManager.H" 00041 #include "Devices/Serial.H" 00042 00043 // ###################################################################### 00044 Pololu::Pololu(OptionManager& mgr, const std::string& descrName, 00045 const std::string& tagName, const char *defdev) : 00046 ModelComponent(mgr, descrName, tagName), 00047 itsPort(new Serial(mgr)) 00048 { 00049 // set a default config for our serial port: 00050 itsPort->configure(defdev, 57600 , "8N1", false, false, 1); 00051 00052 // attach our port as a subcomponent: 00053 addSubComponent(itsPort); 00054 00055 // Initialize our internals: 00056 zero = new rutz::shared_ptr<NModelParam<float> >[PololuNUMSERVOS]; 00057 posmult = new rutz::shared_ptr<NModelParam<float> >[PololuNUMSERVOS]; 00058 negmult = new rutz::shared_ptr<NModelParam<float> >[PololuNUMSERVOS]; 00059 pos = new byte[PololuNUMSERVOS]; 00060 for (uint i = 0; i < PololuNUMSERVOS; i ++) 00061 { 00062 pos[i] = 127; char buf[20]; 00063 00064 sprintf(buf, "Zero%d", i); 00065 zero[i] = NModelParam<float>::make(buf, this, 0.0F); 00066 00067 sprintf(buf, "PosMult%d", i); 00068 posmult[i] = NModelParam<float>::make(buf, this, 1.0F); 00069 00070 sprintf(buf, "NegMult%d", i); 00071 negmult[i] = NModelParam<float>::make(buf, this, 1.0F); 00072 } 00073 } 00074 00075 // ###################################################################### 00076 Pololu::~Pololu() 00077 { 00078 delete [] pos; 00079 delete [] negmult; 00080 delete [] posmult; 00081 delete [] zero; 00082 } 00083 00084 // ###################################################################### 00085 bool Pololu::move(const int servo, const float position) 00086 { return moveRaw(servo, calibToRaw(servo, position)); } 00087 00088 // ###################################################################### 00089 float Pololu::getPosition(const int servo) const 00090 { 00091 if (servo < 0 || servo >= PololuNUMSERVOS) 00092 LFATAL("Invalid servo number %d", servo); 00093 return rawToCalib(servo, pos[servo]); 00094 } 00095 00096 // ###################################################################### 00097 void Pololu::calibrate(const int servo, const byte neutralval, const byte minval, 00098 const byte maxval) 00099 { 00100 if (servo < 0 || servo >= PololuNUMSERVOS) 00101 LFATAL("Invalid servo number %d", servo); 00102 00103 zero[servo]->setVal(float(neutralval)); 00104 negmult[servo]->setVal(1.0F / (float(neutralval) - float(minval))); 00105 posmult[servo]->setVal(1.0F / (float(maxval) - float(neutralval))); 00106 } 00107 00108 // ###################################################################### 00109 bool Pololu::moveRaw(const int servo, const byte rawpos) 00110 { 00111 char command[5]; 00112 command[0] = 128; //sync 00113 command[1] = 1; //device # 00114 command[2] = 2; //set position 7-bit command 00115 command[3] = servo; //servo num 00116 command[4] = rawpos; //data 00117 00118 00119 // write command buffer 00120 if (itsPort->write(command, 5) == 5) 00121 { 00122 // update our position: 00123 pos[servo] = rawpos; 00124 return true; 00125 } 00126 else 00127 return false; 00128 } 00129 00130 // ###################################################################### 00131 bool Pololu::setSpeed(const int servo, const byte speed) 00132 { 00133 char command[5]; 00134 command[0] = 128; //sync 00135 command[1] = 1; //device # 00136 command[2] = 1; //set speed command 00137 command[3] = servo; //servo num 00138 command[4] = speed; //data 00139 00140 00141 // write command buffer 00142 if (itsPort->write(command, 5) == 5) 00143 return true; 00144 else 00145 return false; 00146 00147 } 00148 00149 // ###################################################################### 00150 bool Pololu::setNeutral(const int servo, const short int pos) 00151 { 00152 char command[6]; 00153 command[0] = 128; //sync 00154 command[1] = 1; //device # 00155 command[2] = 5; //set neutral command 00156 command[3] = servo; //servo num 00157 command[4] = pos >> 7; //data MSB 00158 command[5] = (pos & 0x7F); //data LSB 00159 00160 // write command buffer 00161 if (itsPort->write(command, 6) == 6) 00162 return true; 00163 else 00164 return false; 00165 00166 } 00167 00168 // ###################################################################### 00169 bool Pololu::setParam(const int servo, 00170 bool on_off, bool direction, char range) 00171 { 00172 char command[5]; 00173 command[0] = 128; //sync 00174 command[1] = 1; //device # 00175 command[2] = 0; //set param command 00176 command[3] = servo; //servo num 00177 command[4] = 0x00; 00178 command[4] |= (on_off << 6); 00179 command[4] |= (direction << 5); 00180 command[4] |= (range & 0x1f); 00181 00182 // write command buffer 00183 if (itsPort->write(command, 5) == 5) 00184 return true; 00185 else 00186 return false; 00187 00188 } 00189 00190 // ###################################################################### 00191 bool Pololu::moveRawHack(const int servo, const byte rawpos, const int port) 00192 { 00193 // Command Buffer: 00194 // [0] is start character 00195 // [1] is which servo to move 00196 // [2] is position to move servo to (0 to MAX_POSITION) 00197 char command[3]; 00198 command[0] = 255; 00199 command[1] = servo; 00200 command[2] = rawpos; 00201 int fd; 00202 if(port == 1) 00203 fd = open("/dev/ttyS0", O_RDWR); 00204 else 00205 fd = open("/dev/ttyS1", O_RDWR); 00206 if(fd==-1) LFATAL("open failed"); 00207 if(write(fd, command, 3)==-1){ 00208 perror("open"); 00209 LFATAL("write failed"); 00210 } 00211 close(fd); 00212 return true; 00213 } 00214 00215 // ###################################################################### 00216 byte Pololu::getPositionRaw(const int servo) const 00217 { 00218 if (servo < 0 || servo >= PololuNUMSERVOS) 00219 LFATAL("Invalid servo number %d", servo); 00220 00221 return pos[servo]; 00222 } 00223 00224 // ###################################################################### 00225 float Pololu::rawToCalib(const int servo, const byte rawpos) const 00226 { 00227 if (servo < 0 || servo >= PololuNUMSERVOS) 00228 LFATAL("Invalid servo number %d", servo); 00229 00230 float position; 00231 if (rawpos >= byte(zero[servo]->getVal())) 00232 position = (float(rawpos) - zero[servo]->getVal()) * 00233 posmult[servo]->getVal(); 00234 else 00235 position = (float(rawpos) - zero[servo]->getVal()) * 00236 negmult[servo]->getVal(); 00237 00238 if (position < -1.0F) position = -1.0F; 00239 else if (position > 1.0F) position = 1.0F; 00240 00241 return position; 00242 } 00243 00244 // ###################################################################### 00245 byte Pololu::calibToRaw(const int servo, const float position) const 00246 { 00247 if (servo < 0 || servo >= PololuNUMSERVOS) 00248 LFATAL("Invalid servo number %d", servo); 00249 00250 if (position > 1.0F || position < -1.0F) 00251 LFATAL("Invalid position %f (range -1.0..1.0)", position); 00252 00253 int rawpos; 00254 if (position < 0.0F) 00255 rawpos = int(position / negmult[servo]->getVal() + 00256 zero[servo]->getVal() + 0.49999F); 00257 else 00258 rawpos = int(position / posmult[servo]->getVal() + 00259 zero[servo]->getVal() + 0.49999F); 00260 00261 if (rawpos < 0) rawpos = 0; else if (rawpos > 255) rawpos = 255; 00262 00263 return byte(rawpos); 00264 } 00265 00266 // ###################################################################### 00267 /* So things look consistent in everyone's emacs... */ 00268 /* Local Variables: */ 00269 /* indent-tabs-mode: nil */ 00270 /* End: */