フェーズ4

E4-01 PWM概念:DS3218サーボに真ん中付近のPWMを出してみる

シリーズ:実験シリーズ(フェーズ4)
対応ロードマップ:フェーズ4 / E4-01
この記事で扱う範囲:PWMの周期とパルス幅の関係を確認し、DS3218サーボに真ん中付近の位置へ移動させるPWMを出します。今回は、サーボを大きく動かすことが目的ではありません。まずは、サーボを安全に接続し、PWM信号で制御する入口を作ります。

1. 目的

今回は、フェーズ4の最初として、PWMでサーボを動かすための基礎を作ります。
フェーズ3では、IMUを使って姿勢を読み、異常姿勢を検出したら ERROR に移る安全停止の流れを作りました。
フェーズ4では、いよいよロボットを実際に動かす部品である サーボ を扱います。

ただし、最初からサーボを大きく動かすと危険です。
サーボはLEDやセンサと違い、

  • 急に動く
  • 力が強い
  • 電流を多く使う
  • 配線ミスで電源や部品を壊す可能性がある

という注意点があります。
そのため今回は、最初の実験として、

PWMとは何かを知る  
    ↓  
周期とパルス幅の関係を理解する  
    ↓  
サーボ用の別電源を用意する  
    ↓  
評価ボードとサーボ電源のGNDを共通にする  
    ↓  
サーボを真ん中付近の位置へ移動させるPWMを1つ出す  
    ↓  
サーボが大きく暴れないことを確認する

という流れで進めます。
今回のゴールは、サーボの可動範囲を調べることではありません。
まずは、

  • PWMの周期が分かる
  • パルス幅でサーボの位置が変わることが分かる
  • サーボ電源を評価ボードとは別にする理由が分かる
  • GND共通が必要な理由が分かる
  • サーボを真ん中付近の位置へ移動させるPWMを出せる

ところまでを確認します。

2. 前提・環境

2-1. 前提

この記事は、次の内容が終わっている前提で進めます。

  • フェーズ0:ビルド / 書き込み / main到達 / UARTログ出力
  • フェーズ1:GPIO出力の基本
  • E2-02:1msごとの時刻を作る
  • E2-03:周期処理
  • E2-05:状態で整理(IDLE / RUN / ERROR)
  • E3-07:異常姿勢時に安全停止へ移る考え方を確認している

今回からサーボを扱います。
サーボは、評価ボードの3.3Vピンや5Vピンから直接電源を取らず、
サーボ用の別電源 を使います。

2-2. 使用するもの

  • 評価ボード:RTK7EKA8M2S00001BE
  • e² studio + FSP
  • Tera Term
  • サーボ:DS3218
  • UBEC:HENGE ハイボルテージ対応 UBEC
    • 入力電圧:7V - 25.5V
    • 対応:2-6S LiPo / 6-16セル Ni-Mh
    • 出力電圧:5V / 8A または 6V / 8A
    • 電流:8A、ピーク時12A(15秒未満)
    • 重量:16g
    • サイズ:45 x 22 x 7.5mm
  • バッテリー:URGENEX 7.4V 1000mAh LiPo Battery 2S 35C JST Plug
  • メス-メスジャンパ線、メス-片側バラ線ジャンパ
  • WFR-2BP、WFR-3BP
  • SFE-ROB-19224
  • サーボ延長ケーブル、またはサーボ信号線を取り出せる配線
  • 可能であればテスター

2-3. 今回の電源構成

今回は、次のように電源を分けます。

RA8M2評価ボード
  └─ USB / デバッガ側から給電
DS3218サーボ
  └─ LiPoバッテリー → UBEC → サーボ電源

重要なのは、次の点です。

評価ボードの電源でサーボを動かさない

サーボは動き出す瞬間に大きな電流を使います。
評価ボードから直接サーボ電源を取ると、電圧が下がったり、評価ボードがリセットしたり、最悪の場合は壊れる可能性があります。
そのため、サーボの赤線と茶色線、または赤線と黒線は、UBEC側につなぎます。
評価ボードからサーボへ出すのは、基本的に PWM信号線 です。
PWM信号を正しく伝えるために、評価ボードのGNDとUBEC側のGNDは共通にします。

2-4. UBECの出力電圧について

