ウインカーLED化計画その後・マイコンチッププログラムのソースコード

愛車のバイクVFRのウインカーをLEDに換装する作業が終わりました。
ウインカー系統をLEDに換装する場合は、ウインカーリレーもLED対応型に変更しなければなりません。今回、私の場合はこの部分も自作をすることにしたのでした。

心臓部にマイコンチップを搭載し、各種の動作をソフトウェアから指令するのです。もちろん、『オンスタート動作』(ウインカーを投入した直後から点灯サイクルが始まる)にもこだわり、回路の設計もしました。
この日記では、自分がどのように考えて回路を作ったり、苦労をしたのかを包み隠さず書き込んでいるのですが、一つだけ公開していない部分がありました。
マイコンチップ内で動くプログラム』です。

https://…/2006/01/11/ ウインカーLED化計画・オンスタート回路
https://…/2006/01/18/ ウインカーLED化計画・論理回路
https://…/2006/01/24/ ウインカーLED化計画・制御ソフトウェア製作

別に隠していたわけではないのですが、簡単に変更できる特徴があるため微調整がしやすく、ちょくちょくプログラムを書き換えては走行試験を繰り返していたのでしたが、初期段階としての『とりあえず安定のαリリース』が完成したのでした。
プログラムが読めない方でも、雰囲気ぐらいつかんでもらえればと思いまして、ココに乗せておきます。


何度かはこの日記に登場してはいますが、『プログラムはステートと呼ぶ状態間を、ある条件で推移する』という設計になっています。

f:id:vfr750f2:20060118225328g:plain
・ステート推移図


興味がある方は、クリックしてみてください。興味の無い方は頭痛になるのでやめておきましょう。

;******************************************************************************
;       PIC 16F84A ウインカーリレープログラム Ver 3.03
;------------------------------------------------------------------------------
;       クロック入力    4MHz    1命令4クロック --> 1uS/1命令
;******************************************************************************

        LIST    P=PIC16F84A
        INCLUDE "P16F84A.INC"

        __config        _CP_OFF & _PWRTE_ON & _WDT_ON & _HS_OSC


;====== 定数定義 ==============================================================
WKin            EQU     0               ;PORT-A:ウインカー電流検知入力ビット
PSin            EQU     5               ;PORT-A:ポディションランプ検知入力ビット
HZin            EQU     6               ;PORT-A:ハザードスイッチ入力ビット
WKout           EQU     2               ;PORT-B:ウインカーFETゲート出力
PSout           EQU     1               ;PORT-B:ポディションランプFETゲート出力
HZout           EQU     0               ;PORT-B:ハザードFETゲート出力

INTVAL          EQU     d'173'          ;ウインカ点滅周期定数   ;[V3]
WAITVAL         EQU     d'4'            ;ノイズ対策安定待ち定数 ;[V3]

;メモリマップ
CNT_WKONOFF     EQU     0x4f            ;点滅周期ユーザーカウンタ用メモリ
CNTnMS          EQU     0x4e            ;nmSウエイト用メモリ
CNTBITCNT       EQU     0x4d            ;[V3]ノイズ対策用ビット監視カウンタ

;====== ブートストラップ ======================================================
        ORG     00H                     ; プログラム配置アドレス指定
        GOTO    INIT

        ORG     04H
INIT
        BSF     STATUS,RP0              ; Bank 1 へ切替
        BCF     INTCON,GIE              ; 割り込みは使用しない
;テスト中だけは静電気対策でプルアップを有効にしておく
        BSF     OPTION_REG,NOT_RBPU     ; PortB 入力プルアップ抵抗を無効にする
        MOVLW   b'11100001'             ; PortB b0b5b6b7を入力に設定
        MOVWF   TRISB                   ; PortB b0b5b6b7を入力に設定
        CLRF    TRISA                   ; PortA 全ポートを出力に設定
        BCF     STATUS,RP0              ; Bank 0 へ戻る

