Ultrafire 502B Cree XML U2 - 4-mode化改造 自転車けんちゃん

大学サークルで自転車に魅せられて30年以上たちました。 いまだにロングライドと言えば日の出から日の入りまで 走っています。

ホーム > 改造 - ライト > Ultrafire 502B Cree XML U2 - 4-mode化改造

Ultrafire 502B Cree XML U2 - 4-mode化改造

4-mode化がうまくできましたので公開します。

モードは自転車用0.25秒周期点滅(Mid光強度)
High,、HighとMidの中間、Midの4種類です。

こちらが回路図。赤が改造のポイントです。
XML_U2_4mode_20120109-2.jpg
リファレンス番号:種類、会社、型番、(マーキング文字)
IC1:PIC、Microchip、型番不明、(マーキングなし)
IC2:Serial EEPROM、Hua Hong NEC、K24C020、(K24C02D)
TR1,2:N-Channel MOSFET、dhtpower、CT2032、(A2SHB)
D1:Schottky Barrier Diode、TOSHIBA、1SS389、(S4)

この回路は変なところがあります。
TR1はソースとドレインが逆向きになっているので
スイッチがOFFになっていても内部ダイオードの
方向に電流が流れます。
ついでに、スイッチがOFFでもゲートは
フローティング状態なのでTR1はOFFになりません。
試しにTR1を外してみても問題なく動作します。
外すと抵抗が少なくなってランタイムが短くなりますので
そのままにしておきます。
#2012/01/29 追記
#このFET は電池逆挿しの保護回路のようですね。


改造手順
・EEPROM(IC2)削除
・PIC(IC1)を外す
・10Kオーム抵抗(R1)を外す
・PIC(IC1)の4番ピンをパターンカット
・PIC(IC1)の3番ピンをパターンカット
・PIC(IC1)に新作を実装する
・PIC(IC1)の4番ピン-R1のVDD側をジャンパーで接続
・パスコン(C1)に47uFの極小セラコンを並列に追加

パターンカット箇所の写真と改造後の基板
ultrafire_20111217-20.jpg XML_U2_4mode_20120109-1.jpg

解説はこちらこちらを参照してください。
前回からの変更点ですが、
パワーオンリセットフラグを確認することにより
瞬断とOFFからの起動を区別するようにしました。
2.0~1.5VまではブラウンアウトリセットでSRAMの内容は保持されます
1.5V以下になるとSRAMの内容は不定となり、パワーオンリセットになります。
保持されていたメモリーの内容を読み出すための謎のリフレッシュ
動作はこちらのプログラムでも必要です。

こちらがプログラムです。
お好きな方はご自由にコピー、流用、改造してください。
(参考にしたよ~ってコメントいただけるとうれしいいです。)
// ========================================================
// バージョン   1.3 (2012/1/3)
// デバイス     PIC12F629(675)
// コンパイラ   HI-TECH C Compiler for PIC10-12-16 MCUs V9.83
// 作成者       自転車けんちゃん
// 仕様
//   UltraFireのLED制御回路
//   4モード(点滅、Low-Mid-High点灯)
//   点滅:0.25秒周期で点滅(0.05秒ON,0.20秒OFF)
//   Low点灯 :5ms周期、デューティ40%のPWMでLEDを点灯
//   Mid点灯 :5ms周期、デューティ60%のPWMでLEDを点灯
//   High点灯:5ms周期、デューティ80%のPWMでLEDを点灯
//
// クロックの設定
//   Clock            :4MHz
//   命令            :1us
//   プリスケーラ    :プリスケーラOFF
//   タイマ0(TMR0)    :250us(1us x 250 x 1)
//   PWM周期        :5ms(250us x 20)
//
// I/Oポートの設定
//   GP0 (7 pin):PWM出力
//   GP1 (6 pin):NC  (WPU)
//   GP2 (5 pin):NC  (WPU)
//   MCLR(4 pin):MCLR(このピンはチップにWPU機能なし)
//   GP4 (3 pin):NC  (WPU)
//   GP5 (2 pin):NC  (WPU)

#include <htc.h>

// タイマ割込みの周期 250us(1カウント=1us)
// カウントアップ方式なので256-250を設定するただし、
// 割り込みにより再設定するので+アルファの調整が必要
#define TIMER_250us        (6+18)
// PWM点滅周期 5ms(=250us*20)
#define    PWM_5MS            20
// PWMのデューティ 40%(=8/20) 80%(=16/20)
#define    PWM_DUTY20        4
#define    PWM_DUTY40        8
#define    PWM_DUTY60        12
#define    PWM_DUTY80        16
// 点滅周期 0.25秒(=5ms*50)
#define    BLINK_250MS        50
// 点滅のON期間 100%=(50/50) 20%(=10/50)
#define BLINK_DUTY100    50
#define BLINK_DUTY20    10
// 点滅のMODE
#define MODE_BLINK        0
#define MODE_LOW            1
#define MODE_MID            2
#define MODE_HIGH            3

