工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

PWMを読み取り、RCレシーバー入力をデコードし、フェイルセーフを適用します

コンポーネントと消耗品

>
Arduino UNO
× 1
SG90マイクロサーボモーター
× 2

このプロジェクトについて

このプロジェクトには、Arduino入力ピンでRCレシーバー(またはその他のPWM信号)を読み取るだけでなく、トランスミッター信号が失われた場合にフェイルセーフを適用するために使用できる、一般的で効率的なコードが含まれています。

以下は、このページの下部にあるコードPWMread_RCfailsafe.inoを使用してサーボミキサーとして機能するArduinounoを示すビデオです。

PWMread_RCfailsafe.inoの関数は、割り込みレジスタを管理し、異なるピンを使用する異なるプロジェクト間で簡単に移動できるので便利です。

以下のビデオの例:

  • フェイルセーフは、受信機に送信機からの信号がない場合にアクティブになります。エレベーターチャンネルはフルに設定され、エルロンチャンネルはニュートラルに設定されています
  • 青いサーボの方向はスロットル位置によって設定されます
  • 青いサーボの移動範囲(速度)は、送信機の側面にあるスライダーで設定します
  • 送信機のギアスイッチを使用してミキシングをオン/オフにします

コンテンツ

  • PWMによるサーボの制御方法
  • RCモデル/ロボットでのArduinoの使用例
  • コードの概要:フェイルセーフを使用してRCレシーバーからPWMをデコードします
  • PWMread_RCfailsafe.inoの使用方法
  • 受信機のフレームレートと周波数を表示する
  • サーボミキシングの例
  • 採用されたアプローチの根拠
  • 制限

サーボとスピードコントローラーはPWMによってどのように制御されますか?

このプロジェクトの残りの部分では、サーボと速度コントローラーの制御に使用されるPWM信号を理解していることを前提としています。これは、これらのパルス幅変調(PWM)信号がどのように機能するかを説明する優れたビデオです。

また、次の実用的な知識も必要です。

  • Arduino IDE
  • float、boolean、およびint変数
  • ループの場合
  • Forループ
  • 配列
  • サーボライブラリ

RCモデル/ロボットでのArduinoの使用例

あなたはあなたの想像力によってのみ制限されます:

  • サーボミキシングの適用、ライトのオン/オフの切り替え、ポンプ/バルブの制御、オーダーメイドのシーケンスの設定...
  • コントローラーを作成します(つまり、飛行安定化/自動操縦、機首方位保持、高度/深度保持、自動レベラー、感知して回避、帰宅...)
  • 信号の喪失やバッテリー電圧の低下にRCモデルを対応させます...
  • 設定を変更したり、モデルメモリ機能を使用したりすることなく、複数のモデル/プロジェクトに同じ送信機を使用できます。

コードの概要:フェイルセーフを使用してRCレシーバーからPWMをデコードする

このコードは、ピン変更割り込みを使用してPWM(パルス幅変調)信号を測定します。使用される機能は、Arduino Uno、Nano、またはPro Miniで、割り込みの設定とデジタルまたはアナログピン(A6およびA7を除く)からのデータの抽出を自動化します。これにより、初心者でもコードを使いやすくなります。

このプロジェクトの主な目的は、プロジェクト間ですばやく移動できるフェイルセーフ「モジュール」を備えた汎用RCレシーバーを作成することでした。そのため、「使用方法」セクションに示されているサンプルコードは、目的を達成するための手段として使用できます。

注: このコードは、ソフトウェアシリアルまたはピン変更割り込みを使用するその他のライブラリでは機能しません。

コードがどのように機能するかに興味がある人のために:

  • 入力ピンは配列で識別されます。この配列は任意の長さにすることができます。
  • セットアップ機能は、ピンアレイにリストされている各ピンに適切なレジスタを設定することにより、ピン変更割り込みを有効にします。
  • 選択したピンのいずれかで電圧が変化すると、ピンがISR(PCINT0_vect)->ポートB、ISR(PCINT1_vect)->ポートCまたはISR(PCINT2_vect)->ポートD。
  • 各ISR内で、FORループとIFステートメントを使用して、変更されたピンと、それが属するRCチャネルを判別します。割り込みの時間は、メインループ()に戻る前にmicros()を使用して記録されます。
  • ピン交換間の時間間隔は、パルス幅と繰り返し周期の計算に使用されます。
  • 新しいパルスがいつ受信されたかを示すために、各ISRにフラグが設定されます
  • フラグは、ISRによって収集されたデータを抽出して処理するために、残りの関数によって使用されます