今回使うUBECは、出力を 5V または 6V にできるものです。
DS3218は高トルクのサーボなので、6Vで使う場面もあります。
ただし、最初の実験では、サーボを大きく動かすことが目的ではありません。
そのため、最初は安全側として 5V出力 から始める方がよいです。

最初の確認:5V出力
動作確認後:必要に応じて6V出力を検討

6Vにすると力が出やすくなる一方で、動作も強くなります。
初心者向けの最初の実験では、まず5Vで真ん中付近のPWMを出し、配線と信号が正しいことを確認します。

2-5. LiPoバッテリーの注意

LiPoバッテリーは、扱いを間違えると危険です。
最低限、次の点を守ります。

  • ショートさせない
  • 充電にはLiPo対応充電器を使う
  • 膨らんだバッテリーは使わない
  • 熱い、においがする、異常がある場合はすぐ使用をやめる
  • 実験中は目を離さない
  • 配線変更は、バッテリーを外してから行う

今回の実験では、サーボが大きく動かないように真ん中付近のPWMだけを出します。
それでも、電源を入れた瞬間にサーボが少し動くことがあります。
サーボホーンを付ける場合は、指やケーブルを巻き込まない向きにしておきます。

3. 今回の変更点

3-1. 配線変更

今回は、フェーズ3までのIMU配線とは別に、サーボを接続します。
基本の接続は次の通りです。

LiPoバッテリー
  ↓
UBEC
  ↓
DS3218サーボの電源線

評価ボードとサーボの接続は、次の3本を意識します。

サーボ側接続先役割
赤線UBECの +5V または +6Vサーボ用電源
茶色線 / 黒線UBECのGNDサーボ用GND
橙色線 / 黄色線 / 白線評価ボードのPWM出力ピン制御信号

さらに重要なのが、次の接続です。

評価ボードのGND ─ UBECのGND

これを 共通GND にします。
信号線だけをつないでも、GNDが共通でないと、サーボから見るとPWM信号の基準が分かりません。
その結果、動かない、たまに動く、変な動きをする、という原因になります。

サーボ配線2
サーボ配線1

3-2. 設定変更

今回は、FSPでPWM出力用のタイマを1つ追加します。
例として、GPTを使う前提で説明します。
FSP Configuratorで、次のような設定にします。

PWM設定

項目設定例
Pin Output SupportEnabled
Nameg_timer_servo0
ModeSaw-wave PWM
Period20
Period UnitMilliseconds
Duty Cycle Percent8
GTIOCA Output EnabledTrue
GTIOCA Stop LevelPin Level Low
GTIOCB Output EnabledFalse
CallbackNULL
Servo PWM FSP Conf 1
Servo PWM FSP Conf 2

Pin設定

Servo PWM FSP Conf 3

サーボ用PWMでは、一般的に次のような考え方を使います。

パルス幅意味の目安
約1.0ms片側
約1.5ms中立付近
約2.0ms反対側

ただし、これはあくまで目安です。
サーボによって安全な範囲は違います。
そのため今回は、いきなり1.0msや2.0msを出さず、まずは 1.5ms付近 だけを出します。

3-3. コード変更

今回は、次の処理を追加します。

  • PWM用タイマをOpenする
  • PWM周期を20msとして扱う
  • パルス幅1500usを真ん中付近として設定する
  • PWM出力をスタートする
  • UARTログで、設定したパルス幅を表示する

今回の中心は、次の考え方です。

サーボ角度を直接指定しているのではなく、PWMのパルス幅を変えてサーボに位置を伝えている

つまり、今回の段階では、

90度にしなさい

と命令しているのではありません。
実際には、

20msごとに、1.5msだけHighになる信号を出す

という信号を出しています。
サーボ側がそのPWM信号を見て、真ん中付近に動こうとします。

4. PWMとは何か

4-1. PWMはON/OFFの時間を変える信号

PWMは、信号を高速にON/OFFし、そのONの時間を変える方法です。
サーボでは、次のような信号を一定周期で出します。

周期:20msHighの時間:1.5msLowの時間:18.5ms

イメージは次の通りです。

High  ┌────┐                  ┌────┐
      │    │                  │    │
Low ──┘    └──────────────────┘    └────
      ←1.5ms→←     18.5ms     →
      ←         20ms          →

この Highになっている時間 をパルス幅と呼びます。

4-2. サーボはパルス幅を見て位置を決める