unsigned char pwm_cnt;            // PWMの一周期(5ms)をカウント
unsigned char pwm_h_cnt;        // PWMのHigh期間をカウント(1us/1カウント)
unsigned char pwm_h_width;    // PWMのHパルス幅
bit           pwm_h_flg;        // PWMのHigh期間を示すフラグ

unsigned char blink_cnt;        // 点滅の一周期(0.25sec)をカウント
unsigned char blink_h_cnt;    // 点滅のHigh期間をカウント(5ms/1カウント)
unsigned char blink_h_width;// 点滅のHigh期間の幅
bit           blink_h_flg;    // 点滅のHigh期間を示すフラグ

bit           t5ms_flg;            // 5ms周期で立つフラグ

unsigned char mode;                    // 点灯モード
bit           mode_b0_flg;    // 点灯モードのbit0
bit           mode_b1_flg;    // 点灯モードのbit1

__CONFIG(
   FOSC_INTRCIO    // INTOSC oscillator, I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKI
 & WDTE_ON            // WDT enabled
// & WDTE_OFF            // WDT disabled
 & PWRTE_ON            // PWRT enabled (74ms reset)
 & MCLRE_ON            // GP3/MCLR pin function is MCLR
 & BOREN_ON            // Brown-out Detect(BOD) enabled
// & BOREN_OFF        // Brown-out Detect(BOD) disabled
 & CP_OFF                // Program Memory code protection is disabled
 & CPD_OFF);        // Data memory code protection is disabled

// =================== 割り込み処理 ====================
void interrupt ISR(void) {

    TMR0 = TIMER_250us;            // TIMERのリロード
    T0IF = 0;                                // TMR0割り込みクリア

    if(!(--pwm_cnt)){                // -1してから0判定
        t5ms_flg = 1;                    // 5ms周期でmain関数にフラグを渡す
                                                    // PWMの1周期終了 次の設定を行う
        pwm_cnt = PWM_5MS;         // PWMの1周期カウンタを初期化
        pwm_h_cnt = pwm_h_width;// PWMのHパルス幅を設定
        pwm_h_flg = 1;                // PWMのH期間を示す
    }else{
        if(!(--pwm_h_cnt)){        // -1してから0判定
            pwm_h_flg = 0;            // PWMのH期間終了(カウンターはオーバーランする)
        }
    }

    GP0=pwm_h_flg & blink_h_flg;    // PWMがH期間かつ、点滅のH期間にONにする。
}
// ==================== ノイズに強くするために頻繁に再設定する値 ===========================
void init_periodic(void) {
    // コンパレータの設定
    CMCON  = 0b00000111;
                // 0 (COUT)
                // 0 (CINV)
                // 0 (CIS)
                // 111 (CM=111:コンパレータOFF)
#ifdef __PIC12F675_H
    // ADの設定
    ANSEL  = 0b00000000;
                // 0,000(Tad=2xTosc:2us),0000(AN3-0 OFF)
    ADCON0 = 0b00000000;
                // 0  (ADFM 0:AD変換データ左詰め, 1:右詰め)
                // 0  (VCFG 0:Vref=VDD, 1:Vref=Vref pin)
                // 00 (NU 00:初期値)
                // 00 (CHSx 00:アナログ入力ピンAN0, 00:AN0)
                // 0  (GODONE 0read:変換終了 1read/write:変換スタート)
                // 0  (ADON 0:ADC電源OFF, 1:ON)
#endif
    // I/Oの設定
    TRISIO = 0b00111110;
                // 00,111110(TRISIO5-0:GPIOの出力は0,入力は1)
    WPU    = 0b00111110;
                // 00,111010(WPU5-0:1でプルアップ,0で使わない)

    // WPUとタイマーの設定
    OPTION_REG = 0b00011000;
                //0 (nGPPU  1:WPU使わない, 0:WPU使う)
                //0 (INTEDG 1:INTピン立上がりエッジ, 0:立下り)
                //0 (T0CS   1:タイマ0のクロックを外部クロック使用, 0:内部クロックを使用)
                //1 (T0SE   1:タイマ0を外部クロックの立上がり同期, 0:立下り同期)
                //1 (PSA    1:プリスケーラをWDTで使用, 0:タイマで使用)
                //000 (PSx   (000:1/1 WDT プリスケーラ 18ms)

    if(mode==MODE_HIGH){                    // High点灯のパラメータ設定
        blink_h_width = BLINK_DUTY100;    // 点灯の場合は周期と同じ値を設定
        pwm_h_width   = PWM_DUTY80;            // PWMのHパルス幅を設定
    }else if(mode==MODE_MID){            // MID点灯のパラメータ設定
        blink_h_width = BLINK_DUTY100;    // 点灯の場合は周期と同じ値を設定
        pwm_h_width   = PWM_DUTY60;            // PWMのHパルス幅を設定
    }else if(mode==MODE_LOW){            // LOW点灯のパラメータ設定
        blink_h_width = BLINK_DUTY100;    // 点灯の場合は周期と同じ値を設定
        pwm_h_width   = PWM_DUTY40;            // PWMのHパルス幅を設定
    }else{                                                // 点滅のパラメータ設定
        blink_h_width = BLINK_DUTY20;        // 点滅の場合は点灯期間の長さを設定
        pwm_h_width   = PWM_DUTY40;            // PWMのHパルス幅を設定
    }
}