;====== アイドルステート ======================================================
;
START_IDLE
        CLRWDT                          ; ウォッチドックタイマリセット
        BCF     PORTA,PSout             ; PS出力OFF
        BCF     PORTA,HZout             ; HZ出力OFF
        BSF     PORTA,WKout             ; WK出力ON…電流検知のため

LOOP_IDLE
        CLRWDT                          ; ウォッチドックタイマリセット

        BTFSC   PORTB,WKin              ; ウインカ電流を検知した場合は
        GOTO    START_WINK              ; ウインカステートへ

        ;[V3]ノイズ対策・n回連続で信号検知してからポディションステートへ
;[V3]   BTFSC   PORTB,PSin              ; ホディションランプ検知の場合は
;[V3]   GOTO    START_POSIDLE           ; ポディションランプ付きアイドルステートへ
        BTFSS   PORTB,PSin              ;[V3]1  ホディションランプ非検知の場合は
        GOTO    IDLE1                   ;[V3]   アイドルステート継続
        BTFSS   PORTB,PSin              ;[V3]2
        GOTO    IDLE1                   ;[V3]
        BTFSS   PORTB,PSin              ;[V3]3
        GOTO    IDLE1                   ;[V3]
        BTFSS   PORTB,PSin              ;[V3]4
        GOTO    IDLE1                   ;[V3]
        BTFSS   PORTB,PSin              ;[V3]5
        GOTO    IDLE1                   ;[V3]
        GOTO    START_POSIDLE

IDLE1
        ;[V3]ノイズ対策・n回連続で信号検知してからハザードステートへ
;[V3]   BTFSC   PORTB,HZin              ; ハザードスイッチ検知の場合は
;[V3]   GOTO    START_HAZ               ; ハザードステートへ
        BTFSS   PORTB,HZin              ;[V3]1
        GOTO    IDLE2                   ;[V3]
        BTFSS   PORTB,HZin              ;[V3]2
        GOTO    IDLE2                   ;[V3]
        BTFSS   PORTB,HZin              ;[V3]3
        GOTO    IDLE2                   ;[V3]
        BTFSS   PORTB,HZin              ;[V3]4
        GOTO    IDLE2                   ;[V3]
        BTFSS   PORTB,HZin              ;[V3]5
        GOTO    IDLE2                   ;[V3]
        GOTO    START_HAZ               ;[V3]

IDLE2
        GOTO    LOOP_IDLE


;====== ポディションランプ付きアイドルステート ================================
;
START_POSIDLE
        CLRWDT                          ; ウォッチドックタイマリセット
        BCF     PORTA,HZout             ; HZ出力OFF
        BSF     PORTA,PSout             ; PS出力ON…ホディションランプ点灯
        BSF     PORTA,WKout             ; WK出力ON…電流検知のため

LOOP_POSIDLE
        CLRWDT                          ; ウォッチドックタイマリセット

        BTFSC   PORTB,WKin              ; ウインカ電流を検知した場合は
        GOTO    POS_TO_WINK             ; ウインカ移行ステートへ

        ;[V3]ノイズ対策・n回連続で信号非検知してからアイドルステートへ
;[V3]   BTFSS   PORTB,PSin              ; ホディションランプ非検知の場合は
;[V3]   GOTO    START_IDLE              ; アイドルステートへ
        BTFSC   PORTB,PSin              ;[V3]
        GOTO    POSIDLE11               ;[V3]
        BTFSC   PORTB,PSin              ;[V3]
        GOTO    POSIDLE12               ;[V3]
        BTFSC   PORTB,PSin              ;[V3]
        GOTO    POSIDLE13               ;[V3]
        BTFSC   PORTB,PSin              ;[V3]
        GOTO    POSIDLE14               ;[V3]
        BTFSC   PORTB,PSin              ;[V3]
        GOTO    POSIDLE15               ;[V3]
        GOTO    START_IDLE              ;[V3]

POSIDLE11
        NOP
POSIDLE12
        NOP
POSIDLE13
        NOP
POSIDLE14
        NOP
POSIDLE15
        ;[V3]ノイズ対策・n回連続で信号非検知してからハザードステートへ
