回路図

lighting_with_human_sensor

人感センサー

このセンサーは、検知後 約22秒間 出力がhigh(1)となっていました

pyroelectric_detector

ケース

IMG_1435-2.jpg

ソフトウエア(フローチャート)

ソースコード

 /*********** 人感照明 ************
 * File:   main.c
 * Author: masan
 *
 * Created on 2022/10/8, 19:10
 */


//------------ ハードウエア情報 -------------
//  CPU PIC16F1705
//  RA0(13) input   ICSPDAT
//  RA1(12) input   ICSPCLK
//  RA2(11) input   KEY入力
//  RA3(4)  input   MCLR
//  RA4(3)  output  CLKOUT=Fosc/4
//  RA5(2)  input   人感センサー入力
//  RC0(10) input   未使用  
//  RC1(9)  input   未使用  
//  RC2(8)  output  リレーON
//  RC3(7)  output  OPA2OUT/AN7(analog)
//  RC4(6)  output  未使用:TEST6
//  RC5(5)  input   OPA2IN+(analog 光センサ接続)  
//
//  光センサー  (JRC)

// PIC16F1705 コンフィグレーション

// CONFIG1
#pragma config FOSC = INTOSC    // Oscillator Selection Bits (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = ON       // Watchdog Timer Enable
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = ON    // Clock Out Enable (CLKOUT function is enabled on the CLKOUT pin)
#pragma config IESO = OFF       // Internal/External Switchover Mode (Internal/External Switchover Mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PPS1WAY = ON     // Peripheral Pin Select one-way control (The PPSLOCK bit cannot be cleared once it is set by software)
#pragma config ZCDDIS = ON      // Zero-cross detect disable (Zero-cross detect circuit is disabled at POR)
#pragma config PLLEN = OFF      // Phase Lock Loop enable (4x PLL is enabled when software sets the SPLLEN bit)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOR = OFF      // Low-Power Brown Out Reset (Low-Power BOR is disabled)
#pragma config LVP = ON         // Low-Voltage Programming Enable (Low-voltage programming enabled)

//************************ インクルードファイル ***********************
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>

//******************* 関数定義 **************************************************
void init_OSC(void);                                    //オシレータ初期設定
void init_PORT(void);                                   //ポート初期設定
void init_OPamp(void);                                  //OPamp初期設定
void init_ADC(void);                                    //ADC初期設定
void init_Timer1(void);                                 //Timer1初期設定
void init_Timer2(void);                                 //Timer2初期設定

//******************* PORTの定義など ************************
#define _XTAL_FREQ  2000000             //2MHz
#define KEY_input   PORTAbits.RA2       //常時点灯スイッチ
#define HUMAN_input PORTAbits.RA5       //人感センサー入力
#define LED_ON      PORTCbits.RC2       //1でLED ON  
#define TEST6       PORTCbits.RC4       //RC4(6):TEST6

//***************************** グローバル変数 **********************************
unsigned char   human_flag = 0;                     //人検知 0:No,40:Yes
unsigned short  adc_value = 0;                      //adc値
unsigned short  illuminance = 1000;                 //照度
unsigned short  pre1_illuminance = 1000;            //1回前の照度
unsigned short  pre2_illuminance = 1000;            //2回前の照度
unsigned short  pre3_illuminance = 1000;            //3回前の照度


//************************ プログラム *****************************************
//******************** オシレータ初期設定 ***************************************
//  入力    なし      
//  処理    内部オシレータ           
//  出力    Fosc(2MHz)       
//******************************************************************************
void init_OSC(void){                   //オシレータ初期設定
    OSCCONbits.SPLLEN = 0;              //PLLを使用しない
    OSCCONbits.IRCF = 0b1100;           //2MHz選択
    WDTCONbits.WDTPS = 14;              //ウォッチドックタイマー16sec
}

//******************** ポート初期設定 ***************************************
//  入力    無し           
//  処理    ポート初期設定
//          RA0(13) input   ICSPDAT
//          RA1(12) input   ICSPCLK
//          RA2(11) input   KEY入力
//          RA3(4)  input   MCLR
//          RA4(3)  output  CLKOUT=Fosc/4
//          RA5(2)  input   人感センサー入力
//          RC0(10) input   未使用  
//          RC1(9)  input   未使用
//          RC2(8)  output  リレーON
//          RC3(7)  output  OPA2OUT/AN7(analog)
//          RC4(6)  output  未使用:TEST6
//          RC5(5)  input   OPA2IN+(analog 光センサ接続) 
//  出力    無し     
//******************************************************************************
void init_PORT(void){                                   //ポート初期設定
    TRISA = 0x2f;   ANSELA = 0;     //all digital 
    TRISC = 0x23;   ANSELC = 0x28;  //RC5:analog_input,RC3:analog
}

//****************** OPamp初期設定 ******************************************
//  入力   OPA2+(RC5:5pin)
//  処理   OPamp初期設定(OPA2をフォロワー設定)
//  出力   OPA2OUT(RC3:7pin=AN7)
//******************************************************************************
void init_OPamp(void){             //OPamp初期設定
    OPA2CONbits.OPA2UG = 1;         //OPA2フォロワー設定
    OPA2CONbits.OPA2SP = 1;         //OPA2 high GBWP mode
    OPA2CONbits.OPA2PCH = 0;        //OPA2 +入力=OPA2IN+
    OPA2CONbits.OPA2EN = 1;         //OPA2 イネーブル
}

