Edit on GitHub

Introduction

The Embedded C SDK enables users to create their own CM-530 firmware from scratch. Example implementations for basic features are provided on this page.

NOTE : This Embedded C SDK is intended for experienced users and programmers. ROBOTIS recommends that first time DYNAMIXEL users use the provided CM-530 firmware.

NOTE : Custom CM-530 firmware cannot be used with R+ Task software. After flashing custom firmware to the CM-530 it will not be usable with R+ Task until the default firmware is restored.

CM-530

The CM-530 SDK can be found on our Download Center

File Structure

Getting Started

WARNING: You may encounter following errors during installation:

  • EX error :/usr/bin/sh: fork: Resource temporarily unavailable
  • make: *** [CM530.lss] Error 128

Solution to the installtion errors:

  1. Download a file - msys-1.0-vista64.zip
  2. Extract the file.
  3. Copy and paste the extracted file into C:\WinARM\utils\bin.

Install JRE

JRE(Java Runtime Environment) is a required component to run Eclipse.

To verify whether JRE has been installed input ‘java’ at the command prompt. You can download JRE here.

Download JRE

Select the version that best matches your working system.

Install WinARM

You can download WinARM

Download WinARM.

The downloaded file is a compressed file. Decompressed the file in C:\WinARM directory.

You must register WinARM to complete installation.
Go to [Control Panel] > [System] > [Advanced system settings] and select [Advanced] tab. Click on the [Environment Variables] button.

Find “Path” variable in the [System variables] group and edit its value.
If the “Path” variable is not exist then create new path by clicking on the “New” button.

Click on the [New] button and add below items at the end of path lists for Windows 10 users.

C:\WinArm\bin
C:\WinARM\utils\bin

Other than Windows 10, append below items at the end of the variable value. Don’t miss the delimiter ‘;’(semicolon) in between each path.

C:\WinArm\bin;C:\WinARM\utils\bin;

To verify proper installation, open the command window and type ‘arm-eabi-gcc –v’.
If it does not work well, turn off the cmd window and re-run cmd, then try again.

Install Eclipse

You can download Eclipse here.

Download Eclipse Helios SR2

Select the version that best matches your working system.
To run Eclipse just run the eclipse.exe file.

Verify Installation

Verify successful installation.by opening a sample project.
Decompress the file (no root user rights needed).

When you first run Eclipse, it requires to set up workspace like the picture below.

Run Eclipse and go to File – New – Makefile Project with Existing Code.

Click on Browse select 01 LED and click on Verify.

After selecting the project go to Project – Clean, Build

To see progress check the terminal window.
If progress is not as shown below then check the working development environment.

WARNING: You may encounter following errors during installation:

  • EX error :/usr/bin/sh: fork: Resource temporarily unavailable
  • make: *** [CM530.lss] Error 128

Solution to the installtion errors:

  1. Download a file - msys-1.0-vista64.zip
  2. Extract the file.
  3. Copy and paste the extracted file into C:\WinARM\utils\bin.

Restore RoboPlus

The result made by Embedded C is a controller firmware (bin file). If you install it, you cannot use RoboPlus since the existing controller firmware is erased. If you want to use RoboPlus again, you must install the original controller firmware built-in from the factory. You can install the original controller firmware easily using RoboPlus Manager.

For more information, please refer to Firmware Restoration of RoboPlus Manager.

Programming

Hardware Port Map

The following hardware port map shows the hardware main pin functions of the controller.
Macros and libraries for the STM32F10X ports and internal functionalities are provided for easy access and control.

CM-530