サーボは、PWMの周期そのものよりも、主にパルス幅を見て位置を決めます。
そのため、サーボを動かすには、PWMの周期を大きく変えるのではなく、Highになっている時間、つまりパルス幅を変更します。
たとえば一般的なRCサーボでは、目安として次のようになります。

1.0ms付近 → 片側へ動く
1.5ms付近 → 真ん中付近へ動く
2.0ms付近 → 反対側へ動く

ただし、サーボによって実際の範囲は違います。
そのため、今回のE4-01では範囲を攻めません。
まずは真ん中付近の1.5msを出し、

PWMでサーボを制御する入口ができた

ことを確認します。

4-3. Duty比だけで考えると分かりにくい

PWMではDuty比という言葉も出てきます。
Duty比は、周期のうちHighになっている割合です。
たとえば、周期20msでパルス幅1.5msなら、

1.5ms / 20ms = 0.075

なので、Duty比は約7.5%です。
ただし、サーボ制御では、初心者のうちはDuty比よりも、

パルス幅が何usか

で考えた方が分かりやすいです。
今回も、コードでは次のように扱います。

1500usのパルスを出す

この方が、サーボの中立付近をイメージしやすくなります。

5. 配線

5-1. 基本の配線

今回の配線は、次のようになります。

URGENEX 7.4V LiPo
      ↓
HENGE UBEC
      ↓
DS3218サーボ電源

評価ボードとの接続は次の通りです。

RA8M2 PWM出力ピン  ── サーボ信号線
RA8M2 GND         ── UBEC GND
UBEC +5V/+6V      ── サーボ +電源
UBEC GND          ── サーボ GND

重要なのは、サーボの電源を評価ボードから取らないことです。

NG:評価ボードの3.3Vや5VからDS3218を動かす
OK:LiPo → UBEC → DS3218で動かす

5-2. サーボの線の色

サーボの線色は製品によって違うことがあります。
よくある例は次の通りです。

線色役割
電源 +
茶色 / 黒GND
橙 / 黄 / 白信号

ただし、必ず手元のサーボの表記や販売ページ、資料を確認してください。
線を間違えると、サーボや電源を壊す可能性があります。

5-3. 電源投入前チェック

電源を入れる前に、次を確認します。

  • LiPoのプラスとマイナスを逆にしていない
  • UBECの入力と出力を間違えていない
  • UBECの出力が5V設定になっている
  • サーボの赤線がUBECの+側につながっている
  • サーボのGNDがUBECのGNDにつながっている
  • 評価ボードのGNDとUBECのGNDがつながっている
  • PWM信号線がサーボの信号線につながっている
  • サーボホーンが机や指やケーブルに当たらない
  • 配線変更中はLiPoを外している

可能であれば、サーボを接続する前に、テスターでUBECの出力電圧を確認します。

UBEC出力が5V設定なら、約5V付近になっていることを確認する

6. 手順

6-1. FSPでPWM用タイマを追加する

FSP Configuratorで、PWM出力用のGPTを追加します。
設定例は次の通りです。

Timer Driver:GPT
Mode:PWM
Period:20ms
PWM出力:GTIOCA または GTIOCB
Callback:今回は不要

今回の実験では、PWM出力が1本あれば十分です。
使用するピンは、評価ボードでGPTのPWM出力に割り当てできるピンを選びます。
実際のピン名は、FSP ConfiguratorのPins設定と、評価ボードのピン配置に合わせてください。

6-2. サーボをまだ接続せずに書き込む

最初は、サーボを接続しない状態でプログラムを書き込みます。
理由は、プログラムやPWM設定が間違っていた場合に、サーボが急に動くのを避けるためです。
まずは、

ビルドできる書き込めるUARTログが出る

ところまで確認します。

6-3. 電源を切ってサーボを接続する

次に、評価ボードとLiPoを外した状態で、サーボを接続します。
接続する順番は、次のようにすると安全です。

1. 評価ボードの電源を外す
2. LiPoを外す
3. UBECとサーボを接続する
4. 評価ボードGNDとUBEC GNDを接続する
5. 評価ボードのPWM出力ピンとサーボ信号線を接続する
6. 配線を確認する
7. 評価ボードを起動する
8. 最後にLiPoを接続する

6-4. PWMを出して真ん中付近を確認する

プログラムを実行すると、PWM出力を開始します。
今回のコードでは、パルス幅を1500usに設定します。