次のYouTube動画作成者 Joop Brokking は、RCレシーバーをarduinoに接続するために同じ方法を使用する別のプロジェクトについて話します。最初の8分間で、Joopはハウツーを明確に説明します ピン変更割り込みを使用して、RCレシーバーからのPWM信号を測定します。

この詳細はすべて、このページの下部にダウンロードできるPWMread_RCfailsafe.inoによって管理されています。

ポート操作に関するいくつかの有用な情報もここにあります: https://tronixstuff.com/2011/10/22/tutorial-arduino-port-manipulation/

ピンチェンジ割り込み処理に加えて、専用関数RC_decode()が書き込まれ、パルス幅(1000-2000uS)をトランスミッタからの+ -100%制御信号に変換します。フェイルセーフは、10〜330Hzおよび500〜2500uSの信号許容誤差を使用して有効な送信機信号をチェックします。信号が失われた場合、RC_decode()は事前に決定されたフェイルセーフ値を返します。

特定の送信機の校正値とフェイルセーフ位置は、 PWMread_RCfailsafe.ino のチャネルごとに設定できます。

PWMread_RCfailsafe.inoの使用方法

ステップ1: ハードウェア セットアップ あり Arduino 宇野

Arduino Unoを使用したセットアップ例に従う場合は、レシーバーを次のように接続します(それ以外の場合は、独自のプロジェクトを使用している場合は、ステップ2に直接ジャンプします)

  • 5vピンとGNDピンを使用してレシーバーに電力を供給します
  • メスからオスのジャンパー線を使用して、レシーバーからの信号ピンをArduinoのピン2〜7に接続します。 (2チャンネルレシーバーを使用している場合は、ピン2と3のみに接続します)
  • サーボミキサーの例では、一方のサーボ信号線をピン9に接続し、もう一方をピン10に接続します。
<図>

ステップ2:PWMread_RCfailsafe.inoをスケッチフォルダーにコピーします

スケッチRC_Read_Exampleの例は、ページの下部にダウンロード用に含まれています。以下の手順に従うときに、これをメインスケッチとして使用できます。

PWMread_RCfailsafe.inoファイルをコピーして、メインスケッチを含むフォルダーに貼り付けます。次にIDEでスケッチを開くと、PWMread_RCfailsafe.ino内のコードを含む2番目のタブが表示されます。

<図>

ステップ3:指定 入力 ピン

ArduinoIDEでメインスケッチを開くか、再度開きます。

PWMread_RCfailsafeタブをクリックし、「USER DEFINED VARIABLES」タイトルまでスクロールダウンして、配列pwmPIN []に入力ピンを入力します。

注: 任意の数のピンを任意の順序で使用できます。入力が多いほど、コードが割り込みルーチンのアドレス指定に費やす時間が長くなることに注意してください。注A6およびA7はアナログ専用ピンであり、使用できません。

Arduino MEGAは現在サポートされていませんが、食欲があれば簡単に修正できます。

注: pwmPIN []の最初の要素はチャネル1、2番目の要素はチャネル2などです。受信者からのすべてのチャネルを使用する場合は、受信者のチャネル1がチャネルに対応していることを確認することをお勧めします。 1 in pwmPIN [] ...

<図>

ステップ4: レビュー 利用可能 機能 PWMread_RCfailsafe.ino

<図>

ステップ5: 印刷 パルス データ から シリアル

RC_Read_Exampleコードをアップロードし、送信機の電源を入れて、生のパルス幅データをシリアルに印刷します。

RC_avail()関数を使用して、すべてのチャネルで新しいデータが受信されたことを確認してから、print_RCpwm()を使用してパルス幅データをシリアルに送信する必要があります。

<図>

ステップ6: 送信機を調整する

print_RCpwm()を介してシリアルに出力されたパルス幅データを使用して、配列RC_min []、RC_mid []、およびRC_max []の値を手動で変更し、各チャネルを+ -100%の範囲に調整します。

<図>

ステップ7:キャリブレーションされたチャネルを印刷します から シリアル

print_RCpwm()関数をコメントアウトする

RC_decode(channel)関数を使用して、各チャネルを+ -1の範囲に調整します。

次に、decimal2percentage()関数に続いてSerial.println( "")

を使用して、キャリブレーションされた各チャネルをシリアルに出力します。 <図>

ステップ8: フェイルセーフを設定する

