OpenCM 9.04 hangs when using Serial Port

Good afternoon, in our work we use the OpenCM 9.04, 3 ax-12a board, and when we display the state of the dynamics in Serial, then at some point the goal position values are not correct and the controller quickly freezes after that. Only restart helps. What is it and how to fix the situation?

When I set the angle to all the engines, I check in a loop to see if they have completed the command. Only then does the code continue.

void WaitServosPosPerformed() {
  int* servosPos = new int[JOINT_N];
  if (DEBUG_LEVEL >= 1) DEBUG_SERIAL.println("Current servos position: ");
  while (true) {
    int* servosPos = GetServosPos();
    bool* isMoving = GetServosMoving();
    if (DEBUG_LEVEL >= 1) {
      for (byte i = 0; i < JOINT_N; i++) {
        DEBUG_SERIAL.print(servosPos[i]);
        if (i < JOINT_N - 1) DEBUG_SERIAL.print(", ");
        else DEBUG_SERIAL.println();
      }
    }
    if (DEBUG_LEVEL >= 2) {
      for (byte i = 0; i < JOINT_N; i++) { // 1 - движение, 0 - движения нет
        DEBUG_SERIAL.print(isMoving[i]);
        if (i < JOINT_N - 1) DEBUG_SERIAL.print(", ");
        else DEBUG_SERIAL.println();
      }
    }
    if ((isMoving[0] == 0 && isMoving[1] == 0 && isMoving[2] == 0)) break;
    delay(10);
  }
  DEBUG_SERIAL.print("Motors performed position: ");
  for (byte i = 0; i < JOINT_N; i++) {
    DEBUG_SERIAL.print(servosPos[i]);
    if (i < JOINT_N - 1) DEBUG_SERIAL.print(", ");
    else DEBUG_SERIAL.println();
  }
}

int* GetServosPos() {
  int *pos = new int[JOINT_N];
  for (byte i = 0; i < JOINT_N; i++) {
    pos[i] = dxl.getPresentPosition(i + 1);
  }
  return pos;
}

int GetServoMoving(byte servoId) {
  return dxl.readControlTableItem(MOVING, servoId);
}

bool* GetServosMoving() {
  bool *moving = new bool[JOINT_N];
  for (byte i = 0; i < JOINT_N; i++) {
    moving[i] = dxl.readControlTableItem(MOVING, i + 1);
  }
  return moving;
}

Can someone tell me how to win this?

1 Like

Hmm Not sure,

Seems it is overflow. Can you throw me the whole code? (Or github reposi).

I wil get it to test

DeltaAppiledRobotics/Dynamixel_Delta.ino at main · THEb0nny/DeltaAppiledRobotics · GitHub

Oh sure. I experimented again yesterday. Almost all messages that go to Serial are now under the condition that DEBUG_LEVEL is greater than 0. I set it to 0, there are almost no messages in Serial now. But the controller still freezes. Is it a memory leak? Is it because of calls to dxl methods to find out the motors?

1 Like

Sorry, just checked your comment out.

When I simply tested your .ino code, it seems my serial port is also freezed.

Not sure what the main cause is issued. Can you check your dynamic allocation by simply replacing the normal data type? Plus, I can not understand what you mean this sentence: Is it because of calls to dxl methods to find out the motors?

I turned off printing in Serial, but the controller still hangs.

1 Like

We tried not to use the WaitServosPosPerformed function and our robot stopped hanging. That’s why I say that methods that read values from actuators cause the controller to hang.

1 Like

Below is my own example code to read the “Present Position” which never cause the freeze in my case. I wanted to look into your code and find a root cause, but as I have no understanding your code unless I put my resources and time much, nor it’s been long time I used the C/C++, it is difficult for me to look into further. I highly recommend replacing your dynamic allocation method with just normal data type for test only and see if the freeze is caused by the memory leakeage by the dynamic memory allocation (using new operator). (*As far as I know, you should free your heap memory (using delete operator) if not using such addresses)

#include <Dynamixel2Arduino.h>


#define DXL_SERIAL   Serial3 //OpenCM9.04 EXP Board's DXL port Serial. (Serial1 for the DXL port on the OpenCM 9.04 board)
#define DEBUG_SERIAL Serial
const int DXL_DIR_PIN = 22; //OpenCM9.04 EXP Board's DIR PIN. (28 for the DXL port on the OpenCM 9.04 board)

//Please see eManual Control Table section of your DYNAMIXEL.
//This example is written for DYNAMIXEL AX & MX series with Protocol 1.0.
//For MX 2.0 with Protocol 2.0, refer to write_x.ino example.
#define CW_ANGLE_LIMIT_ADDR         6
#define CCW_ANGLE_LIMIT_ADDR        8
#define ANGLE_LIMIT_ADDR_LEN        2
#define OPERATING_MODE_ADDR_LEN     2
#define TORQUE_ENABLE_ADDR          24
#define TORQUE_ENABLE_ADDR_LEN      1
#define MOVING_SPEED_ADDR           32
#define MOVING_SPEED_ADDR_LEN       2
#define LED_ADDR                    25
#define LED_ADDR_LEN                1
#define GOAL_POSITION_ADDR          30
#define GOAL_POSITION_ADDR_LEN      2
#define PRESENT_POSITION_ADDR       36
#define PRESENT_POSITION_ADDR_LEN   2
#define TIMEOUT 10    //default communication timeout 10ms

