効率的なArduino PWMリーダー&RC受信機デコーダー:フェイルセーフ内蔵
必要なパーツと用品
| パーツ | 数量 | 備考 |
|---|---|---|
| Arduino UNO | 1 | Nano/Pro Miniでも可 |
| SG90 マイクロサーボ | 2 | サーボミキサー実演用 |
プロジェクト概要
RC受信機(または任意のPWM信号)を任意のArduino入力ピンで読み取り、送信機信号喪失時にフェイルセーフを発動させる、汎用的で効率的なコードを提供します。ピンチェンジ割り込みを用いるため、pulseIn()のようにメインループをブロックしません。
下記動画では、このコード(PWMread_RCfailsafe.ino)を使ってArduino Unoをサーボミキサーとして動作させています:
- 送信機信号喪失でフェイルセーフ発動:エレベーター全アップ、エルロン中立
- 青いサーボの向きをスロットルで制御
- 青いサーボの可動範囲(レート)を送信機側スライダーで設定
- ギアスイッチでミキシングON/OFF
目次
- サーボ/PWM制御の仕組み
- RC模型/ロボットでのArduino活用例
- コード概要:フェイルセーフ付きRC受信機PWMデコード
PWMread_RCfailsafe.inoの使い方- 受信機フレームレート・周波数の表示
- サーボミキシング例
- アプローチの理由
- 制限事項
サーボとスピードコントローラーはPWMでどう制御されるか
PWM信号(パルス幅変調)の理解を前提とします。詳しくはJoop Brokking氏の動画が参考になります。また、Arduino IDE、変数型、制御構文、配列、Servoライブラリの基礎知識も必要です。
RC模型/ロボットでのArduino活用例
- サーボミキシング、ライト制御、ポンプ/バルブ制御、独自シーケンス実行
- 飛行安定化/オートパイロット、方位保持、高度/深度保持、自動水平、障害物回避、帰還機能などのコントローラー実装
- 電波切れや低電圧検知への対応
- 同じ送信機で複数機体を、設定変更なし/モデルメモリなしで運用
コード概要:フェイルセーフ付きRC受信機PWMデコード
ピンチェンジ割り込みでPWM信号を測定。Uno/Nano/Pro Miniの全デジタル/アナログピン(A6/A7除く)に対応。割り込みレジスタ設定を自動化し、異なるプロジェクト/ピン配置へ容易に移植可能です。
注意: SoftwareSerial等、ピンチェンジ割り込みを使用するライブラリと併用不可。
仕組み:
- 入力ピンを配列
pwmPIN[]で指定(任意の長さ・順序) - セットアップ関数で各ピンのピンチェンジ割り込みレジスタを有効化
- 電圧変化で3つのISRのいずれかが発火:
PCINT0_vect(Port B)、PCINT1_vect(Port C)、PCINT2_vect(Port D) - ISR内でどのピンが変化したか判定、
micros()で時刻記録 - パルス幅と繰り返し周期を計算
- フラグで新規パルス受信を通知
- メインループ側の関数でフラグをチェックしデータ取得・処理
詳細はポート操作チュートリアルも参照。
専用関数RC_decode()でパルス幅(1000〜2000μs)を±100%(±1.0)の制御信号に変換。フェイルセーフは10〜330Hz、500〜2500μsの許容範囲外で所定値を返します。キャリブレーション値とフェイルセーフ位置は各チャネルごとにPWMread_RCfailsafe.ino内で設定可能。
PWMread_RCfailsafe.inoの使い方
ステップ1:ハードウェア接続例(Arduino Uno)
- 受信機を5V/GNDで給電
- 受信機信号ピンをArduinoピン2〜7に接続(2chならピン2,3のみ)
- サーボミキサー例の場合:サーボ信号線をピン9,10に接続
ステップ2:ファイルをスケッチフォルダにコピー
PWMread_RCfailsafe.inoをメインスケッチと同じフォルダに配置。IDEで開き直すと2つ目のタブとして表示されます。
ステップ3:入力ピンを指定
PWMread_RCfailsafeタブの「USER DEFINED VARIABLES」セクションでpwmPIN[]配列にピン番号を入力。最初の要素がチャネル1、2番目がチャネル2...対応。A6/A7は使用不可。Megaは未対応(要望があれば対応可能)。
ステップ4:利用可能な関数を確認
setup_pwmRead():初期化RC_avail():全チャネル新データ受信でtrueRC_decode(ch):指定チャネルを±1.0でデコード+フェイルセーフprint_RCpwm():生パルス幅をシリアル出力(キャリブレーション用)PWM_read(ch):指定チャネル新パルス検出でtruePWM_time()/PWM()/PWM_period()/PWM_freq()/PWM_duty():汎用PWM測定値取得
ステップ5:生パルス幅をシリアル出力して確認
付属のRC_Read_Exampleを書き込み、送信機ONでシリアルモニタを見る。RC_avail()でデータ揃い次第print_RCpwm()で出力。
ステップ6:送信機キャリブレーション
シリアル出力された生パルス幅を見て、RC_min[], RC_mid[], RC_max[]を手動調整。フルレートで操作して最大解像度を得ること。
ステップ7:キャリブレーション済み値を出力確認
print_RCpwm()をコメントアウトし、RC_decode(ch)で±1.0に変換、decimal2percentage()でパーセント表示。
ステップ8:フェイルセーフ位置設定
RC_failsafe[]に各チャネルのフェイルセーフ位置(±1.0範囲)を設定。送信機ON/OFFで動作確認。※受信機側のフェイルセーフ機能は無効化推奨(そうでないとArduinoが信号喪失を検知できない)。
受信機フレームレート・周波数の表示
チャネル1(最初のパルス)でPWM_read(1)→PWM_period(), PWM_freq()で取得・表示。フレーム周期がわかると、データ未受信時のフェイルセーフ発動タイミング(例:21ms経過で強制更新)を制御できます。RC_Read_Example.inoに実装例あり。
サーボミキシング例
付属のRC_ServoMixer_Example.inoで、チャネル2(エレベーター)とチャネル3(エルロン)をミキシングし、2つのサーボ(ピン9,10)を駆動。方向・レート・サブトリム設定も含む。ミキシング式:
mix1 = ch2 - ch3 (エレベーター - エルロン)
mix2 = ch2 + ch3 (エレベーター + エルロン)
出力を±1.0にクリップ後、calc_uS()でサーボ用パルス幅(μs)に変換:
pulse_μs = 1500 + (servo_position_% × rates × direction + sub_trim) × 500
標準ニュートラル1500μs、±500μs(=1000〜2000μs)が基本。レート1.0で±500μs、2.0で±1000μs。
このアプローチを採った理由
pulseIn()はパルス待ちでブロッキングし、マルチチャネルではデータ取りこぼし発生。ピンチェンジ割り込み+直接ポート操作ならメインループをほぼ止めず高速処理可能だが、実装が面倒。そこで「汎用.inoファイルをコピーするだけで割り込みの恩恵を受けられる」仕組みを作りました。
制限事項
micros()関数の分解能
4μsステップでカウント。実用上十分だが、タイマー割り込みで0.5μs分解能化も可能(参考)。
効率
6ch受信時、ISR実行時間は約24μs/回。パルス1つでISRが2回(立ち上がり/立ち下がり)走るため96μs。6chで約288μs/フレーム。受信機周期20msとするとCPU使用率約1.44%。pulseIn()ならチャネルごとに最大20msブロックされるので大幅改善。2chなら0.16%。
実用的な最大周波数
他用途で使う場合、最大約2.5kHzまで(micros()で100ステップ分解能)。1chでCPU 3%、最小測定デューティ0.03(12μs)。より高周波ならISRを専用実装すべし。
コード
PWMread_RCfailsafe.ino:メインライブラリ(割り込みルーチン、デコード、フェイルセーフ含む)RC_Read_Example.ino:生データ表示・キャリブレーション・フェイルセーフ確認用RC_FrameRate.ino:フレームレート・周波数表示用RC_ServoMixer_Example.ino:サーボミキシング実演用
全コードは記事内に掲載(長いためここでは省略)。GitHub等から入手可能。
回路図
RC受信機:ICSPピンの5V/GNDから給電、信号6chをピン2〜7へ。
マイクロサーボ1:5V/GND、信号→ピン9。
マイクロサーボ2:3.3V/GND、信号→ピン10。
製造プロセス
- Arduino UNOで作るLCDアニメーション&ゲーム入門
- Arduinoとスマホで作るスマート電圧計 – 簡単DIYプロジェクト
- Arduinoで温湿度ロガーを作る – DHT11とEthernetシールドでSDカード記録
- DHT11 と Blynk で温湿度をリアルタイム監視する Arduino チュートリアル
- Python 3からArduino UNOを制御 – シリアル通信でLED点滅デモ
- Arduino Nanoと128x64 OLEDで実行するセルラーオートマトン「ライフゲーム」
- Arduino NanoとRDA5807Mで作るコンパクトFMラジオ
- ArduinoとTEA5767で作る高性能FMラジオ受信機
- ArduinoとGoogleスプレッドシート連携 リアルタイムRFID勤怠管理システム
- Arduino用絶縁アナログ入力回路の設計:LM331 V-F変換+フォトカプラでノイズ耐性を確保
- C言語の入出力マスター:標準関数とファイル操作