各チャネルのRC_failsafe []アレイのフェイルセーフ位置を調整します(+ -1の範囲)。

送信機のオンとオフを切り替えて、フェイルセーフが希望どおりに動作することを確認します。

これで、RC入力をスケッチで使用できるようになりました。

注: 受信機のフェイルセーフ機能を無効にする必要がある場合があります。そうしないと、arduinoは送信機信号の損失に応答できなくなります。

<図>

受信機のフレームレートと周波数を表示する

受信機のパルス繰り返し周期と周波数をシリアルに印刷できます。 PWM_period()およびPWM_freq()を使用して印刷用のデータを抽出する前に、関数PWM_read(channel number)を使用して、選択したチャネルで新しいデータが使用可能であることを確認してください。サンプルコードはRC_FrameRate.inoで入手できます。

これは各レシーバーフレームで送信される最初のパルスになるため、最初のチャネルを使用することをお勧めします。 PWM_read()はRC_decode(CH)と同じフラグを使用するため、PWM_read()が最初に呼び出されることを確認してください。

以下のスクリーンショットを参照してください:

<図>

レシーバー期間は、次のデータセットが到着するまでのコードの時間を示すため、知っておくと便利です。 RC_avail()が所定の時間(21ms)後に新しいRCデータを検出しない場合は、RC_decode()を実行して、フェイルセーフをトリガーするか、プログラム(PIDコントローラーの場合もあります)を一定の頻度で実行し続けます。

これは、RC_Read_Example.inoで次のifステートメントによって実現されます。

  now =millis(); if(RC_avail()|| now --rc_update> 21)rc_update =now; // RC_decode()を使用してRC入力データを更新します// PIDコントローラーを実行します//サーボミキシングを適用します//サーボを配置します}  

サーボミキシングの例

2つのレシーバーチャネル(この場合はチャネル2と3、エレベータとエルロン)を混合する方法を示すために、RC_ServoMixer_Example.inoを含めました。スケッチには、サーボの方向、速度、およびサブトリムを設定する方法も示されています。サーボライブラリは、ピン9と10を介してサーボを制御するために使用されます。

以下は、コードのサーボミキシングセクションのスクリーンショットです。

<図>

ミックスは、2つのチャネルを加算および減算し、出力を-1から+1の範囲に制限するだけで実現されます。エレベーターとエルロンのミキシングを適用する場合、サーボごとに1つずつ2つの出力を作成します。

mix1 =チャネル2-チャネル3(elv-ail)

mix2 =チャネル2+チャネル3(elv-ail)

サーボを配置する前に、+ -100%(+ -1)信号をサーボのマイクロ秒単位の同等のパルス幅に変換する必要があります。 RC_ServoMixer_Example.inoでは、関数calc_uS()を使用してこれを行います。この関数はスケッチの下部に配置され、下のスクリーンショットに示されています。

<図>

各サーボに指定された方向、レート、およびサブトリムは、サーボの適切なパルス幅を計算するために使用されます。

標準のニュートラルパルスは1500uSで、ニュートラルの両側の通常の範囲は+ -500uSです。これにより、最小パルス幅は1000uS(-100%)、最大パルス幅は2000uS(+ 100%)になります。したがって、レート、方向、およびサブトリムが適用されたパルスは、次のように計算できます。

パルス、uS =1500 +(servo_position _%*レート*方向+サブトリム)* 500

サーボの方向、速度、サブトリムは、静的にすることも、別のレシーバーチャネルからの入力に応じてスケッチによって動的に変更することもできます。

採用されたアプローチの理論的根拠

pulseIn(PIN、HIGH)関数を使用してRCレシーバーを読み取ることは可能ですが、pulseIn()は、パルスの開始と終了を待機している間、loop()のコードをブロックし、貴重な処理時間を浪費します。複数の入力データがある場合も失われる可能性があります。

速度を上げるには、Arduinoのピン変更割り込み機能と直接ポート操作を使用して、loop()内のコードを最小限の遅延で実行できるようにするのが最適です。ただし、これは単にpulseIn(PIN、HIGH)を呼び出すよりも複雑で時間がかかります。

したがって、プロジェクト間を移動できる一般的なコードを記述して、両方の長所を活用したいと思いました。必要なのは、.inoファイル(関数と割り込みルーチンを含む)をコピーしてメインのスケッチフォルダーに貼り付け、入力ピンを指定してから、スケッチで関数を使用することだけです。

制限事項

micros()関数