Pin # Pin Name NET NAME Description
1 Vbat VCC_33L 3.3V power supply
2 PC13 LED0 LED POWER
3 PC14 LED_TX LED TX
4 PC15 LED_RX LED RX
5 OSC_IN XTAL1 X-TAL INPUT
6 OSC_OUT XTAL2 X-TAL OUTPUT
7 NRST RESET RESET
8 PC0 SIG_ADC0 ADC0 INPUT
9 PC1 ADC_SELECT0 ANALOG MUX SELECT0
10 PC2 ADC_SELECT1 ANALOG MUX SELECT1
11 PC3 VDD_VOLT input voltage ADC
12 VSSA VSSA ADC reference voltage 3.3V
13 VDDA VDDA ADC reference voltage 0V
14 PA0 SIG_MOT1+ #1 external port OUPUT
15 PA1 SIG_MOT1- 1 external port OUPUT
16 A2 SIG_MOT2+ #2 external port OUPUT
17 PA3 SIG_MOT2- #2 external port OUPUT
18 VSS4 GND 0V reference voltage
19 VDD4 VCC_33L 3.3V reference voltage
20 PA4 NC RESERVED
21 PA5 SIG_ADC1 ADC1 INPUT
22 PA6 SIG_BUZZER Buzzer OUTPUT
23 PA7 NC RESERVED
24 PC4 SIG_MIC MIC Signal INPUT
25 PC5 NC RESERVED
26 PB0 NC RESERVED
27 PB1 NC RESERVED
28 PB2 BOOT1 RESERVED
29 PB10 PC_TXD PC transmit
30 PB11 PC_RXD PC receive
31 VSS1 GND 0V reference voltage
32 VDD1 VCC_33L 3.3V reference voltage
33 PB12 LED3 LED AUX
34 PB13 LED4 LED MANAGE
35 PB14 LED5 LED PROGRAM
36 PB15 LED6 LED PLAY
37 PC6 SIG_MOT3+ #3 external port OUPUT
38 PC7 SIG_MOT3- #3 external port OUPUT
39 PC8 SIG_MOT4+ #4 external port OUPUT
40 PC9 SIG_MOT4- #4 external port OUPUT
41 PA8 SIG_MOT5+ #5 external port OUPUT
42 PA9 NC RESERVED
43 PA10 NC RESERVED
44 PA11 SIG_MOT5- #5 external port OUPUT
45 PA12 ZIGBEE_RESET Zigbee ENABLE
46 PA13 USB_SLEEP USB connections
47 VSS2 GND 0V reference voltage
48 VDD2 VCC_33L 3.3V reference voltage
49 PA14 SW_RT R Button
50 PA15 SW_LF L Button
51 PC10 SW_DN D Button
52 PC11 SW_UP U Button
53 PC12 ZIGBEE_TXD Zigbee transmit
54 PD2 ZIGBEE_RXD Zigbee receive
55 PB3 SW_START START Button
56 PB4 ENABLE_TX Dynamixel transmit ENABLE
57 PB5 ENABLE_RX Dynamixel receive ENABLE
58 PB6 DXL_TXD Dynamixel transmit
59 PB7 DXL_RXD Dynamixel receive
60 BOOT0 BOOT0 RESERVED
61 PB8 SIG_MOT6+ #6 external port OUPUT
62 PB9 SIG_MOT6- #6 external port OUPUT
63 VSS3 GND 0V reference voltage
64 VDD3 VCC_33L 3.3V reference voltage

The external ports of the CM-530 are listed below from 1 to 6. Please refer to CM-530 controller for reference regarding ports.

  1. OUT1 : Output voltage 3.3V (0.3A max)
  2. VCC (5V)
  3. ADC : Ports for analog signal devices
  4. GND
  5. OUT2 : Output voltage 3.3V (0.3A max)

Open Project

Open 01 LED project

Run Eclipse and go to Fle – New – makefile Project with existing code.

Click on Browse select 01 LED and click on Verify.

After selecting the project go to Project – Clean, Build

To see progress check the terminal window.
If progress is not as shown below then check the working development environment.

Download bin File

After a successful build the bin file will be located at the sample directory.
The firmware can be loaded into the controller via bootloader from RoboPlus Terminal.
Please refer to the bootloader program for firmware installation and running.

Boot Loader