;[V3]   BTFSC   PORTB,HZin              ; ハザードスイッチ検知の場合は
;[V3]   GOTO    POS_TO_HAZ              ; ハザードステートへ
        BTFSS   PORTB,HZin              ;[V3]
        GOTO    POSIDLE21               ;[V3]
        BTFSS   PORTB,HZin              ;[V3]
        GOTO    POSIDLE22               ;[V3]
        BTFSS   PORTB,HZin              ;[V3]
        GOTO    POSIDLE23               ;[V3]
        BTFSS   PORTB,HZin              ;[V3]
        GOTO    POSIDLE24               ;[V3]
        BTFSS   PORTB,HZin              ;[V3]
        GOTO    POSIDLE25               ;[V3]
        GOTO    POS_TO_HAZ

POSIDLE21
        NOP
POSIDLE22
        NOP
POSIDLE23
        NOP
POSIDLE24
        NOP
POSIDLE25
        GOTO    LOOP_POSIDLE

        ;ウインカ移行ステート
        ;ポディションからウインカーに移行させるときは短時間消灯させ、ウインカーブザーを鳴動させる
POS_TO_WINK
        BCF     PORTA,HZout             ;[V3]HZ出力OFF
        BCF     PORTA,PSout             ;[V3]PS出力OFF
        BCF     PORTA,WKout             ;[V3]WK出力OFF
        CALL    WAIT2MS                 ;[V3]
        CALL    WAIT2MS                 ;[V3]
        CALL    WAIT2MS                 ;[V3]
        CALL    WAIT2MS                 ;[V3]
        CALL    WAIT2MS                 ;[V3]
        GOTO    START_WINK              ;[V3]

        ;ハザード移行ステート
        ;ポディションからハザードに移行させるときは短時間消灯させ、ウインカーブザーを鳴動させる
POS_TO_HAZ
        BCF     PORTA,HZout             ;[V3]HZ出力OFF
        BCF     PORTA,PSout             ;[V3]PS出力OFF
        BCF     PORTA,WKout             ;[V3]WK出力OFF
        CALL    WAIT2MS                 ;[V3]
        CALL    WAIT2MS                 ;[V3]
        CALL    WAIT2MS                 ;[V3]
        CALL    WAIT2MS                 ;[V3]
        CALL    WAIT2MS                 ;[V3]
        GOTO    START_HAZ               ;[V3]

;====== ウインカステート ======================================================
;
START_WINK
        CLRWDT                          ; ウォッチドックタイマリセット
        BCF     PORTA,PSout             ; PS出力OFF
        BCF     PORTA,HZout             ; HZ出力OFF
        BSF     PORTA,WKout             ; WK出力ON…ウインカ点灯

LOOP_WINK
        ;****** ウインカ点灯待機 **********************************************
        CLRWDT                          ; ウォッチドックタイマリセット          ;1step -->      1step
        BSF     PORTA,WKout             ; WK出力ON…ウインカ点灯                ;1step -->      2step

        ;電流が安定するまで10mSは待機
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->   2002step
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->   4002step
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->   6002step
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->   8002step
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->  10002step
        CALL    WAIT1MS                 ; 1mS --> 1000step                      ;      -->  11002step

        MOVLW   INTVAL                  ; ループ回数の初期値をセット            ;1step -->  11003step
        MOVWF   CNT_WKONOFF             ;                                       ;1step -->  11004step

        MOVLW   WAITVAL                 ;[V3]ノイズ対策用ビット監視カウンタをリセット  -->  11005step
        MOVWF   CNTBITCNT               ;[V3]                                          -->  11006step

LOOP_WINK_ON                                                                    ;ループ内  2013step
        CLRWDT                          ; ウォッチドックタイマリセット          ;1step -->    1step

        ;[V3]ノイズ対策・n回連続で信号非検知してからハザードステートへ
