暗くなると一定時間だけLEDが点灯する賢いライトです。
ブレッドボード
PICマイコン PIC12F1822P
カーボン抵抗器 150Ω (茶緑茶金)、100kΩ(茶黒黄金)
LED
バッテリスナップ
電池ボックス(単3×3本用)
ファイル名:sensor_light_12f1822.c
XC8 Compiler用
/* * LED1 : PIN 7 (RA0) : 1-ON, 0-off * * * ANALOG PORT : PIN 3 (AN3) * */#include <xc.h>#include <stdint.h>#define ledOn() (RA0 = 1)#define ledOff() (RA0 = 0)#define led() (RA0 ^= 1) // LEDを点滅する// Configuration 1#pragma config FOSC = INTOSC // Internal Clock#pragma config WDTE = OFF // NO Watchdog timer#pragma config PWRTE = ON // Program start at Power on after 64ms#pragma config MCLRE = OFF // No Ext Reset, Enable RA3 input pin#pragma config CP = OFF // No Code protect#pragma config CPD = OFF // No Data Protect#pragma config BOREN = ON // Brown out enable#pragma config CLKOUTEN = OFF // CLKOUT as RA4#pragma config IESO = OFF // No Internal External clock#pragma config FCMEN = OFF // No FCM// Configuration 2#pragma config WRT = OFF // No Write Protect#pragma config PLLEN = OFF // No PLL#pragma config STVREN = ON // Reset on Stack over / under flow#pragma config BORV = HI // Watch Voltage drop (2.5V = HI)#pragma config LVP = OFF // No Low Voltage Programmingvoid wait(volatile uint32_t i){ while (i-- > 0);}void initIO(void)// I/Oポートの初期化{ OSCCON = 0b01110010 ; // Internal clock 8MHz OPTION_REG = 0b00010000 ; // Weak Pull up Resistor RA4-OFF, others ON ANSELA = 0b00010000 ; // Analog PORT AN3(RA4) TRISA = 0b00011000 ; // Input : RA34, Output: others WPUA = 0b00001000 ; // Weak pullup : RA3 PORTA = 0b00000000 ; // Initialize PORTA}void initAdc8(void)// A/Dコンバータの初期化{ ANSELA = 0b00010000; //RA4 Analog port, others digital port ADCON0 = 0b00001101; //0:unimp, 00011:AN3, 0:GOnDone, 1:ADC enable ADCON1 = 0b01000000; //0:Left jutified (8bit res.), 100:Fosc/4 ,0:Reserved, 00:AVDD=VREF CM1CON0 = 0x00; //Comparator disable}uint8_t getAdc8(void)// 精度8bitでA/D変換{ uint8_t d; //ADC wait(10); GO_nDONE = 1; while (GO_nDONE); d = ADRESH; return d;}void initTimer0(void)// タイマの初期化{ OPTION_REG &= 0b11111000; // Clear Prescale parameter OPTION_REG |= 0b00000111; // Prescaler 1:256 TMR0 = 0; // initialize Timer0 TMR0IF = 0; // Timer0 interrupt enable TMR0IE = 1; // Enable Timer0 Interrupt GIE = 1; // Enable Interrupt}/* * 1 interrupt * => 1/8 * 4 (instruction exec clock) * 256(prescaler) * 256 = 32768 us , * 1 sec = 1 / 32768e-6 = 30.517 counts */static volatile unsigned int T0count;#define TIMER0_1SEC 30void interrupt InterFunction( void )// 割り込み関数{ // Timer0 Interrupt if (TMR0IF == 1) { // Timer0割り込みが発生したとき TMR0 = 0; T0count++; TMR0IF = 0; }}void main(void) { int i; uint8_t adc_value; // 明るさを表す数値 initIO(); // I/Oポートの初期化 initAdc8(); // A/Dコンバータの初期化 initTimer0(); // Timer0の初期化 // LEDが3回点滅 for (i = 0; i < 6; i++) { led(); wait(10000); } ledOff(); while (1) { adc_value = getAdc8(); // A/Dコンバータで明るさを検出 if (adc_value < 220) { // 明るいときは LED消灯 ledOff(); } else { // 暗いときは60秒間点灯する for (T0count = 0 ; T0count < TIMER0_1SEC * 60; ) { ledOn(); } // 明るくなるまでLEDを消灯して待つ while (adc_value >= 220) { ledOff(); adc_value = getAdc8(); // A/Dコンバータで明るさを検出 } } }}ヘッダファイル: sensor_light.h
/* * sensor light configuration header file * * KAIMU 2017/07/09 * */#define FIRST_LED_BLINK_COUNT 3 // 最初にLEDが点滅する回数#define TIMER_SECOND 5 // 暗くなってからLEDが点灯し、消えるまでの時間(秒数)#define SENSOR_PARAMETER 220 //明るさセンサの感度 数値が大きいほど明るくても反応しやすくなる#define LED_PWM 5 // LEDの暗く/明るくなる速度 (5~500)#define BUZ_LENGTH 500 // ブザーのなる長さ#define BUZ_TONE 50 // ブザーの音の高さソースファイル: led-timer-12f1822.c
/* * File: led-marker-timer-12f1822.c * Author: kaimu * * Created on Jul 9, 2017 *//* * LED1 : PIN 7 (RA0) : 1-ON, 0-off * * Buzzer : PIN 6 (RA1) * * ANALOG PORT : PIN 3 (AN3) * */#include <xc.h>#include <stdint.h>#include "sensor_light.h"enum STATUS {ST_STANDBY , ST_TIMER, ST_TIMEOUT} Status; #define ledOn() (RA0 = 1)#define ledOff() (RA0 = 0)#define led() (RA0 ^= 1) // LEDを点滅する#define buz() (RA1 ^= 1) // Buzzerの鳴動// Configuration 1#pragma config FOSC = INTOSC // Internal Clock#pragma config WDTE = OFF // NO Watchdog timer#pragma config PWRTE = ON // Program start at Power on after 64ms#pragma config MCLRE = OFF // No Ext Reset, Enable RA3 input pin#pragma config CP = OFF // No Code protect#pragma config CPD = OFF // No Data Protect#pragma config BOREN = ON // Brown out enable#pragma config CLKOUTEN = OFF // CLKOUT as RA4#pragma config IESO = OFF // No Internal External clock#pragma config FCMEN = OFF // No FCM// Configuration 2#pragma config WRT = OFF // No Write Protect#pragma config PLLEN = OFF // No PLL#pragma config STVREN = ON // Reset on Stack over / under flow#pragma config BORV = HI // Watch Voltage drop (2.5V = HI)#pragma config LVP = OFF // No Low Voltage Programmingvoid wait(volatile uint32_t i){ while (i-- > 0);}void initIO(void)// I/Oポートの初期化{ OSCCON = 0b01110010 ; // Internal clock 8MHz OPTION_REG = 0b00010000 ; // Weak Pull up Resistor RA4-OFF, others ON ANSELA = 0b00010000 ; // Analog PORT AN3(RA4) TRISA = 0b00011000 ; // Input : RA34, Output: others WPUA = 0b00001000 ; // Weak pullup : RA3 PORTA = 0b00000000 ; // Initialize PORTA}void initAdc8(void)// A/Dコンバータの初期化{ ANSELA = 0b00010000; //RA4 Analog port, others digital port ADCON0 = 0b00001101; //0:unimp, 00011:AN3, 0:GOnDone, 1:ADC enable ADCON1 = 0b01000000; //0:Left jutified (8bit res.), 100:Fosc/4 ,0:Reserved, 00:AVDD=VREF CM1CON0 = 0x00; //Comparator disable}uint8_t getAdc8(void)// 精度8bitでA/D変換{ uint8_t d; //ADC wait(10); GO_nDONE = 1; while (GO_nDONE); d = ADRESH; return d;}void initTimer0(void)// タイマの初期化{ OPTION_REG &= 0b11111000; // Clear Prescale parameter OPTION_REG |= 0b00000111; // Prescaler 1:256 TMR0 = 0; // initialize Timer0 TMR0IF = 0; // Timer0 interrupt enable TMR0IE = 1; // Enable Timer0 Interrupt GIE = 1; // Enable Interrupt}/* * 1 interrupt * => 1/8 * 4 (instruction exec clock) * 256(prescaler) * 256 = 32768 us , * 1 sec = 1 / 32768e-6 = 30.517 counts */static volatile unsigned int T0count;#define TIMER0_1SEC 30void interrupt InterFunction( void )// 割り込み関数{ // Timer0 Interrupt if (TMR0IF == 1) { // Timer0割り込みが発生したとき TMR0 = 0; T0count++; TMR0IF = 0; }}void buzzer(int length) { int i; for (i = 0; i < length; i++) { buz(); wait(BUZ_TONE); }}void main(void) { int i; uint8_t adc_value; // 明るさを表す数値 initIO(); // I/Oポートの初期化 initAdc8(); // A/Dコンバータの初期化 initTimer0(); // タイマの初期化 Status = ST_STANDBY; // 状態はSTANBY状態に設定 T0count = 0; // 時計をリセット buzzer(100); //ブザを鳴らす // 電源投入直後、最初にLEDを点滅 for (i = 0 ; i < FIRST_LED_BLINK_COUNT; i++) { led(); wait(20000L); led(); wait(20000L); } ledOff(); while (1) { switch (Status) { // 状態Statusに応じて切り替え case ST_STANDBY : // STANDBY 状態 adc_value = getAdc8(); // A/Dコンバータで明るさを検出 if (adc_value < SENSOR_PARAMETER) { // 明るいときは LED消灯 ledOff(); } else { buzzer(BUZ_LENGTH); // ブザを鳴らす Status = ST_TIMER; // 暗いときはTIMER状態へ移行 T0count = 0; } break; case ST_TIMER : // TIMER状態 for (i = 0; i < 1000; i += LED_PWM) { // LEDが徐々に暗くなる ledOn(); wait(1000 - i); // LED点灯時間が1000→990→980→…→20→10と短くなる ledOff(); wait(i); // LED消灯時間が0→10→20→…→980→990と長くなる } for (i = 0; i < 1000; i += LED_PWM) { // LEDが徐々に明るくなる ledOff(); wait(1000 - i); // LED消灯時間が1000→990→980→…→20→10と短くなる ledOn(); wait(i); // LED点灯時間が0→10→20→…→980→990と長くなる } adc_value = getAdc8(); // 明るさをチェック if (adc_value < SENSOR_PARAMETER) { // 明るいときはLEDを消灯しSTANDBY状態へ ledOff(); Status = ST_STANDBY; } if (T0count > TIMER0_1SEC * TIMER_SECOND) { // TIMER_SECOND 秒経過したら Status = ST_TIMEOUT; // TIMEOUT状態へ } break; case ST_TIMEOUT : // TIMEOUT 状態 ledOff(); // LED消灯 adc_value = getAdc8(); // 明るさをチェック if (adc_value < SENSOR_PARAMETER) { // 明るいときはLEDを消灯しSTANDBY状態へ Status = ST_STANDBY; } break; default : // 異常なStatus値の場合はSTANDBY状態へ Status = ST_STANDBY; } } return;}