Boot Loader makes the users possible to use the controller. Boot Loader cannot be erased by the users. If it is broken down, the controller cannot be used. Boot Loader is built-in on the controller when it is manufactured in the factory.

The available commands in Boot Loader can be found using “Help” command.

Entering/Exiting Boot Loader

Entering Boot Loader

To enter into the boot loader, while pressing the ‘#’ button(Shift + 3), turn on the controller or press down the reset switch.
If you did correctly, following screen page will be shown.

Exiting Boot Loader

If the work is completed, you may exit by jumping to the desired address using “GO” command or by resetting the controller.

How to Use APP/SYS

The program start position can be set by APP/SYS command. Once the program start position is set, the program is executed on the program start position when the power is turned on or reset.

The memory map using STM32F103RE is as below.

Install/Execute Program

Preparations for installing a firmware of the controller are as follows:

A firmware of the controller can be installed according to the procedure below.

  1. Input “L” command (or Load) in Boot Loader.

  2. Select “Transmit File” in the Files menu of RoboPlus Terminal, and then select the prepared firmware. (bin file)

  3. The file is transmitted. Please do not let the power of the controller turn off, and be careful the cable does not take off while the file is being transmitted.

  4. When the file transmission is completed, you can execute the program using GO command.

    • In case of inputting only “GO” command, the program is executed from 0 address.
    • Like G [Address], if you input execution address (hexadecimal) after “G” command, the program is executed from the location.

Additional Description

File creation

The newly made file can be changed from the sample\makefile designation. From makefile you can rename the file after ‘MAIN_OUT =’.

Object file list

From the illustration ‘sample\app\src’ directory object files are produced from the .c files; where the Makefile requires these object files.

Firmware start address

The memory maps and bootloader domain are divided into the following.

The firmware starting address is 0X8003000 by default user-modifiable.
The following example is with address 0X8003000

  1. changing stm32.ld

  2. changing the vector table

Examples

LED Control

Each LED of the controller can be controlled.

Button

Input of the button can be received.

Serial Communication

PC and the controller can perform serial communication.

Buzzer

Buzzer on the controller can be used.

MIC

External sounds can be detected through MIC.

int main(void)
{
  /* System Clocks Configuration */
  RCC_Configuration();
  /* NVIC configuration */
  NVIC_Configuration();
  /* NVIC configuration */
  GPIO_Configuration();
  SysTick_Configuration();
  GPIO_ResetBits(PORT_LED_POWER, PIN_LED_POWER);
   
  while(1)
  {
    if( GPIO_ReadInputDataBit(PORT_MIC, PIN_MIC) != SET)
    {
      GPIO_ResetBits(PORT_LED_MANAGE, PIN_LED_MANAGE);
      GPIO_ResetBits(PORT_LED_PROGRAM, PIN_LED_PROGRAM);
      GPIO_ResetBits(PORT_LED_PLAY, PIN_LED_PLAY);
      GPIO_ResetBits(PORT_LED_TX, PIN_LED_TX);
      GPIO_ResetBits(PORT_LED_RX, PIN_LED_RX);
      GPIO_ResetBits(PORT_LED_AUX, PIN_LED_AUX);
      mDelay(1000);
    }
    else
    {
      GPIO_SetBits(PORT_LED_MANAGE, PIN_LED_MANAGE);
      GPIO_SetBits(PORT_LED_PROGRAM, PIN_LED_PROGRAM);
      GPIO_SetBits(PORT_LED_PLAY, PIN_LED_PLAY);
      GPIO_SetBits(PORT_LED_TX, PIN_LED_TX);
      GPIO_SetBits(PORT_LED_RX, PIN_LED_RX);
      GPIO_SetBits(PORT_LED_AUX, PIN_LED_AUX);
    }
  }
  return 0;
}

OLLO Servo CW/CCW

Learning ollo servo motor rotation direction

Refer to controller’s port for port and pin number in 06 OLLO MOTOR ROTATE\APP\src\main.c