;[V3]   BTFSC   PORTB,HZin              ; ハザードスイッチ検知の場合は          
;[V3]   GOTO    START_HAZ               ; ハザードステートへ                    
        BTFSS   PORTB,HZin              ;[V3]                                   ;1step -->    2step
        GOTO    LOOP_WINK01                                                     ;2step -->    4step
        BTFSS   PORTB,HZin              ;[V3]
        GOTO    LOOP_WINK02
        BTFSS   PORTB,HZin              ;[V3]
        GOTO    LOOP_WINK03
        BTFSS   PORTB,HZin              ;[V3]
        GOTO    LOOP_WINK04
        BTFSS   PORTB,HZin              ;[V3]
        GOTO    LOOP_WINK05
        GOTO    START_HAZ

LOOP_WINK01
        NOP
LOOP_WINK02
        NOP
LOOP_WINK03
        NOP
LOOP_WINK04
        NOP
LOOP_WINK05
        BTFSS   PORTB,WKin              ; ウインカ電流が検知できない場合は      ;1step -->    5step
        DECF    CNTBITCNT,1             ;[V3]電流非検知でカウントダウン         ;1step -->    6step

        INCF    CNTBITCNT,1             ;[V3]一度足してから引くことで           ;1step -->    7step
        DECFSZ  CNTBITCNT,1             ;[V3]カウンタ値が0か照合する            ;1step -->    8step
        GOTO    LOOP_WINK1              ;[V3]                                   ;2step -->   10step
        GOTO    START_IDLE              ;[V3]カウンタ値が0ならアイドルステートへ;これはループと関係ない

LOOP_WINK1
        CALL    WAIT2MS                                                         ;      --> 2010step

        DECFSZ  CNT_WKONOFF,1           ; ループカウンタを減算し                ;1step --> 2011step
        GOTO    LOOP_WINK_ON            ; 結果が0以外であればLOOP_WINK_ONへ     ;2step --> 2013step


        ;****** ウインカ消灯待機 **********************************************
        CLRWDT                          ; ウォッチドックタイマリセット          ;1step -->     1step
        BCF     PORTA,WKout             ; WK出力OFF…ウインカ消灯               ;1step -->     2step

        ;点灯期間とタイミングを合わせるためのウエイト
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->   2002step
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->   4002step
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->   6002step
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->   8002step
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->  10002step
        CALL    WAIT1MS                 ; 1mS --> 1000step                      ;      -->  11002step

        MOVLW   INTVAL                  ; ループ回数の初期値をセット            ;1step -->  11003step
        MOVWF   CNT_WKONOFF             ;                                       ;1step -->  11004step

        NOP                             ;[V3]                                          -->  11005step
        NOP                             ;[V3]                                          -->  11006step

LOOP_WINK_OFF                                                                   ;ループ内 2008step
        CLRWDT                          ; ウォッチドックタイマリセット          ;1step -->     1step
;[V3]   BTFSC   PORTB,HZin              ; ハザードスイッチ検知の場合は          
;[V3]   GOTO    START_HAZ               ; ハザードステートへ                    
        BTFSS   PORTB,HZin              ;[V3]                                   ;1step -->    2step
        GOTO    LOOP_WINK21                                                     ;2step -->    4step
        BTFSS   PORTB,HZin              ;[V3]
        GOTO    LOOP_WINK22
        BTFSS   PORTB,HZin              ;[V3]
        GOTO    LOOP_WINK23
        BTFSS   PORTB,HZin              ;[V3]
        GOTO    LOOP_WINK24
        BTFSS   PORTB,HZin              ;[V3]
        GOTO    LOOP_WINK25
        GOTO    START_HAZ

LOOP_WINK21
        NOP                             ; ウインカ電流を切っているため          ;1step -->     5step
LOOP_WINK22
        NOP                             ; 電流検知はしない                      ;1step -->     6step
LOOP_WINK23
        NOP                             ;                                       ;1step -->     7step
LOOP_WINK24
        NOP                             ;                                       ;1step -->     8step
