羽ばたきラジコンの翼をコントロールするサーボを改良しました。
PIC12F1822マイコンの機能の一つ、コンペア機能を使うことで、ハードウェア上でワンショットパルスを生成することが出来ます。
さらに、コンペアマッチによるパルス出力は、マイコンのCCP1機能があるRA2、RA5に限られます。
私の羽ばたきラジコンは2つのサーボを制御出来ればよいので、ソフトウェア上でコンペア機能をRA2ピンとRA5ピンをタイミング良く切り替えることが出来れば良いわけです。
しかし、なぜかピンの切り替えがうまくいかず、ソフトウェアでON、OFF出力を切り替えてごまかしていました。
今までのように、ソフトウェアでピン出力の切り替えを行うと、実行処理のタイミングなどで切り替えタイミングがずれてしまい、正確なPWM出力が出せません。
正確なPWMではない訳ですから、サーボが誤作動し、ジッターと呼ばれる現象を引き起こしてしまいます。
今回はCCP1ピンをうまく切り替えることが出来、ジッターをなくすことに成功しました。
CCP1ピンの切り替え
CCP1ピンの切り替え自体は、APFCONレジスタで出力先をRA2かRA5に選択できるようになっています。
具体的に私の開発環境であるCCS-Cコンパイラで表記すると、
setup_ccp1(CCP1_A2);
でRA2ピンをCCP出力ピンにすることが出来、
setup_ccp1(CCP1_A5);
にすると、RA5ピンをCCP出力ピンに変更できます。
ところが、単独でのピン変更は確認できましたが、プログラムの実行中にピンの変更をしても、ダイレクトに設定変更できません。
そこで、コンペアマッチを使った簡単なプログラムを作り不具合の特定を行いました。
プログラムの内容は、
RA2ピンON → 1秒 → RA2ピンOFF → 2秒 → RA5ピンON → 1秒 → RA5ピンOFF → 2秒 →
を繰り返します。
コンペアマッチは「RA2ピンON → 1秒 → 」のところで使います。
「2秒」はdelay関数で時間稼ぎして生成しています。本来ピンのONと同時にdelay関数を呼び出しているので、プログラム上では「3秒」の時間稼ぎをしています。
下記のプログラムはRA2とRA5の切り替えに不具合があるプログラムです。
/*****************************************************/
#include
#fuses NOWDT, INTRC_IO , PUT, NOMCLR, NOBROWNOUT, NOLVP, NOCPD, NOPROTECT, NOIESO, NOCLKOUT, NOFCMEN, NOWRT, NOLVP
#use delay(clock=1000000)
/********************************
* メイン関数
********************************/
void main()
{
setup_oscillator(OSC_1MHZ); //内部発振 1MHzに設定
set_tris_a(0x00); //全ピン出力設定
//タイマ1設定
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
//無限ループ処理
while(1)
{
setup_ccp1(CCP_OFF); //CCP一旦停止
setup_ccp1(CCP_COMPARE_CLR_ON_MATCH | CCP1_A2); //CCPコンペアマッチ A2ピン出力設定
CCP_1 = 30000; //CCPコンペア値(約1秒)セット
set_timer1(0); //タイマ1ゼロセット(カウント開始)
delay_ms(3000); //ディレイ3秒開始
setup_ccp1(CCP_OFF);
setup_ccp1(CCP_COMPARE_CLR_ON_MATCH | CCP1_A5);
CCP_1 = 30000;
set_timer1(0);
delay_ms(3000);
}
}
RA2とRA5ピンにLEDをつなげて動作確認してみると・・・・・
動作確認
http://youtu.be/lHr4qMi9kW4
なんとも不思議な動きを見せます。
良く点滅の仕方を見ると、どうやらソフトウェア上でピンの切り替えをしてもピン出力をONにするフラグが残っていて、それが不具合の原因ではないかと思われます。
割り込み関連のフラグなど、可能性のあるものを一つ一つ確認していくと、ピンの出力設定がONになっていることが原因であると分かりました。
そこで、CCP1の設定の際に、出力しないピンをOFFに設定してみるとやっと不具合が解決しました。
以下サンプルプログラムと動作確認の動画になります。
/*****************************************************/
#include
#fuses NOWDT, INTRC_IO , PUT, NOMCLR, NOBROWNOUT, NOLVP, NOCPD, NOPROTECT, NOIESO, NOCLKOUT, NOFCMEN, NOWRT, NOLVP
#use delay(clock=1000000)
/********************************
* メイン関数
********************************/
void main()
{
setup_oscillator(OSC_1MHZ); //内部発振 1MHzに設定
set_tris_a(0x00); //全ピン出力設定
//タイマ1設定
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
//無限ループ処理
while(1)
{
output_low(PIN_A5); //A5ピン出力OFF
setup_ccp1(CCP_OFF); //CCP一旦停止
setup_ccp1(CCP_COMPARE_CLR_ON_MATCH | CCP1_A2); //CCPコンペアマッチ A2ピン出力設定
CCP_1 = 30000; //CCPコンペア値(約1秒)セット
set_timer1(0); //タイマ1ゼロセット(カウント開始)
delay_ms(3000); //ディレイ3秒開始
output_low(PIN_A2); //A2ピン出力OFF
setup_ccp1(CCP_OFF);
setup_ccp1(CCP_COMPARE_CLR_ON_MATCH | CCP1_A5);
CCP_1 = 30000;
set_timer1(0);
delay_ms(3000);
}
}
動作確認
http://youtu.be/fKugc2G3EcI
LEDの点滅も正常に動いています。
このサンプルをもとに、羽ばたきモーション用のミキシング回路のプログラムを作成し、ジッターフリーのサーボコントロールを実現しています。
コメント