今回はタイマーの動作仕様を変更してみます。
目次
変更後の動作仕様のイメージ
前回、タイマーとしての基本的な機能は実装しましたので、今回は機能を追加したいと思います。
レトルトカレーをお湯で温める場合を想定します。例えば加熱時間が3分の場合、温め終わるちょっと前にご飯を用意しておきたいこともあります。
例えば次のようなイメージです。
レトルトカレーを温め始めたときにタイマーを開始しします。
タイマーを開始してから2分30秒経過すると短い時間ブザーがちょっと鳴って、ご飯を準備する合図にします。
タイマー開始3分後、アラーム音が鳴ってレトルトカレーが温め終わる、という感じです。
動作仕様
タイマーの時間や、途中でアラームを鳴らす時間はご自分の用途に合わせてみてください。
特に用途がない場合、次のような機能を追加してみてください。
3分タイマーで、残り30秒になったら一度ブザーを短い時間鳴らして、
そのあと点滅パターンを変える。3分経過したら、アラーム音を鳴らす。
処理の流れとしては、
- 2分30秒、今まで通りのプログラムで時間を計測
- ブザーを短い時間鳴らす
- 残りの時間は点滅パターンを変えて時間を計測
- ブザーを鳴らす
という感じです。
解答例
具体的な動作仕様は次のようにしてみました。
- 2分30秒、今まで通りのプログラムで時間を計測
➡︎ あとで点滅パターンを変えたいので、この期間は2秒に1回LEDを点滅することにします。 - ブザーを短い時間鳴らす
➡︎ 300msだけブザーを鳴らします。 - 残りの時間は点滅パターンを変えて時間を計測
➡︎ 残りの時間は1秒に1回点滅することにします。 - ブザーを鳴らす
➡︎ 「ピピピッ」と3回アラーム音を鳴らします。
実装方法はいろいろあると思いますが、次のようにプログラムを作成してみました。
- タイマー時間は変更しやすいように、トータル時間と残り時間を
#define
で定義してみました - 2秒に1回の点滅は、タイマーのカウントが偶数の時だけLEDを点滅する、という処理にしてみました。偶数の判定は
timer%2 == 0
というように2で割った余りが0かどうかでif
文で判定しています。 - 途中でアラーム音を短時間鳴らしますが、この部分のLEDを点滅して時間計測するため、LEDの消灯時間を調整しています。例えばアラーム音を300ms鳴らす場合、LEDの制御は「650ms消灯、50ms点灯」というベタな実装にしています。
(本来の消灯時間950ms)−(アラーム音の300ms)=650ms
このような実装で次のようにプログラムを作成してみました。
/*
* PICマイコン電子工作入門 基礎編 第29回
* チャレンジ課題 解答例
*/
#include <xc.h>
// タイマー時間設定
#define TIMER_TOTAL 180 // トータルのタイマー時間 (秒)
#define TIMER_REMAIN 30 // 動作を変える残りの時間 (秒)
#define ALARM_NOTIFY 300 // 途中のアラーム音の長さ (単位はミリ秒で950ms未満にする)
// PIC12F1822 Configuration Bit Settings
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF // Internal/External Switchover (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF // PLL Enable (4x PLL disabled)
#pragma config STVREN = OFF // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
// クロック周波数指定
// __delay_ms()関数が使用する
#define _XTAL_FREQ 1000000
void main(void) {
// PICマイコン設定
OSCCON = 0b01011000; // 内部クロック周波数を1MHzに設定
ANSELA = 0b00000000; // すべてのピンをデジタルモードに設定
TRISA = 0b00001000; // すべてのピンを出力モードに設定(ただしRA3ピンは常に入力モード)
// ブザーをOFF、LEDをONにする
LATA4 = 0; // ブザー
LATA5 = 1; // LED
// スイッチが押されるまで待つ
while( RA3 ) {
}
// 最初は2秒に1回LEDを点滅する
// 変数timerが偶数の時のみLEDを点滅する
for(uint16_t timer=0; timer<(TIMER_TOTAL - TIMER_REMAIN); timer++) {
if(timer%2 == 0) {
// timerが偶数のときはLEDを点滅して1秒計測
LATA5 = 0;
__delay_ms(950);
LATA5 = 1;
__delay_ms(50);
LATA5 = 0;
} else {
// timerが奇数のときは何もしないで1秒計測
__delay_ms(1000);
}
}
// 途中で一度ブザーを鳴らす
LATA4 = 1;
__delay_ms(ALARM_NOTIFY);
LATA4 = 0;
// アラーム音の時間分、差し引いてLEDを点滅して時間計測
__delay_ms(950 - ALARM_NOTIFY);
LATA5 = 1;
__delay_ms(50);
// 残り時間は1秒に1回LEDを点滅
// ブザーを鳴らすために1回点滅したので、残り時間はマイナス1秒にする
for(uint16_t timer=0; timer<(TIMER_REMAIN - 1); timer++) {
LATA5 = 0;
__delay_ms(950);
LATA5 = 1;
__delay_ms(50);
}
// アラーム音を3回鳴らす
for(uint8_t i=0; i<3; i++) {
// ピッ
LATA4 = 1;
__delay_ms(70);
LATA4 = 0;
__delay_ms(70);
// ピッ
LATA4 = 1;
__delay_ms(70);
LATA4 = 0;
__delay_ms(70);
// ピーッ
LATA4 = 1;
__delay_ms(70);
LATA4 = 0;
// 1回分の音パターンの間を少し空ける
__delay_ms(800);
}
// 動作を止める
while(1) {
}
// 以下の命令は実行されない
return;
}
更新履歴
日付 | 内容 |
---|---|
2016.12.5 | 新規投稿 |