Skip to content

Commit 21b6579

Browse files
committed
add: fast_bulk_read example
1 parent a7258fa commit 21b6579

File tree

13 files changed

+1078
-0
lines changed

13 files changed

+1078
-0
lines changed
Lines changed: 335 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
1+
/*******************************************************************************
2+
* Copyright 2017 ROBOTIS CO., LTD.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*******************************************************************************/
16+
17+
/* Author: Ryu Woon Jung (Leon), Honghyun Kim */
18+
19+
//
20+
// ********* Bulk Read and Bulk Write Example *********
21+
//
22+
//
23+
// Available DYNAMIXEL model on this example : All models using Protocol 2.0
24+
// This example is tested with two DYNAMIXEL P Series, and an U2D2
25+
// Be sure that DYNAMIXEL P properties are already set as %% ID : 1 and 2 / Baudnum : 1 (Baudrate : 57600)
26+
//
27+
28+
#if defined(__linux__) || defined(__APPLE__)
29+
#include <fcntl.h>
30+
#include <termios.h>
31+
#define STDIN_FILENO 0
32+
#elif defined(_WIN32) || defined(_WIN64)
33+
#include <conio.h>
34+
#endif
35+
36+
#include <stdlib.h>
37+
#include <stdio.h>
38+
39+
#include "dynamixel_sdk.h" // Uses DYNAMIXEL SDK library
40+
41+
// Control table address
42+
#define ADDR_PRO_TORQUE_ENABLE 512 // Control table address is different in DYNAMIXEL model
43+
#define ADDR_PRO_LED_RED 513
44+
#define ADDR_PRO_GOAL_POSITION 564
45+
#define ADDR_PRO_PRESENT_POSITION 580
46+
47+
// Data Byte Length
48+
#define LEN_PRO_LED_RED 1
49+
#define LEN_PRO_GOAL_POSITION 4
50+
#define LEN_PRO_PRESENT_POSITION 4
51+
52+
// Protocol version
53+
#define PROTOCOL_VERSION 2.0 // See which protocol version is used in the DYNAMIXEL
54+
55+
// Default setting
56+
#define DXL1_ID 1 // DYNAMIXEL#1 ID: 1
57+
#define DXL2_ID 2 // DYNAMIXEL#2 ID: 2
58+
#define BAUDRATE 57600
59+
#define DEVICENAME "COM3" // Check which port is being used on your controller
60+
// ex) Windows: "COM1" Linux: "/dev/ttyUSB0" Mac: "/dev/tty.usbserial-*"
61+
62+
#define TORQUE_ENABLE 1 // Value for enabling the torque
63+
#define TORQUE_DISABLE 0 // Value for disabling the torque
64+
#define DXL_MINIMUM_POSITION_VALUE -150000 // DYNAMIXEL will rotate between this value
65+
#define DXL_MAXIMUM_POSITION_VALUE 150000 // and this value (note that the DYNAMIXEL would not move when the position value is out of movable range. Check e-manual about the range of the Dynamixel you use.)
66+
#define DXL_MOVING_STATUS_THRESHOLD 20 // DYNAMIXEL moving status threshold
67+
68+
#define ESC_ASCII_VALUE 0x1b
69+
70+
int getch()
71+
{
72+
#if defined(__linux__) || defined(__APPLE__)
73+
struct termios oldt, newt;
74+
int ch;
75+
tcgetattr(STDIN_FILENO, &oldt);
76+
newt = oldt;
77+
newt.c_lflag &= ~(ICANON | ECHO);
78+
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
79+
ch = getchar();
80+
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
81+
return ch;
82+
#elif defined(_WIN32) || defined(_WIN64)
83+
return _getch();
84+
#endif
85+
}
86+
87+
int kbhit(void)
88+
{
89+
#if defined(__linux__) || defined(__APPLE__)
90+
struct termios oldt, newt;
91+
int ch;
92+
int oldf;
93+
94+
tcgetattr(STDIN_FILENO, &oldt);
95+
newt = oldt;
96+
newt.c_lflag &= ~(ICANON | ECHO);
97+
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
98+
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
99+
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
100+
101+
ch = getchar();
102+
103+
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
104+
fcntl(STDIN_FILENO, F_SETFL, oldf);
105+
106+
if (ch != EOF)
107+
{
108+
ungetc(ch, stdin);
109+
return 1;
110+
}
111+
112+
return 0;
113+
#elif defined(_WIN32) || defined(_WIN64)
114+
return _kbhit();
115+
#endif
116+
}
117+
118+
int main()
119+
{
120+
// Initialize PortHandler instance
121+
// Set the port path
122+
// Get methods and members of PortHandlerLinux or PortHandlerWindows
123+
dynamixel::PortHandler *portHandler = dynamixel::PortHandler::getPortHandler(DEVICENAME);
124+
125+
// Initialize PacketHandler instance
126+
// Set the protocol version
127+
// Get methods and members of Protocol1PacketHandler or Protocol2PacketHandler
128+
dynamixel::PacketHandler *packetHandler = dynamixel::PacketHandler::getPacketHandler(PROTOCOL_VERSION);
129+
130+
// Initialize GroupBulkWrite instance
131+
dynamixel::GroupBulkWrite groupBulkWrite(portHandler, packetHandler);
132+
133+
// Initialize GroupFastBulkRead instance
134+
dynamixel::GroupFastBulkRead groupFastBulkRead(portHandler, packetHandler);
135+
136+
int index = 0;
137+
int dxl_comm_result = COMM_TX_FAIL; // Communication result
138+
bool dxl_addparam_result = false; // addParam result
139+
bool dxl_getdata_result = false; // GetParam result
140+
int dxl_goal_position[2] = {DXL_MINIMUM_POSITION_VALUE, DXL_MAXIMUM_POSITION_VALUE}; // Goal position
141+
142+
uint8_t dxl_error = 0; // DYNAMIXEL error
143+
uint8_t dxl_led_value[2] = {0x00, 0xFF}; // DYNAMIXEL LED value for write
144+
uint8_t param_goal_position[4];
145+
int32_t dxl1_present_position = 0; // Present position
146+
uint8_t dxl2_led_value_read; // DYNAMIXEL LED value for read
147+
148+
// Open port
149+
if (portHandler->openPort())
150+
{
151+
printf("Succeeded to open the port!\n");
152+
}
153+
else
154+
{
155+
printf("Failed to open the port!\n");
156+
printf("Press any key to terminate...\n");
157+
getch();
158+
return 0;
159+
}
160+
161+
// Set port baudrate
162+
if (portHandler->setBaudRate(BAUDRATE))
163+
{
164+
printf("Succeeded to change the baudrate!\n");
165+
}
166+
else
167+
{
168+
printf("Failed to change the baudrate!\n");
169+
printf("Press any key to terminate...\n");
170+
getch();
171+
return 0;
172+
}
173+
174+
// Enable DYNAMIXEL#1 Torque
175+
dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, DXL1_ID, ADDR_PRO_TORQUE_ENABLE, TORQUE_ENABLE, &dxl_error);
176+
if (dxl_comm_result != COMM_SUCCESS)
177+
{
178+
printf("%s\n", packetHandler->getTxRxResult(dxl_comm_result));
179+
}
180+
else if (dxl_error != 0)
181+
{
182+
printf("%s\n", packetHandler->getRxPacketError(dxl_error));
183+
}
184+
else
185+
{
186+
printf("DYNAMIXEL#%d has been successfully connected \n", DXL1_ID);
187+
}
188+
189+
// Enable DYNAMIXEL#2 Torque
190+
dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, DXL2_ID, ADDR_PRO_TORQUE_ENABLE, TORQUE_ENABLE, &dxl_error);
191+
if (dxl_comm_result != COMM_SUCCESS)
192+
{
193+
printf("%s\n", packetHandler->getTxRxResult(dxl_comm_result));
194+
}
195+
else if (dxl_error != 0)
196+
{
197+
printf("%s\n", packetHandler->getRxPacketError(dxl_error));
198+
}
199+
else
200+
{
201+
printf("DYNAMIXEL#%d has been successfully connected \n", DXL2_ID);
202+
}
203+
204+
// Add parameter storage for DYNAMIXEL#1 present position
205+
dxl_addparam_result = groupFastBulkRead.addParam(DXL1_ID, ADDR_PRO_PRESENT_POSITION, LEN_PRO_PRESENT_POSITION);
206+
if (dxl_addparam_result != true)
207+
{
208+
fprintf(stderr, "[ID:%03d] groupFastBulkRead addparam failed", DXL1_ID);
209+
return 0;
210+
}
211+
212+
// Add parameter storage for DYNAMIXEL#2 LED value
213+
dxl_addparam_result = groupFastBulkRead.addParam(DXL2_ID, ADDR_PRO_LED_RED, LEN_PRO_LED_RED);
214+
if (dxl_addparam_result != true)
215+
{
216+
fprintf(stderr, "[ID:%03d] groupFastBulkRead addparam failed", DXL2_ID);
217+
return 0;
218+
}
219+
220+
while(1)
221+
{
222+
printf("Press any key to continue! (or press ESC to quit!)\n");
223+
if (getch() == ESC_ASCII_VALUE)
224+
break;
225+
226+
// Allocate goal position value into byte array
227+
param_goal_position[0] = DXL_LOBYTE(DXL_LOWORD(dxl_goal_position[index]));
228+
param_goal_position[1] = DXL_HIBYTE(DXL_LOWORD(dxl_goal_position[index]));
229+
param_goal_position[2] = DXL_LOBYTE(DXL_HIWORD(dxl_goal_position[index]));
230+
param_goal_position[3] = DXL_HIBYTE(DXL_HIWORD(dxl_goal_position[index]));
231+
232+
// Add parameter storage for DYNAMIXEL#1 goal position
233+
dxl_addparam_result = groupBulkWrite.addParam(DXL1_ID, ADDR_PRO_GOAL_POSITION, LEN_PRO_GOAL_POSITION, param_goal_position);
234+
if (dxl_addparam_result != true)
235+
{
236+
fprintf(stderr, "[ID:%03d] groupBulkWrite addparam failed", DXL1_ID);
237+
return 0;
238+
}
239+
240+
// Add parameter storage for DYNAMIXEL#2 LED value
241+
dxl_addparam_result = groupBulkWrite.addParam(DXL2_ID, ADDR_PRO_LED_RED, LEN_PRO_LED_RED, &dxl_led_value[index]);
242+
if (dxl_addparam_result != true)
243+
{
244+
fprintf(stderr, "[ID:%03d] groupBulkWrite addparam failed", DXL2_ID);
245+
return 0;
246+
}
247+
248+
// Bulkwrite goal position and LED value
249+
dxl_comm_result = groupBulkWrite.txPacket();
250+
if (dxl_comm_result != COMM_SUCCESS) printf("%s\n", packetHandler->getTxRxResult(dxl_comm_result));
251+
252+
// Clear bulkwrite parameter storage
253+
groupBulkWrite.clearParam();
254+
255+
do
256+
{
257+
// Bulkread present position and LED status
258+
dxl_comm_result = groupFastBulkRead.txRxPacket();
259+
if (dxl_comm_result != COMM_SUCCESS)
260+
{
261+
printf("%s\n", packetHandler->getTxRxResult(dxl_comm_result));
262+
}
263+
else if (groupFastBulkRead.getError(DXL1_ID, &dxl_error))
264+
{
265+
printf("[ID:%03d] %s\n", DXL1_ID, packetHandler->getRxPacketError(dxl_error));
266+
}
267+
else if (groupFastBulkRead.getError(DXL2_ID, &dxl_error))
268+
{
269+
printf("[ID:%03d] %s\n", DXL2_ID, packetHandler->getRxPacketError(dxl_error));
270+
}
271+
272+
// Check if groupFastBulkRead data of DYNAMIXEL#1 is available
273+
dxl_getdata_result = groupFastBulkRead.isAvailable(DXL1_ID, ADDR_PRO_PRESENT_POSITION, LEN_PRO_PRESENT_POSITION);
274+
if (dxl_getdata_result != true)
275+
{
276+
fprintf(stderr, "[ID:%03d] groupFastBulkRead getdata failed", DXL1_ID);
277+
return 0;
278+
}
279+
280+
// Check if groupFastBulkRead data of DYNAMIXEL#2 is available
281+
dxl_getdata_result = groupFastBulkRead.isAvailable(DXL2_ID, ADDR_PRO_LED_RED, LEN_PRO_LED_RED);
282+
if (dxl_getdata_result != true)
283+
{
284+
fprintf(stderr, "[ID:%03d] groupFastBulkRead getdata failed", DXL2_ID);
285+
return 0;
286+
}
287+
288+
// Get present position value
289+
dxl1_present_position = groupFastBulkRead.getData(DXL1_ID, ADDR_PRO_PRESENT_POSITION, LEN_PRO_PRESENT_POSITION);
290+
291+
// Get LED value
292+
dxl2_led_value_read = groupFastBulkRead.getData(DXL2_ID, ADDR_PRO_LED_RED, LEN_PRO_LED_RED);
293+
294+
printf("[ID:%03d] Present Position : %d \t [ID:%03d] LED Value: %d\n", DXL1_ID, dxl1_present_position, DXL2_ID, dxl2_led_value_read);
295+
296+
}while(abs(dxl_goal_position[index] - dxl1_present_position) > DXL_MOVING_STATUS_THRESHOLD);
297+
298+
// Change goal position
299+
if (index == 0)
300+
{
301+
index = 1;
302+
}
303+
else
304+
{
305+
index = 0;
306+
}
307+
}
308+
309+
// Disable DYNAMIXEL#1 Torque
310+
dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, DXL1_ID, ADDR_PRO_TORQUE_ENABLE, TORQUE_DISABLE, &dxl_error);
311+
if (dxl_comm_result != COMM_SUCCESS)
312+
{
313+
printf("%s\n", packetHandler->getTxRxResult(dxl_comm_result));
314+
}
315+
else if (dxl_error != 0)
316+
{
317+
printf("%s\n", packetHandler->getRxPacketError(dxl_error));
318+
}
319+
320+
// Disable DYNAMIXEL#2 Torque
321+
dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, DXL2_ID, ADDR_PRO_TORQUE_ENABLE, TORQUE_DISABLE, &dxl_error);
322+
if (dxl_comm_result != COMM_SUCCESS)
323+
{
324+
printf("%s\n", packetHandler->getTxRxResult(dxl_comm_result));
325+
}
326+
else if (dxl_error != 0)
327+
{
328+
printf("%s\n", packetHandler->getRxPacketError(dxl_error));
329+
}
330+
331+
// Close port
332+
portHandler->closePort();
333+
334+
return 0;
335+
}

0 commit comments

Comments
 (0)