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
注意:ライブラリの入ってるフォルダーの一個前を設定する
[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) は使用できません。
使用方法
- ライブラリの初期化
各エンコーダーを初期化します。以下の例は、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秒ごとにデータを表示
}
}
- エンコーダーデータの取得
各エンコーダーからカウントやRPS、角度、距離のデータを取得するためには、getEncoderData()関数を使用します。
encoder1.getEncoderData(TIM2, &data1);
この関数は、以下のようなデータをIncEncData構造体に格納します。
count: カウント値rps: 回転数 (RPS)deg: 角度 (度)-
distance: 回転距離 -
エンコーダーのリセット
エンコーダーのカウントをリセットするには、reset()関数を使用します。
encoder1.reset(TIM2);
この関数は、指定したエンコーダーのカウントを0にリセットします。
取得方法を具体的に説明します。エンコーダーデータの各値(カウント、RPS、角度、回転距離)の取得手順について説明します。
各データの取得方法
エンコーダーデータを取得するには、次の手順でgetEncoderData()を使用します。
- カウント値 (
count) - エンコーダーの現在のカウント値は、
getEncoderData()で取得されます。 IncEncData構造体のcountメンバにカウント値が格納されます。
encoder.getEncoderData(TIM2, &data1);
printf("カウント値 = %d\n", data1.count);
- 回転数 (RPS)
getEncoderData()を呼び出すと、IncEncData構造体のrpsメンバにRPS(1秒あたりの回転数)が格納されます。
encoder.getEncoderData(TIM2, &data1);
printf("RPS = %.2f\n", data1.rps);
- 角度 (
deg) - エンコーダーの回転軸が何度回転したか(0°~360°)は、
IncEncData構造体のdegメンバに格納されます。
encoder.getEncoderData(TIM2, &data1);
printf("角度 (度) = %.2f\n", data1.deg);
- 回転距離 (
distance) - 回転軸やホイールが回転によって移動した距離は、
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エンコーダーのカウントをリセット
ビルド手順
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
- コードをビルドし、Nucleoボードに書き込みます。
pio run --target upload
- シリアルモニタを使用して、出力結果を確認します。
注意事項
- 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