LEDフラッシャーIC「M34-1L,2L,8L」の点滅をPICで再現する

LEDを点滅させるためのICとして、M34シリーズの三端子LEDフラッシャ-ICというものが有ります。
これは、トランジスタのように3本の端子が出ているパーツで、接続するだけで指定された周期でLEDを点滅させる事が出来ます。

点滅の周期は型番によって異なり、以下の通りとなっています。

M34-1L  1.0  秒周期 ON-OFF比率 = 1:8
M34-2L  0.5  秒周期 ON-OFF比率 = 1:8
M34-4L  0.25 秒周期 ON-OFF比率 = 1:8
M34-8L  0.125秒周期 ON-OFF比率 = 1:2



実際にどんな感じで点滅するか、YouTubeに動画があがってました。


M34シリーズの主な用途は、製造元のデータシートによると以下のものが想定されているようです。

点滅するバッチ
イヤリング
グリーティングカード
ディスコライト
自転車のライト
車のアラーム
警告ライト
クリスマス用のデコレーション
おもちゃ等...



このICは、1個50円くらいの安価なICですが仕様上1つで最大2~3つのLEDまでしかコントロールする事が出来ません。


そこで今回は、このフラッシャ-IC相当の機能をPIC(16F88)で再現してみます。

PICの16F88は、I/Oに最大16ピン割り当てることが出来るため、5倍以上のLEDをコントロールできます。
また、マイコンを使用するとLED毎に異なる点滅パターンを割り当てたり、すべてのLEDを正確に同じタイミングで点滅させる事も簡単です。


で、実際に作ってみた結果が以下の通りです。
4秒周期で、M34-1L, M34-2L, M34-8Lの機能を順に再現しています。


3つ目の0.125秒周期のパターンは動画だと綺麗に点滅できていなさそうですが、これは動画がフレームレートが15fpsしかないからで、実物を見るとちゃんと毎秒8回点滅しています。
また回路は、前回作ったPICライタの動作確認回路を流用しました。


プログラムは以下の通りです。
タイマ割込みを使用して点滅パターンを制御しています。

#include <stdio.h>
#include <htc.h>
 
#define TIMER_INTERVAL (0xffff - 20000) // TMRモジュールのカウント初期値
                                       // 2000を指定すると 8MHz, 1/1プリスケーラで1msecになる
 
__CONFIG (  FOSC_INTOSCIO & // 内部クロック
            WDTE_OFF &      // watchdogオフ
            PWRTE_OFF &     // Power-up Timer
            MCLRE_OFF &     // MCLRピンを汎用I/Oとして使用
            BOREN_OFF &     // 電圧降下によるリセットオフ
            LVP_OFF &       // Low-Voltage Programmingオフ
            CPD_OFF &       // EEPROM  プロテクトオフ
            WRT_OFF &       // FrashROMプロテクトオフ
            DEBUG_ON &      // ICDデバッグを有効にする
            CCPMX_RB0 &     // RB0をCCPとして使用
            CP_OFF );       // コードプロテクトオフ
 
 
// プロトタイプ宣言
void SetLED( unsigned char data );
void HardwareSetup( void );
 
// グローバル変数
unsigned char       GL_LedData;         // LED表示パターン
unsigned long int   GL_SystemTimeSec = 0;   // CPU起動からの経過時間
 
 
//****************************************************************************************
// Function     : main
// Description  : メイン処理
//****************************************************************************************
void main( void )
{
    unsigned long int loop = 0;
 
    // ハードウェアの初期化
    HardwareSetup()
 
    // 割り込みベースで動作するので、メイン処理は無し
    while( 1 ) {
        ; // nop
    }           
}
 
