...
POST No. 2590607
Open CR을 이용하여 다이나믹셀 제어시 Timer 사용 방법
2019-08-16 14:14:12 rudtn1022

 현재 Open CR을 이용하여 다이나믹셀을 제어하고 있습니다.(아두이노 이용)

 

 시스템 제어시, 제어시간을 측정하기 위하여 아두이노의 millis() 함수를 이용하려 했습니다.

 

 Open CR만을 이용할 경우 millis()함수를 사용 가능한 것을 확인하였습니다.

 

 Open CR을 다이나믹셀과 연결하여 패킷을 송수신할 경우 millis() 함수가 제 기능을 하지 못합니다. (시간 측정이 안됩니다.)

 

 

 1. 패킷을 송수신하더라도 시간 측정이 가능한 함수가 있을 까요?( 아두이노)

 

 2. 아래와 같은 Timer 클래스가 정의된 파일 위치를 찾고 싶은데 어디에 있는지 잘 모르겠습니다. 가능하다면 Timer 함수 설명된 파일을 올려주실 수 있을 까요?

 

  Timer.stop();
  Timer.setPeriod();         
  Timer.attachInterrupt();
  Timer.start();
 

2019-08-16 14:14:12
rudtn1022
2019-08-16 16:52:07 손의형

안녕하세요,

 

millis()는 다이나믹셀 패킷의 송수신에 영향을 받지 않습니다.

어떠한 환경에서 함수를 호출하여 사용했는지 알 수 없으나 패킷의 송수신 시간을 측정하는 경우, 빠른 통신속도를 사용할 경우 송수신이 1ms 이내이면 정상적으로 측정되지 않을 수 있습니다.

Timer 클래스는 HardwareTimer로부터 상속된 클래스입니다.

HardwareTimer.cpp 파일을 참고하시기 바랍니다.

아래 예제는 millis를 이용하여 XL430-W250의 동작 완료시간을 측정하도록 변경한 DYNAMIXEL SDK의 read_write 예제입니다.

감사합니다.

 

#include <DynamixelSDK.h>


// Control table address
#define ADDR_PRO_TORQUE_ENABLE 64 // Control table address is different in Dynamixel model
#define ADDR_PRO_GOAL_POSITION 116
#define ADDR_PRO_PRESENT_POSITION 132

// Protocol version
#define PROTOCOL_VERSION 2.0 // See which protocol version is used in the Dynamixel

// Default setting
#define DXL_ID 1 // Dynamixel ID: 1
#define BAUDRATE 57600
#define DEVICENAME "OpenCR_DXL_Port" // This definition only has a symbolic meaning and does not affect to any functionality

#define TORQUE_ENABLE 1 // Value for enabling the torque
#define TORQUE_DISABLE 0 // Value for disabling the torque
#define DXL_MINIMUM_POSITION_VALUE 0 // Dynamixel will rotate between this value
#define DXL_MAXIMUM_POSITION_VALUE 4000 // 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.)
#define DXL_MOVING_STATUS_THRESHOLD 20 // Dynamixel moving status threshold

#define ESC_ASCII_VALUE 0x1b

#define CMD_SERIAL Serial

int getch()
{
while(1)
{
if( CMD_SERIAL.available() > 0 )
{
break;
}
}

return CMD_SERIAL.read();
}

int kbhit(void)
{
return CMD_SERIAL.available();
}

