PIC(16F886)を使用してラーメンタイマーを製作します。
仕様を決定する
- 設定時間は3・4・5・9分とする(9分はパスタを茹でる時間です)
- 設定方法はselect-swを押すたびにカウントアップしていき9分からは又3分に戻る
- 3分は赤・4分は青・5分は緑・9分は黄色のLED(すべて5φ)で表示する
- start-swを押すとselectされていたLEDが点滅に変わり動作中を表示する
- 設定時間になると5秒間ブザーが鳴ると同時に赤色の終了表示用LED(3φ)が点灯し最初の時間設定に戻る
回路図の作成
PICには16F886を使用しました。特に理由はありません。手持ちの中から決めました。
ブザーには自励式の物を使用しました。
主要パーツと組立
主要パーツリスト
PIC | 16F886 | 1 |
プッシュSW | 2 | |
ブザー | 自励式 | 1 |
LED | 5φ4色 | 各1 |
SW | 電源スイッチ | 1 |
電池ボックス | 単三2本用 | 1 |
ユニバーサル基板 | 72X47 | 1 |
透明ケース | 秋月SK-16 110x80x33 | 1 |
組立にはユニバーサル基板を使用しました
プログラムの作成
プログラムにはXC8を使用しました
/*
* File: RAMENTimer2.c
* Author: 上州散歩
*
* Created on 2015/02/14, 14:06
* 2017/03/07
* 2017/03/29 9分を追加
* 2022/08/24 SWのチャタリング対応など
* タイマー割り込みの演習を基にしたラーメンタイマーの制作
* sw2(select)で3分・4分・5分・9分を選択
* SW1を押すとスタートする。LEDが点滅する
* 途中でSW1を押すと最初の時間選択に戻る
* 設定時間になると5秒間ブザーが鳴り(FinishLEDも5秒間点灯)最初の時間選択に戻る
*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
// CONFIG1
#pragma config FOSC = INTRC_NOCLKOUT// Oscillator Selection bits
//Clockは内蔵発振器:9pinはRA7:10pinはRA6
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF // RE3/MCLR pin function select bit (RE3/MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = OFF // Brown Out Reset Selection bits (BOR disabled)
#pragma config IESO = OFF // Internal External Switchover bit (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
#pragma config LVP = OFF // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming)
// CONFIG2
#pragma config BOR4V = BOR40V // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT = OFF // Flash Program Memory Self Write Enable bits (Write protection off)
/*
*
*/
#define _XTAL_FREQ 4000000 //クロックは内蔵4MHz
static unsigned char Cnt300mS; //8.192x37=303.104mS
static bit T300mS;
static unsigned char Cntsel; //セレクトカウンタ (3 or 4 or 5)
static bit Fstart; //スタートフラグ
static unsigned int Cnttime; //タイマーカウンタ 3分or4分or5分
static bit Fend;
static unsigned int i;
static unsigned int n;
void main(void) {
//初期化
ANSEL = 0x00; //すべてデジタルで使用
ANSELH = 0x00; //すべてデジタルで使用
TRISA = 0x00; //全bitを出力に設定
TRISB = 0b00000011; //RB0,RB1を入力にそれ以外を出力に指定
TRISC = 0x00; //全bitを出力に設定
PORTA = 0x00; //ポートをイニシャライズする
PORTB = 0x00; //ポートをイニシャライズする
PORTC = 0x00; //ポートをイニシャライズする
OPTION_REG = 0b00000100; //ポートBの内部プルアップをイネーブルにする
//プリスケーラを32にする
//立ち下がりでインタラプトがかかる
WPUB = 0b00000011; //ポートB0,B1の内部プルアップをイネーブルにする
//初期化終わり
kaishi:
Cnt300mS = 37; // 1/4MHz*4*32*256 = 8.192ms * 37=303.104ms
T300mS = 0;
Cntsel = 3; //セレクトカウンタ初期値は3
//sw2を押す毎に 3→4→5→9 となり次は3に戻る
Fstart = 0;
Cnttime = 600; //タイマーは最初3分に設定 3*60/0.3=600
T0IE = 0; //TMR0割り込みを禁止
INTE = 1; //INT割り込みを許可
GIE = 1; //グローバルインタラプト許可
Fend = 0;
INTF = 0;
RC2 = 0;
RC3 = 0;
i = 1000000; //他励式の場合のブザー鳴動時間
n = 10; //自励式の場合のブザー鳴動時間(約5秒)
while(Fstart == 0){ //SW1(start)が押されるまでループ
if (RB1==0) { //もしSW2が押されると
Cntsel++; //セレクトカウンタをカウントアップ
__delay_ms(300); //SW2のチャタリング対応
}
if (Cntsel >=7) { //セレクトカウンタは最大6
Cntsel = 3;
}
if (Cntsel == 3) {
RA0 = 1; //セレクトカウンタが3ならLED1を点灯
RA1 = 0;
RA2 = 0;
RA3 = 0;
Cnttime = 600;
}
if (Cntsel == 4) {
RA1 = 1; //セレクトカウンタが4ならLED2を点灯
RA0 = 0;
RA2 = 0;
RA3 = 0;
Cnttime = 800;
}
if (Cntsel == 5) {
RA2 = 1; //セレクトカウンタが5ならLED3を点灯
RA0 = 0;
RA1 = 0;
RA3 = 0;
Cnttime = 1000;
}
if (Cntsel == 6){
RA3 = 1; //セレクトカウンタが6ならLED4を点灯
RA0 = 0;
RA1 = 0;
RA2 = 0;
Cnttime = 1800;
}
}
while(Fstart == 1 && Fend == 0) {
if (T300mS){
T300mS = 0;
Cnttime--;
if (Cntsel == 3){
RA0 = ~RA0; //ビット反転(点滅させる)
}
if (Cntsel == 4){
RA1 = ~RA1;
}
if (Cntsel == 5){
RA2 = ~RA2;
}
if (Cntsel == 6){
RA3 = ~RA3;
}
}
if (Cnttime == 0){
RC3 = 1;
Fend = 1;
/*
while ( i ){ //他励式のブザー鳴動
RC2 = 1;
__delay_us(350);
RC2 = 0;
__delay_us(250);
i--;
}
*/
while (n){ //自励式のブザー鳴動
RC2 = 1;
__delay_ms(500);
n--;
}
}
}
RC2 = 0;
goto kaishi;
}
//インタラプトルーティン
//
static void interrupt intr (void) {
if (T0IF == 1){
T0IF = 0;
Cnt300mS--;
if (Cnt300mS == 0) {
Cnt300mS = 37;
T300mS = 1;
}
}
if (INTF == 1){
__delay_ms(500); //SW1のチャタリング対応
INTF = 0;
if (Fstart == 0) {
Fstart = 1;
T0IE = 1;
}
else {
Fend = 1;
}
}
}
動作確認・完成写真
最初使用したスイッチのチャタリングで誤動作が発生しましたが、チャタリング対応ディレイタイムを大きくすることで問題なく動作しました。しかしスマホが有ればラーメンタイマーなんていらないかもしれませんが、これはこれで便利に使えそうです。らーめん好きなもんで。
コメント