- PWM信号とは何ですか?
- GPIOピンでPWMを生成するようにPICをプログラミングする
- 回路図
- シミュレーション
- PICマイクロコントローラーを使用してサーボモーターを制御するためのハードウェアセットアップ
PWM信号の生成は、すべての組み込みエンジニアの武器に不可欠なツールです。サーボモーターの位置の制御、コンバーター/インバーターの少数のパワーエレクトロニクスICの切り替え、単純なLED輝度制御など、多くのアプリケーションに非常に便利です。PICマイクロコントローラーでは、必要なレジスターを設定することにより、 比較、キャプチャー、およびPWM (CCP)モジュールを使用してPWM信号を生成できます。これは、PICPWMチュートリアルですでに学習しています。しかし、その方法には1つの大きな欠点があります。
PIC16F877Aは、我々はCCPモジュールを使用する場合、唯一のピンRC1とRC2にPWM信号を生成することができます。ただし、PWM機能を使用するためにより多くのピンが必要になる状況が発生する可能性があります。たとえば私の場合、CCPモジュールが絶望的なロボットアームプロジェクト用に6つのRCサーボモーターを制御したいと思います。これらのシナリオでは、タイマーモジュールを使用してPWM信号を生成するようにGPIOピンをプログラムできます。このようにして、必要なピンでできるだけ多くのPWM信号を生成できます。マルチプレクサICの使用のような他のハードウェアハックもありますが、プログラミングで同じことが達成できるのに、なぜハードウェアに投資するのですか。したがって、このチュートリアルでは、PIC GPIOピンをPWMピンに変換する方法を学習し、それをテストするために、デジタルオシロスコープを使用してプロテウスでシミュレーションします。PWM信号を使用してサーボモーターの位置を制御し、ポテンショメーターを変更してデューティサイクルを変更します。
PWM信号とは何ですか?
詳細に入る前に、PWM信号とは何かについて少しブラッシュアップしましょう。パルス幅変調(PWM)は、制御回路で最も一般的に使用されるデジタル信号です。この信号は、事前定義された時間と速度でハイ(5v)とロー(0v)に設定されます。信号がハイのまま である時間 は 「オン時間」 と呼ばれ、信号がローのままである 時間 は 「オフ時間」 と呼ばれ ます。 以下で説明するように、PWMには2つの重要なパラメータがあります。
PWMのデューティサイクル
PWM信号がHIGH(オンタイム)のままである時間のパーセンテージは、デューティサイクルと呼ばれます。信号が常にオンの場合は100%のデューティサイクルであり、常にオフの場合は0%のデューティサイクルです。
デューティサイクル=ターンオン時間/(ターンオン時間+ターンオフ時間)
変数名 |
参照 |
PWM_Frequency |
PWM信号の周波数 |
T_TOTAL |
PWMの完全な1サイクルにかかる合計時間 |
トン |
PWM信号の時間 |
T_OFF |
PWM信号のオフ時間 |
Duty_cycle |
PWM信号のデューティサイクル |
それでは、数学をやってみましょう。
これは、周波数が単に時間の逆数である標準的な式です。頻度の値は、ユーザーのアプリケーション要件に基づいてユーザーが決定および設定する必要があります。
T_TOTAL =(1 / PWM_Frequency)
ユーザーがデューティサイクル値を変更すると、プログラムはそれに応じてT_ON時間とT_OFF時間を自動的に調整する必要があります。したがって、上記の式を使用して、Duty_CycleとT_TOTALの値に基づいてT_ONを計算できます。
T_ON =(Duty_Cycle * T_TOTAL)/ 100
1サイクル全体のPWM信号の合計時間は、オン時間とオフ時間の合計になるためです。上記のようにオフ時間T_OFFを計算できます。
T_OFF = T_TOTAL – T_ON
これらの公式を念頭に置いて、PICマイクロコントローラーのプログラミングを開始できます。このプログラムには、PICタイマーモジュールとPIC ADCモジュールが含まれ、POTからのADC値に応じて変化するデューティサイクルに基づいてPWM信号を作成します。これらのモジュールを初めて使用する場合は、ハイパーリンクをクリックして適切なチュートリアルを読むことを強くお勧めします。
GPIOピンでPWMを生成するようにPICをプログラミングする
このチュートリアルの完全なプログラムは、いつものようにWebサイトの下部にあります。このセクションでは、プログラムが実際にどのように記述されているかを理解しましょう。すべてのプログラムと同様に、構成ビットを設定することから始めます。メモリビューオプションを使用して設定しました。
// CONFIG #pragma config FOSC = HS //オシレータ選択ビット(HSオシレータ) #pragma config WDTE = OFF //ウォッチドッグタイマーイネーブルビット(WDT無効) #pragma config PWRTE = OFF //パワーアップタイマーイネーブルビット(PWRT無効) #pragma config BOREN = ON //ブラウンアウトリセットイネーブルビット(BOR有効) #pragma config LVP = OFF //低電圧(シングルサプライ)インサーキットシリアルプログラミングイネーブルビット(RB3はデジタルI / O 、MCLRのHVをプログラミングに使用する必要があります) #pragma config CPD = OFF //データEEPROMメモリコード保護ビット(データEEPROMコード保護オフ) #pragma config WRT = OFF //フラッシュプログラムメモリ書き込みイネーブルビット(書き込み保護オフ;すべてのプログラムメモリはEECON制御によって書き込むことができます) #pragma config CP = OFF //フラッシュプログラムメモリコード保護ビット(コード保護オフ) // #pragmaconfigステートメントはプロジェクトファイルのインクルードの前に置く必要があります。 // ONとOFFに#defineの代わりにプロジェクト列挙型を使用します。 #include
次に、ハードウェアで使用されるクロック周波数について説明します。ここでは、私のハードウェアは20MHzの水晶を使用しています。ハードウェアに基づいて、値を入力できます。続いて、PWM信号の周波数値が続きます。ここでの私の目的は50HzのPWM周波数を必要とする趣味のRCサーボモーターを制御することなので、周波数値として0.05KHzを設定しました。これは、アプリケーションの要件に基づいて変更することもできます。
#define _XTAL_FREQ 20000000 #define PWM_Frequency 0.05 // KHz(50Hz)
これで、Frequencyの値が得られたので、上記の式を使用してT_TOTALを計算できます。結果を10で割り、ミリ秒単位の時間の値を取得します。私の場合、T_TOTALの値は2ミリ秒になります。
int T_TOTAL =(1 / PWM_Frequency)/ 10; //周波数から合計時間を計算します(ミリ秒単位))// 2ミリ秒
続いて、ADC PICチュートリアルで説明したように、ポテンショメータの位置を読み取るためにADCモジュールを初期化します。次に、毎回呼び出される割り込みサービスルーチンがあります。タイマーがオーバーフローし、後でこれに戻ります。ここでは、メイン関数を確認しましょう。
main関数内で、タイマーモジュールを構成します。ここでは、0.1ミリ秒ごとにオーバーフローするようにタイマーモジュールを構成しました。時間の値は、以下の式を使用して計算できます。
RegValue = 256-((Delay * Fosc)/(Prescalar * 4))遅延(秒)およびFosc(hz)
私の場合、プリスケーラーが64、Foscが20MHzで0.0001秒(0.1ms)の遅延の場合、レジスター(TMR0)の値は248になります。したがって、構成は次のようになります。
/ *****タイマーのポート構成****** / OPTION_REG = 0b00000101; //外部周波数と64をプリスケーラとして持つTimer0 //プルアップも有効にし ますTMR0 = 248; //0.0001秒の時間値をロードします; delayValueは、 TMR0IE = 1 のみで0〜256の範囲にすることができます。// PIE1レジスタのタイマー割り込みビットを有効にするGIE = 1; //グローバル割り込みを有効にする PEIE = 1; //ペリフェラル割り込みを有効にする / *********** ______ *********** /
次に、入力と出力の構成を設定する必要があります。ここでは、ADC値を読み取るためにAN0ピンを使用し、PWM信号を出力するためにPORTDピンを使用しています。したがって、それらを出力ピンとして開始し、以下のコード行を使用してローにします。
/ ***** I / Oのポート構成****** / TRISD = 0x00; //ポートDのすべてのピンが出力される ように MCUに指示しますPORTD = 0x00; //すべてのピンを0に初期化します/ *********** ______ *********** /
無限の while ループ内で、デューティサイクルからオンタイム(T_ON)の値を計算する必要があります。 オンタイム 及び デューティ サイクルは、我々が内部にそれを繰り返し行うようにPOTの位置に基づいて変化 しながら 次のようにループ。0.0976は、100を取得するために1024を掛ける必要がある値であり、T_ONを計算するには、ミリ秒単位で値を取得するために10を掛ける必要があります。
while(1) { POT_val =(ADC_Read(0)); // ADCを使用してPOTの値を読み取ります Duty_cycle =(POT_val * 0.0976); // 0から1024から0から100に マップT_ON =((Duty_cycle * T_TOTAL)* 10/100); //ミリ秒単位の数式単位を使用してオンタイムを計算します __delay_ms(100); }
タイマーは0.1msごとにオーバーフローするように設定されているため、タイマー割り込みサービスルーチンISRは0.1msごとに呼び出されます。サービスルーチン内では、countという変数を使用し、0.1ミリ秒ごとにインクリメントします。このようにして、f時間を追跡できます。PICマイクロコントローラの割り込みの詳細については、リンクをたどってください
if(TMR0IF == 1)//タイマーオーバーフローが原因でタイマーフラグがトリガーされました-> 0.1ミリ秒ごとにオーバーフローするように設定されています { TMR0 = 248; //タイマー値をロードし ますTMR0IF = 0; //タイマー割り込みフラグ カウントを クリアします++; //0.1msごとのカウント増分-> count / 10は、カウントの値をミリ秒単位で示します}
最後に、T_ONとT_OFFの値に基づいてGPIOピンを切り替えます。ミリ秒単位で時間を追跡する count 変数があり ます 。したがって、その変数を使用して、時間が オンタイム より短いかどうかを確認します。オンの場合はGPIOピンをオンのままにし、そうでない場合はオフにして、新しいサイクルが始まるまでオフのままにします。これは、1つのPWMサイクルの合計時間と比較することで実行できます。同じことを行うためのコードを以下に示します
if(count <=(T_ON))//時間が時間より短い場合 RD1 = 1; // GPIOをオンにし ます elseRD1 = 0; //それ以外の 場合は GPIOをオフにしますif(count> =(T_TOTAL * 10))//新しいサイクルが開始するまでオフのままにしますcount = 0;
回路図
PICマイクロコントローラーのGPIOピンでPWMを生成するための回路図は本当に簡単です。オシレーターでPICに電力を供給し、ポテンショメーターをピンAN0に接続し、サーボモーターをピンRD1に接続するだけで、GPIOピンを使用してPWM信号を取得できます。 RD1はランダムではありません。ポテンショメータとサーボモーターはどちらも、回路図に示すように7805から調整される5Vから電力を供給されます。
シミュレーション
プロジェクトをシミュレートするために、プロテウスソフトウェアを使用しました。以下に示す回路を構築し、コードをシミュレーションにリンクして実行します。プログラムに従ってRD1GPIOピンでPWM信号を取得し、電位差計の位置に基づいてPWMのデューティサイクルを制御する必要があります。以下のGIFは、ポテンショメータを介してADC値が変更されたときにPWM信号とサーボモーターがどのように応答するかを示しています。
PICマイクロコントローラーを使用してサーボモーターを制御するためのハードウェアセットアップ
私の完全なハードウェアセットアップを以下に示します。私のチュートリアルをフォローしている人にとって、このボードは見覚えがあるはずです。これは、これまでのすべてのチュートリアルで使用したものと同じボードです。私がどのようにそれを構築するかを知りたい場合は、点滅するLEDチュートリアルを参照できます。それ以外の場合は、上記の回路図に従ってください。すべて正常に動作するはずです。
プログラムをアップロードしてポテンショメータを変更すると、サーボがポテンショメータの位置に基づいて位置を変更するのがわかります。プロジェクトの完全な動作は、このページの最後にあるビデオに示されています。プロジェクトを理解し、構築を楽しんでいただければ幸いです。ご不明な点がございましたら、フォーラムに投稿してください。できる限りお答えします。
複数のサーボモーターを制御するオプションを追加して、すでに構築したArduinoロボットアームと同様に、ロボットアームを構築することで、このプロジェクトを前進させることを計画しています。それまではまた会いましょう!!