羽ばたき飛行機の滑空制御装置GPAT10製作編

Sponsored link


羽ばたき飛行機の滑空制御装置GPAT10設計編の続きになります。

制御装置の仕様が固まったので実際にコードを書いてみる事にしました。

基本は、16ビットタイマで受信機から出るPWMをキャプチャ、すぐに同じ16 ビットタイマでPWMを出力するループを作ります。
PWM入出力の合間に入力信号から条件分岐をし、制御する事にします。

以上の様にコードを書くと、結構問題が出てきました。16ビットをフル活用したタイマ測定が出来ないのです。
仕方なく、10ビットタイマに分解能を落としてコードを書きました。
10ビットタイマを4MHzで駆動させるようにしたので、周期は2.5msちょっとになります。
ラジコンのPWMのON時間は最大でも2.2ms程度なのでぎりぎり対応出来ます。
20msの周期は受信機のPWMをキャプチャしたらすぐに波形出力をするため、時間の制御は必要ありません。
下にβ版のソースコードを載せておきます。
※素人が作ったプログラムなので、改善する点があれば教えていただければ幸いです。

/*
 * ATtiny10_program.c
 *
 * Created: 2012/10/02
 * Author: hiro
 */ 

#ifndef F_CPU
#define F_CPU 4000000UL
#endif

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define LED PB0
#define DELAY 100

#define PLS_UP		1
#define PLS_DOWN	0

uint8_t pls_state;//パルスキャプチャフラグ
uint8_t oneshotP;//ワンショットパルス生成フラグ
uint16_t b=0 ;//受信機パルス格納変数
uint16_t count = 0x03ff;//受信機パルス計算結果格納変数


uint8_t i;//初期化実行変数
uint16_t motor_OFF = 0;//モーターOFFパルス格納変数
uint16_t motor_ON = 0;//モーターONパルス格納変数

uint16_t power_select = 0;//モーターON or OFF 条件分岐変数
//power_select == 0 通常駆動
//power_select == 1 モータースロー駆動
//power_select == 2 モーター停止


uint8_t glide_mode;//滑空モードフラグ
uint8_t cycle = 0;//PWMサイクルカウント格納
uint8_t hall_cont = 0;//磁気センサーカウントフラグ

/******************************************/
/*タイマ0オーバーフロー割り込み
/******************************************/
ISR(TIM0_OVF_vect)
{
   
   if(oneshotP == 1){
	   switch(power_select)
	   {
			case 0:	OCR0A = count;	//出力パルス入力
					oneshotP = 0;	//ワンショットフラグOFF
					cycle ++;
					break;
	
			case 1:	OCR0A = motor_ON;
					oneshotP = 0;
					cycle ++;
					break;
			case 2:	OCR0A = motor_OFF;
					oneshotP = 0;
					cycle ++;
					break;
	   }
   }else{
	   OCR0A = 0x03ff;	//パルスOFF
	   oneshotP = 0;
   }
}



/******************************************/
/*タイマ0 インプットキャプチャ割り込み
/******************************************/
ISR(TIM0_CAPT_vect)
{
	if(pls_state == PLS_UP){
		TCNT0 = 0x0000;	//カウントアップ初期化
		pls_state = PLS_DOWN;//フラグ変更
		TCCR0B = 0x0A;//(00001010) 下降エッジキャプチャ設定
	}else{
	
	pls_state = PLS_UP;//フラグ変更
		TCNT0 = 0x03FF;	//カウントアップ初期化
		b=ICR0;
		count = 0x03ff - b;
		TCCR0B = 0x4A;//(01001010) 上昇エッジキャプチャ設定
		oneshotP = 1;//ワンショットフラグON
	}
}



/******************************************/
/*入力変化割り込み(ホールセンサー)bit_is_clear()
/******************************************/
ISR(PCINT0_vect)
{
	if (bit_is_clear(PINB,PINB2)){
		if ( power_select ==1 ){
			if (hall_cont==0){
				hall_cont = 1;
			}else{
				hall_cont = 0;
				power_select = 2;
				OCR0A = motor_OFF;
				//oneshotP = 0;
			}
		}
	}
}



