[BC17-04] マイコン・センサ・ライト
暗くなると一定時間だけLEDが点灯する賢いライトです。
使用部品
使用部品
ブレッドボード
PICマイコン PIC12F1822P
カーボン抵抗器 150Ω (茶緑茶金)、100kΩ(茶黒黄金)
LED
バッテリスナップ
電池ボックス(単3×3本用)
回路図
回路図
実体配線図
実体配線図
PICkit3によるマイコンへのプログラム書き込みのための配線
PICkit3によるマイコンへのプログラム書き込みのための配線
完成品
完成品
ファームウェア
ファームウェア
最初のファームウェア
最初のファームウェア
ファイル名: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 Programming
void 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 30
void 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 Programming
void 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 30
void 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;
}