Skip to content

Altair_library_for_mbed

https://github.com/Altairu/Altair_library/tree/main/Altair_library_for_mbed

概要

Altair_library は、mbed 用のライブラリ集です。ロボット制御やセンサーデータの取得を容易にするための多くの機能を提供します。

導入方法

1. ライブラリの配置

Altair_library フォルダーを PlatformIO プロジェクトの lib フォルダー内に配置します。配置後のディレクトリ構成は以下のようになります。

<Your_Project_Folder>
│
├── lib
│   └── Altair_library
│       ├── Altairlibrary.h
│       ├── encoder.h
│       ├── MotorDriver.h
│       ├── PIDController.h
│       ├── Servo.h
│       ├── encoder.cpp
│       ├── Servo.cpp
│       ├── Kinematics.h
│       ├── TwoWheelKinematics.h
│       ├── robot_control.h
│       ├── inverse_kinematics.h
│       ├── README.md
│       └── ...
│
└── src
    └── main.cpp
もしくは, 以下のように「lib_extra_dirs」を設定するとライブラリを使える.

注意:ライブラリの入ってるフォルダーの一個前を設定する

[env:nucleo_f446re]
platform = ststm32
board = nucleo_f446re
framework = mbed
lib_extra_dirs = /home/altair/OneDrive/lib

2. main.cpp での使用

プロジェクトの src フォルダー内にある main.cpp で、次のように Altairlibrary.h をインクルードしてください。

#include "mbed.h"
#include "Altairlibrary.h"

int main() {
    // 初期化コードを書く

    while (true) {
        // メインループコードを書く
    }
}

ライブラリ内容

Altair_library には以下のファイルが含まれています:

  • Altairlibrary.h: 全てのヘッダーファイルをインクルードするマスターヘッダー
  • encoder.h / encoder.cpp: エンコーダ用のライブラリ(非推奨:incenc.hをおすすめする)
  • incenc.h/incenc.cpp : エンコーダ用のライブラリ
  • MotorDriver.h: モータードライバー用のライブラリ
    モーターの正転・逆転、PWM制御、ショートブレーキ機能をサポートしています。
  • PIDController.h: PIDコントローラーライブラリ
    PID制御を実装するための簡単なインターフェースを提供します。P、I、D ゲインを設定し、制御ループ内で PID 演算を行います。
  • Servo.h / Servo.cpp: サーボモーター用のライブラリ
    任意の角度でサーボを動かすための簡単なインターフェースを提供します。
  • TwoWheelKinematics.h: 二輪運動学のライブラリ
    二輪ロボットの前進・旋回動作を計算し、左右のモーター速度を制御するための機能を提供します。
  • Kinematics.h: 足回りロボット運動学のライブラリ
    四輪オムニ、三輪オムニ、四輪メカナムの運動学をサポートし、各ホイールの目標速度を計算します。
  • robot_control.h: 足回りロボットの制御ライブラリ
    上記の運動学ライブラリと PID コントローラーを組み合わせて、足回りロボットの制御を行います。スレッドを使った並列処理にも対応しています。
  • inverse_kinematics.h: 自己位置推定ライブラリ
    各ホイールのエンコーダデータからロボットの現在位置と姿勢を推定します。Omni3、Omni4の構成に対応しており、自己位置をリアルタイムで推定します。
  • AltairSerial.h: シリアル通信ライブラリ

各ライブラリの詳細な使用方法については、readme フォルダー内に個別の README を掲載していますので、そちらをご覧ください。また、はじめて.md には mbed の基礎的な書き方が記載されていますので、初心者の方はまずこちらを参照してください。

https://github.com/Altairu/Altair_library/tree/main/Altair_library_for_mbed/readme

以下に数個readmeより取り出して記述しています

MotorDriver ライブラリ

概要

MotorDriver ライブラリは、DCモーターを制御するためのライブラリです。

使用方法

初期化

#include "Altairlibrary.h"

// ps1Pinとps2PinにはモータードライバのPWMピンを指定して初期化します
MotorDriver motor(PD_5, PD_6);

