Contents

[Robot Arm] Firmware setup

Define

  • DH table

    DH-table.png
    DH table

  • Link length

    DOF6Kinematic(0.109f, 0.035f, 0.146f, 0.115f, 0.052f, 0.072f)

Class

  • DummyHand
  • DummyRobot
    • TuningHelper
    • CommandHandler
    • CtrlStepMotor* motro[7] (6 motors + 1 gripper)
    • DummyHand

Environmental setup

這裡有嘗試過利用 STM32CubeIDE 來編譯 Firmware,但是因為 STM32CubeIDE 編譯器不一樣,所以會出現 undefined reference 的錯誤

STM32CubeIDE

操作步驟

  1. 開啟 STM32CubeIDE

  2. 選擇 File -> Import -> Existing Projects into Workspace

    (注意要用 Workbench 來開)

  3. 在匯入專案前,要保留 github 上 pull 下來的 file structure (不能把 Firmware 拖出來),這樣 IDE 才會跳出轉換通知

問題

No such file or directory
可以到 properties -> C/C++ General -> Paths and Symbols -> Source Location -> Add Folder -> 選擇專案的路徑
Undefine reference to
感覺是編譯器不同造成的問題,現在還無解

Clion

操作步驟

Follow 這篇稚暉君寫的 Clion 開發環境架設,注意幾件事情:

  1. 安裝 Clion 2019

    (補丁在這篇下載,下載完成後直接照著 Readme 操作)

  2. STM32CubeMX 版本不能最新,目前使用版本 6.5.0

  3. arm-none-eabi-gcc 版本不能最新,不然也會有 undefined reference 的問題,目前使用版本 9-2019-q4-major,下載 .zip 版本

  4. 記得安裝時路徑不能有空格,不然會出現找不到路徑的問題

  5. 其他像是 MinGW、OPENOCD 都可以直接安裝最新版本

問題

CMakeList.txt 版本與 CMake 不合
稚暉君的 CMakeList.txt minimum request CMake 版本 3.20,但是 Clion Bundle 的 CMake 只有 3.15,把 CMakeList.txt 的 minimum version 改成 3.15 可以解決
Undefine reference to
arm-none-eabi-gcc 載到新的版本,編譯器不同造成的問題,可能跟 linking 的順序有關係,將版本降到 9-2019-q4-major 可以解決

程式內容

STM32F1

STM32F4

其他問題

使用 CubeProgrammer 讀取 STM32 Device ID
連上 STM32 之後可以直接找 ID 所在的 register,每種型號的 ID(96 bits) 對應位置如下: 而這裡要注意的是, size 不能調太大,如果從你要看的 register 算起,剩下的 register 不到你設定的 size,那麼就會 reading fail 這個是成功的例子: 這顆 STM32F103C8T6 ,他的 ID 位置為 0x1FFFF7E8,ID 為:
使用 Clion printf scanf 來 debug

可以參考這裡設定 步驟如下:

  1. 新增 retarget.h 和 retarget.c
  2. 把裡面重複的幾個函數刪掉
  3. 在 main.c 裡面加入 RetargetInit(&huart1);
  4. 在要使用 printf 的地方加入 #include "retarget.h"
在 Clion 裡面設定 STlink

可以參考這裡設定 步驟如下:

  1. 選擇 edit configuration
  2. 新增 openocd configuration
  3. 在資料夾裡面新建 stlink.cfg 注意這裡不能跟稚暉君用一樣的 source [find target/cs32f1x.cfg] 要改成 source [find target/stm32f1x.cfg] 因為版本不同的關係,他的比較舊
xxxx.elf is not executable

這個也是沒有設定 stlink.cfg 的關係

  1. 選擇 edit configuration
  2. 新增 openocd configuration
  3. 在資料夾裡面新建 stlink.cfg
稚暉君的馬達 ID 計算方式

