LED警光灯の自作(プログラムは簡単)

実は PIC マイコンを触るのは前作の LED 警光灯から! すなわち超初心者であり、入門書を読んで LED の点滅プログラムから始まって、現在のところ LED 警光灯を作るにあたりなんとか基本的なところが分かったかなーというレベルである。

15 年くらい前までは PLL 式の消防・救急無線受信機を作ったり(基板から起こしてたヨ!)などと電子工作で遊んでいたのだが、そのうち別なことに興味が移り、長い事はんだごては押し入れの奥にしまっていた。 ところが今回ので再び電子工作熱が復活気味!

いや〜 PIC って面白いですね。 今までアナログでやってた事が、プログラム次第で何でも出来るのは二重の楽しみ。


えっ、さっさとプログラムを公開しやがれですか? はい。 上記理由でお見せするにはお恥ずかしいのですが、思い切って公開しやがりまくります。


↓ ここから

;PIC12F629で消防車・救急車のLED警光灯(大阪サイレン製)を再現
;DIP SW でフラッシュパターンを変更(トリプルフラッシュ(同時・交互)/ランダムフォー(同時・交互))
;2010/03/25 ver.1
;*********************************************
list p=12f629
#include

__CONFIG _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT

;*********************************************

i EQU 0x20 ;ループカウンタ用変数
j EQU 0x21 ;ループカウンタ用変数
k EQU 0x22 ;ループカウンタ用変数

MODE EQU 0x23; フラッシュ表示モード保存用変数

ORG 0x000
GOTO init

;割り込みハンドラ
ORG 0x004
retfie

;*********************************************
;初期化開始
init
;内部クロック補正
bsf STATUS,RP0 ;BANK=1
call 0x3ff
movwf OSCCAL
bcf STATUS,RP0 ;BANK=0
;割り込みを禁止
clrf INTCON
;コンパレータ使用禁止
movlw 0x07
movwf CMCON
;GPIO 0/1 を出力、2,3 を入力(2ビットDIPスイッチ用)に設定する
bsf STATUS,RP0 ;BANK=1
movlw b'11111100';GPIO 0/1 をLED出力に使用
movwf TRISIO
bcf STATUS,RP0 ;BANK=0

MOVLW b'00000000'
MOVWF MODE ; 0 → フラッシュモード(変数)リセット

;*********************************************
;DIPスイッチ状態判断処理。 プルアップ状態(ONで 0, OFFで 1)
sw_handan
movf GPIO,w ;DIPスイッチ状態を w レジスタに読み込み

;レジスタの値を2回右へシフトする
bcf STATUS,C ;キャリーフラグをリセット
movwf MODE ;w レジスタの値を MODE(変数) レジスタにコピー
rrf MODE,w ;MODE レジスタの内容を右へシフト、w レジスタに入れる
movwf MODE ;w レジスタの値を MODE(変数) レジスタにコピー
rrf MODE,w ;MODE レジスタの内容を右へシフト、w レジスタに入れる

andlw 0x0f ;w レジスタ上位4ビットマスク、下位4ビット取り出し
movwf MODE ;w レジスタの値を MODE レジスタに保存

;DIPスイッチ読み込み完了! DIPSWの状態が 0000(無効)|0011 の形で保存される。

;*********************************************
;DIPスイッチによるフラッシュパターン分岐処理
;DIP SW フラッシュパターン名
;DISP1 11 トリプルフラッシュ(同時)
;DISP2 10 トリプルフラッシュ(交互)
;DISP3 01 ランダムフォー(同時)
;DISP4 00 ランダムフォー(交互)

;チェック1
;トリプルフラッシュ(同時)
movlw b'00001111' ;全てOFF状態
subwf MODE,w ;MODE から w レジスタの値を引く
btfsc STATUS,Z ;結果が 0(Z フラグが立つ)だったら DISP1へ
GOTO DISP1

;チェック2
;トリプルフラッシュ(交互)
movlw b'00001110' ;DIP1のみON
subwf MODE,w ;MODE から w レジスタの値を引く
btfsc STATUS,Z ;結果が 0(Z フラグが立つ)だったら DISP2へ
GOTO DISP2

;チェック3
;ランダムフォー(同時)
movlw b'00001101' ;DIP2のみON
subwf MODE,w ;MODE から w レジスタの値を引く
btfsc STATUS,Z ;結果が 0(Z フラグが立つ)だったら DISP3へ
GOTO DISP3

;チェック4
;ランダムフォー(交互)
movlw b'00001100' ;DIP1,2がON
subwf MODE,w ;MODE から w レジスタの値を引く
btfsc STATUS,Z ;結果が 0(Z フラグが立つ)だったら DISP4へ
GOTO DISP4

