カモメのはばたきを パルスモータとH8/36078で
                         制御しました


 田宮製の「はばたきカモメ工作セット」のカモメを パルスモータとH8/36078で制御しました。
 オリジナルは、電池でモータを回してカモメをはばたせていたので「ギーコ・ギーコ」と単純にはばたいていましたが、パルスモータとH8/36078での制御で羽ばたく速度が変えられる様になりました。

●パルスモータ駆動のカモメのはばたき

 パルスモータ駆動ではばたいているカモメです。 はねが上下にはばたいています。
 
 後ろの左の基板は、H8/36078Lを搭載したマイコン基板で3.3Vで動いています。
 後ろの右の基板は、パルスモータ駆動回路を搭載した基板で、ロジックは3.3V、モータ駆動電圧は12Vを可変3端子レギュレータで10V程度に落として使用しています。
 手前は「はばたきカモメ工作セット」から取り外したカモメとパルスモータです。




 パルスモータとカモメの支柱です。パルスモータで直接駆動しています。



 

●カモメ駆動の波形

 パルスモータ駆動回路の入力波形です。
 シンクロスコープが2チャンネルしかないので、Φ1〜Φ4の内Φ1とΦ2を見ました。




 パルスモータ駆動回路の入出力波形です。
 上が入力波形、下が出力波形です。




●パルスモータ駆動方式のカモメはばたき制御の仕組み

 次に様に、H8内蔵のタイマB1で100uS周期の信号を作成します。そして、この100uS周期に同期して、PM制御と、スイッチのチャタリング除去をしてスイッチの入力をします。





●回路構成
 マイコン基板とモータ駆動基板の回路図です。 
 マイコン基板は、10MHzの内部発信器と内蔵タイマを使ったので外付け部品は操作用とインタフェース用だけでシンプルです。
 




パルスモータ駆動基板も、N-Ch FET NDS9936と電源回路でこれもシンプルです。






●プログラム
 HEW4で作成したプルグラムリストを示します。割込は使わず、Main関数に全てを入れました。
 コメントは、修正していない部分も有ります。

 Main関数の流れは、
  ・タイマの初期設定
  ・ポートの初期設定
  ・while(1){内で、タイマB1の100uS周期に同期して、PM制御と、スイッチのチャタリング除去をしてスイッチの入力します。
  ・100uS毎のタイマをカウントして、PM駆動相変更をします。

  ・100uS毎のタイマをカウントして、20mS毎にスイッチスキャンして、スイッチ押下が有ればPM駆動相変更時間を変更します。



/***********************************************************************/

#include "iodefine.h"

void main(void)
{
volatile unsigned int i,t20mS,tPm,tPmMax;
volatile unsigned char InSwitchData, InSwitch0, InSwitch1, InSwitch2;
volatile unsigned char MotorRotateVal;

//**********  パルスモータ制御
#define PmDir_1 (unsigned char)0x04 // Φ1 パルスモータ制御
#define PmDir_2 (unsigned char)0x10 // Φ2 パルスモータ制御
#define PmDir_3 (unsigned char)0x20 // Φ3 パルスモータ制御
#define PmDir_4 (unsigned char)0x40 // Φ4 パルスモータ制御


//ウオッチドックタイマー停止
WDT.TCSRWD.BYTE = (unsigned char)0x5E; /* TCSRWD ウオッチドックタイマー停止 */
i = 0x82; /* ダミー*/
WDT.TCSRWD.BYTE = (unsigned char)0x80; /* TCSRWD ウオッチドックタイマー停止 */

//10MHzの内部Oscをポートに出力
CKCSR.BYTE = 0x82; /* CKCSR 内部Oscをポートに出力 */

//スイッチスキャン周期をタイマB1に設定 100uS
TB1.TMB1.BYTE = (unsigned char)0x86; // TMB1 オートリロード、クロック:Φ/4=2.5MHz 設定
TB1.TLB1 = (unsigned char)0x06; // TLB1 オートリロード値、256-250=6 設定

//モータ回転制御
IO.PDR7.BYTE = PmDir_1;
IO.PCR7 = 0xFF; /* PCR7 出力ポート*/

//スイッチ入力ポート制御
AD.ADCSR.BYTE = (unsigned char)0x05;

t20mS = 0; //20mSタイマカウンタをクリア
tPm = 0; //PMサイクルタイマカウンタをクリア
tPmMax = 500; //PMサイクル値を設定 100uS単位

while(1){

// 100uS毎のタイマB1はONか?
if(IRR2.BIT.IRRTB1){ //タイマB1はオーバーフローしたか??
IRR2.BIT.IRRTB1 = 0; //タイマB1フラグをリセット
t20mS++; //20mSタイマカウンタを+1
tPm++; //PMサイクルタイマカウンタを+1

// PM駆動相変更タイムか?
if(tPm > tPmMax){ //PMサイクルタイマカウンタはオーバーフローしたか??
tPm = 0; //PMサイクルタイマカウンタをクリア
MotorRotateVal = IO.PDR7.BYTE & 0x74;
if(MotorRotateVal == PmDir_1) //PM駆動相はΦ1 か??
IO.PDR7.BYTE = PmDir_2;
else if(MotorRotateVal == PmDir_2) //PM駆動相はΦ2 か??
IO.PDR7.BYTE = PmDir_3;
else if(MotorRotateVal == PmDir_3) //PM駆動相はΦ3 か??
IO.PDR7.BYTE = PmDir_4;
else //PM駆動相はΦ4 か??
IO.PDR7.BYTE = PmDir_1;
}


// スイッチスキャンタイムか(20mS)?
if(t20mS > 200){ //スイッチスキャンタイムか(20mS)?
t20mS = 0; //スイッチスキャンタイムカウンタをクリア


IO.PDR2.BYTE = IO.PDR2.BYTE ^ 0x01; //LED表示反転

// スイッチ入力してチャタフリー
InSwitch2 = InSwitch1; //スイッチデータシフト
InSwitch1 = InSwitch0; //スイッチデータシフト
InSwitch0 = ~IO.PDRB.BYTE; //スイッチデータ入力

InSwitchData = ~InSwitch2;
InSwitchData = InSwitchData & InSwitch1;
InSwitchData = InSwitchData & InSwitch0;

// モータ回転数増加指令か?
if(InSwitchData & 0x01){
if(tPmMax >= 1200){
tPmMax = 1200;
} //END of if(MotorRotateVal >= 115){
else{
tPmMax = tPmMax + 10; // TCORB PWMのパルス巾設定
} //END of else{
} //END of if(InSwitchData & 0x01){

// モータ回転数減少指令か?
if(InSwitchData & 0x02){
if(tPmMax <= 10){
tPmMax = 10;
TV.TCORB = MotorRotateVal;
} //END of if(MotorRotateVal <= 10){
else{
tPmMax = tPmMax - 10; // TCORB PWMのパルス巾設定
} //END of else{
} //END of if(InSwitchData & 0x02){

} //END of if(IRR2.BIT.IRRTB1){

} // スイッチスキャンタイムか(20mS)?

} //END of while(1){

}


ホームへ戻る