メソッド

  • void setSpeed(int speed): モーターの速度と回転方向を設定します。速度は -100 から 100 の範囲で指定します。
  • 100 はフルスピードで前進
  • -100 はフルスピードで後退
  • 0 は停止

  • void stop(): モーターをフリーラン状態で停止させます(慣性による停止)。

  • void brake(): モーターをショートブレーキを用いて迅速に停止させます。

サンプルコード

#include "mbed.h"
#include "Altairlibrary.h"

MotorDriver motor(PA_6, PA_7);

int main() {
    motor.setSpeed(50);  // モーターを50%の速度で前進
    ThisThread::sleep_for(2s);

    motor.setSpeed(-50); // モーターを50%の速度で後退
    ThisThread::sleep_for(2s);

    motor.setSpeed(0);   // モーターをフリーランで停止(慣性による停止)
    ThisThread::sleep_for(2s);

    motor.stop();        // モーターをフリーランで停止(慣性による停止)
}

詳細な説明

  • setSpeed(int speed): 指定された速度でモーターを制御します。speed の値に応じて、モーターが前進・後退し、0 の場合はショートブレーキで停止します。
  • stop(): モーターのPWM信号を0に設定し、フリーラン状態で停止させます。この場合、モーターは慣性で徐々に止まります。
  • brake(): ショートブレーキ機能を使用してモーターを即座に停止させます。PWM信号を強制的にHIGHに設定することで、モーターの端子を短絡し、回転を急速に止めます。

注意事項

  • 高速回転から急停止させると、モーターやドライバに負荷がかかるため、適切な使用を心がけてください。

Servo ライブラリ

概要

Servo ライブラリは、サーボモーターを制御するための簡単なライブラリです。サーボモーターの角度を指定して制御することができます。

使用方法

初期化

#include "Altairlibrary.h"

// サーボモーターが接続されているピンを指定して初期化する
Servo servo(PD_9);

メソッド

  • void write(float angle): サーボモーターの角度を設定します。角度は 0 度から 180 度の範囲で指定します。

サンプルコード

#include "mbed.h"
#include "Altairlibrary.h"

Servo servo(PD_9);

int main() {
    while (true) {
        servo.write(0.0);   // サーボを0度に設定
        ThisThread::sleep_for(1s);

        servo.write(90.0);  // サーボを90度に設定
        ThisThread::sleep_for(1s);

        servo.write(180.0); // サーボを180度に設定
        ThisThread::sleep_for(1s);
    }
}

エンコーダーライブラリの使用方法

概要

このライブラリは、STM32 Nucleoボード上でエンコーダーの読み取りを簡単に実行できるようにするためのものです。エンコーダーのカウント、角度、RPS(回転数)、距離などのデータを取得し、リセットする機能を提供します。

対応するエンコーダー設定

以下のタイマーとピン設定を使用します:

  • TIM2: PB_3 (CH1), PA_5 (CH2)
  • TIM3: PC_6 (CH1), PC_7 (CH2)
  • TIM4: PB_6 (CH1), PB_7 (CH2)

注意: TIM5 (PA_0, PA_1) は使用できません。

使用方法

  1. ライブラリの初期化

各エンコーダーを初期化します。以下の例は、TIM2、TIM3、TIM4に接続されたエンコーダーを初期化するコードです。

#include "mbed.h"
#include "Altairlibrary.h"

IncEnc encoder1, encoder2, encoder3;
IncEncData data1, data2, data3;

