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