// ==================== 起動時に1回だけ設定する値 ===========================
void init_once(void) {

    pwm_cnt   = 1;        //次の割り込みで初期化が発生する値
    blink_cnt = 1;        //次の割り込みで初期化が発生する値

    pwm_h_flg = 0;        // 最初の出力は0
    blink_h_flg = 0;    // 最初の出力は0

    TMR0 = TIMER_250us;    // TIMER周期 250us

    GP0 = 0;            // LED消灯

    T0IE = 1;            // TMR0割り込み許可
    GIE = 1;            // 全体割り込み許可
}

// ==================== メイン処理 ===========================
void main(void)    {

    // モード記憶用変数のリフレッシュ
    // この記述が無いとSRAMの内容は破壊されます。
    mode_b0_flg  = !mode_b0_flg;
    mode_b0_flg  = !mode_b0_flg;

    mode_b1_flg  = !mode_b1_flg;
    mode_b1_flg  = !mode_b1_flg;

    if(!nPOR){
        // Power On リセットの時は点滅に設定
        mode_b0_flg  = MODE_BLINK&1;
        mode_b1_flg  = (MODE_BLINK>>1)&1;
    }else{
        //modeの個別ビットを一つの変数modeに変換
        mode = mode_b0_flg | (mode_b1_flg <<1 );
        //modeをインクリメント
        mode++;
        mode&=3;
        //mode変数を個別のビットに分解して格納
        mode_b0_flg=(mode&1)?1:0;
        mode_b1_flg=(mode&2)?1:0;
    }
    nPOR=1;    //Power On リセットフラグをクリア

    init_periodic();    // 周期的設定

    init_once();            // 起動時設定

    CLRWDT();                    // ウォッチドッグのクリア
    while(1) {
        init_periodic();    // 周期的設定

        if(t5ms_flg){        // 5ms間隔のpwm周期で実行
            t5ms_flg = 0;
            CLRWDT();            // ウォッチドッグのクリア

            if(!(--blink_cnt)){                    // -1してから0判定
                                                                    // 点滅の1周期終了
                blink_cnt = BLINK_250MS;    // 点滅の1周期カウンタを初期化
                blink_h_cnt=blink_h_width;// 点滅のパルス幅を設定
                blink_h_flg=1;                        // 点滅のH期間を示す
            }else{
                if(!(--blink_h_cnt)){            // -1してから0判定
                    blink_h_flg=0;                    // 点滅のH期間終了(カウンターはオーバーランする)
                }
            }
        }
    }
}
[ 2012/01/09 20:38 ] 改造 - ライト | TB(0) | CM(4)
書記長、明けましておめでとうございます!!

メカ屋のアッシには理解不能な図が並んでますが・・・

 ところで、肋骨はもう完治ですかっ!???
[ 2012/01/10 08:40 ] [ 編集 ]
会長、明けましておめでとうございます。

肋骨は治りました。
でも、富士山までに少し鍛えないと・・・
[ 2012/01/10 23:15 ] [ 編集 ]
初めまして。アメリカ在住47年の者ですが、LEDへの電流制御はどのようにしているのかを教えて下さい。回路図を見るかぎり抵抗(resistor)とかがLED付近に無いですが。。。

ご返事有難うございました。こんな方法もあるのかと驚きました。多分この方式はメーカーの部品又は値段のの節約になるからかと思いますが、LEDの Lumen/watt の効率(efficiency)は、大分悪くなると思います。
[ 2015/04/24 10:56 ] [ 編集 ]
池田さんこんばんは、コメントありがとうございます。

確かにその通りです。初めて見た時私もビックリしました。パルス駆動の為、瞬間電力はトランジスタやLEDの定格を超えています。ものによっては、0.5オーム程度の電流制限抵抗が付いているものもあります。経験的には昇圧回路無しであれば、壊れたことはないです。昇圧回路付きは壊れます。
[ 2015/04/25 21:34 ] [ 編集 ]
コメントの投稿













管理者にだけ表示を許可する
プロフィール

けんちゃん

Author:けんちゃん
東京在住、和歌山生まれ
自称、和田峠ニスト
中華カーボンと手組みホイールでシクロクロス参戦中