Dynamixel  2.9.5
RoadNarrows Robotics Dynamixel Package
spintest.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: Dynamixel
4 //
5 // File: spintest.c
6 //
7 /*! \file
8  *
9  * $LastChangedDate: 2011-07-15 14:10:46 -0600 (Fri, 15 Jul 2011) $
10  * $Rev: 1139 $
11  *
12  * \brief Simple continuous spin test of a servo.
13  *
14  * \author Robin Knight (robin.knight@roadnarrows.com)
15  *
16  * \copyright
17  * \h_copy 2011-2017. RoadNarrows LLC.\n
18  * http://www.roadnarrows.com\n
19  * All Rights Reserved
20  */
21 // Permission is hereby granted, without written agreement and without
22 // license or royalty fees, to use, copy, modify, and distribute this
23 // software and its documentation for any purpose, provided that
24 // (1) The above copyright notice and the following two paragraphs
25 // appear in all copies of the source code and (2) redistributions
26 // including binaries reproduces these notices in the supporting
27 // documentation. Substantial modifications to this software may be
28 // copyrighted by their authors and need not follow the licensing terms
29 // described here, provided that the new terms are clearly indicated in
30 // all files where they apply.
31 //
32 // IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
33 // OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
34 // PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
35 // DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
36 // EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
37 // THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
40 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
41 // FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
42 // "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
43 // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
44 //
45 ////////////////////////////////////////////////////////////////////////////////
46 
47 #include <sys/select.h>
48 #include <stdio.h>
49 #include <unistd.h>
50 #include <string.h>
51 #include <stdlib.h>
52 #include <libgen.h>
53 #include <ctype.h>
54 
55 #include "rnr/rnrconfig.h"
56 #include "rnr/opts.h"
57 #include "rnr/log.h"
58 
59 #include "dynamixel/Dynamixel.h"
60 #include "dynamixel/libDynamixel.h"
61 
62 #include "version.h"
63 
64 #define APP_EC_OK 0
65 #define APP_EC_USAGE 2
66 #define APP_EC_EXEC 4
67 
68 
69 //
70 // The command with option and argument values.
71 //
72 static char *Argv0; ///< the command
73 static char *OptsSerDev = "/dev/ttyUSB0"; ///< the serial device
74 static int OptsBaudRate = 1000000; ///< serial baudrate
75 static int OptsSpeed = 200; ///< servo speed
76 static int ArgServoId = -1; ///< servo id
77 
78 
79 /*!
80  * \brief Program information.
81  */
82 static OptsPgmInfo_T AppPgmInfo =
83 {
84  // usage_args
85  "id",
86 
87  // synopsis
88  "Spin dynamixel servo continuously.",
89 
90  // long_desc =
91  "The %P test application spins the given servo continuously at the given "
92  "speed.",
93 
94  // diagnostics
95  NULL
96 };
97 
98 /*!
99  * \brief Command line options information.
100  */
101 static OptsInfo_T AppOptsInfo[] =
102 {
103  // -d, --device <device>
104  {
105  "device", // long_opt
106  'd', // short_opt
107  required_argument, // has_arg
108  true, // has_default
109  &OptsSerDev, // opt_addr
110  OptsCvtArgStr, // fn_cvt
111  OptsFmtStr, // fn_fmt
112  "<device>", // arg_name
113  "Serial device interface", // opt desc
114  },
115 
116  // -b, --baudrate <baud>
117  {
118  "baudrate", // long_opt
119  'b', // short_opt
120  required_argument, // has_arg
121  true, // has_default
122  &OptsBaudRate, // opt_addr
123  OptsCvtArgInt, // fn_cvt
124  OptsFmtInt, // fn_fmt
125  "<baud>", // arg_name
126  "Serial interface baudrate", // opt desc
127  },
128 
129  // -s, --speed <speed>
130  {
131  "speed", // long_opt
132  's', // short_opt
133  required_argument, // has_arg
134  true, // has_default
135  &OptsSpeed, // opt_addr
136  OptsCvtArgInt, // fn_cvt
137  OptsFmtInt, // fn_fmt
138  "<speed>", // arg_name
139  "Speed of servo. <0 = CCW, 0 = stop, >0 = CW.", // opt desc
140  },
141 
142  {NULL, }
143 };
144 
145 //
146 // Global Data
147 //
148 int ServoDir = DYNA_DIR_CW;
149 DynaHandle_T *DynaHandle;
150 
151 bool_t peekc(uint_t msec)
152 {
153  int fno = fileno(stdin);
154  fd_set fdset;
155  uint_t usec = msec * 1000;
156  struct timeval timeout;
157  int rc;
158 
159  FD_ZERO(&fdset);
160  FD_SET(fno, &fdset);
161 
162  // timeout (gets munged after each select())
163  timeout.tv_sec = (time_t)(usec / 1000000);
164  timeout.tv_usec = (time_t)(usec % 1000000);
165 
166  if( (rc = select(fno+1, &fdset, NULL, NULL, &timeout)) > 0 )
167  {
168  fflush(stdin);
169  }
170 
171  return rc>0? true: false;
172 }
173 
174 /*!
175  * \brief Main argument initialization.
176  *
177  * \param argc Command-line argument count.
178  * \param argv Command-line argument list.
179  *
180  * \par Exits:
181  * Program terminates on conversion error.
182  */
183 static void MainInitArgs(int argc, char *argv[])
184 {
185  // name of this process
186  Argv0 = basename(argv[0]);
187 
188  // parse input options
189  argv = OptsGet(Argv0, &PkgInfo, &AppPgmInfo, AppOptsInfo, true,
190  &argc, argv);
191 
192  if( argc < 1 )
193  {
194  OptsInvalid(Argv0, "no servo id specified.");
195  }
196  else
197  {
198  ArgServoId = atoi(argv[0]);
199  }
200 
201  if( OptsSpeed < 0 )
202  {
203  ServoDir = DYNA_DIR_CCW;
204  OptsSpeed = -OptsSpeed;
205  }
206  else
207  {
208  ServoDir = DYNA_DIR_CW;
209  }
210 }
211 
212 static int AppDynaInit()
213 {
214  int rc;
215  ushort_t lim;
216  ushort_t speed;
217  ushort_t torque;
218  byte_t alarms;
219 
220  //
221  // Create interface
222  //
223  DynaHandle = dynaCreateInterface(OptsSerDev, OptsBaudRate);
224 
225  if( DynaHandle == NULL )
226  {
227  LOGERROR("failed to create interface.");
228  return -APP_EC_EXEC;
229  }
230 
231  //
232  // Ping servo
233  //
234  if( !dynaPing(DynaHandle, ArgServoId) )
235  {
236  LOGERROR("failed to ping servo %d.", ArgServoId);
237  return -APP_EC_EXEC;
238  }
239 
240  //
241  // Set up continuous mode
242  //
243  rc = dynaRead16(DynaHandle, ArgServoId, DYNA_ADDR_LIM_CW_LSB, &lim, &alarms);
244  if( (rc == DYNA_OK) && (lim != DYNA_CW_POS_CONT_MODE) )
245  {
246  dynaWrite16(DynaHandle, ArgServoId,
248  sleep(1); // writing to EEPROM needs a little time - servo is blocked
249  }
250 
251  rc = dynaRead16(DynaHandle, ArgServoId, DYNA_ADDR_LIM_CCW_LSB, &lim, &alarms);
252  if( (rc == DYNA_OK) && (lim != DYNA_CCW_POS_CONT_MODE) )
253  {
254  dynaWrite16(DynaHandle, ArgServoId,
256  sleep(1); // writing to EEPROM needs a little time - servo is blocked
257  }
258 
259  //
260  // Set speed
261  //
263  if( ServoDir == DYNA_DIR_CW )
264  {
265  speed |= (ushort_t)DYNA_GOAL_SPEED_DIR_CW;
266  }
267  else
268  {
269  speed |= (ushort_t)DYNA_GOAL_SPEED_DIR_CCW;
270  }
271  dynaWrite16(DynaHandle, ArgServoId, DYNA_ADDR_GOAL_SPEED_LSB, speed,
272  &alarms);
273 
274  // set torque limit
275  torque = DYNA_TORQUE_MAX_RAW;
276  dynaWrite16(DynaHandle, ArgServoId, DYNA_ADDR_LIM_TORQUE_LSB, torque,
277  &alarms);
278 
279  return APP_EC_OK;
280 }
281 
282 static void AppDynaRun()
283 {
284  while(1)
285  {
286  if( peekc(10) )
287  {
288  break;
289  }
290  }
291 }
292 
293 static void AppDynaDeinit()
294 {
295  byte_t alarms;
296 
297  // stop servo
298  dynaWrite16(DynaHandle, ArgServoId, DYNA_ADDR_GOAL_SPEED_LSB, 0, &alarms);
299 }
300 
301 static void AppBanner()
302 {
303  printf("\n");
304  printf("Spinning servo %d %s at raw speed of %d.\n",
305  ArgServoId,
306  (ServoDir==DYNA_DIR_CW? "clockwise": "counter-clockwise"),
307  OptsSpeed);
308  printf("Press <CR> to stop.\n");
309 
310 }
311 
312 /*!
313  * \brief Main.
314  *
315  * \param argc Command-line argument count.
316  * \param argv Command-line argument list.
317  *
318  * \par Exit Status:
319  * Program exits with 0 success, \h_gt 0 on failure.
320  */
321 int main(int argc, char *argv[])
322 {
323  int rc;
324 
325  MainInitArgs(argc, argv);
326 
327  if( (rc = AppDynaInit()) == APP_EC_OK )
328  {
329  AppBanner();
330  AppDynaRun();
331  AppDynaDeinit();
332  }
333 
334  return rc >= 0? APP_EC_OK: -rc;
335 }
#define DYNA_TORQUE_MAX_RAW
maximum raw torque
Definition: Dynamixel.h:282
#define DYNA_OK
not an error, success
Definition: Dynamixel.h:78
#define DYNA_ADDR_GOAL_SPEED_LSB
goal speed lsb (RW)
Definition: Dynamixel.h:940
#define DYNA_ADDR_LIM_CW_LSB
clockwise angle limit lsb (RW)
Definition: Dynamixel.h:464
int main(int argc, char *argv[])
Main.
Definition: spintest.c:321
#define DYNA_CCW_POS_CONT_MODE
continuous mode (with cw limit)
Definition: Dynamixel.h:488
static int OptsSpeed
servo speed
Definition: spintest.c:75
#define DYNA_DIR_CW
clockwise direction
Definition: Dynamixel.h:191
static void MainInitArgs(int argc, char *argv[])
Main argument initialization.
Definition: spintest.c:183
static OptsPgmInfo_T AppPgmInfo
Program information.
Definition: spintest.c:82
static char * Argv0
the command
Definition: spintest.c:72
static char * OptsSerDev
the serial device
Definition: spintest.c:73
#define DYNA_DIR_CCW
counterclockwise direction
Definition: Dynamixel.h:193
static const PkgInfo_T PkgInfo
Definition: version.h:45
#define DYNA_GOAL_SPEED_MAG_MASK
speed magnitude field mask
Definition: Dynamixel.h:945
#define DYNA_GOAL_SPEED_DIR_CW
clockwise direction
Definition: Dynamixel.h:951
#define DYNA_GOAL_SPEED_DIR_CCW
counterclockwise direction
Definition: Dynamixel.h:950
Package version information.
#define DYNA_ADDR_LIM_CCW_LSB
counterclockwise angle limit lsb (RW)
Definition: Dynamixel.h:483
static int ArgServoId
servo id
Definition: spintest.c:76
static OptsInfo_T AppOptsInfo[]
Command line options information.
Definition: spintest.c:101
static int OptsBaudRate
serial baudrate
Definition: spintest.c:74
#define DYNA_CW_POS_CONT_MODE
continuous mode (with ccw limit)
Definition: Dynamixel.h:469