STM32L010F4P6マイコンを使ってマイクロサーボSG92R(SG-90の強化版)を動かしてみた

前回の続き。
STM32マイコン STM32L010F4P6マイクロサーボ SG92R を動かした。

データシートを確認する

STM32マイコン STM32L010F4P6のデータシートは前回と同じなので省略。

マイクロサーボSG92Rのデータシートそのものが見つからなかったので,
マイクロサーボ9g SG-90 のデータシートを参照する。

SG-90_ds

Specifications

とのこと。

つまりサーボコネクタの赤色線を電源の+に, 茶色線をGNDに接続して橙色線に図に書かれている信号を入力すると動く。

STM32とSG92Rサーボを接続

前回の回路にSG92Rサーボを追加した。

image01

STM32CubeIDEでプロジェクトを開く

前回のプロジェクトを再利用する。

CubeIDEをアップデートしたので Version: 1.8.0。

screenshot01

なんとC++17を選択できるようになっていたので選んでみた。
(前から選べたかも知れない。)

screenshot02

STM32L010F4P6のタイマ設定

PWM信号はSTM32L010F4P6のGeneral-purpose timerである TIM2 を PWM mode に設定して作ることにする。
タイマ割り込みを使わないのでTIM2 global interruptはデフォルト設定。

Application note AN4013 - st.com
STM32 cross-series timer overviewより引用。

an4013_p01

an4013_p02

an4013_p08

PA0をTIM2_CH1に割り当ててPWM出力ピンにする。
(このピンにSG92Rの橙色線を接続する。)

screenshot03

とりあえずクロックは4MHzに設定する。

screenshot04

TIM2の設定。

Prescaler (PSC - 16 bits value)
Prescaler (PSC - 16 bits value) must be between 0 and 65 535.

Counter Period (AutoReload Register - 16 bits value )
Counter Period (AutoReload Register - 16 bits value ) must be between 0 and 65 535.

screenshot05

タイマ周期は50Hzになるように, 以下の計算式より算出した。

an4013

an4013

Updateevent=TIM_CLK(PSC+1)×(ARR+1)×(RCR+1) Update_event = \frac{TIM\_ CLK}{(PSC+1) \times (ARR+1) \times (RCR+1)} より

ほしい値は各レジスタの設定値なので
右辺の分母を両辺に掛けて, Update_event を両辺から割ると

(PSC+1)×(ARR+1)×(RCR+1)=TIM_CLKUpdate_event (PSC+1) \times (ARR+1) \times (RCR+1) = \frac{TIM\_ CLK}{Update\_ event} となって

ここに

(PSC+1)×(ARR+1)=4×10650=4×102×10450=400×10450=8×104=80000 \begin{aligned} (PSC+1) \times (ARR+1) &= \frac{4 \times 10^6}{50} \\ &= \frac{4 \times 10^2 \times 10^4}{50} \\ &= \frac{400 \times 10^4}{50} \\ &= 8 \times 10^4 \\ &= 80000 \end{aligned}

STM32L010F4P6マイコンの ARRレジスタは16ビットレジスタなので, そのレジスタに設定できる最大値は 2161=655352^{16} - 1 = 65535

計算で得られた値 80000 は ARRレジスタの最大値を超える値なので設定できない。
なのでプリスケーラでクロック源から1/2にする設定(PSC=1)にする。

(1+1)×(ARR+1)=800002×(ARR+1)=80000ARR+1=800002ARR=8000021=39999 \begin{aligned} (1+1) \times (ARR+1) & = 80000 \\ 2 \times (ARR+1) & = 80000 \\ ARR+1 &= \frac{80000}{2} \\ ARR &= \frac{80000}{2} - 1 \\ &= 39999 \end{aligned}

結果
Prescaler (PSC - 16 bits value) には 1を
Counter Period (AutoReload Register - 16 bits value ) には 39999を
設定する。

SG92Rを動かすプログラム

SG92Rを0°から45°づつ180°まで繰り返し動くプログラムを書いてみた。

CPP
/*
 * Application.cpp
 *
 * Copyright 2021 Akihiro Yamamoto.
 * Licensed under the Apache License, Version 2.0
 * <https://spdx.org/licenses/Apache-2.0.html>
 *
 */
#include <ST7032iLcd.hpp>

extern I2C_HandleTypeDef hi2c1;
extern TIM_HandleTypeDef htim2;

static ST7032iLcd i2c_lcd(hi2c1);

using PwmTimerCounts = uint16_t;
constexpr static const PwmTimerCounts PwmPeriod =
    40000; // 40000 counts = 20 milliseconds
constexpr static const PwmTimerCounts ServoAngle0 =
    PwmPeriod * 0.5 / 20.0; // 0.5 milliseconds / 20 milliseconds