int main(void)
{
   /* System Clocks Configuration */
  RCC_Configuration();
  /* NVIC configuration */
  NVIC_Configuration();
  /* GPIO configuration */
  GPIO_Configuration();
  SysTick_Configuration();
  GPIO_ResetBits(PORT_SIG_MOT1P,PIN_SIG_MOT1P);
  GPIO_ResetBits(PORT_SIG_MOT1M,PIN_SIG_MOT1M);
  GPIO_ResetBits(PORT_LED_POWER, PIN_LED_POWER);
   
  while(1)
  {
    GPIO_SetBits(PORT_SIG_MOT1P,PIN_SIG_MOT1P);
    GPIO_ResetBits(PORT_SIG_MOT1M,PIN_SIG_MOT1M);
    mDelay(5000);
    GPIO_SetBits(PORT_SIG_MOT1M,PIN_SIG_MOT1M);
    mDelay(5000);
    GPIO_SetBits(PORT_SIG_MOT1P,PIN_SIG_MOT1P);
    GPIO_SetBits(PORT_SIG_MOT1M,PIN_SIG_MOT1M);
    mDelay(2000);
  }
  return 0;
}

OLLO Servo Position

Learning ollo servo motor position reading

int main(void)
{
  /* System Clocks Configuration */
  RCC_Configuration();
  /* NVIC configuration */
  NVIC_Configuration();
  /* GPIO configuration */
  GPIO_Configuration();
  SysTick_Configuration();
  /* ADC configuration */
  ADC_Configuration();
  GPIO_ResetBits(PORT_SIG_MOT1P,PIN_SIG_MOT1P);
  GPIO_ResetBits(PORT_SIG_MOT1M,PIN_SIG_MOT1M);
  GPIO_ResetBits(PORT_SIG_MOT2P,PIN_SIG_MOT2P);
  GPIO_ResetBits(PORT_SIG_MOT2M,PIN_SIG_MOT2M);
  GPIO_ResetBits(PORT_SIG_MOT3P,PIN_SIG_MOT3P);
  GPIO_ResetBits(PORT_SIG_MOT3M,PIN_SIG_MOT3M);
  GPIO_ResetBits(PORT_SIG_MOT4P,PIN_SIG_MOT4P);
  GPIO_ResetBits(PORT_SIG_MOT4M,PIN_SIG_MOT4M);
  GPIO_ResetBits(PORT_SIG_MOT5P,PIN_SIG_MOT5P);
  GPIO_ResetBits(PORT_SIG_MOT5M,PIN_SIG_MOT5M);
  GPIO_ResetBits(PORT_SIG_MOT6P,PIN_SIG_MOT6P);
  GPIO_ResetBits(PORT_SIG_MOT6M,PIN_SIG_MOT6M);
  GPIO_ResetBits(PORT_LED_POWER, PIN_LED_POWER);
   
  while(1)
  {
    GPIO_ResetBits(PORT_ADC_SELECT0,PIN_ADC_SELECT0);
    GPIO_ResetBits(PORT_ADC_SELECT1,PIN_ADC_SELECT1);
    mDelay(10);
    /* Start ADC1,ADC2 Software Conversion */
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    ADC_SoftwareStartConvCmd(ADC2, ENABLE);
    mDelay(10);
    POT_1 = (ADC_GetConversionValue(ADC1))>>2;
    POT_4 = (ADC_GetConversionValue(ADC2))>>2;
    GPIO_SetBits(PORT_ADC_SELECT0,PIN_ADC_SELECT0);
    GPIO_ResetBits(PORT_ADC_SELECT1,PIN_ADC_SELECT1);
    mDelay(10);
    /* Start ADC1,ADC2 Software Conversion */
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    ADC_SoftwareStartConvCmd(ADC2, ENABLE);
    mDelay(10);
    POT_2 = (ADC_GetConversionValue(ADC1))>>2;
    POT_5 = (ADC_GetConversionValue(ADC2))>>2;
    GPIO_ResetBits(PORT_ADC_SELECT0,PIN_ADC_SELECT0);
    GPIO_SetBits(PORT_ADC_SELECT1,PIN_ADC_SELECT1);
    mDelay(10);
    /* Start ADC1,ADC2 Software Conversion */
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    ADC_SoftwareStartConvCmd(ADC2, ENABLE);
    mDelay(10);
    POT_3 = (ADC_GetConversionValue(ADC1))>>2;
    POT_6 = (ADC_GetConversionValue(ADC2))>>2;
    TxDWord16(POT_1);
    TxDByte_PC(' ');
    TxDWord16(POT_2);
    TxDByte_PC(' ');
    TxDWord16(POT_3);
    TxDByte_PC(' ');
    TxDWord16(POT_4);
    TxDByte_PC(' ');
    TxDWord16(POT_5);
    TxDByte_PC(' ');
    TxDWord16(POT_6);
    TxDByte_PC(' ');
    TxDByte_PC('\r');
    TxDByte_PC('\n');
  }
  return 0;
}