uint8_t turn_on = 1;
uint8_t turn_off = 0;
uint16_t present_position = 0;

uint set_speed = 200;

const uint8_t DXL_ID = 1;
const float DXL_PROTOCOL_VERSION = 1.0;

uint16_t goalPosition1 = 0;
uint16_t goalPosition2 = 1023;

unsigned long current_time = 0;
unsigned long saved_time = 0;

Dynamixel2Arduino dxl(DXL_SERIAL, DXL_DIR_PIN);

void setup() {
  // put your setup code here, to run once:
  
  // For Uno, Nano, Mini, and Mega, use UART port of DYNAMIXEL Shield to debug.
  DEBUG_SERIAL.begin(115200);   //Set debugging port baudrate to 115200bps
  while(!DEBUG_SERIAL);         //Wait until the serial port for terminal is opened
  
  // Set Port baudrate to 57600bps. This has to match with DYNAMIXEL baudrate.
  dxl.begin(1000000);
  // Set Port Protocol Version. This has to match with DYNAMIXEL protocol version.
  dxl.setPortProtocolVersion(DXL_PROTOCOL_VERSION);

  // Turn off torque when configuring items in EEPROM area
  if(dxl.write(DXL_ID, TORQUE_ENABLE_ADDR, (uint8_t*)&turn_off , TORQUE_ENABLE_ADDR_LEN, TIMEOUT))
    DEBUG_SERIAL.println("DYNAMIXEL Torque off");
  else
    DEBUG_SERIAL.println("Error: Torque off failed");

  delay(100);
  // Set to Joint Mode
  if(dxl.write(DXL_ID, CW_ANGLE_LIMIT_ADDR, (uint8_t*)&goalPosition1, ANGLE_LIMIT_ADDR_LEN, TIMEOUT)
        && dxl.write(DXL_ID, CCW_ANGLE_LIMIT_ADDR, (uint8_t*)&goalPosition2, ANGLE_LIMIT_ADDR_LEN, TIMEOUT))
    DEBUG_SERIAL.println("Set operating mode");
  else
    DEBUG_SERIAL.println("Error: Set operating mode failed");
  
  delay(100);
  // Turn on torque
  if(dxl.write(DXL_ID, TORQUE_ENABLE_ADDR, (uint8_t*)&turn_on, TORQUE_ENABLE_ADDR_LEN, TIMEOUT))
    DEBUG_SERIAL.println("Torque on");
  else
    DEBUG_SERIAL.println("Error: Torque on failed");
  
  delay(100);

  if(dxl.write(DXL_ID, MOVING_SPEED_ADDR, (uint8_t*)&set_speed, MOVING_SPEED_ADDR_LEN, TIMEOUT))
    DEBUG_SERIAL.println("SET SPEED");
  else
    DEBUG_SERIAL.println("Error: SET SPEED failed");

  delay(100);

}

void loop() {

  DEBUG_SERIAL.print("Goal Position : ");
  DEBUG_SERIAL.println(goalPosition1);
  dxl.write(DXL_ID, GOAL_POSITION_ADDR, (uint8_t*)&goalPosition1, GOAL_POSITION_ADDR_LEN, TIMEOUT);


  while((current_time - saved_time) <= 5000){
    // Read DYNAMIXEL Present Position
    current_time = millis();

    DEBUG_SERIAL.print("Present Position : ");

    // dxl.read(DXL_ID, PRESENT_POSITION_ADDR, PRESENT_POSITION_ADDR_LEN, (uint8_t*)&present_position, sizeof(present_position), TIMEOUT);
    
    present_position = dxl.getPresentPosition(DXL_ID);
    
    DEBUG_SERIAL.println(present_position);
  }

  saved_time = current_time;
  
  // // Set Goal Position
  DEBUG_SERIAL.print("Goal Position : ");
  DEBUG_SERIAL.println(goalPosition2);  
  dxl.write(DXL_ID, GOAL_POSITION_ADDR, (uint8_t*)&goalPosition2, GOAL_POSITION_ADDR_LEN, TIMEOUT);

    while((current_time - saved_time) <= 5000){
    // Read DYNAMIXEL Present Position
    current_time = millis();
    
    DEBUG_SERIAL.print("Present Position : ");

    // dxl.read(DXL_ID, PRESENT_POSITION_ADDR, PRESENT_POSITION_ADDR_LEN, (uint8_t*)&present_position, sizeof(present_position), TIMEOUT);
    
    present_position = dxl.getPresentPosition(DXL_ID);
    
    DEBUG_SERIAL.println(present_position);
  }

  saved_time = current_time;

}

Okay, I’ll try to implement the code differently

1 Like

I decided. I read an incomplete manual on how to return an array from a function in c++. There was no information on how to delete an array from memory. Now I delete and my robot works stably for a long time.

1 Like

Hello @bonny

It’s a relief that you has resolved freezing issue.

Summarizing your approach, the solution to the freezing is to manually free the heap. Below is the simplified code.

int main()
{
// Heap
int *ptr_arr = new int[10];

// Free heap
delete [] ptr_arr;
}

If okay, put the reference page where you’ve found the solution here, and have not other users to suffers the similar problem.