PWM period = 20000 us
Servo pulse = 1500 us

サーボが真ん中付近に少し動けば、PWM信号が伝わっている可能性が高いです。
ただし、サーボがすでに真ん中付近にある場合は、ほとんど動かないこともあります。
その場合でも、異音や大きな暴れがなければ、まずはOKです。

6-5. すぐ電源を切れる状態で確認する

初回は、次のようにします。

  • サーボを手で押さえ込まない
  • サーボホーンの近くに指を置かない
  • ケーブルを巻き込まないようにする
  • 異音、発熱、においがあればすぐLiPoを外す

今回は、動きを楽しむ回ではありません。

PWM信号を出せたサーボが大きく暴れない配線と電源の基本が確認できた

ここまで確認できれば十分です。

7. コード

※下記は考え方を分かりやすくするためのシンプルな例です。
※ GPTインスタンス名、UARTインスタンス名、PWM出力ピンは、自分のプロジェクトに合わせて置き換えてください。
※ ここでは g_timer_servo0_ctrl / g_timer_servo0_cfg という名前でPWM用タイマを作った想定にしています。
※ PWM出力ピンが GTIOCA か GTIOCB かは、FSPの設定に合わせて変更してください。
※ 今回は中立付近の1500usだけを出します。最小・最大方向へ動かすのは次回にします。

#include "hal_data.h"
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>

/*
 * サーボPWMの基本設定
 * 一般的なRCサーボでは 20ms周期、1.5ms付近が中立の目安。
 */
#define SERVO_PWM_PERIOD_US          (20000U)
#define SERVO_NEUTRAL_PULSE_US       (1500U)

/*
 * 安全のため、E4-01では中立付近だけを出す。
 * 最小/最大の確認はE4-02で行う。
 */
#define SERVO_TEST_PULSE_US          (SERVO_NEUTRAL_PULSE_US)

/*
 * PWM出力に使うピン。
 * FSPで GTIOCA を使う場合は GPT_IO_PIN_GTIOCA、
 * GTIOCB を使う場合は GPT_IO_PIN_GTIOCB に変更する。
 */
#define SERVO_PWM_OUTPUT_PIN         (GPT_IO_PIN_GTIOCA)

static void uart_print(const char * p_text);
static bool servo_pwm_start(void);
static bool servo_pwm_set_pulse_us(uint32_t pulse_us);

void hal_entry(void)
{
    fsp_err_t err;
    char msg[120];

    err = R_SCI_B_UART_Open(&g_uart0_ctrl, &g_uart0_cfg);
    if (FSP_SUCCESS != err)
    {
        while (1)
        {
            ;
        }
    }

    uart_print("E4-01 PWM servo basic start\r\n");

    if (!servo_pwm_start())
    {
        uart_print("Servo PWM start error\r\n");
        while (1)
        {
            ;
        }
    }

    if (!servo_pwm_set_pulse_us(SERVO_TEST_PULSE_US))
    {
        uart_print("Servo PWM duty set error\r\n");
        while (1)
        {
            ;
        }
    }

    snprintf(msg, sizeof(msg),
             "PWM period=%lu us, pulse=%lu us\r\n",
             (unsigned long)SERVO_PWM_PERIOD_US,
             (unsigned long)SERVO_TEST_PULSE_US);
    uart_print(msg);

    uart_print("Servo neutral pulse output\r\n");

    while (1)
    {
        /*
         * E4-01では、中立付近のPWMを出したままにする。
         * まだ角度を変えたり、往復動作させたりしない。
         */
    }
}

static bool servo_pwm_start(void)
{
    fsp_err_t err;

    /*
     * FSPで作成したPWM用GPTをOpenする。
     * g_timer_servo0_ctrl / g_timer_servo0_cfg は、
     * 自分のFSP設定名に合わせて変更する。
     */
    err = R_GPT_Open(&g_timer_servo0_ctrl, &g_timer_servo0_cfg);
    if (FSP_SUCCESS != err)
    {
        return false;
    }

    /*
     * PWM出力を開始する。
     * FSP側で周期20msに設定しておく。
     */
    err = R_GPT_Start(&g_timer_servo0_ctrl);
    if (FSP_SUCCESS != err)
    {
        return false;
    }

    return true;
}