int main() {
    // 各エンコーダーの初期化
    encoder1.init(PB_3, PA_5, TIM2);  // TIM2 (PB_3, PA_5)
    encoder2.init(PC_6, PC_7, TIM3);  // TIM3 (PC_6, PC_7)
    encoder3.init(PB_6, PB_7, TIM4);  // TIM4 (PB_6, PB_7)

    while (true) {
        // エンコーダーデータの取得
        encoder1.getEncoderData(TIM2, &data1);
        encoder2.getEncoderData(TIM3, &data2);
        encoder3.getEncoderData(TIM4, &data3);

        // 結果の表示
        printf("Encoder1 (TIM2): Count = %d, RPS = %.2f, Degree = %.2f, Distance = %.2f\n",
               data1.count, data1.rps, data1.deg, data1.distance);
        printf("Encoder2 (TIM3): Count = %d, RPS = %.2f, Degree = %.2f, Distance = %.2f\n",
               data2.count, data2.rps, data2.deg, data2.distance);
        printf("Encoder3 (TIM4): Count = %d, RPS = %.2f, Degree = %.2f, Distance = %.2f\n",
               data3.count, data3.rps, data3.deg, data3.distance);

        ThisThread::sleep_for(1000ms);  // 1秒ごとにデータを表示
    }
}
  1. エンコーダーデータの取得

各エンコーダーからカウントやRPS、角度、距離のデータを取得するためには、getEncoderData()関数を使用します。

encoder1.getEncoderData(TIM2, &data1);

この関数は、以下のようなデータをIncEncData構造体に格納します。

  • count: カウント値
  • rps: 回転数 (RPS)
  • deg: 角度 (度)
  • distance: 回転距離

  • エンコーダーのリセット

エンコーダーのカウントをリセットするには、reset()関数を使用します。

encoder1.reset(TIM2);

この関数は、指定したエンコーダーのカウントを0にリセットします。

取得方法を具体的に説明します。エンコーダーデータの各値(カウント、RPS、角度、回転距離)の取得手順について説明します。

各データの取得方法

エンコーダーデータを取得するには、次の手順でgetEncoderData()を使用します。

  1. カウント値 (count)
  2. エンコーダーの現在のカウント値は、getEncoderData()で取得されます。
  3. IncEncData構造体のcountメンバにカウント値が格納されます。
encoder.getEncoderData(TIM2, &data1);
printf("カウント値 = %d\n", data1.count);
  1. 回転数 (RPS)
  2. getEncoderData()を呼び出すと、IncEncData構造体のrpsメンバにRPS(1秒あたりの回転数)が格納されます。
encoder.getEncoderData(TIM2, &data1);
printf("RPS = %.2f\n", data1.rps);
  1. 角度 (deg)
  2. エンコーダーの回転軸が何度回転したか(0°~360°)は、IncEncData構造体のdegメンバに格納されます。
encoder.getEncoderData(TIM2, &data1);
printf("角度 (度) = %.2f\n", data1.deg);
  1. 回転距離 (distance)
  2. 回転軸やホイールが回転によって移動した距離は、IncEncData構造体のdistanceメンバに格納されます。
encoder.getEncoderData(TIM2, &data1);
printf("回転距離 = %.2fmm\n", data1.distance);

コード例

以下のコードは、エンコーダーからデータを取得する具体例です。TIM2を使って、カウント値、RPS、角度、回転距離を1秒ごとに取得・表示します。

#include "mbed.h"
#include "Altairlibrary.h"

IncEnc encoder1;
IncEncData data1;

int main() {
    // エンコーダーの初期化 (例: TIM2)
    encoder1.init(PB_3, PA_5, TIM2);

    while (true) {
        // エンコーダーデータの取得
        encoder1.getEncoderData(TIM2, &data1);

        // 各値を表示
        printf("カウント値 = %d\n", data1.count);
        printf("RPS = %.2f\n", data1.rps);
        printf("角度 (度) = %.2f\n", data1.deg);
        printf("回転距離 = %.2fmm\n", data1.distance);

        ThisThread::sleep_for(1000ms);  // 1秒ごとにデータを表示
    }
}

リセット方法

エンコーダーのカウント値をリセットしたい場合は、reset()関数を使用します。これにより、エンコーダーのカウントが0にリセットされます。

encoder1.reset(TIM2);  // TIM2エンコーダーのカウントをリセット

ビルド手順

  1. platformio.ini ファイルに以下の設定を追加して、Mbed OSを使用します。
