14 February 2016

赤外線リモコン作成 (シーリングライト照明)

赤外線リモコン作成 (TVの「d」ボタンが壊れたため)』で作成したリモコンが不要となったので、回路を有効活用するためにシーリングライト照明用にプログラムをすこし変更した。

回路

20151024-irsender-circuit.png

20151024-irsender-board.jpg
回路作成例

PIC12F1822 プログラム

/*
 * 赤外線リモコン 簡易送信機
 * File:   main.c
 *
 * Created on 2016/02/13, 19:50
 */
 
#include <stdio.h>
#include <stdlib.h>
#define     EEPROM_SIZE     256
#include <xc.h>
 
 
// Generated with MPLABX (Window menu - PIC memory views - Configuration bits)
// 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 disabled)
#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 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 PLLEN = OFF      // PLL Enable (4x PLL disabled)
#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), high trip point selected.)
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
 
 
#ifndef _XTAL_FREQ
/* 例:4MHzの場合、4000000 をセットする */
#define _XTAL_FREQ 4000000
#endif
 
/*
 * 赤外線発信時間(マイクロ秒)の定義:家電協フォーマット版
 */
#define TIMING_START_HI     3500
#define TIMING_START_LO     1600
#define TIMING_SIGNAL_HI    540
#define TIMING_SIGNAL_1_LO  1200
#define TIMING_SIGNAL_0_LO  360
 
/*
 * パナソニックのシーリングライトのリモコンデータ(CH2版)
 */
// メーカーコード
unsigned char code_maker1 = 0x34;
unsigned char code_maker2 = 0x4A;
// 点灯
unsigned char code_01_3 = 0x90;
unsigned char code_01_4 = 0xAC;
unsigned char code_01_5 = 0x3C;
// 全灯
unsigned char code_02_3 = 0x90;
unsigned char code_02_4 = 0x2C;
unsigned char code_02_5 = 0xBC;
// 常夜灯
unsigned char code_03_3 = 0x90;
unsigned char code_03_4 = 0x6C;
unsigned char code_03_5 = 0xFC;
// 消灯
unsigned char code_04_3 = 0x90;
unsigned char code_04_4 = 0xEC;
unsigned char code_04_5 = 0x7C;
 
/*
 * PWMで赤外線コード送信
 *
 * @param c 送信するコード
 */
void decode_bit(unsigned char c) {
    for (int i = 0; i < 8; i++) {
        if (c & (0x80 >> i)) {
            // PORTAbits.RA2 = 1;        // ← 単なる矩形波ではダメな例
            CCP1CON = 0b00001100;
            __delay_us(TIMING_SIGNAL_HI);
            // PORTAbits.RA2 = 0;
            CCP1CON = 0b00000000;
            __delay_us(TIMING_SIGNAL_1_LO);
        } else {
            CCP1CON = 0b00001100;
            __delay_us(TIMING_SIGNAL_HI);
            CCP1CON = 0b00000000;
            __delay_us(TIMING_SIGNAL_0_LO);
        }
    }
}
 
/*
 * mainエントリー関数
 */
int main(int argc, char** argv) {
    // 基本機能の設定
    OSCCON = 0b01101010;    // 内部オシレーター 4MHz
    TRISA = 0b00001000;     // IOポートRA0〜RA5を出力モード(ただしRA3は入力専用)
    ANSELA = 0b00000000;    // A/D変換をAN0,AN1,AN2,AN4を無効
    PORTA = 0;
 
    CCP1SEL = 0;            // RA2をCCP1(PWM)のP1Aで用いる
    CCP1CON = 0b00000000;   // PWM(シングル)
    T2CON = 0b00000000;     // TMR2プリスケーラ値を1倍に設定, Timer2はこの時点ではOFF
    // PR2 = Fosc / (Fpwm * 4 * Prescale) + 1 = 4000000 / (38000 * 4 * 1) + 1 = 27
    PR2 = 0x19;             // 経験値より27ではなく25とする
    CCPR1L = 0x08;          // PR2=0x19の場合デューティ値は6bit
    CCPR1H = 0;
    TMR2 = 0;               // Timer2カウンタを0
 
    // EEPROMより発信信号の種類をロード(0x01:点灯, 0x02:全灯, 0x03:常夜灯, 0x04:消灯)
    unsigned char config_mode = (unsigned char) eeprom_read(0);
    if (config_mode < 0x01 || 0x04 < config_mode) {
        config_mode = 0x01;
    }
    __delay_ms(1);
 
    // EEPROMに次回の発信信号の種類を書き込み(電源を入れる毎、次の信号が出るようにする)
    unsigned char config_mode_next = config_mode + 1;
    if (0x04 < config_mode_next) {
        config_mode_next = 0x01;
    }
    eeprom_write(0, (unsigned char) config_mode_next);
 
    // PWM開始
    TMR2ON = 1;
    // 0.05秒待つ
    __delay_ms(50);
 
    // 通電中は、赤外線信号を送信し続ける
    for (;;) {
        // スタートビット(リーダ)
        CCP1CON = 0b00001100;
        __delay_us(TIMING_START_HI);
        CCP1CON = 0b00000000;
        __delay_us(TIMING_START_LO);
 
        // 送信データ本体
        decode_bit(code_maker1);
        decode_bit(code_maker2);
 
        switch (config_mode) {
            case 0x01:
                decode_bit(code_01_3);
                decode_bit(code_01_4);
                decode_bit(code_01_5);
                break;
            case 0x02:
                decode_bit(code_02_3);
                decode_bit(code_02_4);
                decode_bit(code_02_5);
                break;
            case 0x03:
                decode_bit(code_03_3);
                decode_bit(code_03_4);
                decode_bit(code_03_5);
                break;
            case 0x04:
                decode_bit(code_04_3);
                decode_bit(code_04_4);
                decode_bit(code_04_5);
                break;
        }
 
        // ストップビット(トレーラ)
        CCP1CON = 0b00001100;
        __delay_us(TIMING_SIGNAL_HI);
        CCP1CON = 0b00000000;
        __delay_us(TIMING_SIGNAL_HI);
 
        __delay_ms(20);
    }
 
}