static bool servo_pwm_set_pulse_us(uint32_t pulse_us)
{
    fsp_err_t err;
    timer_info_t timer_info;
    uint32_t duty_counts;

    /*
     * 今回は安全のため、想定外に小さい/大きい値を受け付けない。
     * E4-01では1500usだけを使うが、関数としては簡単な範囲チェックを入れておく。
     */
    if ((pulse_us < 1000U) || (pulse_us > 2000U))
    {
        return false;
    }

    err = R_GPT_InfoGet(&g_timer_servo0_ctrl, &timer_info);
    if (FSP_SUCCESS != err)
    {
        return false;
    }

    /*
     * FSPのGPTは、Dutyをカウント値で設定する。
     *
     * 例:
     * 周期 20ms のカウント数が timer_info.period_counts
     * 出したいパルス幅が 1500us
     *
     * duty_counts = period_counts * 1500 / 20000
     */
    duty_counts = (uint32_t)(((uint64_t)timer_info.period_counts * pulse_us) /
                             SERVO_PWM_PERIOD_US);

    err = R_GPT_DutyCycleSet(&g_timer_servo0_ctrl,
                             duty_counts,
                             SERVO_PWM_OUTPUT_PIN);
    if (FSP_SUCCESS != err)
    {
        return false;
    }

    return true;
}

static void uart_print(const char * p_text)
{
    fsp_err_t err;

    err = R_SCI_B_UART_Write(&g_uart0_ctrl,
                             (uint8_t *) p_text,
                             strlen(p_text));
    if (FSP_SUCCESS != err)
    {
        while (1)
        {
            ;
        }
    }

    /*
     * UART送信完了待ちの簡易版。
     * 本格的にはUARTコールバックで送信完了を待つ形にする。
     */
    for (volatile uint32_t i = 0; i < 1000000U; i++)
    {
        __asm volatile ("nop");
    }
}

8. コードの見方(今回大事なところだけ)

8-1. 20ms周期を使う

サーボ制御では、まず周期を決めます。
今回のコードでは、次のようにしています。

#define SERVO_PWM_PERIOD_US          (20000U)

20000us は、20msです。
つまり、次のような信号を繰り返します。

20msごとに1回パルスを出す

8-2. 真ん中付近は1500us

今回のコードでは、中立付近のパルス幅を次のようにしています。

#define SERVO_NEUTRAL_PULSE_US       (1500U)

1500us は、1.5msです。
多くのRCサーボでは、1.5ms付近が中立位置の目安になります。
ただし、サーボの個体差や種類によって、完全な中心とは限りません。
正確な中心出しは、後のキャリブレーションで扱います。

8-3. Duty比ではなくパルス幅で考える

コードの中では、最終的にGPTへDutyのカウント値を設定しています。

duty_counts = (uint32_t)(((uint64_t)timer_info.period_counts * pulse_us) / SERVO_PWM_PERIOD_US);

ここでやっていることは、次の計算です。

20msのうち、1500usだけHighにする

初心者のうちは、

Duty比を何%にするか

よりも、

パルス幅を何usにするか

で考えた方が分かりやすいです。
たとえば、20ms周期で1500usなら、Duty比は約7.5%です。
しかし、サーボ制御では、

1500usを出している

と考えた方が、次回以降の角度確認につながりやすくなります。

8-4. R_GPT_InfoGet() で周期カウントを取得する

GPTのDuty設定では、パルス幅をそのままusで渡すのではなく、タイマのカウント値に変換して渡します。
そのため、今回は R_GPT_InfoGet() で周期のカウント数を取得しています。

err = R_GPT_InfoGet(&g_timer_servo0_ctrl, &timer_info);

その後、

timer_info.period_counts

を使って、1500usに相当するカウント値を計算しています。
これにより、タイマの内部クロックの細かい値を直接意識しなくても、
「20ms中の1500us」という考え方で扱いやすくなります。

8-5. E4-01では動かし続けない

今回のコードでは、サーボを左右に動かす処理は入れていません。

while (1)
{
}

真ん中付近のPWMを出したままにします。
今回は、サーボを動かして遊ぶのではなく、
PWM信号を出して、サーボが中立付近へ動くことを安全に確認する のが目的です。
そのため、今回は1.5msのパルス幅だけを使います。
サーボを最小・中立・最大へ動かす確認は、次回のE4-02で行います。

9. 実行結果

9-1. UARTログ

プログラムを実行すると、Tera Termには次のようなログが出ます。