IR Sensor

Here you can learn how t o use the ADC of external ports.

int main(void)
{
  /* System Clocks Configuration */
  RCC_Configuration();
  /* NVIC configuration */
  NVIC_Configuration();
  /* GPIO configuration */
  GPIO_Configuration();
  SysTick_Configuration();
  /* ADC configuration */
  ADC_Configuration();
  GPIO_ResetBits(PORT_SIG_MOT1P,PIN_SIG_MOT1P);
  GPIO_ResetBits(PORT_SIG_MOT1M,PIN_SIG_MOT1M);
  //GPIO_ResetBits(PORT_LED_POWER, PIN_LED_POWER);
   
  while(1)
  {
    GPIO_SetBits(PORT_SIG_MOT1P, PIN_SIG_MOT1P);
    GPIO_ResetBits(PORT_SIG_MOT1M, PIN_SIG_MOT1M);
    GPIO_ResetBits(PORT_ADC_SELECT0,PIN_ADC_SELECT0);
    GPIO_ResetBits(PORT_ADC_SELECT1,PIN_ADC_SELECT1);
    uDelay(30);
    /* Start ADC1,ADC2 Software Conversion */
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    //ADC_SoftwareStartConvCmd(ADC2, ENABLE);
    uDelay(5);
    IR_1 = (ADC_GetConversionValue(ADC1));
    GPIO_ResetBits(PORT_SIG_MOT1P, PIN_SIG_MOT1P);
    GPIO_ResetBits(PORT_SIG_MOT1M, PIN_SIG_MOT1M);
    TxDWord16(IR_1);
    TxDByte_PC('\r');
    TxDByte_PC('\n');
    mDelay(5);
  }
  return 0;
}

Read/Write Dynamixel

The location of DYNAMIXEL can be set and read. (For more details refer to DYNAMIXEL SDK)

int main(void)
{
  /* System Clocks Configuration */
  RCC_Configuration();
  /* NVIC configuration */
  NVIC_Configuration();
  /* GPIO configuration */
  GPIO_Configuration();
  SysTick_Configuration();
  dxl_initialize( 0, 1 );
  USART_Configuration(USART_PC, Baudrate_PC);
  TxDString("\n\nDynamixel Read/Write example for CM-530\n\n");
   
  while(1)
  {
    bMoving = dxl_read_byte( id, P_MOVING );
    CommStatus = dxl_get_result();
    if( CommStatus == COMM_RXSUCCESS )
    {
      if( bMoving == 0 )
      {
        // Change goal position
        if( INDEX == 0 )
          INDEX = 1;
        else
          INDEX = 0;
        // Write goal position
        dxl_write_word( id, P_GOAL_POSITION_L, GoalPos[INDEX] );
      }
      PrintErrorCode();
      // Read present position
      wPresentPos = dxl_read_word( id, P_PRESENT_POSITION_L );
      TxDWord16(GoalPos[INDEX]);
      TxDString("   ");
      TxDWord16(wPresentPos);
      TxDByte_PC('\r');
      TxDByte_PC('\n');
    }
    else
      PrintCommStatus(CommStatus);
  }
  return 0;
}