[env:nucleo_f446re]
platform = ststm32
board = nucleo_f446re
framework = mbed
build_flags = 
    -DMBED_CONF_TARGET_DEFAULT_TICKER_TIMER=9
    -DMBED_TICKLESS
  1. コードをビルドし、Nucleoボードに書き込みます。
pio run --target upload
  1. シリアルモニタを使用して、出力結果を確認します。

注意事項

  • TIM5 (PA_0, PA_1) は使用できません。そのため、他のタイマーでエンコーダーを設定してください。
  • 各エンコーダーは専用のタイマーを使用する必要があります。同じタイマーで複数のエンコーダーを読み取ることはできません。

PIDController ライブラリ

概要

PIDController ライブラリは、PID制御を簡単に実装するためのライブラリです。

使用方法

初期化

#include "Altairlibrary.h"

// PIDゲインとサンプリング時間を設定してPIDControllerを初期化する
PIDController pid(1.0, 0.1, 0.01, 10, 0.01);

パラメータの説明

PIDController pid(1.0, 0.1, 0.01, 10, 0.01); では、以下のように各パラメータが設定されています。

  • 1.0: Kp (比例ゲイン) - 誤差に対する応答の速さを決定します。大きくすると応答が速くなりますが、オーバーシュートのリスクが増えます。
  • 0.1: Ki (積分ゲイン) - 誤差が継続しているときに出力を増加させ、定常偏差を修正します。大きくすると定常偏差が減少しますが、応答が遅くなる可能性があります。
  • 0.01: Kd (微分ゲイン) - 誤差の変化率に基づいて出力を減少させ、オーバーシュートを防止します。大きくするとシステムの安定性が向上しますが、過度に大きいとノイズに敏感になります。
  • 10: time_constant (時定数) - PID制御の出力に対するローパスフィルタの時定数です。出力の滑らかさを調整します。
  • 0.01: dt (サンプリング時間) - 制御ループのサンプリング時間です。制御ループがどのくらいの頻度で実行されるかを決定します。

メソッド

  • float compute(float setpoint, float measured_value): 設定値 (setpoint) と測定値 (measured_value) に基づいて、PID制御出力を計算します。

  • void reset(): PIDの内部状態をリセットします。

サンプルコード

#include "mbed.h"
#include "Altairlibrary.h"

PIDController pid(1.0, 0.1, 0.01, 10, 0.01);

int main() {
    float setpoint = 100.0; // 目標値
    float measured_value = 95.0; // 現在の測定値

    while (true) {
        float output = pid.compute(setpoint, measured_value);
        ThisThread::sleep_for(100ms);
    }
}
#include "mbed.h"
#include "Altairlibrary.h"
#include "rtos.h"

// ピン定義
#define ENCODER_PIN_A PA_1
#define ENCODER_PIN_B PA_0
#define MOTOR_PIN_1 PB_8
#define MOTOR_PIN_2 PB_9

// エンコーダー、モータードライバー、PIDコントローラーのインスタンス作成
Encoder encoder(ENCODER_PIN_A, ENCODER_PIN_B);
MotorDriver motor(MOTOR_PIN_1, MOTOR_PIN_2);
PIDController pid(0.4, 0.05, 0.025, 20, 0.001); // Kp, Ki, Kd, 時定数, サンプリング時間 

Thread control_thread;
float setpoint = 1.0; // 目標RPS

void controlLoop() {
    while (1) {
        int32_t rps = encoder.getRPS(); // 現在の回転速度(RPS)

        float control_signal = pid.compute(setpoint, rps); // PID制御で出力を計算
        float motor_speed = (float)(control_signal); 
        if (motor_speed > 100) motor_speed = 100;
        if (motor_speed < -100) motor_speed = -100;

        motor.setSpeed(motor_speed); // モーター速度制御
    }
}

int main() {
    control_thread.start(controlLoop); // PID制御スレッドを開始

    while (1) {
        // 他のタスクをここで実行
        ThisThread::sleep_for(1s); // 主にメインループが他のことをやっている間、制御ループは別スレッドで動作する
    }
}
Note

著者:Shion Noguchi