E4-01 PWM servo basic start
PWM period=20000 us, pulse=1500 us
Servo neutral pulse output

このログが出れば、少なくとも次の処理までは進んでいます。

  • UART初期化
  • PWM用GPTのOpen
  • PWM用GPTのStart
  • 1500us相当のDuty設定

9-2. サーボの動き

サーボは、電源を入れた瞬間やPWMを受け取った瞬間に、少し動くことがあります。
次のような状態なら、まずは正常と考えてよいです。

  • サーボが中立付近に少し動く
  • すでに中立付近にあるため、ほとんど動かない
  • 大きく暴れない
  • 異音が続かない
  • UBECやバッテリーが熱くならない
  • 評価ボードがリセットしない

今回は、角度が正確に90度になっているかは気にしません。
見るポイントは、

サーボが大きく暴れず、PWMで保持されているように見えるか

です。

9-3. ここで無理に角度を変えない

この段階で、

1000usも試したい
2000usも試したい
動かしてみたい

と思うかもしれません。
ただし、今回はまだ行いません。
理由は、サーボの取り付け状態やホーンの向きによっては、
端まで動かしたときに机や部品に当たる可能性があるためです。

10. ハマりポイント/原因と対策

10-1. サーボがまったく動かない

原因

  • UBECからサーボへ電源が供給されていない
  • UBECの入力側と出力側を間違えている
  • LiPoバッテリーが接続されていない
  • サーボの電源線とGND線を間違えている
  • PWM信号線が正しいピンにつながっていない
  • FSPでPWM出力ピンが有効になっていない
  • 評価ボードGNDとUBEC GNDが共通になっていない

対策

  • まずLiPoを外して、配線を見直す
  • UBECの入力側がLiPo、出力側がサーボになっているか確認する
  • 可能であれば、テスターでUBEC出力が約5Vになっているか確認する
  • サーボの赤線が+、茶色/黒線がGNDになっているか確認する
  • 評価ボードのPWMピンとサーボ信号線がつながっているか確認する
  • 評価ボードGNDとUBEC GNDを必ずつなぐ
  • FSP Configuratorで、PWM出力ピンがGPIOではなくGPT出力に割り当てられているか確認する

10-2. サーボがガタガタ震える

原因

  • PWM周期が20msになっていない
  • パルス幅が想定外の値になっている
  • GNDが共通になっていない
  • サーボ電源が不安定
  • 配線が抜けかけている
  • サーボに負荷がかかっている

対策

  • FSPのPWM周期が20msになっているか確認する
  • コードで SERVO_TEST_PULSE_US1500U になっているか確認する
  • 評価ボードGNDとUBEC GNDをつなぎ直す
  • サーボホーンが机や配線に当たっていないか確認する
  • サーボを手で押さえ込まない
  • いったんLiPoを外し、配線を挿し直してから再確認する

10-3. 評価ボードがリセットする

原因

  • サーボ電源を評価ボードから取っている
  • サーボの動作で電圧が下がっている
  • GND配線が不安定
  • サーボ電源とロジック電源の配線が混ざっている
  • サーボの突入電流やノイズの影響を受けている

対策

  • DS3218の電源は、評価ボードから取らず、LiPo → UBECから供給する
  • 評価ボードはUSBまたはデバッガ側から給電する
  • UBECのGNDと評価ボードのGNDだけを共通にする
  • サーボ電源の+側を評価ボードの5Vや3.3Vへつながない
  • まずは5V出力で確認する
  • 配線が細すぎる、接触が悪い場合は見直す

10-4. サーボが急に大きく動いて怖い

原因

  • 初回起動時にサーボの現在位置と中立指令がずれている
  • サーボホーンの取り付け角度がずれている
  • 以前の位置から中立へ戻ろうとしている
  • 誤って1000usや2000usなどを出している
  • FSPの周期設定が想定と違い、パルス幅がずれている

対策

  • まずLiPoを外す
  • コードが 1500U だけを出す設定になっているか確認する
  • FSPの周期が20msになっているか確認する
  • サーボホーンを外せる場合は、ホーンを外して中立確認する
  • ホーンを付ける場合は、動いても机や指に当たらない向きにする
  • E4-01では、最小/最大方向へ動かさない

10-5. ビルドエラーになる

