周囲が暗くなると、LEDが点滅する回路を、100円均一ショップで買ったプラスチックケースに入れてみた。
・PICマイコン PIC12F1822-I/P
・ICソケット 8PIN
・LED φ5mm 3個
・カーボン抵抗器 51Ω 3個、100kΩ
・フォトトランジスタ NJL7502L
・積層セラミックコンデンサ 0.1uF
・ユニバーサル基板 AE-DB1 片面ユニバーサル基板(ブレッドボード配線パターンタイプ) Dタイプ(47×36mm) ガラスコンポジット
・電池ボックス(単3形×1本用リード線付)2個
・ワイドクリアケース(2段) 直径73mmx高さ72mm
・配線材
回路図
基板部品配置パタン(例)
(XC8 ソースコード)
/* * File: led-marker-2019.c * Author: kaimu * * Created on September 22, 2019, 5:57 PM *//* * Input * RA4/AN3 (PIN2) : photo transistor, bright:0, dark:1 * Output * RA0 [PIN7] : LED0 , active Low * RA1 [PIN6] : LED1 , active Low * RA2 [PIN5] : LED2 , active Low */#include <xc.h>#include <stdint.h>////// ここから、プログラミングのためのデータや関数を定義する /////#pragma config FOSC = INTOSC // 内部クロック使用。#pragma config WDTE = OFF // ウォッチドッグタイマなし。#pragma config PWRTE = ON // 64ms後にプログラム開始。#pragma config MCLRE = OFF // 外部リセットなし。RA3は入力ピン。#pragma config CP = OFF // コード保護なし。#pragma config CPD = OFF // データ保護なし。#pragma config BOREN = ON // 電源電圧低下時のリセットあり。#pragma config CLKOUTEN = OFF // クロック出力不可。#pragma config IESO = OFF // 内部外部クロックなし。#pragma config FCMEN = OFF // FCMなし。// 動作設定その2// Configuration 2#pragma config WRT = OFF // 書き込み保護なし。#pragma config PLLEN = OFF // PLLなし。#pragma config STVREN = ON // スタックオーバー/アンダーフローでリセット。#pragma config BORV = LO // 電源電圧低下監視閾値はLowモード#pragma config LVP = OFF // 低電圧プログラムなし。// I/Oポートの定義 (LEDを接続するポートが変わった時はここを変更する)#define PORT_LED_0 RA0#define TRISA_LED_0 TRISA0#define PORT_LED_1 RA1#define TRISA_LED_1 TRISA1#define PORT_LED_2 RA2#define TRISA_LED_2 TRISA2// A/D変換用I/Oポートの設定定義#define PORT_ADC ANSA4#define TRISA_ADC TRISA4#define PORT_NO_ADC 3#define led0on() (PORT_LED_0 = 0)#define led0off() (PORT_LED_0 = 1)#define led0() (PORT_LED_0 ^= 1)#define led1on() (PORT_LED_1 = 0)#define led1off() (PORT_LED_1 = 1)#define led1() (PORT_LED_1 ^= 1)#define led2on() (PORT_LED_2 = 0)#define led2off() (PORT_LED_2 = 1)#define led2() (PORT_LED_2 ^= 1)void wait(volatile uint32_t t)// Delay{ while (t-- > 0) NOP();}void initIo(void) { //OSCCON = 0b01111010; // PLL disable, 16MHz internal clock // OSCCON = 0b01100010; // PLL disable, 8MHz internal clock OSCCON = 0b01101010; // PLL disable, 4MHz internal clock //OSCCON = 0b01011010; // PLL disable, 1MHz internal clock //OSCCON = 0b00111010; // PLL disable, 500kHz internal clock INTEDG = 0; // Interrupt on falling edge of RB0/INT pin INTE = 1; // External Interrupt Enable GIE = 1; //Interrupt Enable ANSELA = 0b00000000; //ALL digital port CM1CON0 = 0x00; //Comparator disable TRISA = 0b00001000; //I/O Direction. RA0-2,4-5 : output, RA3 : Input //OPTION_REGbits.nWPUEN = 1; //// weak pull-up disable //WPUA = 0b00000000; // weak pull-up disable OPTION_REGbits.nWPUEN = 0; //// weak pull-up enable WPUA = 0b00001000; // weak pull-up 3 enable LATA = 0b00000000; // PORTA Latch Settings}// A/D変換関数void initAdc(void) { PORT_ADC = 1; // PORT_ADCで定義されたポートをアナログポートにする。 TRISA_ADC = 1; // A/D変換端子を入力モードにする。 ADCON0 = 0b00000001 | (PORT_NO_ADC << 2); //AD変換を有効化。 ADCON1 = 0b01000000; // 0:(ADFM=0)精度10bit, 100:Fosc/4 ,0:Reserved, 00:AVDD=VREF CM1CON0 = 0x00; //コンパレータを無効化。}uint16_t getAdc(void)// A/D変換した値を得る。// 戻り値: A/D 変換されたアナログ信号の大きさ(0〜1023){ uint16_t adcvalue; //ADC wait(10); GO_nDONE = 1; while (GO_nDONE); adcvalue = ADRESH << 2 | ADRESL >> 6; return adcvalue;}int8_t isdark(void)// 光センサの出力から、「暗い」かどうか判断する。// 戻り値; 「暗い」と判断したとき -1// それ以外 0{ uint16_t photo; // 光センサの出力値 int8_t result; // 戻り値 uint16_t darkness_threshold = 900; //「暗い」と判断する閾値 photo = getAdc(); // 光センサの出力をA/D変換 if (photo > darkness_threshold) { //「暗い」とき result = -1; } else { // 「明るい」とき result = 0; } return result;}// Timer0 制御関数volatile uint32_t TimerCounter; // Counter of Timer Interrupt#define T0UNIT 15UL // TimerCounter at 1 sec.void initTimer0(void)//Initialize Timer 0// count up every 256*256us = 65536us = 65.536ms (clock 4/4=1MHz, prescaler 1:256// if you want t[s] timer, TimerCount <= t / 0.065536{ TMR0IF = 0; // interrupt flag clear TimerCounter = 0; // Timer Interrupt Counter clear //OPTION_REG = 0b01010111; // Timer0 Internal clock, Prescaler 1:256 OPTION_REG &= 0b11000000; // Masking Timer0 bits OPTION_REG |= 0b00010111; // Timer0 Internal clock, Prescaler 1:256 // Timer0 Interrupt occured every 65.536ms TMR0IE = 1; // enable Timer0 interrupt GIE = 1; // enable interrupt}void waittimeout(uint32_t timeLimit) { uint32_t timeLimitCount = timeLimit * T0UNIT; // 時間切れまでのカウント数 TimerCounter = 0; // タイマのリセット。計時開始。 timeLimitCount = T0UNIT * timeLimit; while (TimerCounter < timeLimitCount) { //制限時間になるまでの処理 }}void starttimer0() { TimerCounter = 0; // タイマのリセット。計時開始。}int8_t istimeout0(uint32_t timeLimit)//指定時間に達していなければ、0xffを返し、指定時間に達していたら0x0を返す。{ uint8_t retvalue; if (TimerCounter < T0UNIT * timeLimit) { retvalue = 0xff; } else { retvalue = 0x00; } return retvalue;}void __interrupt() intr(void)// Interrupt processing function{ if (INTF == 1) { INTF = 0; } if (TMR0IF == 1) { TMR0IF = 0; //Clear TMR0 Interrupt flag TimerCounter++; }}void main(void) { initIo(); // I/O port初期化 initTimer0(); // Timer0 初期化 initAdc(); // A-D convertor 初期化 led0off(); //LED0を消す led1off(); //LED1を消す led2off(); //LED2を消す while (1) { //無限ループ。次の}までの間を無限回繰り返す。 if (isdark()) { led0on(); wait(5000); led0off(); wait(5000); led1on(); wait(5000); led1off(); wait(5000); led2on(); wait(5000); led2off(); wait(5000); } else { led0off(); led1off(); led2off(); } }}