00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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
00050 itsPort->configure(defdev, 57600 , "8N1", false, false, 1);
00051
00052
00053 addSubComponent(itsPort);
00054
00055
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;
00113 command[1] = 1;
00114 command[2] = 2;
00115 command[3] = servo;
00116 command[4] = rawpos;
00117
00118
00119
00120 if (itsPort->write(command, 5) == 5)
00121 {
00122
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;
00135 command[1] = 1;
00136 command[2] = 1;
00137 command[3] = servo;
00138 command[4] = speed;
00139
00140
00141
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;
00154 command[1] = 1;
00155 command[2] = 5;
00156 command[3] = servo;
00157 command[4] = pos >> 7;
00158 command[5] = (pos & 0x7F);
00159
00160
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;
00174 command[1] = 1;
00175 command[2] = 0;
00176 command[3] = servo;
00177 command[4] = 0x00;
00178 command[4] |= (on_off << 6);
00179 command[4] |= (direction << 5);
00180 command[4] |= (range & 0x1f);
00181
00182
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
00194
00195
00196
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
00268
00269
00270