//****************************************************************************************
// Function     : intr
// Description  : 割り込み処理(10msec周期)
//****************************************************************************************
static void interrupt intr( void )
{
    static int intr_counter;
    //------------------------------------
    // Timer1割り込みが発生したときの処理
    //------------------------------------
    if ( PIR1bits.TMR1IF == 1 ) {
        TMR1 = TIMER_INTERVAL;  // タイマーをリセット
 
        //----------------------------
        // カウンタを加算(100で1秒)
        //----------------------------
        intr_counter++;
        if ( intr_counter >= 100 ) {
            intr_counter = 0;
            GL_SystemTimeSec++;
        }
 
        //----------------------------------------------
        // 点滅させるべきLEDを、1秒周期で切り替える
        //----------------------------------------------
        if ( GL_SystemTimeSec % 2 == 0 ) {
            GL_LedData = 0b00111100;
        } else {
            GL_LedData = 0b11000011;
        }
 
        //----------------------------------------------
        // 4秒周期で点滅パターンを切り替える
        //----------------------------------------------
        switch ( ( GL_SystemTimeSec / 4 ) % 3 ) {
            case 0:
                // M34-1L相当点滅パターン : 1秒(ON-OFF比1:8)
                if ( intr_counter <= 12 ) {
                    SetLED( GL_LedData ); 
                } else {
                    SetLED( 0x00 );
                }
                break;
            case 1:
                // M34-2L   相当点滅パターン : 0.5秒(ON-OFF比1:8)   
                if (    (intr_counter >=  0 && intr_counter <=  6) ||
                    (intr_counter >= 50 && intr_counter <= 56) ) {
                    SetLED( GL_LedData );
                } else {
                    SetLED( 0x00 );
                }
                break;
            case 2:
                // M34-8L   相当点滅パターン : 0.125秒(ON-OFF比1:2) 
                if (    (intr_counter%12) <= 5 ) {
                    SetLED( GL_LedData );
                } else {
                    SetLED( 0x00 );
                }
                break;
        }
 
        PIR1bits.TMR1IF = 0;    // 割り込みフラグを落とす
    }   
}
 
 
//****************************************************************************************
// Function     : HardwareSetup
// Description  : ハードウェア初期化処理
//****************************************************************************************
void HardwareSetup( void )
{
    //----------------------------------
    // 内部クロックを8MHz駆動にする
    //----------------------------------
    OSCCONbits.IRCF = 7;        
 
    //----------------------------------
    // ポートのモードを初期化する
    //----------------------------------
    ANSEL = 0;
    T1CONbits.T1OSCEN = 0;  
    TRISB = 0x00;
    TRISAbits.TRISA0 = 0;   // RA0を出力にする
    TRISAbits.TRISA1 = 0;   // RA1を出力にする  
 
 
    //----------------------------------
    // Timer1の初期化
    //----------------------------------
    PIR1bits.TMR1IF = 0;    // Timer1割り込みフラグを落としておく
    PIE1bits.TMR1IE = 1;    // Timer1割り込みを有効
 
    T1CONbits.T1CKPS = 0;   // プリスケーラを1/1にする
    TMR1 = TIMER_INTERVAL;  // タイマー値をセットします
 
    T1CONbits.TMR1ON = 1;   // Timer1を有効にする
 
    //----------------------------------
    // 割り込みを有効にする
    //----------------------------------
    INTCONbits.PEIE = 1;    // 外部割込みを有効にする
    INTCONbits.GIE  = 1;    // Grobal interruptを有効にする
}
 
 
//****************************************************************************************
// Function     : SetLED
// Description  : 指定されたビットに対応するLEDを点灯する
//****************************************************************************************
void SetLED( unsigned char data )
{
    PORTBbits.RB0 = (data & 0x01) ? 1 : 0;
    PORTBbits.RB1 = (data & 0x02) ? 1 : 0;
    PORTBbits.RB2 = (data & 0x04) ? 1 : 0;
    PORTBbits.RB3 = (data & 0x08) ? 1 : 0;
    PORTBbits.RB4 = (data & 0x10) ? 1 : 0;
    PORTBbits.RB5 = (data & 0x20) ? 1 : 0;
    PORTAbits.RA0 = (data & 0x40) ? 1 : 0;
    PORTAbits.RA1 = (data & 0x80) ? 1 : 0;
}

関連記事

コメントを残す

メールアドレスが公開されることはありません。