arduinoのマイクロ秒タイミングはmicros()関数を使用して実行されます。この関数は4uSステップでカウントされます。これは、1000〜2000uSのパルスを測定するときに4マイクロ秒の精度があることを意味します。実用的な観点からは、これで十分です。

必要に応じて、タイマー割り込みを使用して、この分解能を0.5uSに向上させることができます。以下のリンクを参照してください:

https://www.instructables.com/id/How-to-get-an-Arduino-micros-function-with-05us-pr/

PWMread_RCfailsafe.inoの効率

PWMread_RCfailsafe.inoを使用して6または9チャネルレシーバーを読み取る場合、処理時間の1.4〜2.0%がピン変更割り込みルーチンの実行に費やされますが、これは許容範囲を超えています。

ただし、コードの制限と、必要に応じてコードを高速化する方法を理解することは常に良いことです。

以下は、選択した入力チャネルの数に応じて、各ISRの実行にかかる時間のリストです。

1チャンネル<8uS

2チャンネル<12uS

3チャンネル<16uS

4チャンネル<20uS

5チャンネル<20uS

6チャンネル<24uS

注: 使用するチャネルが多いほど、各ISRの実行にかかる時間が長くなります。これは、ISRが呼び出されるたびにforループが各チャネルを通過するためです。

低周波数(つまり50Hz)のRC信号を測定する場合、この余分な時間(非効率)はごくわずかです。

上記に加えて、ISRに出入りするのに約4uSかかります。 1つのパルスに対して、ISRは2回実行されます。1回はパルスの開始時(LOWからHIGH)で、もう1回は終了時(HIGHからLOW)です。

6つのRC入力を使用する場合に1つのパルスを測定するのにかかる時間は

です。

2 *(ISRを入力するための4us + ISRを実行するための24uS)=2 * 28 =48uS。

注: これは測定可能な最小パルス幅です。

6つのチャネルすべてを読み取るのにかかる時間は288uS(6 * 48uS)です

受信機の繰り返し周期が20ミリ秒であると仮定すると、割り込みは時間の1.44%(0.000288 / 0.02)の間実行されます。これは、pulseIn()関数を使用するよりもはるかに優れています。 pulseIn()は、ピンごとに最大20ミリ秒の間コードをブロックします。

FYI: arduinoにRC入力が2つしかない場合、ISRは0.16%の時間(0.000032 / 0.02)で実行されます

最大実用頻度 Hz)

このコードを他の目的で使用する場合は、実用的な最大周波数を2.5kHzにすることをお勧めします。これにより、micros()関数から100ステップの分解能が得られます(+ -0.025kHz)。

この周波数で1つの入力ピンを使用する場合、時間の3%が割り込みに費やされます。これは、測定可能な最小デューティが0.03であることを意味します。これは、12uSの最小パルスに相当します。

より高い周波数の場合は、アプリケーションに合わせてISRを書き直してください。

コード

  • PWMread_RCfailsafe
  • RC_Read_Example
  • RC_FrameRate
  • RC_ServoMixer_Example