//**************************** ADC初期設定 **************************************
//  入力    AN7(RC3:7pin)
//  処理    ADC初期設定
//  出力    なし
//******************************************************************************
void init_ADC(void){                                    //ADC初期設定
    ADCON0bits.CHS = 7;         //analog input AN7
    ADCON1bits.ADCS = 4;        //Fosc/4=2MHz/4=500kHz(2uSec)=Tad 
    ADCON1bits.ADFM = 1;        //output data is right justified
    ADCON1bits.ADPREF = 0;      //Vref+ = VDD(5V)
    ADCON1bits.ADNREF = 0;      //Vref- = GND
    ADCON2bits.TRIGSEL = 4;     //トリガーTimer1オーバーフロー
    //割り込み設定
    PIR1bits.ADIF = 0;          //ADC割り込みフラグクリア
    PIE1bits.ADIE = 1;          //ADC割り込み許可
    
    ADCON0bits.ADON = 1;        //ADC enable
}

//********************** 割り込み処理 *******************************************
//---------------------- ADC割り込み処理 ----------------------------------------
//  入力    割り込み(17mSec毎)
//  処理    ADC割り込みでデータを入力
//  出力   ADC_value
//
//----------------------- Timer2割り込み処理 -----------------------------------
//  入力    割り込み(0.5Sec毎),人感センサー
//  処理    人感センサを検知しtらhuman_flagに40をセット
//          人感センサを検知しない場合 human_flag--
//  出力    human_flag   
//******************************************************************************
void __interrupt(high_priority) ISR(void){
    //---------------------- ADC割り込み処理(17Sec毎) ----------------------------------------
    if(PIR1bits.ADIF == 1){                                                     //--- ADC割り込み処理 ---
        if(LED_ON == 0){                                                        //LEDが点灯している時は、 何もしない。消灯時illuminanceを計算する
            adc_value = ADRESH; 
            adc_value = (adc_value << 8) + ADRESL;                              //10bitデータをセット
            
            illuminance = (adc_value + pre1_illuminance + pre2_illuminance + pre3_illuminance) / 4; //LEDが点灯していないとき計測する、データーの平均化をする 
            pre3_illuminance = pre2_illuminance;                                //保持データをセットする
            pre2_illuminance = pre1_illuminance;                                //保持データをセットする
            pre1_illuminance = illuminance;                                     //保持データをセットする
        }
        asm("CLRWDT");                                                          //ウォッチドックタイマークリア
        PIR1bits.ADIF = 0 ;                                                     // ADC割り込みフラグをクリアする
    }
    
    //----------------------- Timer2割り込み処理(0.5Sec毎) -----------------------------------
    if(PIR1bits.TMR2IF ==  1){                                  //
        //--- 人感センサー入力 ---
        if(HUMAN_input == 1)    human_flag = 40;                                //人検知 Yes 40*0.5sec=20sec
        else{
            if(human_flag >1)   human_flag--;                                   //human_flagを減算する
            else                human_flag = 0;
        }
        PIR1bits.TMR2IF = 0;                                                    //Timer2割り込みフラグクリア                   
    }    
}

//**************************** Timer1初期設定 **************************************
//  入力    LFINTOSC(31kHz)
//  処理    Timer1初期設定(ADC トリガー)  25uSec*2~16=16.9秒ごとにトリガー
//  出力    なし
//******************************************************************************
void init_Timer1(void){
    T1CONbits.TMR1CS = 3;       //LFINTOSC(31kHz)
    T1CONbits.T1CKPS = 3;       //プリスケーラ1/8=31kHz/8=3875Hz(258uSec)
    T1CONbits.TMR1ON = 1;       //Timer1 ON  
}

//**************************** Timer2初期設定 **************************************
//  入力    fosc/4=2MHz/4=500kHz
//  処理    500kHz/64(prescaler)=7182.5Hz,7182.5/223+1(PR2)=32Hz,32Hz/16=2Hz(0.5Sec)
//  出力    0.5秒毎の割り込み発生
//******************************************************************************
void init_Timer2(void){
    T2CONbits.T2CKPS = 7;       //プリスケーラ1/64=500kHz/64=7182.5Hz
    PR2 = 223;                  //7182.5Hz/(223+1)=32Hz
    T2CONbits.T2OUTPS = 15;     //32Hz/16=2Hz(0.5Sec)
    //--- 割り込み設定 ---
    PIR1bits.TMR2IF = 0;          //Timer2割り込みフラグクリア
    PIE1bits.TMR2IE = 1;          //Timer2割り込み許可    
    
    T2CONbits.TMR2ON = 1;       //Timer1 ON  
}


//*********************** MAIN PROGRAM *****************************************
//******************************************************************************
void main(void) {
    init_OSC();                                     //オシレータ初期設定(4MHz)
    init_PORT();                                    //ポート初期設定  
    
    init_Timer1();                                  //Timer1初期設定
    init_OPamp();                                   //OPamp初期設定
    init_ADC();                                     //ADC初期設定
    init_Timer2();                                  //Timer2初期設定
    
    //--- 割込み許可 ---
    INTCONbits.PEIE = 1 ;              // 周辺装置割り込みを許可する
    INTCONbits.GIE  = 1 ;              // 全割り込み処理を許可する

    while(1){
        //--- キー入力 ---
        if(KEY_input == 0)          LED_ON = 1;                                 //キー入力(常に点灯)あり:LED ON 
        //--- 照光入力 ---
        else if(illuminance > 100)  LED_ON = 0;                                 ////昼:LED OFF   
        //--- 人感センサー入力 ---
        else if(human_flag == 0)    LED_ON = 0;                                 //人検知なし:LED OFF
        else                        LED_ON = 1;                                 //人検知あり :LED ON  
    }
}