constexpr static const PwmTimerCounts ServoAngle180 =
    PwmPeriod * 2.4 / 20.0; // 2.4 milliseconds / 20 milliseconds

// degree: 0 to 180
static void moveTo(uint8_t degree) {
  uint32_t count = ServoAngle0 + (ServoAngle180 - ServoAngle0) * degree / 180;
  __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, count);
  std::string buff(50, ' ');
  std::snprintf(buff.data(), buff.size(), u8"カクド 「%3d」 ド", degree);
  i2c_lcd.setDdramAddress(0);
  i2c_lcd.putString(buff);
}

extern "C" void application_setup() {
  i2c_lcd.init();
  moveTo(0);
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
}

extern "C" void application_loop() {
  constexpr static const uint8_t step_angles = 45;
  constexpr static const uint8_t num_of_detents = 1 + 180 / step_angles;
  constexpr static const uint8_t slow_down = 30;
  static uint16_t i = 0;

  HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_4);
  HAL_Delay(200);
  moveTo(i / slow_down * step_angles);
  i = (i + 1) % (slow_down * num_of_detents);
}
クリックして展開し、詳細を表示

プロジェクトのビルド

Ctrl + B でビルド。

screenshot06

TEXT
11:30:31 **** Incremental Build of configuration Debug for project hello_stm32l0 ****
make -j16 all 
arm-none-eabi-g++ -o "hello_stm32l0.elf" @"objects.list"   -mcpu=cortex-m0plus -T"C:\Users\aki\STM32CubeIDE\workspace_1.7.0\hello_stm32l0\STM32L010F4PX_FLASH.ld" --specs=nosys.specs -Wl,-Map="hello_stm32l0.map" -Wl,--gc-sections -static --specs=nano.specs -mfloat-abi=soft -mthumb -Wl,--start-group -lc -lm -lstdc++ -lsupc++ -Wl,--end-group
c:\st\stm32cubeide_1.7.0\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.9-2020-q2-update.win32_2.0.0.202105311346\tools\arm-none-eabi\bin\ld.exe: hello_stm32l0.elf section `.text' will not fit in region `FLASH'
c:\st\stm32cubeide_1.7.0\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.9-2020-q2-update.win32_2.0.0.202105311346\tools\arm-none-eabi\bin\ld.exe: region `FLASH' overflowed by 3892 bytes
collect2.exe: error: ld returned 1 exit status
make: *** [makefile:79: hello_stm32l0.elf] Error 1
"make -j16 all" terminated with exit code 2. Build might be incomplete.

11:30:32 Build Failed. 3 errors, 0 warnings. (took 348ms)
クリックして展開し、詳細を表示

はい、エラー。

TEXT
ld.exe: region `FLASH' overflowed by 3892 bytes
クリックして展開し、詳細を表示

FLASH領域から溢れた。

あふれたのは仕方がないのでReleaseビルドにする。

screenshot07

TEXT
11:43:25 **** Incremental Build of configuration Release for project hello_stm32l0 ****
make -j16 all 
arm-none-eabi-size   hello_stm32l0.elf 
   text	   data	    bss	    dec	    hex	filename
  11424	    124	   1752	  13300	   33f4	hello_stm32l0.elf
Finished building: default.size.stdout
 

11:43:25 Build Finished. 0 errors, 0 warnings. (took 217ms)
クリックして展開し、詳細を表示

screenshot08

デバッグ関連のコードが無くなるので、収まった。

screenshot09

ST-Linkでプログラミング

前回と同じなので省略。

実行

サーボ角度 0 度

angle0

周波数と周期の関係は f=1Tf = \frac{1}{T} なので 119.946×103=50.135Hz\frac{1}{19.946 \times 10 ^{-3}} = 50.135 \mathrm{Hz}

angle0

サーボ角度 45 度

angle45

サーボ角度 90 度

angle90

サーボ角度 135 度

angle135

サーボ角度 180 度

angle180

ここでもう一度マイクロサーボSG-90のデータシートを確認すると

SG-90_ds

データシートに書かれたとおりの信号を与えている。

Position “0” (1.45 ms pulse) is middle, “90” (~2.4 ms pulse) is all the way to the right, “-90” (~ 0.5 ms pulse) is all the way left.

データシートには

GitHubリポジトリ

https://github.com/ak1211/hello_stm32l0/tree/Servo

https://github.com/ak1211/hello_stm32l0/releases/tag/Servo

著作権表示

著者: Akihiro Yamamoto

リンク: https://ak1211.com/posts/7714/

ライセンス: CC BY-NC-SA 4.0

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Please attribute the source, use non-commercially, and maintain the same license.

コメント

検索を開始

キーワードを入力して記事を検索

↑↓
ESC
⌘K ショートカット