PWMread_RCfailsafe Arduino
この.inoファイルには、RCレシーバーをデコードし、トランスミッター信号が失われた場合にフェイルセーフを適用するために使用される関数とピン変更割り込みルーチン(ISR)が含まれています。このファイルをコピーしてメインスケッチと同じフォルダーに貼り付けます(スケッチを開くと、このコードはarduino IDEの2番目のタブとして表示されます)。次に、ファイルの指示に従います。
 / * Kelvin Nelson 24/07/2019 * *フェイルセーフを使用したRCレシーバーのパルス幅変調(PWM)デコード* *このコードには、任意の方形波信号を測定するための使いやすい関数が含まれています。 arduiuno pro mini、nanoまたはunoピン(A6およびA7を除く)。 *このコードは、RC受信機で使用することを目的としていますが、pulseIn(PIN、HIGH)の直接の代替として、他のほとんどのPWM測定アプリケーションでも使用できます。 *(これまで、1khzを超える周波数またはarduinoメガでテストされていません)* * RC信号パルスは、各入力ピンのパルス幅持続時間(1000-2000uS)から-+ 100に変換できます。スケッチで使用するための%(-+ 1.0)出力。 *この変換のキャリブレーションとフェイルセーフ設定は、チャネルごとに設定できます。 (フェイルセーフ公差10-330Hzおよび500-2500uS)。 * *各ピンの生データ、つまりパルスの時間、パルス幅、フレーム長、デューティ、周波数も抽出できます。 * *セットアップは迅速で、このファイルの構成は次のとおりです。* *-コードの概要*-関数のリスト*-スケッチ例を含む使用方法*-ユーザー定義変数->入力ピン、トランスミッターの指定キャリブレーション、およびフェイルセーフ。 *-グローバル変数と関数**コードの概要:* *コードは、適切なレジスタを設定することにより、選択したピンのピン変更割り込みを有効にします。 * *選択したピンのいずれかで電圧が変化すると、そのピンが属するレジスタに応じて、3つの割り込みサービスルーチンのいずれかがトリガーされます。 * --ISR(PCINT0_vect)、ISR(PCINT1_vect)、またはISR(PCINT2_vect)* *各ISR内で、コードはどのピンが変更されたかを判別し、メインループ()に戻るまでの時間を記録します。 * *ピン交換間の時間間隔は、パルス幅とフレーム長を計算するために使用されます。 * *フラグは、新しいパルスがいつ受信されたかを示すためにISRによって設定されます。 * *フラグは、各ISRによって収集されたデータを抽出して処理するために使用されます。 * *まったく同じではありませんが、このコードは、このビデオで説明されているものと同様の原則に従います。https://youtu.be/bENjl1KQbvo * * ///機能のリスト://出力タイプ機能の名前注記// void setup_pwmRead()は、ピン変更割り込みを使用してPWM測定を初期化します// RC RECEIVER DECODING // boolean RC_avail()は、新しいRCデータが利用可能になるとHIGHを返します// float RC_decode(channel number)は、選択したRCチャネルを+ -100の範囲にデコードします// void print_RCpwm()RCチャネルの生データをシリアルポート(キャリブレーションに使用)に出力します。//GENERICPWMMEASUREMENTS // boolean PWM_read(channel number)は、新しいパルスが発生するとHIGHを返します。特定のチャネルで検出されました。 //この関数は、パルスデータを割り込みルーチンの外部の変数に保存します//残りのPWM関数を使用する直前に呼び出す必要があります。//unsignedlongPWM_time()は、パルスの開始時の時間を返します// float PWM()パルス幅を返します// floatPWM_period()はパルス間の時間を返します// float PWM_freq()は周波数を計算します// float PWM_duty()はデューティを計算します//注:PWM_read(CH)とRC_decode(CH)は同じフラグを使用します新しいデータがいつ利用可能になるかを検出します。つまり、両方が同じチャネルで同時に使用されるとデータが失われる可能性があります。//提案:PWM_read(CH)を使用してRCチャネルのフレームレートを検索する場合は、それを呼び出します。 RC_decode(CH)の前。 RC_decode(CH)からの出力は、デフォルトでフェイルセーフになります。//使用方法(スケッチの例を含む)//以下のコードの「USERDEFINED VARIABLES」タイトルの下:////ステップ1:入力ピンをに入力します配列pwmPIN [] ={}。 ////-任意の数のピンをpwmPIN []に入力できます(0〜13およびA0〜A5で使用可能なピン)//-ピンは番号順にする必要はありません。たとえば、pwmPIN [] ={A0、 5チャネルの場合は5,6,10,8}、2チャネルの場合はpwmPIN [] ={A0,5} //-配列の最初の要素は「チャネル1」のピン番号で、2番目の要素はピンです。 「チャネル2」の番号...など//-RCレシーバーに接続されているすべてのピンは、アレイの先頭にある必要があります。つまり、最初の2つのチャネルはRC入力であり、3番目のチャネルは超音波センサーのエコーピンなどの別のデバイスに接続できます。////ステップ2:RC受信機がすべての入力に接続されている場合は、RC_inputsを次のように設定します。 0、受信機に接続されているチャネル数を指定しない場合、つまりRC_inputs =2; ////ステップ3:スケッチフォルダに含まれているこの.inoファイルを使用して簡単なスケッチをアップロードして送信機を調整し、生のPWM値を印刷しますシリアルに(または、必要な機能をコピーしてスケッチに貼り付けます)//シリアルモニターからの情報を使用して、送信機に合わせて配列RC_min []、RC_mid []、RC_max []の値を手動で更新します(フルレートを使用して最高の解像度を取得します)。 // RCチャネルPWMデータをシリアルに印刷するためのスケッチ例。 / * void setup(){setup_pwmRead(); Serial.begin(9600); } void loop(){if(RC_avail())print_RCpwm(); } * ///ステップ4:-1.0〜 + 1.0の範囲で各チャネルのフェイルセーフ位置を選択し、それを配列に入力しますRC_failsafe [] ={} //注:arduinoに応答させたい場合送信機信号が失われると、受信機のフェイルセーフ機能を無効にする必要がある場合があります(フェイルセーフ機能がある場合)。//フェイルセーフの動作を確認し、キャリブレーションされたチャネルをシリアルに印刷するためのスケッチ例:/ * unsigned long now; //一定の間隔でデータを更新するタイミング変数unsignedlong rc_update; constintチャネル=6; //レシーバーチャネルの数を指定しますfloatRC_in [channels]; //レシーバーからのキャリブレーションされた入力を格納する配列voidsetup(){setup_pwmRead(); Serial.begin(9600); } void loop(){now =millis(); if(RC_avail()|| now --rc_update> 25){// RCデータが利用可能であるか、最後の更新から25msが経過した場合(レシーバーのフレームレートに合わせて調整)rc_update =now; // print_RCpwm(); //受信者からシリアルに生データを出力するためのコメントを解除しますfor(int i =0; i  =0 &&pwmPIN [i] <=7)pwmPIN_port [i] =2; //ピンはPCINT2_vect(PORT D)に属しますelse if(pwmPIN [i]> =8 &&pwmPIN [i] <=13)pwmPIN_port [i] =0; //ピンはPCINT0_vect(PORT B)に属します//ピン番号(つまり、ピン11またはピンA0)をポートレジスタのピン位置に変換します。マクロを使用してこれを行うより良い方法がある可能性があります... //(ポートレジスタからピンの状態を直接読み取ると、ISRのコードが高速化されます)if(pwmPIN [i] ==0 || pwmPIN [i ] ==A0 || pwmPIN [i] ==8)pwmPIN_reg [i] =0b00000001; else if(pwmPIN [i] ==1 || pwmPIN [i] ==A1 || pwmPIN [i] ==9)pwmPIN_reg [i] =0b00000010; else if(pwmPIN [i] ==2 || pwmPIN [i] ==A2 || pwmPIN [i] ==10)pwmPIN_reg [i] =0b00000100; else if(pwmPIN [i] ==3 || pwmPIN [i] ==A3 || pwmPIN [i] ==11)pwmPIN_reg [i] =0b00001000; else if(pwmPIN [i] ==4 || pwmPIN [i] ==A4 || pwmPIN [i] ==12)pwmPIN_reg [i] =0b00010000; else if(pwmPIN [i] ==5 || pwmPIN [i] ==A5 || pwmPIN [i] ==13)pwmPIN_reg [i] =0b00100000; else if(pwmPIN [i] ==6)pwmPIN_reg [i] =0b01000000; else if(pwmPIN [i] ==7)pwmPIN_reg [i] =0b10000000; }}// SETUP OF PIN CHANGE INTERRUPTSvoid setup_pwmRead(){ for(int i =0; i  num_ch) RC_inputs =num_ch; // define the number of pins connected to an RC receiver. } // INTERRUPT SERVICE ROUTINES (ISR) USED TO READ PWM INPUT// the PCINT0_vect (B port register) reacts to any changes on pins D8-13.// the PCINT1_vect (C port register) "" "" A0-A5.// the PCINT2_vect (D port register) "" "" D0-7.// port registers are used to speed up if statements in ISR code:// https://www.arduino.cc/en/Reference/PortManipulation http://tronixstuff.com/2011/10/22/tutorial-arduino-port-manipulation/// http://harperjiangnew.blogspot.co.uk/2013/05/arduino-port-manipulation-on-mega-2560.html// READ INTERRUPTS ON PINS D8-D13:ISR routine detects which pin has changed, and returns PWM pulse width, and pulse repetition period.ISR(PCINT0_vect){ // this function will run if a pin change is detected on portB pciTime =micros(); // Record the time of the PIN change in microseconds for (int i =0; i  RC_inputs) return 0; // if channel number is out of bounds return zero. int i =CH - 1; // determine the pulse width calibration for the RC channel. The default is 1000, 1500 and 2000us. int Min; if(CH <=size_RC_min) Min =RC_min[CH-1]; else Min =1000; int Mid; if(CH <=size_RC_mid) Mid =RC_mid[CH-1]; else Mid =1500; int Max; if(CH <=size_RC_max) Max =RC_max[CH-1]; else Max =2000; float CH_output; if(FAILSAFE(CH) ==HIGH){ // If the RC channel is outside of failsafe tolerances (10-330hz and 500-2500uS) if(CH> size_RC_failsafe) CH_output =0; // and if no failsafe position has been defined, set output to neutral else CH_output =RC_failsafe[i]; // or if defined set the failsafe position } else{ // If the RC signal is valid CH_output =calibrate(PW[i],Min,Mid,Max); // calibrate the pulse width to the range -1 to 1. } return CH_output; // The signal is mapped from a pulsewidth into the range of -1 to +1, using the user defined calibrate() function in this code. // 0 represents neutral or center stick on the transmitter // 1 is full displacement of a control input is one direction (i.e full left rudder) // -1 is full displacement of the control input in the other direction (i.e. full right rudder)}/* * Receiver Calibration */ // NEED TO SPEED UPfloat calibrate(float Rx, int Min, int Mid, int Max){ float calibrated; if (Rx>=Mid) { calibrated =map(Rx, Mid, Max, 0, 1000); // map from 0% to 100% in one direction } else if (Rx ==0) { calibrated =0; // neutral } else { calibrated =map(Rx, Min, Mid, -1000, 0); // map from 0% to -100% in the other direction } return calibrated * 0.001;}// Basic Receiver FAIL SAFE// check for 500-2500us and 10-330Hz (same limits as pololu)boolean FAILSAFE(int CH){ int i =CH-1; boolean failsafe_flag =LOW; if(pwmFlag[i] ==1) // if a new pulse has been measured. { pwmFlag[i] =0; // set flag to zero if(pwmPeriod[i]> 100000) // if time between pulses indicates a pulse rate of less than 10Hz { failsafe_flag =HIGH; } else if(pwmPeriod[i] <3000) // or if time between pulses indicates a pulse rate greater than 330Hz { failsafe_flag =HIGH; } if(PW[i] <500 || PW[i]> 2500) // if pulswidth is outside of the range 500-2500ms { failsafe_flag =HIGH; } } else if (micros() - pwmTimer[i]> 100000) // if there is no new pulswidth measurement within 100ms (10hz) { failsafe_flag =HIGH; } return failsafe_flag; }/* * Quick print function of Rx channel input */void print_RCpwm(){ // display the raw RC Channel PWM Inputs for (int i =0; i =0) Serial.print(" "); if (abs(pc) <100) Serial.print(" "); if (abs(pc) <10) Serial.print(" "); Serial.print(" ");Serial.print(pc);Serial.print("% ");}/* * GENERIC PWM FUNCTIONS */unsigned long pin_time;float pin_pwm;float pin_period;boolean PWM_read(int CH){ if(CH <1 &&CH> num_ch) return false; int i =CH-1; boolean avail =pwmFlag[i]; if (avail ==HIGH){ pwmFlag[i] =LOW; noInterrupts(); pin_time =pwmTimer[i]; pin_pwm =PW[i]; pin_period =pwmPeriod[i];割り込み(); } return avail;}unsigned long PWM_time(){return pin_time;}float PWM_period(){return pin_period;}float PWM(){return pin_pwm;}float PWM_freq(){ float freq; return freq =1000000 / pin_period; // frequency Hz}float PWM_duty(){ float duty; duty =pin_pwm/pin_period; return duty;}
