メカトロニクス研究部会
メカトロニクス研究部会とは、仙台高専名取キャンパスに籍を置く研究部会です。 主に高専ロボコンへの出場、広瀬キャンパス科学部と合同でのロボコンの運営・出場を行っています。
講習
講習です。(WIP)
PC基礎知識講習
PC基礎知識講習です。(WIP)
内容のリクエストは当該Issueまで。
ファイルパスってなんやねん
今回はファイルパスってなんやねん!って話ッス。
ファイルパスis何
ファイルパスってのは「ファイルの場所」です。
ファイルがPC内のどこにあるのか、それを表すための文字列です。
例(ユーザー名「hoge」のユーザーディレクトリ):C:\Users\hoge(Windows)/home/hoge(Linux)/Users/hoge(macOS)
見ての通りWindowsだけファイルパスの書き方が違います。
これはまぁ歴史的経緯でゴチャゴチャあるのですが、 Windowsが/を区切りに使えなかったので仕方なく\を使ったんだそうです。
あと先頭のC:もWindows独特のもので、ドライブ文字と言います。
ざっくり言えばUSBメモリやらSDカードやらDVDドライブやらに1個ずつ割り振られてるアルファベットです。
歴史的経緯からCから割り当てます。
うまくggれない!そんな時は
皆さん誰しも一回は「なんかいくら調べても欲しい情報出てこんわ。はぁ〜つっかえ」と思うことありますよね。ね?(圧)
この記事…っつーかコラムではggるコツを殴り書きます。いんたーねったーの勘ってやつを文書化ってね。
一.不要な情報は省くべし
もちろん、初学の内容なら何が不要かは分からないと思うんですけど、例えばエラーメッセージそのままぶち込んだ時、
C:\Users\xxxxxx\...ってあった時、この部分はユーザー名によって変わるので引っ掛かりにくいです。 (最近のGoogleだとそうでもないけど)
なので、ファイルパスは末尾のファイル名だけ(ライブラリとかフレームワークのファイルの場合)か いっそ無くす(自分で作ったファイルの場合)方が良いです。
二.出来るだけ分かち書きするべし
分かち書きとは、「かがくの ちからって すげー!」みたいに空白で単語を区切ってやる書き方です。
英語含め大体の言語は分かち書きしているので単語の区切りが自明ですが、
中国語・日本語・韓国語、いわゆるCJK言語は分かち書きをしない(韓国語は少しだけ空白入るけど)ので単語の区切りが曖昧です。
それ故、意図しない区切りをされる(例:「たいまつくって」→「松明 喰って」)場合があります。
現在の検索システムはほぼ英語圏で開発されています。 近年はだいぶマシになりましたが、出来るだけ分かち書きをすることで不要な情報が引っ掛かることを防ぐと良いです。
(ちなみに上記の例たちでは全角スペース使ってますが、一応半角スペースの方が良いと思います。多分大丈夫だと思うケド)
回路講習
外部サイトに書かれてます。
制御講習
制御講習です。(WIP)
内容のリクエストは当該Issueまで。
ロボット制御入門
基本的な部分から実際にロボットを動かすまでを学習します。
環境を整えよう その1
ロボットの制御をするためには様々なツールが必要です。
今回はまずどのようなツール・アカウントが必要なのか、ざっくり説明します。
実際に導入するのは次回で、 今回は紹介&垢作成です。
あ、さっさと環境作りたいから別に説明要らんよって人は先進んでいいよ。
(足りなかったらIssue投げて下さい)
ツールの説明
Arm GNU Toolchain
弊部で使ってるマイコン向けの、いわゆるコンパイラとかが一緒くたになったセットです。
CMake
ライブラリとか簡単に組み込めるようにしてくれるヤツです。
Ninja Build
ビルドしてくれるヤツです。なんか速いです。
OpenOCD
マイコンに作ったプログラムをカキコしてくれるヤツです。
STM32CubeMX
弊部で使ってるマイコン向けのプログラムのテンプレートを吐いてくれるヤツです。tskr
Arch Linux・NixOSユーザー以外は要MyST垢です。
(やろうと思えば直リンクで全環境不要にも出来るんだろうけど複雑になりそーなので却下)
JetBrains Toolbox
JetBrains CLionを始めとするJetBrains製品を管理するヤツです。
公式も推奨してるのでNixOSユーザー以外は使おう。
JetBrains CLion
弊部で使わせようと画策しているIDEです。使いやすい(主観マシマシ)です。
要JetBrains垢です。
アカウント作成
JetBrainsアカウント
まずJetBrains公式でフツーにアカウントを作ります。この時使うメアドは何でもいいです。
あとは「JetBrains 学生」とでもggって下さい。(TODO: 学生ライセンス周りの解説追加)
MySTアカウント
STマイクロエレクトロニクスでMySTアカウントを作ります。
次回予告
今回でツールの概要の説明とアカウント作成が終わりました。
次回は実際にこれらのツールをインストールしていきます。自分の環境に合った方のページへ進んでください。
環境を整えよう その2 Linux編
前回はどのようなツール・アカウントが必要なのかを説明しました。
今回はLinux環境におけるインストール方法です。窓共に比べて遥かに楽です。やったね!
ちなみにLinux環境と言いつつ筆者の使ったことのあるDebian系・Arch Linux・NixOSしか書いてないのは許して♡
インストール方法
色々
Debian系:
sudo apt install -y cmake gcc-arm-none-eabi ninja-build openocd
Arch Linux (pacman + makepkg):
sudo pacman -S --noconfirm arm-none-eabi-gcc cmake git ninja openocd
git clone https://aur.archlinux.org/jetbrains-toolbox.git
pushd jetbrains-toolbox
makepkg -cs
sudo pacman -U ./jetbrains-toolbox-*.pkg.tar.*
popd
git clone https://aur.archlinux.org/stm32cubemx.git
pushd stm32cubemx
makepkg -cs
sudo pacman -U ./stm32cubemx-*.pkg.tar.*
popd
Arch Linux (yay):
yay -S --noconfirm arm-none-eabi-gcc cmake jetbrains-toolbox ninja openocd stm32cubemx
NixOS (flake.nix):
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
outputs =
{ nixpkgs, ... }:
let
pkgs = import nixpkgs {
inherit system;
};
system = "x86_64-linux";
in
{
devShells.${system}.default = pkgs.mkShell {
packages = with pkgs; [
cmake
ninja
openocd
pkgsCross.armhf-embedded.buildPackages.gcc
stm32cubemx
];
};
};
}
NixOS (flake.nix + flake-utils):
{
inputs = {
flake-utils.url = "github:numtide/flake-utils"
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs =
{ flake-utils, nixpkgs, ... }:
flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = import nixpkgs { inherit system; };
in
{
devShells.${system}.default = pkgs.mkShell {
packages = with pkgs; [
cmake
ninja
openocd
pkgsCross.armhf-embedded.buildPackages.gcc
stm32cubemx
];
};
}
);
}
NixOS (flake.nix + flake-parts):
{
inputs = {
flake-parts.url = "github:hercules-ci/flake-parts";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs";
};
outputs =
inputs@{ flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
perSystem =
{ pkgs, ... }:
{
devShells.default = pkgs.mkShell {
packages = with pkgs; [
cmake
ninja
openocd
pkgsCross.armhf-embedded.buildPackages.gcc
stm32cubemx
];
};
};
systems = [
"x86_64-linux"
];
};
}
JetBrains Toolbox App(Arch Linux・NixOS以外)
JetBrains Toolbox Appで「ダウンロード」を押して落として展開して下さい。
中にjetbrains-toolbox-***.***.***.***/jetbrains-toolboxが入ってるのでどっかに入れてPATH通して下さい。
JetBrains CLion(NixOS以外)
JetBrains Toolboxを開いて画面の通りにCLionをインスコして下さい。
STM32CubeMX(Arch Linux・NixOS以外)
STM32CubeMXから落として展開します。
中にSetupSTM32CubeMX-***.***.***みたいな名前のヤツを実行して画面の指示に従って下さい。
次回予告
今回で必要なツールは揃いました。
次回はいよいよ実際にプロジェクトを作っていきます。
環境を整えよう その2 Windows編
前回はどのようなツール・アカウントが必要なのかを説明しました。
今回はWindows環境におけるインストール方法です。Linuxに比べるとちょっと煩雑だけど頑張って♡
また、Windows特有の問題として、圧縮ファイルがフォルダのように開けるせいで展開し忘れるというものがあります(ホンマクソ)ので気を付けてね。
インストール方法
Arm GNU Toolchain
Arm GNU Toolchain Downloadsのarm-gnu-toolchain-***.***.rel***-mingw-w64-x86_64-arm-none-eabi.exeみたいな名前のヤツを落として画面の指示に従って下さい。
執筆時点ではarm-gnu-toolchain-14.2.rel1-mingw-w64-x86_64-arm-none-eabi.exeらしいっす。
あとは「設定」→「システム」→「バージョン情報」→「システムの詳細設定」→「環境変数」から環境変数Pathにインストール先**配下のbinを(ここ重要)**追加して完了です。
Path追加はしなくてもいいっぽいけど、どのみちインストール先がどこかってのは要るのでメモしとくか分かりやすいトコに置いてね。
インストール先はデフォルトでC:\Program Files (x86)\Arm GNU Toolchain arm-none-eabi\***.*** rel***みたいな名前のトコです。
執筆時点ではC:\Program Files (x86)\Arm GNU Toolchain arm-none-eabi\14.2 rel1らしいっす。
CMake
Download
CMakeのcmake-***.***.***-windows-x86_64.msiみたいな名前のヤツを落として画面の指示に従って下さい。
執筆時点ではcmake-4.0.1-windows-x86_64.msiらしいっす。
CLionに付いてくるみたいです。なのでインスコはしなくておk。
Ninja Build
ninja-build/ninjaのninja-win.zipを落として展開して下さい。ninja.exeが出てくるハズなのでC:\直下にでもテキトーにディレクトリ作ってぶち込んどいて下さい。
あとは「設定」→「システム」→「バージョン情報」→「システムの詳細設定」→「環境変数」から環境変数Pathにninja.exeをぶち込んだディレクトリを追加して完了です。
こっちもPath追加はしなくていいっぽいけど、インストール先がどこかってのは要るのでメモか分かりやすいトコに置くように。
OpenOCD
openocd-org/openocdのopenocd-v***.***.***-i686-w64-mingw32.tar.gzみたいな名前のヤツを落として下さい。
その場にぶちまけられるのでちゃんと空っぽのディレクトリをC:\直下にでも用意してから展開して下さい。(ここ重要)
…展開したらその中のbinを「設定」→「システム」→「バージョン情報」→「システムの詳細設定」→「環境変数」から環境変数Pathに追加して完了です。
こっちも例によってPath追加はしなくていいっぽいけど、インストーr(ry
STM32CubeMX
STM32CubeMXから落として展開します。
中に入ってるSetupSTM32CubeMX-***.***.***-Win.exeみたいな名前のヤツを実行して画面の指示に従って下さい。
JetBrains Toolbox
JetBrains Toolbox Appで「ダウンロード」を押して実行して画面の指示に従って下さい。
JetBrains CLion
JetBrains Toolboxを開いて画面の通りにCLionをインスコして下さい。
次回予告
今回で必要なツールは揃いました。
次回はいよいよ実際にプロジェクトを作っていきます。
プロジェクトを作ってみよう その1
前回、無事に環境を作り終わったと思うのでプロジェクトを作りましょう。
プロジェクト作成
まずプロジェクトをテンプレから作るのでSTM32CubeMXを開きます。

今回はNUCLEO-F446REを使うので囲ってるボタン↑からプロジェクト作成画面を呼び出します。

ちょっと待つとこんなの↑が出てくるはずなので赤で囲ったテキストボックスにNUCLEO-F446REとぶち込みましょう。
青で囲ったトコではないので注意。

絞り込まれると右下にNUCLEO-F446REが出てくるので、これをクリック(①)した後、「Start Project」を押して(②)下さい。
なんか出ますが取り敢えずYes押しといて下さい。デフォルト設定が適用されるので楽になります。
プロジェクト編集
しばらく待つとなんか出てきます。

コイツがピン編集画面ですが、まず先に赤で囲ったトコを押してクロック編集画面に移ります。

まず①を180に変更し、そのままEnterを押すか②を押すかをすると他の部分をいい感じに設定してくれます。便利。
③でピン設定画面に戻ります。

まず機能一覧をA to Zにして(①)、TIM3を選択(②)します。

TIM3、タイマー3の設定が開きます。
タイマーは、一定間隔で処理したりn回入力された時に処理したりするための機能です。
赤で囲ったチャンネル1・3・4の設定を変更(①)します。PWM Generation CH*を選びます。Output Compare 〜やPWM Generation No Outputではないので注意。
変更したら右のピンのPA6・PB0・PB1に割り当てられますが、今回はそれぞれPC6・PC8・PC9に割り当てたいのでCtrlキーを押しながらD&Dして(②)下さい。
次に、TIM2を選択(③)します。

TIM2、タイマー2の設定が開きます。
赤で囲ったチャンネル1の設定を変更(①)します。
こちらもPWM Generation CH1を選びます。他のを選ばないよう注意。
変更したら右のピンのPA0に割り当てられますが、例によってPB8に割り当てたいのでCtrlキーを押しながらD&Dして(②)下さい。
また、そのままでは信号が1/65536になってしまうため最大値を65535へ設定(③)します。

次に、USART3を選択(①)します。
USART・UARTとは、基板同士で通信するための機能です。
USARTはUARTの上位互換らしいです。が、UARTとしてしか筆者は使ったことがないのでよー分からんです。
ModeでAsynchronousを選択(②)します。これでUARTとして機能します。
NVIC Settingsを選択(③)してチェックを入れます(④)。
これで受信処理を書けます。
(2025/09/17追記ここから)

ピンの割り当てを変えます。初期状態で下の方に割り当てられてるUSART3のピンたちを上の方に持っていきます。
場所は示しましたが、まぁCtrl+ドラッグで移動してれば勝手にハイライトしてくれるので迷うことはないでしょう。
(2025/09/17追記ここまで)
(2025/09/08追記ここから)
完全にGPIO出力ピンの設定忘れてましたねぇ…(アホ)

PA6・7・11とPB12(赤丸で囲ったピンたち)をクリックしてGPIO_Outputを選んでください。
(2025/09/08追記ここまで)
これで今回必要なピン設定は終わりました。⑤からプロジェクト設定画面に移ります。

ここではプロジェクトの生成方法などを設定します。
まずプロジェクト名を設定(①)します。講習用のプロジェクトなんで自分で分かりゃなんでもいいです。
次にプロジェクトの場所を設定(②)します。右のBrowseから選択したりパスをコピペしたりして設定します。
例えば/home/foobar/Documentsとした場合/home/foobar/Documents/(プロジェクト名)以下に生成され、C:\Users\foobar\Documentsとした場合C:\Users\foobar\Documents\(プロジェクト名)以下に生成されます。
(↓↓↓↓↓ここ重要↓↓↓↓↓)
この時、OneDrive・Google Driveなどのクラウドストレージは選ばない方が身のためです。(同期周りでトラブりがち)
あと、OneDriveもそうだけど、特にWindows勢は日本語が含まれるパスには置かないで下さい。(Shift_JISは悪)
(↑↑↑↑↑ここ重要↑↑↑↑↑)
プロジェクトの生成場所の設定が終わったので、生成するファイル共の種類を設定(③)します。
今回はCMakeを使うのでCMakeに設定します。
ここまで終わったら④から次の設定に移ります。

こっちは実際に生成されるコードに関する設定です。
まず、ファイルを分割し編集しやすく(①)します。
次に、使ってないピンの電源供給を止めて省エネにします(②)。
以上で全てのプロジェクト設定が終わった…はずなので右上のボタン(③)を押してコードを生成します。
なんかYes/No聞いてくる時はYesと答えて下さい。ファームウェアの更新です。
次回予告
今回で必要なプロジェクトは無事に作成し終わりました。
次回はCLionでプロジェクトを開くために必要な初期設定をしていきます。
プロジェクトを作ってみよう その2
前回はCubeMXでプロジェクトを生成しました。
今回はCLionでプロジェクトを開きつつ、まだやっていないであろうCLionの初期設定共をこなします。
プロジェクトOPEN!
まずCLionを開きます。JetBrains Toolbox内からでもスタートからでもデスクトップからでもお好きにドーゾ。
初回起動時なんか聞かれた気がしなくもないけど、取り敢えず言語に日本語、地域にアジア(中国以外)、チェックボックス系はとりま全部ONでいいと思います。知らんけど。(TODO)
で、何だかんだ進むとようこそ画面が出ます。大体こういうツールはようこそ画面がある気がする。[要出典]

開く(①)を押すと場所選択させられるので前回作ったプロジェクトが入ってるディレクトリを選択(②)します。
.iocではなく.iocが入ったディレクトリ(かその中のCMakeLists.txt) を選択して下さい。
OK(③)を押せばプロジェクトが読み込まれます。

ちょい待つとCLionがCMakeプロジェクトだと勝手に認識してくれるので、初回設定画面が出てきます。
①はもうON固定でいいです。いくらか楽になります。
諸々設定する前にインストールしたARMのツールチェーンをCLionに登録する必要があるので②を押します。
ツールチェーン追加

そしたらツールチェーンの管理画面が出てくるので左上の+(①)から「システム」(②)を押します。

編集できるようになるので好きな名前にして下さい。(①)
この後すぐ使うので覚えといて下さい。
②にはぞれぞれのツールの場所を指定します。環境構築の時に分かりやすい場所に置いたと思うので、それぞれ指定して下さい。
ビルドツールは今回Ninja
Buildを使うのでWindows勢ならninja.exeを、それ以外勢はninjaをフルパス(PATH通ってればフルパスじゃなくていいけど)で指定して下さい。
Cコンパイラー・C++コンパイラー・デバッガーはArm GNU
Toolchainのヤツを使うので、コヤツのインストール先にあるarm-none-eabi-gcc(.exe)・arm-none-eabi-g++(.exe)・arm-none-eabi-gdb(.exe)をそれぞれ指定して下さい。
うまく行ってればC++コンパイラー欄の下には何も出ず、デバッガー欄の下にはデバッガーの(=コンパイラーの)バージョン情報が出てるはずです。
ツールチェーンの設定が済んだのでOK(③)からCMakeの初期設定に戻りましょう。
仕上げ

戻ってきたら、まず①でさっき作ったツールチェーンを選択します。プロファイル名末尾にその名前が自動で追記されます。
これで下準備は完了したのでOK(②)で閉じます。
OpenOCD
さて、初期設定を済ませたいのでもうひと頑張りします。
基板に実行ファイル書き込むためのソフトであるOpenOCDの場所をCLionに教えてやらねばなりません。

設定は右上の歯車(①)を押して出てくるメニューにいます。「設定」(②)を押します。

CLionの設定はいくつかのカテゴリに分かれています。
目的の場所は「ビルド、実行、デプロイ」(①)の中の「組み込み開発」(②)にあります。
各種ツールの場所を指定する欄が現れるのでOpenOCDの実行ファイルの場所を③にぶち込みます。Windowsならopenocd.exe、それ以外ならopenocdの場所ですね。
すぐ下にCubeMXの場所を指定する欄(④)もあります。空欄にしといてもいいですが、ここで指定しておくとCLion上で.iocを開くとCubeMXが立ち上がってくれるようになります。
終わったら⑤で閉じて下さい。
書き込み設定
更にもうひと頑張り、OpenOCDに関連して書き込むための設定をやって行きます。

上の方にある「(プロジェクト名)」が書いてある欄(①)をクリックします。これは横の実行ボタンで何をするか選択するトコです。
今回はPC上で実行するわけではないので、あらかじめ用意されているものは要らないので削除します。
横の三点リーダー(②)を押すとメニューが出てくるので「削除」(③)を押します。これをもう一つにもやった後、④で編集画面に行きます。

構成の編集画面が出てくるので左上の+(①)を押して「OpenOCDをダウンロードして実行」(②)を選びます。

流石に名称未設定は可哀想な気がするのでテキトーな名前を付けて(①)やります。
②のチェックは後々チームで開発する時、設定を共有出来るのでONでいいと思います。
③は実際に書き込む実行ファイルを選択します。クリックするとプロジェクト名と同じ名前があるはずなので選択します。
ここまでは全ボード共通です。何故なら、次に指定するボード構成ファイルがボードごとの違いを吸収してくれるためです。
というわけで指定していくのですが、なんと有り難いことにCLionがOpenOCDの場所を元にボード構成ファイルをリストアップして選びやすくしてくれます。「支援⋯」(④)を押します。

選びやすく、と言ってもあくまで列挙するだけなので大量の中から目的のものを探す必要があります。
我々が使ってるのはSTM32なので大体st_始まりかstm32始まりで目星を付けると見つかります。
今回はNUCLEO-F446REなのでst_nucleo_f4.cfgを使います。
この時、左の「使用」ではなく、真ん中の「プロジェクトにコピーして使用」(②)を押して下さい。
自分だけで開発するなら影響はないんですが、チーム開発だとOpenOCDの場所に左右される関係で人によっては動かない、という事態になりかねません。
押すとウィンドウが閉じて無事にボード構成ファイルが選択されてるはずなので、構成編集画面を閉じます。(OK押すなりなんなりお好きに)
これで下準備は完了です。
次回予告
今回はプロジェクトをCLionで開いて、ついでに初期設定まで行いました。
これはあくまで初期設定なので、次新しくプロジェクト作るって時はCMake部分の設定だけで済みます。
あと、設定は項目がいっぱいあるので自分好みにカスタマイズしとくと捗ります。
次回はゴールにはあまり関係はないですが、エアシリンダーを動かします。
エアシリンダーを動かしてみよう
いよいよ前回までで作ったプロジェクトで開発していきます。
今回はエアシリンダーを動かします。
ファイル構造について
…とその前に、これから開発していく上でどこに何があるか知っておくと便利です。
ファイル構造について軽く書いておきます。

赤で囲った部分はCMake関連のファイルです。ライブラリを追加する時には触るかもしれませんが、基本こっちから触ることはありません。
水色で囲った部分はマイコンがプログラムを起動するために必要なヤツです。これも放置。
重要なのはここからで、黄色・緑で囲った部分(特に後者)を主に触っていきます。
黄色の方、Incはヘッダーファイルを入れておきます。(Includeの略だろうけど一般的にはincludeが使われるので何故Incなのか謎)
緑の方、Srcはソースファイルを入れておきます。(Source codeの略なんだけど一般的には小文字スタートのsrcが使われるのでなんとも)
ヘッダー・ソースの違いはコラム:ヘッダーとソースの違いを参照。
その他にもCubeMXでやった設定内容が入ったIOCファイル、ライブラリが入ったDriversディレクトリがありますが、触ることはありません。
エアシリンダーを動かそう!
いよいよ本題のエアシリンダーです。

エアシリンダー(図中央)は電磁弁(図左・右)によって制御されます。
電磁弁は赤で示した弁を電気で動かす事で、タンクの圧縮空気を送ったり、外に向かって開放したりします。
制御は単純で、信号のON/OFFで弁を切り替えます。ダントツで一番楽です。
STM32のHAL環境においてGPIOから出力する時はHAL_GPIO_WritePinかHAL_GPIO_TogglePinを使います。Writeというのは、信号のON/OFFを「ONという状態をピンに書き込む」「OFFという状態をピンに書き込む」と捉えているんですね。
一方Toggleは読んで字の如くON/OFFを切り替えます。
引数は両者とも2つ目までは共通で「どのピンに出力するか」をまず渡してやります。Writeの方だけONなのかOFFなのかを渡してやります。Toggleは中に持ってるんで要らんという事です。
例としてはこう。
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); // PA5(GPIOAの5番ピン)にSET(ON)
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); // PA5(同上)にRESET(OFF)
// GPIO? GPIO_PIN_? GPIO_PIN_(RE)SET
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // PA5(同上)をON/OFF切り替え
ON/OFFとはそのまま書かずそれぞれSET/RESETと言ってますね。
これは内部的には「ONであるか」というフラグで見ているので、そこに1をセットすんのか(0で)リセットすんのか、という風に捉えてるわけですね。
ちなみに、CubeMXでピンに名前を付けることができますが、例えば今回のは何もしてなければ「LD2」と言うピンがあるはずなのでこれを例に取ると、
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
// ???_GPIO_Port ???_Pin
のように書けます。便利。
なおこのピンはNUCLEO-F446REの基板表面のLEDに繋がっていてデフォルトで出力モードとなってます。折角なのでコレ使います。
お手元のmain.cを開いて下さい。そんで、/* USER CODE BEGIN 3 */の下にカーソルを移動して頂戴。
(めんdので以降は/* USER CODE BEGIN なんとか */と/* USER CODE END なんとか */の間はUSER CODE なんとかって呼ぶっす)
// (略)
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while(1) {
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// >>>>> こ↑こ↓ <<<<<
}
/* USER CODE END 3 */
}
// (略)
で、ここにON/OFFのコードをぶち込めばON/OFFしてくれるわけです。
が、このままだともれなく秒間1億回弱ぐらいの速度でON/OFFされちゃいます。これでは、いけませんね。
なので、ちゃんと待ってあげましょう。
STM32のHAL環境において待ってあげる時はHAL_Delayを使ってやります。
HAL_Delay(1000);
// ms
この例は1秒待ちます。組み込み開発では大体時間の基本単位がミリ秒な気がします。まぁ丁度いいし妥当。[要出典]
まぁ1秒でも良いんですが0.5秒の方が絵面が面白いなんとなく分かりやすそう[要検証]なので0.5秒でやります。
要するに500ミリ秒ですね。
なのでUSER CODE 3の中身は、
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
HAL_Delay(500);
といった所でしょうかね。ON/OFFを明示的に行うなら、
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
HAL_Delay(500);
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
HAL_Delay(500);
みたいに書けばよき。
基板にぶち込んでみよう!
プログラム出来たんで基板にぶち込みませう。
(TODO:実行ボタン押してる画像)
上にある実行ボタン(多分①とかになるはず)を押すと勝手にビルドした後、
OpenOCDが起動して書き込みまでやってくれます。楽。
これだけ。
次回予告
今回はエアシリンダーを動かしました。ただのON/OFFという所で気付いたかもしれませんが、実は全く同じ方法でLEDも光らせたり出来ます。
次回は足回りの肝、モーターを動かします。
モーターを回してみよう
今回は足回りの要となるモーターを動かします。が、その前に。 今日は、モーターが動くまでの手順について、知っておこう。
どーやって動かすん
実はモーターとマイコンは直接繋がってるわけじゃないです。
電子工作齧ったことあれば何となく察しが付くかとは思いますが、止まったりする時にモーターから逆流してくる電流でマイコン逝きます。
マイコン逝っちゃうので回路的には分けちゃいます。で、その橋渡しをするのがモータードライバーっつぅ回路です。
大抵は略してモタドラとかMD(※Mini Diskじゃないよ)って呼びます。
大体は長方形の基板に、片やモーター側の端子類、片やマイコン側の端子類、って構成で、真ん中に黒くでデッカいヤツが何個か載ってます。
制御方式はいくつかあって、どんくらいの出力にするかを直接電圧で表現するPWM方式もあれば、UARTやらI²CやらCANやらで速度値を送ってやる方式もあります。
後者はぶっちゃけ使うMDによって仕様が違うので解説すんのがめんd紹介しきれない所があるのでドキュメント読んでください。(投げやり)
今回は前者のPWM方式のMDとしてやっていくよ。PWMって何ぞやって人はコラム読んで呉。
ちなみにPWM方式のMDも2種類あって、強弱のPWMと正/逆転切り替えの2信号のタイプ、正転方向のPWMと逆転方向のPWMで直接Hブリッジ触るタイプがあるんだけど、
今回は部内で使ってるのもあって前者の強弱+正逆としてやっていくよ。
そうだ ソース、書こう
皆さんソースっていつも何使ってます?うちはブルドック愛用してます。…ってそうじゃなくて。
具体的にどうやってやんのかっつー話なわけですが。
正逆は「切り替え」って時点で察しは付くと思いますがこれただのGPIOです。前の章でやったやつですね。
なので臆することはありません。
// 例:PA6が正逆切り替え(ONで逆転)とした場合
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET); // 正転
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET); // 逆転
// GPIO? GPIO_PIN_? GPIO_PIN_(RE)SET
のように書けばいーのです。
さぁ続いて肝心要のPWM。コイツは使うのに下準備が要ります。USER CODE 2をご覧ください。
// (略)
int main(void) {
// (略)
/* USER CODE BEGIN 2 */
// >>> ココダヨー <<<
/* USER CODE END 2 */
// (略)
}
// (略)
ここにまず「PWM使いまっせ」と宣言さす必要があるんす。HAL_TIM_PWM_Startって関数を呼んでやります。
// 例:TIM3のCH4で使い始める場合
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4);
// &htim? TIM_CHANNEL_?
これさえ呼んでれば以降はPWMが自由に使えますぜ。
PWMは__HAL_TIM_SET_COMPAREっていう関数を呼ぶと出力を変えられます。
// 例:TIM3のCH4に256/65535(※)のパワーで出力する場合
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 256);
// &htim? TIM_CHANNEL_? ???
// ※65535はタイマーの最大値。今回はCubeMX上で65535に設定してるので65535。
例えば、TIM3のCH4に1秒おきに0→1024/65535→0→…と出力するなら…
// (略)
int main(void) {
// (略)
/* USER CODE BEGIN While */
while(1) {
/* USER CODE END While */
/* USER CODE BEGIN 3 */
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 0); // 0出して...
HAL_Delay(1000); // 1秒待って...
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 1024); // 1024/65535出して...
HAL_Delay(1000); // 1秒待つ
}
/* USER CODE END 3 */
}
// (略)
こう!
これでPWMが出るようになりました。
まわる〜ま〜わる〜よモーターはまわる〜
で、上に書いた2つでもうどうにでもできるようになったので回しましょう。
まぁ、動作テストなので常軌を逸しない程度の速さで回さなければ何やってくれてもいいんだけど、
それじゃあ入門書のイミがねーので試しに0→1000(正転)→0→1000(逆転)→0→…とさせてみましょうか。
ピン設定の兼ね合いで上の例と同じくPWMにはTIM3のCH4、正逆ピンにはPA6を使うよ。
HAL_TIM_PWM_Startまだ書いて無ければ書こう。
// USER CODE 2内
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4);
で、今回例でやる内容の実装っすね。
// USER CODE 3内、「閉じ波括弧前」(←ここ重要)
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 0); // 0にして...
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET); // 正転にして...
HAL_Delay(200); // (いきなり1000にすると負荷やべーかも知れんのでゆっくり増加させる)
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 200); // 200にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 400); // 400にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 600); // 600にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 800); // 800にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 1000); // 1000にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 800); // 800にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 600); // 600にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 400); // 400にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 200); // 200にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 0); // 0にして...
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET); // 逆転にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 200); // 200にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 400); // 400にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 600); // 600にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 800); // 800にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 1000); // 1000にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 800); // 800にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 600); // 600にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 400); // 400にして...
HAL_Delay(200);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 200); // 200にする
HAL_Delay(200);
…と、そのまま愚直に実装してこう。一応forでもうちょいマシにした方も置いとく。
// USER CODE 3内、「「閉じ波括弧前」」(←ここ重要)
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 0);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);
HAL_Delay(200);
for(int i = 200; i < 1001; i += 200) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, i);
HAL_Delay(200);
}
for(int i = 800; -1 < i; i -= 200) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, i);
HAL_Delay(200);
}
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 0);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);
HAL_Delay(200);
for(int i = 200; i < 1001; i += 200) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, i);
HAL_Delay(200);
}
for(int i = 800; -1 < i; i -= 200) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, i);
HAL_Delay(200);
}
見ての通り正逆指定以外は正転も逆転も同じコードなので正逆切り替えをHAL_GPIO_TogglePinに置き換えるともっと簡潔になる。
// USER CODE 3内、(ここ重要→→→)『『『閉じ波括弧前』』』(←←←ここ重要)
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 0);
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_6);
HAL_Delay(200);
for(int i = 200; i < 1001; i += 200) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, i);
HAL_Delay(200);
}
for(int i = 800; -1 < i; i -= 200) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, i);
HAL_Delay(200);
}
…うん、for文の仕様ちゃんと分かってないと分からんだろうし、フツーに分かりづらいコードなので愚直に実装した方がいいと思います…(主観)
次回予告
今回は足回りを動かすために必要なモーターを動かしました。
次回はアクチュエーターから離れて、コントローラー通信を行います。
コントローラーを受信してみよう (WIP)
今回は、今までのアクチュエーターとは打って変わって通信系です。
コントローラーで操作するために信号を受信します。
わが部では現在、コントローラー通信にはESP32-DevKitC-32Eを使用しており、これに下駄基板のEveryday Shumai Party!を履かせています。
ファームウェアとしてESP32-DS4を書き込んだ状態でロボットに設置し、UART1の端子から制御用基板に接続します。
制御用基板側ではESP32-DS4-driverを使うことでデータを扱いやすくしてます。
(ちなみに次のシーズンからこれまた拙作の別の通信系統に置き換わる予定なんだけどとりあえず一旦置いとく)
ほいじゃ、概要はこのぐらいにして実際に配線しようか。
配線上のアリア
今回はPC10とPC11を通信用に割り当てています。…なーんて言われても分かりづらさこの上ないと思うので画像を持ってきました。