/******************************************/
/*メインプログラム
/******************************************/
int main(void)
{
	//発振器の選択
	CCP = 0xD8;
	CLKMSR = 0;//発振器の選択
	CCP = 0xD8;
	CLKPSR = 1;//発振器のプリスケーラ2(4MHz)
	

	//ポート入出力設定
	DDRB = 0x09;
	
	//タイマー設定
	TCCR0A = 0xC3;//(11000011)
	TCCR0B = 0x4A;//(01001010)
	TCCR0C = 0x00;

	
	OCR0A = 0x03ff;	//カウンター比較値
	TCNT0 = 0x0000;	//カウントアップ初期化
	
	
	//割り込み設定
	TIMSK0 = 0x21;
	pls_state = PLS_UP;	//キャプチャーフラグセット
	oneshotP = 0;//ワンショットフラグOFF
	
	
	PCICR = 0x01;
	PCMSK = 0x04;
	
	
	sei();
	

	//初期化プログラム///////////////////////////////////////////////////////
	if(motor_OFF == 0){//モーターOFFパルス公正
		i=0;
		while (i < 10){//電源挿入後、約1秒間の安定パルス確認
			if ( (motor_OFF < (count + 5)) && (motor_OFF > (count - 5)) && (count !=  0x03ff) && (count >  0x0000)){
			
				i++;
				_delay_ms(DELAY);
			}else{
				motor_OFF = count;
				i=0;
			}
		}
	}
	
		
		
		
	if (motor_ON == 0){
		i = 0;
		while (i < 10){//モーターONパルス設定
			if ( (motor_ON < (count+5)) && (motor_ON > (count-5)) && ( (motor_ON < (motor_OFF-10)) || (motor_ON > (motor_OFF+10))) ){
				i++;
			
	_delay_ms(DELAY);
			}else{
				motor_ON = count;
				i=0;
			}
		}
	}
	
	if (motor_ON > motor_OFF){//受信機タイプ選択
		i=0;
	}else{
		i=1;
	}
	//初期化プログラム終了///////////////////////////////////////////////////////
		
	
	
	
	while(1){
		if ( ((count < (motor_ON + 5)) && ( count > (motor_OFF - 5) ) && (i==0) ) || ((count > (motor_ON - 5)) && (count < (motor_OFF + 5)) && (i==1)) ){
			glide_mode = 1;//滑空モード
		
	
			if ( ((count < (motor_OFF + 5)) && (i==0)) || ((count > (motor_OFF - 5)) && (i==1)) ){
			   cli();
			   power_select = 2;//パワー OFF
			   sei();
			}else{
				if (power_select == 0){
					cycle = 0;//サイクルカウント開始
					cli();
					power_select = 1;//パワー Low
					sei();
				}
		}
							   
		if (cycle > 200){//ワンサイクル20msとした場合、約4秒
			   cli();
			   power_select = 2;//パワー OFF
			   sei();
		   }
		}else{
			glide_mode = 0;//羽ばたきモード
			cli();
			power_select = 0;//通常モード
			sei();
		}
	}
}

Sponsored link

製作編

まず、表面実装品にプログラムを書き込む為に、アダプターを作ります。
NCフライスを導入してからはこの様な工作がずっと楽になりました。基盤の配線の間隔は0.5mm。

↓この様にマイコンをセットし、アダプターにビス止めして使います。

秋月電子の実装品と比較

このアダプターを使ってプログラムを書き込み、基盤に実装します。
↓1.6mm厚のベーク基盤を使いました。こちらの配線の間隔は0.2mmです。
部品(基盤以外は全て秋月電子で購入出来るもので作りました。)
・ATtiny10マイコン
・10kΩ抵抗2個
・表面実装用ショットキーバリアダイオード 【SS2040FL】
↑このセンサーはラッチ回路になっていますので、磁石は2つ必要です。
・100μFセラミックコンデンサ

ここまで小さくなるとハンダ付けも大変です。
ニッパーでハンダ線を小さく切って使います。

写真の赤丸の部分に切ったはんだを乗せ、ハンダ付けします。
基盤の間隔が0.2mmなので切ったハンダの大きさが分かるかと思います。ちなみにこれでも大きい方です。

ハンダ付けするとこうなります。

完成品はこちら

コネクターも合わせた質量は1.84g
センサーと一体になっているのでこれだけ軽量に作る事が出来ました。

動作確認してみました。

関連記事

One Response to 羽ばたき飛行機の滑空制御装置GPAT10製作編

  1. tt on 2014年3月8日 at 20:59

    おっさんだと思ってたのに、指がキレーじゃねえかwww

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です