RC_Read_ExampleArduino
An example sketch used to display raw data in order to calibrate your RC receiver and set your the fail safe. The PWMread_RCfailsafe.ino file should be copied into the same folder in order for the functions to be available.
unsigned long now; // timing variables to update data at a regular interval unsigned long rc_update;const int channels =6; // specify the number of receiver channelsfloat RC_in[channels]; // an array to store the calibrated input from receiver void setup() { setup_pwmRead(); Serial.begin(9600);}void loop() { now =millis(); if(RC_avail() || now - rc_update> 25){ // if RC data is available or 25ms has passed since last update (adjust to be equal or greater than the frame rate of receiver) rc_update =now; print_RCpwm(); // uncommment to print raw data from receiver to serial for (int i =0; i 
RC_FrameRateArduino
Example sketch that prints the frame rate and frequency of an RC Receiver. The PWMread_RCfailsafe.ino file should be copied into the same folder in order for the functions to be available.
void setup() { setup_pwmRead(); Serial.begin(9600);}void loop() { // Print RC receiver frame length and frame rate if (PWM_read(1)){ // if a new pulse is detected on channel 1 Serial.print(PWM_period(),0);Serial.print("uS "); Serial.print(PWM_freq());Serial.println("Hz"); }} 
RC_ServoMixer_ExampleArduino
An servo mixing example. Two channels from a 6 channel are receiver are mixed and sent to two servos controlled using the servo library. The PWMread_RCfailsafe.ino file should be copied into the same folder in order for the functions to be available.
// servo variables#include  // include the servo library to control the servosServo servo1; // name each servo output for use with the servo library Servo servo2; // Each servo must be attached to a pin that has a PWM output// on the arduino uno, nano and pro mini these pins are 3, 5, 6, 9, 10 and 11const int servo1_pin =9; // identify the pins that each servo signal wire is connected toconst int servo2_pin =10;// Select Servo Direction, Rates and Sub-trim (the size of each array must match the number of servos)boolean servo_dir[] ={0,1}; // Direction:0 is normal, 1 is reversefloat servo_rates[] ={1,0.5}; // Rates:range 0 to 2 (1 =+-500us (NORMAL), 2 =+-1000us (MAX)):The amount of servo deflection in both directionsfloat servo_subtrim[] ={0.0,0.0}; // Subtrimrange -1 to +1 (-1 =1000us, 0 =1500us, 1 =2000us):The neutral position of the servoboolean servo_mix_on =true;unsigned long now; // timing variables to update data at a regular interval unsigned long rc_update;// Receiver variablesconst int channels =6; // specify the number of receiver channelsfloat RC_in[channels]; // an array to store the calibrated input from receiver void setup() { servo1.attach(servo1_pin, 500, 2500); // attach the servo library to each servo pin, and define min and max uS values servo2.attach(servo2_pin, 500, 2500); setup_pwmRead(); Serial.begin(9600);}void loop() { now =millis(); if(RC_avail() || now - rc_update> 25){ // if RC data is available or 25ms has passed since last update (adjust to> frame rate of receiver) rc_update =now; print_RCpwm(); // uncommment to print raw data from receiver to serial for (int i =0; i 1) mix1 =1; // limit mixer output to +-1 else if(mix1 <-1) mix1 =-1; if(mix2> 1) mix2 =1; // limit mixer output to +-1 else if(mix2 <-1) mix2 =-1; // Calculate the pulse widths for the servos servo1_uS =calc_uS(mix1, 1); // apply the servo rates, direction and sub_trim for servo 1, and convert to a RC pulsewidth (microseconds, uS) servo2_uS =calc_uS(mix2, 2); // apply the servo rates, direction and sub_trim for servo 2, and convert to a RC pulsewidth (microseconds, uS) } else{ // MIXING OFF servo1_uS =calc_uS(RC_in[1],1); // apply the servo rates, direction and sub_trim for servo 1, and convert to a RC pulsewidth (microseconds, uS) servo2_uS =calc_uS(RC_in[2],2); // apply the servo rates, direction and sub_trim for servo 1, and convert to a RC pulsewidth (microseconds, uS) } servo1.writeMicroseconds(servo1_uS); // write the pulsewidth to the servo. servo2.writeMicroseconds(servo2_uS); // write the pulsewidth to the servo. }}int calc_uS(float cmd, int servo){ // cmd =commanded position +-100% // servo =servo num (to apply correct direction, rates and trim) int i =servo-1; float dir; if(servo_dir[i] ==0) dir =-1; else dir =1; // set the direction of servo travel cmd =1500 + (cmd*servo_rates[i]*dir + servo_subtrim[i])*500; // apply servo rates and sub trim, then convert to a uS value if(cmd> 2500) cmd =2500; // limit pulsewidth to the range 500 to 2500us else if(cmd <500) cmd =500; return cmd;}

回路図

This RC Receiver is powered by 5v and ground from the ICSP pins with the 6 signal outputs connected to pins 2-7
Micro servo 1 is powered by 5v pin and ground, with signal wire connected to pin 9
Micro servo 2 powered by 3.3v pin and ground, with signal wired connected to pin 10

製造プロセス

  1. C - 入力と出力
  2. LCDアニメーションとゲーム
  3. Arduinoとスマートフォンを使用したDIY電圧計
  4. 温度および湿度データロガー
  5. DHT11でBlynkの温度と湿度を読み取る方法
  6. Python3とArduinoコミュニケーション
  7. ArduinoおよびOLEDベースのセルオートマトン
  8. ArduinoとRDA8057Mを使用したFMラジオ
  9. Arduino TEA5767FMラジオ受信機
  10. ArduinoとGoogleスプレッドシートに基づく出席システム
  11. Arduino用の絶縁アナログ入力