PR
キーワードサーチ
コメント新着
先日の回路図に続いて、制御マイコンのソフトを。
PICのCコンパイラ「CCS」を持っていますので
それにそった表記となっています。
【概要】
●光電管2個を接続できる回路ですが、
今回は1個でよかったので1個を使用するソフトです。
●液晶表示部へのコマンドなどの部分は へたに記載するとややこしいので、説明文にしています。
【ソース】
#include <16F628A.h>
#fuses NOWDT, HS, PUT, NOPROTECT, BROWNOUT, NOMCLR, NOLVP, NOCPD
#use delay(clock=20000000)
#use rs232(baud=9600, parity=N, xmit=PIN_B2, rcv=PIN_B1, bits=8)
#define SENSE_LED_ON output_high( PIN_B6 )#define SENSE_LED_OFF output_low( PIN_B6 )
#define POWER_LED_ON output_high( PIN_B7 )
#define SENSE_01_LV_OUT output_high( PIN_A0 )#define SENSE_02_LV_OUT output_high( PIN_A1 )
#define GET_SENSE_01 input( PIN_A2 )
#define GET_SENSE_02 input( PIN_A3 )
#define SENSE_01_ON 0x01 // センサー1がON#define SENSE_02_ON 0x01 // センサー2がON
#define MSEC_CNT 0xE795 // 10msecタイマー用設定値
BYTE mode; // モード
#define PASS_MAX 2
BYTE pass_cnt; // 通過カウンタ(連続して通過した回数)
unsigned long cnt_up1; // 計測カウンタ
#define VOID_MAX 100unsigned long void_cnt; // 通過後の無効期間カウンタ
BYTE time_str[21]; // 表示用文字列
/*
10ミリ秒タイマー割込み処理
*/
#int_timer1
void timer1_isr( void )
{
switch ( mode ) {
case 0: // スタート待ち
if ( GET_SENSE_01 == SENSE_01_ON ) {
mode = 1;
pass_cnt = 1; // 一回通過したと判定させる
}
break;
case 1: // スタート通過中
if ( GET_SENSE_01 == SENSE_01_ON ) {
pass_cnt++;
if ( pass_cnt >= PASS_MAX ) {
mode = 2;
cnt_up1 = PASS_MAX; // 計測カウンタにスタート通過分の時間をセット
SENSE_LED_ON;
}
} else {
// 通過カウント中に「非通過」になった
mode = 1;
}
break;
case 2: // 反応無効期間
cnt_up1++; // 計測カウンタUP
void_cnt++; // センサー無効期間カウンタUP
if ( void_cnt > VOID_MAX ) {
mode = 3;
void_cnt = 0;
}
break;
case 3: // ゴール待ち
cnt_up1++; // 計測カウンタUP
if ( GET_SENSE_01 == SENSE_01_ON ) {
mode = 4;
pass_cnt = 1; // 1回通過したと判定させる
}
break;
case 4: // ゴール通過中
if ( GET_SENSE_01 == SENSE_01_ON ) {
pass_cnt++;
if ( pass_cnt >= PASS_MAX ) {
mode = 5;
cnt_up1 += PASS_MAX; // 計測カウンタにゴール通過分の時間を加算
}
} else {
// 通過カウント中に「非通過」になった
mode = 4;
}
break;
case 5: // 結果表示中
// メインループで処理
break;
case 6: // 再スタート待ち期間
void_cnt++;
if ( void_cnt > VOID_MAX ) {
pass_cnt = 0;
void_cnt = 0;
cnt_up1 = 0;
mode = 0;
// SENSE_LED_OFF;
}
break;
}
set_timer1( MSEC_CNT ); // 10msタイマー値の再セット
}
void main( void )
{
BYTE msec;
BYTE sec;
BYTE min;
BYTE i;
// ポートの設定
/*
0 = Output
1 = Input
*/
set_tris_a( 0b00101100 );
set_tris_b( 0b00000011 );
// 電圧安定ウェイト
delay_ms( 1000 );
delay_ms( 1000 );
// PowerLED ON POWER_LED_ON;
// センサーLED OFF SENSE_LED_OFF;
SENSE_01_LV_OUT; SENSE_02_LV_OUT;
// 広域変数の初期化
pass_cnt = 0;
mode = 0;
void_cnt = 0;
cnt_up1 = 0;
// for Timer1 SetUp
// (1 / 20MHz) x 4 = 0.2us
// 1:8 = 1.6us
// 1.6us x 6250 = 10.000ms = int_timer1
// Start 65535 - 6250 = 0xE795
set_timer1( MSEC_CNT );
setup_timer_1( T1_INTERNAL|T1_DIV_BY_8 );
// for Int Enable
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
// LCDの表示を初期化 【液晶をクリアします】
for ( ;; ) {
switch ( mode ) {
case 2: // 計測中
break;
case 5:
SENSE_LED_OFF; // 反応LED OFF
// ミリ秒の値を分と秒に変換
// カウンタ値をテキストに分:秒:ミリ秒に変換する。
// 100で割った余りが1秒以下の値 // その値を60で割った余りが秒
// その値を60で割った商が分
msec = cnt_up1 % 100;
sec = (cnt_up1 / 100) % 60;
min = (cnt_up1 / 100) / 60;
time_str[9] = 0x00; // NULL
time_str[8] = 0x30 + (msec % 10);
time_str[7] = 0x30 + (msec / 10);
time_str[6] = ':';
time_str[5] = 0x30 + (sec % 10);
time_str[4] = 0x30 + (sec / 10);
time_str[3] = ':';
time_str[2] = 0x30 + (min % 10);
time_str[1] = 0x30 + (min / 10);
【ここでシリアル出力する】
// 全部終了で再スタート待ち
mode = 6;
break;
}
}
}
【解説】全体的な考えとして、モードで処理を小分けしています。
そして小分けした処理を10ミリ秒のタイマー割込みで個別処理しています。
通過後のセンサー無効期間を1秒設けています。
センサーの誤動作防止として3回連続反応で通過とみなしています。
まあ、こんなところでしょうか。あくまで参考資料程度に。
【10/10 追記】
え~と、mode変数の定義を割り込み内でダイレクト値にしていますが、
ほんとうならば#defineでわかりやすくするのが正解です。
たいして無いから直値でいいやーと、やってしまいました・・・・
オートクラッチとレフトブレーキ 2013年08月21日
ガレージにいろいろと 2013年06月08日
わらび餅たべてきた。 2013年04月20日