Dynamixel Sync Control

Multiple DYNAMIXEL can be controlled by synchronization. (For more details refer to DYNAMIXEL SDK)

int main(void)
{
  /* System Clocks Configuration */
  RCC_Configuration();
  /* NVIC configuration */
  NVIC_Configuration();
  /* GPIO configuration */
  GPIO_Configuration();
  SysTick_Configuration();
  dxl_initialize( 0, 1 );
  USART_Configuration(USART_PC, Baudrate_PC);
  TxDString("\n\nDynamixel SyncWrite example for CM-530\n\n");
  for( i=0; i<NUM_ACTUATOR; i++ )
  {
    id[i] = i+1;
  }
  // Set goal speed
  dxl_write_word( BROADCAST_ID, P_GOAL_SPEED_L, 0 );
  // Set goal position
  dxl_write_word( BROADCAST_ID, P_GOAL_POSITION_L, AmpPos );
  mDelay(1000);
   
  while(1)
  {
    // Make syncwrite packet
    dxl_set_txpacket_id(BROADCAST_ID);
    dxl_set_txpacket_instruction(INST_SYNC_WRITE);
    dxl_set_txpacket_parameter(0, P_GOAL_POSITION_L);
    dxl_set_txpacket_parameter(1, 2);
    for( i=0; i<NUM_ACTUATOR; i++ )
    {
      dxl_set_txpacket_parameter(2+3*i, id[i]);
      dxl_set_txpacket_parameter(2+3*i+1, dxl_get_lowbyte(GoalPos));
      dxl_set_txpacket_parameter(2+3*i+2, dxl_get_highbyte(GoalPos));
      TxDByte_PC('\r');
      TxDByte_PC('\n');
      TxDWord16(GoalPos);
    }
    dxl_set_txpacket_length((2+1)*NUM_ACTUATOR+4);
    dxl_txrx_packet();
    CommStatus = dxl_get_result();
    if( CommStatus == COMM_RXSUCCESS )
      PrintErrorCode();
    else
      PrintCommStatus(CommStatus);
    GoalPos += 100;
    if( GoalPos > MAX_POSITION )
      GoalPos -= MAX_POSITION;
    mDelay(CONTROL_PERIOD);
  }
  return 0;
}

RC-100/ZIGBEE

The controller can be operated using RC-100.

int main(void)
{
  /* System Clocks Configuration */
  RCC_Configuration();
  /* NVIC configuration */
  NVIC_Configuration();
  /* Configure the GPIO ports */
  GPIO_Configuration();
  SysTick_Configuration();
  zgb_initialize(0);
  USART_Configuration(USART_PC, 57600);
  GPIO_ResetBits(PORT_LED_POWER, PIN_LED_POWER);
   
  while(1)
  {
    if(zgb_rx_check() == 1)
    {
      RcvData = zgb_rx_data();
      TxDWord16(RcvData);
      TxDByte_PC('\r');
      TxDByte_PC('\n');
      if(RcvData & RC100_BTN_1)
        GPIO_ResetBits(PORT_LED_MANAGE, PIN_LED_MANAGE);
      else
        GPIO_SetBits(PORT_LED_MANAGE, PIN_LED_MANAGE);
      if(RcvData & RC100_BTN_2)
        GPIO_ResetBits(PORT_LED_PROGRAM, PIN_LED_PROGRAM);
      else
        GPIO_SetBits(PORT_LED_PROGRAM, PIN_LED_PROGRAM);
      if(RcvData & RC100_BTN_3)
        GPIO_ResetBits(PORT_LED_PLAY, PIN_LED_PLAY);
      else
        GPIO_SetBits(PORT_LED_PLAY, PIN_LED_PLAY);
    }
  }
  return 0;
}