picで赤外線リモコン_nec_を作る
PIC(12F1822)でNEC照明リモコンを作る
製作のきっかけ
現在の住居では玄関用の照明が設置されておらず、台所用の照明を利用します。
また台所照明の壁スイッチは玄関付近になく、夜間時の外出時はリモコンを玄関付近まで
移動させます。
しかしながら、日中は照明を点灯させる必要がないので、夜間に帰宅した場合など、
リモコンの移動させて置くことを忘れる事が多い。
つまりは、リモコンがもう1台ほしい。
リモコン制作にあたり
以下の条件で制作
・ 玄関用なので、OFF/ON ボタンだけあれば良い
・ 出来る限り安価 (自宅にある部品のみで)
リモコン型番は NEC RE0208 Amazonで代替リモコン 約800円で購入可能 配送料の兼ね合いもあるが、買ったほうが安い場合を考慮する
・ PWMを使うと製作が簡単らしいので、自宅在庫の12F1822を利用。
今回の要件を考えると12F822はオーバースペックなのだが、PWM機能がある12F1822より安価な在庫は、自宅に無い。
回路図
製作後に実際に玄関付近だと、赤外線出力が弱いのか未反応
ベース抵抗を1KΩに変更して、何とか(リモコンを照明に向けると)使える状態となった。
純正リモコンでは単3電池2本での3V。赤外線LEDは3つあるので、リモコンの向きは照明に向けなくても反応する
製作したリモコンに不満を感じたら改善したい。
プログラム
main.c
/* * File: main.c * Author: kampari * PIC: 12F1822 * MPLAB X IDE V6.20 * XC8 V2.46 * * VDD 1 8 Vss * - (RA5) 2 7 (RA0) - * - (RA4) 3 6 (RA1) - * SW [IN] (RA3) 4 5 (RA2) [OUT] PWM * * Created on 2024/10/11, 20:30 JST */ #include <xc.h> #define _XTAL_FREQ 4000000 // CONFIG1 #pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin) #pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled) #pragma config PWRTE = ON // Power-up Timer Enable (PWRT enabled) #pragma config MCLRE = OFF // MCLR Pin Function Select (MCLR/VPP pin function is digital input) #pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled) #pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled) #pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset enabled) #pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin) #pragma config IESO = OFF // Internal/External Switchover (Internal/External Switchover mode is enabled) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled) // CONFIG2 #pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off) #pragma config PLLEN = OFF // PLL Enable (4x PLL enabled) #pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset) #pragma config BORV = HI // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.) #pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming) #pragma config DEBUG = OFF // In-Circuit Debugger disabled, ICSPCLK and ICSPDAT are general purpose I/O pins // NEC シーリングライト CH2 ON/OFF // コマンド コード (CH1) コード (CH2) // ON/OFF 82 6d ab 54 82 6d 2b d4 // 参考URL https://shrkn65.nobody.jp/remocon/database.html const unsigned char IR_FixData[4] = { 0x82, 0x6d, 0xab, 0x54 }; void Regster_Int(void) { // 基本機能の設定 OSCCON = 0b01101010; // 内部オシレーター 4MHz TRISA = 0b00001000; // RA3: IN 他:すべてOUT ANSELA = 0b00000000; // アナログモードは使用しない OPTION_REGbits.nWPUEN = 0; // 弱プルアップ個別設定を有効にする WPUA = 0b00001000; // RA3のみ弱プルアップをセットする PORTA = 0b00001000; // RA3: Hi 他:すべてLow //PWMモード設定 APFCONbits.CCP1SEL = 0; // RA2をCCP1(PWM)のP1A使用 CCP1CONbits.P1M = 0b00; // PWM モード, シングル出力 CCP1CONbits.CCP1M = 0b1100; // PWM モード, アクティブ High // TMR2設定 T2CONbits.T2OUTPS = 0b0000; // ポストスケーラを1:1に設定 T2CONbits.T2CKPS = 0b00; // プリスケーラを1:1に設定 T2CONbits.TMR2ON = 0; // TMR2ON OFF // T2CON = 0b00000000; の設定と同義 // 電源ON時の初期値は0だが、備忘 TMR2 = 0; // Timer2カウンタを0 /* * 参考URL: http://eng-serve.com/pic/pic_pwm.html * 16F877A用の計算サイト (12F1822だけど、たぶん同じだろう・・・) * PWM Register Values * Oscillator Frequency Fosc = 4000000 * Clock Frequency Fclk = 1000000 * PWM Freq = 38000 desired...actual: 38462 * Prescaler Value = 1 * PR2 = 25 * Maximum duty value = 105 * Requested Duty Value = 50 * * Code Provided AS IS....Use at your own risk! */ // be sure to set PWM port as output // T2CON = 0b00000100; // prescaler + turn on TMR2; // PR2 = 0b00011001; // CCPR1L = 0b00001101; // set duty MSB // CCP1CON = 0b00011100; // duty lowest bits + PWM mode PR2 = 0b00011001; CCPR1L = 0b00001101; CCP1CONbits.DC1B = 0b01; // 割込み設定 INTCON = 0b00000000; // 割込み初期化 (無効) IOCANbits.IOCAN3 = 1; // RA3がHi-> Low (立下り時) 割込み設定 } int main(int argc, char** argv) { unsigned char codebyte; Regster_Int(); // レジスター初期設定 __delay_ms(50); for (;;) { if (PORTAbits.RA3 == 0){ __delay_ms(50); // 安定化待ち //リーダーコード送信 T2CONbits.TMR2ON = 1; __delay_us(9000); T2CONbits.TMR2ON = 0; __delay_us(4500); // カスタム/データコード送信 for (int i=0;i<4;i++){ codebyte = IR_FixData[i]; for(int j=7;j>=0;j--){ T2CONbits.TMR2ON = 1; __delay_us(560); T2CONbits.TMR2ON = 0; //PWM OFFの時間でOn/Off区別 if (codebyte & (0x80 >> j)) { __delay_us(1690); //Bit on } else { __delay_us(560); //Bit Off } } } //ストップビット送信 T2CONbits.TMR2ON = 1; __delay_us(560); T2CONbits.TMR2ON = 0; __delay_ms(42); // リピート送信 (未点灯(送信エラー)防止策) T2CONbits.TMR2ON = 1; __delay_us(9000); T2CONbits.TMR2ON = 0; __delay_us(2250); // ストップビット T2CONbits.TMR2ON = 1; __delay_us(560); T2CONbits.TMR2ON = 0; __delay_ms(42); } //ボタンの押下があるまでスリープ __delay_ms(1000); // チャタリング対策 // PORTAbits.RA5 = 0; // テスト用LED を RA5に実装(動作確認用) IOCAFbits.IOCAF3 = 0; // RA3の状態変化フラグを0にセット INTCONbits.IOCIE = 1; // 状態変化割り込みを有効にする SLEEP(); NOP(); INTCONbits.IOCIE = 0; // 状態変化割り込みを無効にする // PORTAbits.RA5 = 1; // テスト用LED を RA5に実装(動作確認用) } }
picで赤外線リモコン_nec_を作る.txt · 最終更新: by admin