GOTO sw_handan
;*********************************************
DISP1 ;トリプルフラッシュ(同時)
;ユニット1,2
movlw b'00000011';GPIO 0/1 をオン
movwf GPIO
movlw d'66' ;66ms遅延
movwf i
call DELAYms

movlw b'00000000';GPIO 0/1 をオフ
movwf GPIO
movlw d'33' ;33ms遅延
movwf i
call DELAYms

movlw b'00000011';GPIO 0/1 をオン
movwf GPIO
movlw d'66' ;66ms遅延
movwf i
call DELAYms

movlw b'00000000';GPIO 0/1 をオフ
movwf GPIO
movlw d'33' ;33ms遅延
movwf i
call DELAYms

movlw b'00000011';GPIO 0/1 をオン
movwf GPIO
movlw d'66' ;66ms遅延
movwf i
call DELAYms

movlw b'00000000';GPIO 0/1 をオフ
movwf GPIO
movlw d'200' ;トータル633ms遅延
movwf i
call DELAYms
movlw d'200'
movwf i
call DELAYms
movlw d'200'
movwf i
call DELAYms
movlw d'33'
movwf i
call DELAYms

goto sw_handan

DISP2 ;トリプルフラッシュ(交互)
;ユニット1
bsf GPIO,0 ;LEDオン
movlw d'66' ;66ms遅延
movwf i
call DELAYms

bcf GPIO,0 ;LEDオフ
movlw d'33' ;33ms遅延
movwf i
call DELAYms

bsf GPIO,0 ;LEDオン
movlw d'66' ;66ms遅延
movwf i
call DELAYms

bcf GPIO,0 ;LEDオフ
movlw d'33' ;33ms遅延
movwf i
call DELAYms

bsf GPIO,0 ;LEDオン
movlw d'66' ;66ms遅延
movwf i
call DELAYms

bcf GPIO,0 ;LEDオフ
movlw d'200' ;トータル633ms遅延
movwf i
call DELAYms
movlw d'200'
movwf i
call DELAYms
movlw d'200'
movwf i
call DELAYms
movlw d'33'
movwf i
call DELAYms

;ユニット2
bsf GPIO,1 ;LEDオン
movlw d'66' ;66ms遅延
movwf i
call DELAYms

bcf GPIO,1 ;LEDオフ
movlw d'33' ;33ms遅延
movwf i
call DELAYms

bsf GPIO,1 ;LEDオン
movlw d'66' ;66ms遅延
movwf i
call DELAYms

bcf GPIO,1 ;LEDオフ
movlw d'33' ;33ms遅延
movwf i
call DELAYms

bsf GPIO,1 ;LEDオン
movlw d'66' ;66ms遅延
movwf i
call DELAYms

bcf GPIO,1 ;LEDオフ
movlw d'200' ;トータル633ms遅延
movwf i
call DELAYms
movlw d'200'
movwf i
call DELAYms
movlw d'200'
movwf i
call DELAYms
movlw d'33'
movwf i
call DELAYms

goto sw_handan

DISP3;ランダムフォー(同時)
;ユニット1,2
movlw b'00000011';GPIO 0/1 をオン
movwf GPIO
movlw d'66' ;66ms遅延
movwf i
call DELAYms

movlw b'00000000';GPIO 0/1 をオフ
movwf GPIO
movlw d'33' ;33ms遅延
movwf i
call DELAYms

movlw b'00000011';GPIO 0/1 をオン
movwf GPIO
movlw d'33' ;33ms遅延
movwf i
call DELAYms

movlw b'00000000';GPIO 0/1 をオフ
movwf GPIO
movlw d'33' ;33ms遅延
movwf i
call DELAYms

movlw b'00000011';GPIO 0/1 をオン
movwf GPIO
movlw d'66' ;66ms遅延
movwf i
call DELAYms

movlw b'00000000';GPIO 0/1 をオフ
movwf GPIO
movlw d'33' ;33ms遅延
movwf i
call DELAYms

movlw b'00000011';GPIO 0/1 をオン
movwf GPIO
movlw d'33' ;33ms遅延
movwf i
call DELAYms

movlw b'00000000';GPIO 0/1 をオフ
movwf GPIO
movlw d'166' ;166ms遅延
movwf i
call DELAYms

movlw b'00000011';GPIO 0/1 をオン
movwf GPIO
movlw d'66' ;66ms遅延
movwf i
call DELAYms

movlw b'00000000';GPIO 0/1 をオフ
movwf GPIO
movlw d'100' ;100ms遅延
movwf i
call DELAYms

movlw b'00000011';GPIO 0/1 をオン
movwf GPIO
movlw d'66' ;66ms遅延
movwf i
call DELAYms

