
愛車のバイクVFRのウインカーをLEDに換装する作業が終わりました。
ウインカー系統をLEDに換装する場合は、ウインカーリレーもLED対応型に変更しなければなりません。今回、私の場合はこの部分も自作をすることにしたのでした。
心臓部にマイコンチップを搭載し、各種の動作をソフトウェアから指令するのです。もちろん、『オンスタート動作』(ウインカーを投入した直後から点灯サイクルが始まる)にもこだわり、回路の設計もしました。
この日記では、自分がどのように考えて回路を作ったり、苦労をしたのかを包み隠さず書き込んでいるのですが、一つだけ公開していない部分がありました。
『マイコンチップ内で動くプログラム』です。
https://…/2006/01/11/ ウインカーLED化計画・オンスタート回路
https://…/2006/01/18/ ウインカーLED化計画・論理回路
https://…/2006/01/24/ ウインカーLED化計画・制御ソフトウェア製作
別に隠していたわけではないのですが、簡単に変更できる特徴があるため微調整がしやすく、ちょくちょくプログラムを書き換えては走行試験を繰り返していたのでしたが、初期段階としての『とりあえず安定のαリリース』が完成したのでした。
プログラムが読めない方でも、雰囲気ぐらいつかんでもらえればと思いまして、ココに乗せておきます。
何度かはこの日記に登場してはいますが、『プログラムはステートと呼ぶ状態間を、ある条件で推移する』という設計になっています。
![]() |
・ステート推移図 |
興味がある方は、クリックしてみてください。興味の無い方は頭痛になるのでやめておきましょう。
;****************************************************************************** ; 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*