3色LEDマーカー2019

周囲が暗くなると、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();
        }
    }
}