void setup()
{
Serial.begin(115200);
while(!Serial);

Serial.println("Start..");

// Initialize PortHandler instance
// Set the port path
// Get methods and members of PortHandlerLinux or PortHandlerWindows
dynamixel::PortHandler *portHandler = dynamixel::PortHandler::getPortHandler(DEVICENAME);

// Initialize PacketHandler instance
// Set the protocol version
// Get methods and members of Protocol1PacketHandler or Protocol2PacketHandler
dynamixel::PacketHandler *packetHandler = dynamixel::PacketHandler::getPacketHandler(PROTOCOL_VERSION);

int index = 0;
int dxl_comm_result = COMM_TX_FAIL; // Communication result
int dxl_goal_position[2] = {DXL_MINIMUM_POSITION_VALUE, DXL_MAXIMUM_POSITION_VALUE}; // Goal position

uint8_t dxl_error = 0; // Dynamixel error
int32_t dxl_present_position = 0; // Present position

unsigned long elapsed_time = 0;

// Open port
if (portHandler->openPort())
{
Serial.print("Succeeded to open the port!n");
}
else
{
Serial.print("Failed to open the port!n");
return;
}

// Set port baudrate
if (portHandler->setBaudRate(BAUDRATE))
{
Serial.print("Succeeded to change the baudrate!n");
}
else
{
Serial.print("Failed to change the baudrate!n");
return;
}

// Enable Dynamixel Torque
dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, DXL_ID, ADDR_PRO_TORQUE_ENABLE, TORQUE_ENABLE, &dxl_error);
if (dxl_comm_result != COMM_SUCCESS)
{
Serial.print(packetHandler->getTxRxResult(dxl_comm_result));
}
else if (dxl_error != 0)
{
Serial.print(packetHandler->getRxPacketError(dxl_error));
}
else
{
Serial.print("Dynamixel has been successfully connected n");
}

while(1)
{
Serial.print("Press any key to continue! (or press q to quit!)n");
if (getch() == 'q')
break;

// Write goal position
dxl_comm_result = packetHandler->write4ByteTxRx(portHandler, DXL_ID, ADDR_PRO_GOAL_POSITION, dxl_goal_position[index], &dxl_error);
if (dxl_comm_result != COMM_SUCCESS)
{
Serial.print(packetHandler->getTxRxResult(dxl_comm_result));
}
else if (dxl_error != 0)
{
Serial.print(packetHandler->getRxPacketError(dxl_error));
}

elapsed_time = millis();

do
{
// Read present position
dxl_comm_result = packetHandler->read4ByteTxRx(portHandler, DXL_ID, ADDR_PRO_PRESENT_POSITION, (uint32_t*)&dxl_present_position, &dxl_error);
if (dxl_comm_result != COMM_SUCCESS)
{
Serial.print(packetHandler->getTxRxResult(dxl_comm_result));
}
else if (dxl_error != 0)
{
Serial.print(packetHandler->getRxPacketError(dxl_error));
}

Serial.print("[ID:"); Serial.print(DXL_ID);
Serial.print("] GoalPos:"); Serial.print(dxl_goal_position[index]);
Serial.print(" PresPos:"); Serial.print(dxl_present_position);
Serial.println(" ");

}while((abs(dxl_goal_position[index] - dxl_present_position) > DXL_MOVING_STATUS_THRESHOLD));

elapsed_time = millis() - elapsed_time;

Serial.print("Elapsed Time : ");
Serial.println(elapsed_time);

// Change goal position
if (index == 0)
{
index = 1;
}
else
{
index = 0;
}
}

// Disable Dynamixel Torque
dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, DXL_ID, ADDR_PRO_TORQUE_ENABLE, TORQUE_DISABLE, &dxl_error);
if (dxl_comm_result != COMM_SUCCESS)
{
Serial.print(packetHandler->getTxRxResult(dxl_comm_result));
}
else if (dxl_error != 0)
{
Serial.print(packetHandler->getRxPacketError(dxl_error));
}

// Close port
portHandler->closePort();
}

void loop()
{
}

 

 

 

2019-08-16 16:52:07
will_son
2019-08-17 17:10:26 김경수

답변 감사합니다.

 

제가 사용한 다이나믹셀 패킷 송수신 함수는 다중 모터 제어시 사용하는 bulk, sync 함수 입니다.

 

- groupBulkRead.txRxPacket();

- groupSyncRead.txRxPacket();

 

 

위 함수를 사용하면 millis() 함수가 정상적으로 작동이 안되던데 혹시 millis() 함수 말고 시간 측정을 할 수 있는 함수가 있을까요?  

comment
2019-08-19 12:08:24 rudtn1022
아 해결했습니다.

millis() 대신 micros()를 사용하니 되더군요. 왜 그런지는 정확히는 잘 모르겠습니다.
2019-08-19 12:08:24
rudtn1022
2019-08-17 17:10:26
rudtn1022
답변달기
웹에디터 시작 웹 에디터 끝