赤で囲ったところです。丁度隣り合ってたのでありがた〜く使わせてもらいました。見ての通り青いボタンに最も近い列ですね。
ここにEveryday Shumai Party!を繋げます。

Everyday Shumai Party!のUART1端子から伸ばしてきたDF1Bコネクタ(4ピン)をNUCLEO-F446REに繋げるんですが、
その前にピンアサイン確認しときましょう。
画像の向きにDF1Bコネクターを向けた時、右2つは電源供給(5V)用となっています。コイツのおかげで別電源が要らないんですね。
一方左側は本命のUART通信線となってます。
緑で示した真ん中寄りの方はEveryday Shumai Party!のRXと外部基板のTXを繋ぐ線となっていて、
反対にシアンで示した外寄りの方はEveryday Shumai Party!のTXと外部基板のRXを繋ぐ線となっています。
なのでこの画像のコネクタ線の場合、灰色を+5Vに、白色をGNDに、ピンク色をPC10に、水色をPC11にそれぞれ挿せばいいわけです。
線を経由せず直接ピンからジャンパーワイヤーで配線する場合、TX同士やRX同士を繋がないようにしましょう。たまにやりがち。
ちなみに、今回はESP32とSTM32との通信なので大丈夫ですが、特にArduino UNOなどを使う場合には注意が必要です。
というのも、UARTの信号の電圧が違うのです。(ハァ?)
ESP32とSTM32は、というか基本的には信号は3.3Vなのですが、
どういうわけかArduino UNOはUART信号に 5 V を 使 い や が る のです。
この場合、別途電圧変換基板を噛ます必要があるのでご注意を…(n敗)(てかArduino UNOぐらいしか5VのUART見ない希ガス)
毎日焼売パーティ!32日目
で、コントローラーの信号を受け取るために、まず先述の通りESP32-DevKitC-32Eにファームウェア(ESP32-DS4)を書き込みます。
これはPlatformIOプロジェクトです。まずサクッとPlatformIOをインスコしちゃいましょう。(もちろんもう持ってるんなら飛ばして諸手)
公式を参照…してもらいたい所さんですが公式サイトそのまま進むともれなくVSCode向け拡張機能を入れさせられるのでここで解説します。
まずget-platformio.pyを落とします。見ての通りインストール用のPythonスクリプトですね。
落としたらこれをPythonで実行します。…って言うだけだと詰まる事が多いので手順を。
まずテキトーにCLI開きます。DOS窓(cmd.exe)でもPowerShellでもbashでも何でもいいんですけど、Pythonが使える事が大事です。
例えば、インストーラーでPATHを通すチェックを入れずにインスコしたAnaconda環境でPython使ってるんであればAnaconda Promptとかね。
不安ならpython -Vとかpython3 -Vとか実行してバージョン番号がちゃんと返ってくれば無問題。
「Pythonねぇぞコンニャロ」的なエラー吐いたらまぁ、適宜入れてください。(投げやり)
で、ここまで来ればもうPythonが使えるので、get-platformio.pyがあるディレクトリに移動してもらって、python get-platformio.pyだのpython3 get-platformio.pyだのって実行すればいーわけです。
実行が終わってなんかSuccessとかなんかそんな感じの成功してそうな雰囲気の単語があったら勝ちです。
その場合一緒に「このディレクトリをシステムのPATHに追加してねー」って感じの文言とともにインストール先ディレクトリが示されてるはずなので、
これをPATHに追加します。PATHってなんやねんって人とかどーやって追加すんねんって人はggってください。たぶん秒で引っ掛かります。(投げやり)
追加し終わった後はどこででもplatformioコマンドが使えるはずなので実行してみてください。なんかサブコマンドの一覧とか出てきたらいいと思います。
閑話休題。
さて、PlatformIOも入った所でカキコしましょっか。
ESP32-DS4をお手元のGitでクローンするなりGitHub上でZipに固めて落とすなり色々方法はありますがまぁお好みで。
落としたらそのままそのディレクトリに行って、platformio run -t uploadを実行します。これでいーはず。
ソース書ク丼
最近新潟のソースカツ丼食ったんだけどアレめっちゃうまい(語彙力)。ってのは置いといて。
ソース書いてくんすが、その前にESP32-DS4-driverをプロジェクトに導入しもす。
まず、プロジェクトルート(<プロジェクト名>.iocとかCMakeLists.txtあるトコ)に行ってもらって、
そこにESP32-DS4-driverって名前のディレクトリの中に内容が入ってるように落としてきてください。
例えばGitリポジトリで管理してるならgit submodule add https://github.com/ms0503/ESP32-DS4-driver.gitでいいし、
Gitリポジトリじゃないなら単にgit clone https://github.com/ms0503/ESP32-DS4-driver.gitだし、
ダウンロードしてきたんならESP32-DS4-driver-main.zip/ESP32-DS4-driver-mainを持ってきてESP32-DS4-driverにリネームすればいいし、
まぁ各自いい感じにヨロシク。(投げやり)
で、次にCMakeLists.txtを開いて、40行目とかなんかその辺に、
add_subdirectory(cmake/stm32cubemx)
って書いてるんでその下にでも
add_subdirectory(ESP32-DS4-driver/c)
って書いといてください。これでCMakeくんがESP32-DS4-driverを認識します。
あとは70行目とかその辺に
# Add user defined libraries
ってあるのでその下(言わずもがなカッコ内)に
esp32-ds4
って追加しといてください。そうすればそのセクションは
# Add linked libraries
target_link_libraries(${CMAKE_PROJECT_NAME}
stm32cubemx
# Add user defined libraries
esp32-ds4
)
みたいになってるはず…ですよね?そうなってればおk。
(TODO: ESP32-DS4-driverのC向け実装待ち)
次回予告
今回まででロボットを最低限動かすための知見が溜まったと思います。
次回はこれまでの内容を元に、足回りを動かします。
足回りを動かしてみよう (WIP)
今回は今までの集大成です。いよいよ足回りを動かします。
(WIP)
おわりに
これでロボット制御入門は以上となります。(番外編はあるけど)
環境構築の方法からプロジェクトの作り方、GPIOとPWMの使い方にUARTの受信を一通り行いました。
もちろん、これで作れるロボットは最低限でしかありません。
しかし、GPIOとPWMさえ使えれば、ぶっちゃけ何でも動かせます。ハイ。
なので、まぁ、知らん事は適宜ggりつつこの知見を頭の片隅にでも置いといてくれたらワイ幸いの限りでございます。
では、良い組み込みライフを。
著:渡波 空
番外編:センサーを読み取ってみよう (WIP)
今回は色々なセンサーを読み取ります。
(WIP)
コラム:ヘッダーとソースの違い
C言語・C++(一応C#も使えはするけど一旦置いといて)のコードは2種類あります。
一つはヘッダー、もう一つがソースです。今回はコイツらが何者なのか、どう使い分けるのかを知っていこう。
ヘッダーってなんぞや
まずはヘッダーから。いわゆる.hですね。
ヘッダーは、「このプログラムのどっかにxxxって名前の物が(多分)存在するから使っていいよ〜」ってのを延々と書いているファイルです。
あくまで存在する(と仮定する)という事しか書かないんですね。
そして「(多分)」って書いた通り、嘘を書くことも出来ますし、何なら一番最後に一つのプログラムにするまでエラーにならなかったりします。
嘘を書いたとて、それが本当に存在しないかは最後まで確認しないと分からないですからね。
逆に、ヘッダーに敢えて書かない事で外部から使えない関数などを作ることも可能です。
ソースってなんぞや
一方のソースはいわゆる.c。
ソースはヘッダー以外です。雑いし2種類って言ってる時点でそりゃそうなんだけど、実際この通りなんだよね。
もっと言えば、外部に公開できない(=「プログラムのどっか」が「ファイル内」に限定される)って所を除けばヘッダーの機能も担うし。
ヘッダーがあくまで存在しか書かないのに対して、その実体を作るのが大きな役目です。
なので、ヘッダーは無くても動きますがソースは無いと動きません。(ヘッダーライブラリとか一部例外はあるけど)
コラム:C++で開発するには
今回はC言語で開発しますが、C++のが好きだって人もいるでしょう。多分。
ただ、CubeMXは現状C言語のコードしか吐いてくれないので、C++で開発するにはちょっと細工してやる必要があります。
細工と言っても簡単な話で、C++で書いた関数をCubeMXが吐いたC言語側で呼べばいいのです。早速書いていきます。
ヘッダー書くぞ

まずヘッダーに関数の定義を書きます。main.cから呼び出すんでmain.h(①)が都合良さそうですね。
中には100行弱書いてますが、その中から赤で囲った「USER CODE BEGIN(END) EFP」(②)を探して下さい。
今回はこの中に書いていきます。どうせなら見慣れた名前が良かろうということで関数名は某duinoにあやかってsetupとloopとしました。
メインで呼ぶぞ

先に呼び出しだけ書いちゃいます。main.c(①)を開いて下さい。
例によってその中から「USER CODE BEGIN(END) 2」(②)・「USER CODE BEGIN(END) 3」(③)を探します。
前者ではsetupを、後者ではloopを呼び出しておきます。
C++ソース作るぞ

次に我々がこれからメインで触っていくことになるC++のソースを作ります。
まずSrcの上で右クリック(①)して下さい。メニューが表示されるので、「新規」(②)から「C/C++ ソースファイル」(③)を押します。

作成画面が出てくるので名前を決め(①)ます。今回はcxxmainとしました。
型(②)はソースファイルの言語です。C++なので.cpp(画像では筆者の好みの関係で.cc)を選びます。.cはC言語、.cuはCUDAのソースになってしまいます。
このままではCMakeの対象に入らないので、「ターゲットに追加」(③)にチェックを入れます。
多分デフォでプロジェクト名と同名のヤツにもチェックが入ってくれてるはずなのでそのまま。他はもちろんチェック無し。
OK(④)で完了するとファイルが作成され、自動で開きます。ここにコードを書いていきます。
#include <main.h>
extern "C" {
void setup() {
// 準備
}
void loop() {
// ループ処理
}
} // extern "C"
extern "C"がミソで、コイツを付けることでC言語からも使えるようにします。
他は某duinoよろしく最初に1回だけ実行する部分とループ処理の2つを定義してます。
終わり。
コラム:PWMとは
(音声とか一部を除く)アナログ信号をマイコンから出す時に多分使うであろうPWM。
今回はそんなPWMくんについて詳しく知っておこう。
PWMって何なの⁉️
?「私はPulse Width Modulationの略語と見てます❓️🔍️」
その通り。
んじゃ日本語にするとなんて言うんだって話だけど、そのまま直訳で「パルス幅変調」ってされることがほとんどだね。
…って言うだけじゃこんな記事の価値無いなるんでどういう事かってのも説明していくんね。
まずパルスってのはそのままで、いきなり最大値になったりいきなり最小値になったりする信号のこと。要は0と1を表現するカックカクした信号。
で、そのままだと当然最高速でぶん回すかビタっと止まるかしかできないので、工夫が必要なわけです。
そこでそのパルスの幅、つまり「一定時間のうちONである期間」を変化させることで擬似的に間の値を表現する、それがこの方式の基本的な原理です。
要は引くほど速くスイッチカチカチすることでビミョ〜に点ききらないみたいな、そんな状態を維持してる感じです。
ちなみに「一定時間のうちONである期間」の事をデューティー比って言います。大体%か分数(1/2とか1/4とか)で言ってる。小数で言うことはあまりない気がする。[要出典]
(TODO:やっぱ画像あった方分かりやすくね?こんなんじゃWikipediaの方がマシだろ)
Tips
制御に関したりしなかったりするtipsを書き殴ってるページです。
- C/C++のエラーは書かれている行に問題がなければその上を疑うべし
→例えばセミコロン(;)忘れとかはエラーにその次の行が示される
おまけ
用語集
用語集です。英語も置いておくので検索に活用してね。
用語集 プログラム編
プログラムに関する用語集です。
| 日本語 | 英語 | 意味 |
|---|---|---|
| プログラム | program | 正に我々が書いてるもの。機械への指示書的なやつ。あーしろこーしろを事細かに書いていく。 |
| コンパイル | compile | プログラムを機械が読み取れる形式にすること。 |
| コンパイラ | compiler | プログラムをコンパイルしてくれる奴ら。こいつのお叱り(エラー)はしっかり聞こうな。 |
| リンク | link | コンパイラが大量に吐いた機械が読めるプログラムをひとまとめにすること。 |
| リンカ | linker | リンクして実際に書き込むやつにするやつ。 |
| ビルド | build | プロジェクト全体のコンパイル・リンクを行って実際に書き込むファイルを生成したりすること。 |
| ビルダー | builder | ビルドしてくれるやつ。 |
| 関数 | function | ある程度の処理をまとめたやつ。数学の関数と大筋一緒。ただしf(x)のxみたいな変数はなくてもいい(ハァ?) |
| 変数 | variable | 好きな値を保存できるやつ。ただし種類(例えば整数・文字列・小数など)は最初に決めて固定。 |
| 宣言 | declare | 「こんな変数があるよー」と書いてやること。あくまでも中身は書いてない。 |
| 定義 | define | 実際に変数とか関数の中身を書いてやること。宣言と同時にやることが多い。 |
| 代入 | assign | 変数に値をぶち込むこと。例えばa = 1なら変数aに1を代入すると言う。 |
| 定数 | constant | 最初に定義して以降、書き換えられない変数。例えばピン番号とか実行中には変わらないはずのものとか。 |
| 期待 | expect | コンパイラが仕様を元に「次にこんなものが来るはずだ」と目星を付けること。主にそれが外れ(=プログラムが間違っている)unexpected tokenエラーの形で見る。 |
用語集 基板編
基板に関する用語集です。
| 日本語 | 英語 | 意味 |
|---|---|---|
| マイコン | micro controller, MCU | ロボットの頭脳。プログラムをぶち込まれて仕事をこなし続ける社畜。 |
| 評価ボード | evaluation board | マイコンメーカーとかがマイコンからピンを生やしたりして実際に使える状態にした基板。本来は名前の通りマイコンの性能を評価するために使うらしいがフツーにロボットに積んだりしてる。 |
| ライター | writer, programmer | マイコンにプログラムをぶち込むための道具(基板)。決して火を付ける道具ではない。 |
Nucleo | ST社が発売してる評価ボード。Discoveryに比べ本体の機能が少ないので柔軟に組める(=労力が増える)。 | |
Discovery | ST社が発売してる評価ボード。Nucleoに比べ本体の機能が多くマイコンの機能を試すのに向いている(=実験向き)。 |
用語集 Git編
Gitに関する用語集です。
| 日本語 | 英語 | 意味 |
|---|---|---|
| リポジトリ | repository | ソースコードとか色んなものをバージョン管理しておく場所のこと。 |
| ローカルリポジトリ | local repository | リポジトリのうち、手元にある方。 |
| リモートリポジトリ | remote repository | リポジトリのうち、サーバーとかに置いてる方。GitHubのリポジトリとか。 |
| ブランチ | branch | 作業内容などに応じて適宜切り分けるサブのリポジトリ的なやつ。 |
| 作業ツリー | working tree | 我々が実際に作業してるディレクトリのこと。 |
| ステージ | staging area | コミットの対象にしたファイル共が仮想的に置かれる場所のこと。 |
| コミット | commit | ステージの内容をリポジトリに反映すること。 |
| コミットハッシュ | commit hash | コミットごとに割り振られているIDっぽいやつのこと。40桁の16進数が正式なコミットハッシュだけど他と被ってなければ先頭数桁だけでも使える。 |
| コミットログ | commit log | 今までのコミットの記録のこと。一番最初のコミットから現在の最終コミットまでの系譜を辿ることができる。 |
| プッシュ | push | ローカルリポジトリの内容をリモートリポジトリに送ること。 |
| プル | pull | リモートリポジトリの内容をローカルリポジトリに持ってきて反映させること。 |
| フェッチ | fetch | リモートリポジトリの内容をローカルリポジトリに持ってくること。反映はしない。 |
| マージ | merge | 他のブランチの内容を現在のブランチに統合するやつその1。他のブランチの変更内容をまとめたコミットを1個作ることで統合する。ただし一部状況でよりスマートなfast-forwardが可能。 |
| ファストフォワード | fast-forward | 自分側ブランチから相手側ブランチが切り分けられてから相手側ブランチしか更新されていなかった場合に可能なマージ。変更内容をまとめたコミットを作る代わりに相手側ブランチの最終コミットを自分側ブランチの最終コミットとすることで統合する。 |
| リベース | rebase | 他のブランチの内容を現在のブランチに統合するやつその2。相手側ブランチが切り分けられた次の時点の自分側のコミットが相手側最終コミットの後にされたかのように組み替えてやることで統合する。自分側の分岐点の元(base)を付け替えるからrebase。 |