LOOP_WINK25
        NOP                             ;                                       ;1step -->     9step
        NOP                             ;                                       ;1step -->    10step

        CALL    WAIT2MS                                                         ;      -->  2010step

        DECFSZ  CNT_WKONOFF,1           ; ループカウンタを減算し                ;1step -->  2011step
        GOTO    LOOP_WINK_OFF           ; 結果が0以外であればLOOP_WINK_OFFへ    ;関係ない

        GOTO    LOOP_WINK                                                       ;2step -->  2013step



;====== ハザードステート ======================================================
;
START_HAZ
        CLRWDT                          ; ウォッチドックタイマリセット
        BCF     PORTA,WKout             ; WK出力OFF
        BCF     PORTA,PSout             ; PS出力OFF
        BSF     PORTA,HZout             ; HZ出力ON…ハザード点灯

LOOP_HAZ
        ;****** ハザード点灯待機 **********************************************
        CLRWDT                          ; ウォッチドックタイマリセット          ;1step -->      1step
        BSF     PORTA,HZout             ; HZ出力ON…ハザード点灯                ;1step -->      2step

        ;ウインカーとタイミングを合わせるため10mSは待機
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->   2002step
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->   4002step
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->   6002step
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->   8002step
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->  10002step
        CALL    WAIT1MS                 ; 1mS --> 1000step                      ;      -->  11002step

        MOVLW   INTVAL                  ; ループ回数の初期値をセット            ;1step -->  11003step
        MOVWF   CNT_WKONOFF             ;                                       ;1step -->  11004step

        NOP                             ;[V3]                                   ;1step -->  11005step
        NOP                             ;[V3]                                   ;1step -->  11006step

LOOP_HAZ_ON                                                                     ;ループ内  2013step
        CLRWDT                          ; ウォッチドックタイマリセット          ;1step -->     1step
;[V3]   BTFSS   PORTB,HZin              ; ハザードスイッチ非検知の場合は        
;[V3]   GOTO    START_IDLE              ; アイドルステートへ                    
        BTFSC   PORTB,HZin              ;[V3]                                   ;1step -->    2step
        GOTO    LOOP_HAZ11              ;[V3]                                   ;2step -->    4step
        BTFSC   PORTB,HZin              ;[V3]
        GOTO    LOOP_HAZ12              ;[V3]
        BTFSC   PORTB,HZin              ;[V3]
        GOTO    LOOP_HAZ13              ;[V3]
        BTFSC   PORTB,HZin              ;[V3]
        GOTO    LOOP_HAZ14              ;[V3]
        BTFSC   PORTB,HZin              ;[V3]
        GOTO    LOOP_HAZ15              ;[V3]
        GOTO    START_IDLE              ;[V3]

LOOP_HAZ11
        NOP                             ;                                       ;1step -->     5step
LOOP_HAZ12
        NOP                             ;                                       ;1step -->     6step
LOOP_HAZ13
        NOP                             ;                                       ;1step -->     7step
LOOP_HAZ14
        NOP                             ;                                       ;1step -->     8step
LOOP_HAZ15
        NOP                             ;                                       ;1step -->     9step
        NOP                             ;                                       ;1step -->    10step

        CALL    WAIT2MS                                                         ;      -->  2010step

        DECFSZ  CNT_WKONOFF,1           ; ループカウンタを減算し                ;1step -->  2011step
        GOTO    LOOP_HAZ_ON             ; 結果が0以外であればLOOP_HAZ_ONへ      ;2step -->  2013step


        ;****** ハザード消灯待機 **********************************************
        CLRWDT                          ; ウォッチドックタイマリセット          ;1step -->     1step
        BCF     PORTA,HZout             ; HZ出力OFF…ハザード消灯               ;1step -->     2step

        ;点灯期間とタイミングを合わせるためのウエイト
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->   2002step
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->   4002step
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->   6002step
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->   8002step
        CALL    WAIT2MS                 ; 2mS --> 2000step                      ;      -->  10002step
        CALL    WAIT1MS                 ; 1mS --> 1000step                      ;      -->  11002step

        MOVLW   INTVAL                  ; ループ回数の初期値をセット            ;1step -->  11003step
        MOVWF   CNT_WKONOFF             ;                                       ;1step -->  11004step

        NOP                             ;[V3]                                          -->  11005step
        NOP                             ;[V3]                                          -->  11006step