這裡他將三個 32 bits 的 ID 合併成一個 64 bits 的 ID,計算方式如下: 我直接分別將每片板子透過 STlink debug 連上去看 ID。 大馬達:

  • 42-1 = 120461776082565
  • 42-2 = 120466071115397
  • 42-3 = 120461627709061
  • 42-4 = 120461627184773
  • 42-5 = 120491840722565 小馬達:
  • 20-1 = 80892294279506
  • 20-2 = 80875094290770
  • 20-3 = 80887999181138
  • 20-4 = 80887979258194
  • 20-5 = 80870819377490

比較神奇的是稚暉君的馬達算出來都是 12 位,而我的都是 15 位,看來經過一年多,STM 賣了不少 MCU 出去

printf 重新定向

/posts/robot-arm-4/2023-07-05-21-10-07.png 直接在 main.cpp 裡面加入 RetargetInit(&huart1); 但是會出現 undefined reference to 的問題。 主要的問題出在 retarget.h 和它混編的 c 的問題,所以要在 retarget.h 裡面加上

#ifdef __cplusplus
extern "C"
{
#endif

...

#ifdef __cplusplus
} //extern "C"
#endif

問題就解決了。 reference: stackoverflow

resource

  • retarget.h
#ifndef _RETARGET_H__

#define _RETARGET_H__

#include "stm32f1xx_hal.h"

#include <sys/stat.h>

#include <stdio.h>

void RetargetInit(UART_HandleTypeDef *huart);

int _isatty(int fd);

int _write(int fd, char *ptr, int len);

int _close(int fd);

int _lseek(int fd, int ptr, int dir);

int _read(int fd, char *ptr, int len);

int _fstat(int fd, struct stat *st);

#endif //#ifndef _RETARGET_H__
  • retarget.c
#include <_ansi.h>
#include <_syslist.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/times.h>
#include <retarget.h>
#include <stdint.h>

#if !defined(OS_USE_SEMIHOSTING)

#define STDIN_FILENO  0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2

UART_HandleTypeDef *gHuart;

void RetargetInit(UART_HandleTypeDef *huart)
{
  gHuart = huart;

  /* Disable I/O buffering for STDOUT stream, so that
  * chars are sent out as soon as they are printed. */
  setvbuf(stdout, NULL, _IONBF, 0);
}

int _isatty(int fd)
{
  if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)
      return 1;

  errno = EBADF;
  return 0;
}

int _write(int fd, char *ptr, int len)
{
  HAL_StatusTypeDef hstatus;

  if (fd == STDOUT_FILENO || fd == STDERR_FILENO)
  {
      hstatus = HAL_UART_Transmit(gHuart, (uint8_t *) ptr, len, HAL_MAX_DELAY);
      if (hstatus == HAL_OK)
          return len;
      else
          return EIO;
  }
  errno = EBADF;
  return -1;
}

int _close(int fd)
{
  if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)
      return 0;

  errno = EBADF;
  return -1;
}

int _lseek(int fd, int ptr, int dir)
{
  (void) fd;
  (void) ptr;
  (void) dir;

  errno = EBADF;
  return -1;
}

int _read(int fd, char *ptr, int len)
{
  HAL_StatusTypeDef hstatus;

  if (fd == STDIN_FILENO)
  {
      hstatus = HAL_UART_Receive(gHuart, (uint8_t *) ptr, 1, HAL_MAX_DELAY);
      if (hstatus == HAL_OK)
          return 1;
      else
          return EIO;
  }
  errno = EBADF;
  return -1;
}

int _fstat(int fd, struct stat *st)
{
  if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)
  {
      st->st_mode = S_IFCHR;
      return 0;
  }

  errno = EBADF;
  return 0;
}

#endif //#if !defined(OS_USE_SEMIHOSTING)
  • stlink.cfg
# choose st-link/j-link/dap-link etc.
# adapter driver cmsis-dap
# transport select swd
source [find interface/stlink.cfg]
transport select hla_swd
# source [find target/cs32f1x.cfg]
source [find target/stm32f1x.cfg]

# download speed = 10MHz
adapter speed 10000