movlw b'00000000';GPIO 0/1 をオフ
movwf GPIO
movlw d'133' ;133ms遅延
movwf i
call DELAYms

goto sw_handan

DISP4;ランダムフォー(交互)
;ユニット1
bsf GPIO,0 ;LEDオン
movlw d'66' ;66ms遅延
movwf i
call DELAYms

bcf GPIO,0 ;LEDオフ
movlw d'33' ;33ms遅延
movwf i
call DELAYms

bsf GPIO,0 ;LEDオン
movlw d'33' ;33ms遅延
movwf i
call DELAYms

bcf GPIO,0 ;LEDオフ
movlw d'33' ;33ms遅延
movwf i
call DELAYms

bsf GPIO,0 ;LEDオン
movlw d'66' ;66ms遅延
movwf i
call DELAYms

bcf GPIO,0 ;LEDオフ
movlw d'33' ;33ms遅延
movwf i
call DELAYms

bsf GPIO,0 ;LEDオン
movlw d'33' ;33ms遅延
movwf i
call DELAYms

bcf GPIO,0 ;LEDオフ
movlw d'166' ;166ms遅延
movwf i
call DELAYms

bsf GPIO,0 ;LEDオン
movlw d'66' ;66ms遅延
movwf i
call DELAYms

bcf GPIO,0 ;LEDオフ
movlw d'100' ;100ms遅延
movwf i
call DELAYms

bsf GPIO,0 ;LEDオン
movlw d'66' ;66ms遅延
movwf i
call DELAYms

bcf GPIO,0 ;LEDオフ
movlw d'133' ;133ms遅延
movwf i
call DELAYms

;ユニット2
bsf GPIO,1 ;LEDオン
movlw d'66' ;66ms遅延
movwf i
call DELAYms

bcf GPIO,1 ;LEDオフ
movlw d'33' ;33ms遅延
movwf i
call DELAYms

bsf GPIO,1 ;LEDオン
movlw d'33' ;33ms遅延
movwf i
call DELAYms

bcf GPIO,1 ;LEDオフ
movlw d'33' ;33ms遅延
movwf i
call DELAYms

bsf GPIO,1 ;LEDオン
movlw d'66' ;66ms遅延
movwf i
call DELAYms

bcf GPIO,1 ;LEDオフ
movlw d'33' ;33ms遅延
movwf i
call DELAYms

bsf GPIO,1 ;LEDオン
movlw d'33' ;33ms遅延
movwf i
call DELAYms

bcf GPIO,1 ;LEDオフ
movlw d'166' ;166ms遅延
movwf i
call DELAYms

bsf GPIO,1 ;LEDオン
movlw d'66' ;66ms遅延
movwf i
call DELAYms

bcf GPIO,1 ;LEDオフ
movlw d'100' ;100ms遅延
movwf i
call DELAYms

bsf GPIO,1 ;LEDオン
movlw d'66' ;66ms遅延
movwf i
call DELAYms

bcf GPIO,1 ;LEDオフ
movlw d'133' ;133ms遅延
movwf i
call DELAYms

goto sw_handan

;*********************************************
;ミリ秒遅延ルーチン(1ms 〜 254ms まで)
;内部発振モード4Mhz用
;1命令サイクル = 1/4 クロック = 1x10^6 = 1/1,000,000 = 1μS

DELAYms: ;ix1000サイクル
CLRW ;Wをクリア
ADDWF i,W ;メインルーチンでのミリ秒設定値 i を
MOVWF j ;ループカウンタ j にセットする
;---------------------------
DELAY1k: ;1000サイクルの遅延ループ
MOVLW d'249' ;ループカウンタkに249をセットする
MOVWF k
LOOP1k:
NOP
DECFSZ k,f
GOTO LOOP1k ;2+4x249-1
;---------------------------
DECFSZ j,f ;3xj+997xj=1,000xj
GOTO DELAY1k
RETURN ;メインルーチンに戻る

END

↑ ここまで


ね? 命令を理解するために一つ一つコメントを書いてるでしょ。 ひょっとしたら無駄な処理をしてるかもしれない。 これを見て「オメェここをこうすれば良いですよ」とか言って頂けるともれなく嬉しいです。


↓ 自転車に実装

↓ 点灯

↓ さてお待ちかね!(待ってない?) 動作風景の動画をご覧ください。

左右交互点滅モードは実物を見る機会がないのでホントにこんな風にフラッシュするのか知らん。

↓ ここでもう一回この前のホンモノと比べると・・・


ウホっ! もう完ぺきですやん!!


↓ 最後にこの製品のカタログ(もどき)まで作っちゃいました!


次は PIC で救急車のサイレン音を再現できないだろうか実験に着手。


ていうか、LCARS アニメも作りたいし時間がねー