原因

  • PWM用GPTのインスタンス名がコードと合っていない
  • g_timer_servo0_ctrl / g_timer_servo0_cfg が存在しない
  • GPT_IO_PIN_GTIOCA と実際の出力設定が合っていない
  • GPTドライバを追加していない
  • FSPでGenerate Project Contentしていない
  • R_GPT_InfoGet()R_GPT_DutyCycleSet() の引数が合っていない

対策

  • FSPで作成したPWM用タイマの名前を確認する
  • コード中の g_timer_servo0_ctrl / g_timer_servo0_cfg を、自分のプロジェクトの名前に変更する
  • GTIOCAを使っているなら GPT_IO_PIN_GTIOCA、GTIOCBを使っているなら GPT_IO_PIN_GTIOCB にする
  • FSPでGPTドライバを追加したあと、Generate Project Contentを実行する
  • 生成された hal_data.h に、PWM用タイマの定義があるか確認する

10-6. ログは出るがサーボが反応しない

原因

  • PWMタイマはStartしているが、ピンに出力されていない
  • FSPのPins設定でPWM出力が有効になっていない
  • サーボ信号線が違うピンにつながっている
  • サーボ信号線とGNDの基準が共通になっていない
  • サーボ側が3.3VのPWM信号を認識できていない可能性がある

対策

  • FSP ConfiguratorのPins設定で、使用ピンがGPT出力になっているか確認する
  • 実際につないでいる評価ボードのピンが、FSPで設定したPWM出力ピンと同じか確認する
  • 評価ボードGNDとUBEC GNDを共通にする
  • 別のPWM出力ピンに変更して試す
  • 可能であれば、ロジックアナライザやオシロスコープでPWMが出ているか確認する
  • 3.3V信号で反応しない場合は、信号レベル変換が必要かを検討する

10-7. UBECやバッテリーが熱い、においがする

原因

  • 配線ミスでショートしている
  • サーボ電源の+とGNDを逆にしている
  • サーボがロックして大きな電流が流れている
  • サーボホーンが何かに当たって動けない
  • バッテリーやUBECに異常がある

対策

  • すぐにLiPoを外す
  • すぐに触り続けず、熱が下がるのを待つ
  • 配線を最初から確認し直す
  • サーボホーンが引っかかっていないか確認する
  • 異常が続く部品は使わない
  • 原因が分からないまま再接続しない

11. 今回わかったこと

今回の実験で大事なのは、
サーボはPWMのパルス幅で制御する ということです。
LEDのように単純にON/OFFするのではなく、サーボには次のような信号を送ります。

20ms周期で、1.5msだけHighにする

このパルス幅を変えることで、サーボの位置が変わります。
今回できるようになったことは、次の通りです。

  • PWMの周期とパルス幅の関係を理解した
  • サーボ制御では、Duty比よりパルス幅で考えると分かりやすいことを確認した
  • DS3218を評価ボードから直接給電しない理由を確認した
  • LiPo → UBEC → サーボという電源構成を作った
  • 評価ボードとUBECのGNDを共通にする必要を確認した
  • GPTで20ms周期のPWMを出す入口を作った
  • 中立付近の1500usパルスを出した

12. 次回やること

次回は、E4-02 サーボ1軸(中立/最小/最大) に進みます。
今回のE4-01では、1500usの中立付近だけを出しました。
次回は、サーボを安全に動かすために、

1500us 中立付近少し小さい値少し大きい値

のように、少しずつパルス幅を変えて確認します。
いきなり1000usや2000usへ動かすのではなく、
サーボの動きを見ながら安全な範囲を探します。
最終的には、次のE4-03で使うための、

このサーボでは、どこまで動かしてよいか

を決める準備をします。

13. 関連リンク

  • E3-07:異常姿勢判定→安全停止
  • E4-02:サーボ1軸(中立/最小/最大)
  • E4-03:安全範囲(保護)
  • E4-08:サーボ電源の落とし穴→対策
  • 基礎シリーズ:PWMとは?周期とパルス幅でサーボを動かす考え方
  • 基礎シリーズ:サーボモータとは?
  • 基礎シリーズ:GNDとは?なぜ基準点が必要なのか?
  • 基礎シリーズ:ショートとは?電源の扱いと安全の基本
  • 基礎シリーズ:電圧・電流・抵抗の超要点
  • 基礎シリーズ:LiPoバッテリーの安全な扱い方(予定)

-フェーズ4