LOOP_HAZ_OFF
        CLRWDT                          ; ウォッチドックタイマリセット          ;1step -->     1step
;[V3]   BTFSS   PORTB,HZin              ; ハザードスイッチ非検知の場合は        
;[V3]   GOTO    START_IDLE              ; アイドルステートへ                    
        BTFSC   PORTB,HZin              ;[V3]                                   ;1step -->     2step
        GOTO    LOOP_HAZ21              ;[V3]                                   ;2step -->     4step
        BTFSC   PORTB,HZin              ;[V3]
        GOTO    LOOP_HAZ22              ;[V3]
        BTFSC   PORTB,HZin              ;[V3]
        GOTO    LOOP_HAZ23              ;[V3]
        BTFSC   PORTB,HZin              ;[V3]
        GOTO    LOOP_HAZ24              ;[V3]
        BTFSC   PORTB,HZin              ;[V3]
        GOTO    LOOP_HAZ25              ;[V3]
        GOTO    START_IDLE              ;[V3]

LOOP_HAZ21
        NOP                             ;                                       ;1step -->     5step
LOOP_HAZ22
        NOP                             ;                                       ;1step -->     6step
LOOP_HAZ23
        NOP                             ;                                       ;1step -->     7step
LOOP_HAZ24
        NOP                             ;                                       ;1step -->     8step
LOOP_HAZ25
        NOP                             ;                                       ;1step -->     9step
        NOP                             ;                                       ;1step -->    10step

        CALL    WAIT2MS                                                         ;      -->  2010step

        DECFSZ  CNT_WKONOFF,1           ; ループカウンタを減算し                ;1step -->  2011step
        GOTO    LOOP_HAZ_OFF            ; 結果が0以外であればLOOP_HAZ3へ        ;2step -->  2013step

        GOTO    LOOP_HAZ


;====== サブルーチン ==========================================================
;       2mS = 2000Step
WAIT2MS                                 ;2step コールするのにすでに2step掛かっている
        ;Last 1998step
        MOVLW   d'199'                  ;1step
        MOVWF   CNTnMS                  ;1step
        ;Last 1996step
        NOP
        NOP
        NOP
        NOP
        ;Last 1992step
LOOP_2MS                                ;10step * 199 = 1990step
        CLRWDT                          ;1step -->  1step
        NOP                             ;1step -->  2step
        NOP                             ;1step -->  3step
        NOP                             ;1step -->  4step
        NOP                             ;1step -->  5step
        NOP                             ;1step -->  6step
        NOP                             ;1step -->  7step
        DECFSZ  CNTnMS,1                ;1step -->  8step
        GOTO    LOOP_2MS                ;2step --> 10step

        ;Last 2step
        RETURN                          ;2step

;====== サブルーチン ==========================================================
;       1mS = 1000Step
WAIT1MS                                 ;2step コールするのにすでに2step掛かっている
        ;Last 998step
        MOVLW   d'99'                   ;1step
        MOVWF   CNTnMS                  ;1step
        ;Last 996step
        NOP
        NOP
        NOP
        NOP
        ;Last 992step
LOOP_1MS                                ;10step * 99 = 990step
        CLRWDT                          ;1step -->  1step
        NOP                             ;1step -->  2step
        NOP                             ;1step -->  3step
        NOP                             ;1step -->  4step
        NOP                             ;1step -->  5step
        NOP                             ;1step -->  6step
        NOP                             ;1step -->  7step
        DECFSZ  CNTnMS,1                ;1step -->  8step
        GOTO    LOOP_1MS                ;2step --> 10step

        ;Last 2step
        RETURN                          ;2step

        END
;*end*
https://…/2006/08/31/ ウインカーLED化計画・LEDウインカーバルブVer.2を作ろう!