2020年12月5日土曜日

光るクリスマスオーナメント(その4:完成)

今日も朝から雨で寒い一日でした。晴れて暖かくなったらやることがあったのですが、寒かったので部屋で工作ができました。

光るクリスマスオーナメントがようやく完成です。裏表の雪の結晶はタッピングビスで固定することにしました。電池はカプトンテープで電線を貼り付けるだけです。電源は常にオンになりますが、明るいときはsleepしているので消費電力は僅かです。

表側です。

裏側です。

増えてきた観葉植物を越冬のためにリビングに入れたら部屋が狭くなってしまい、今年はツリーを出さないことに。その代わりに観葉植物をイルミネーションやオーナメントで飾り付けることにしました。

ベンジャミンにぶら下げてみたところです。イルミネーションが青色LEDと白色LEDなので、青っぽい絵面になっています。


イルミネーションが消えているとこんな感じです。

動画をアップしました。


電池はクリスマスまでもつ見積もりですが、どうなるでしょうか?


回路図です。

PICのソースです。バグがあるかもしれません。無保証です。著作権は留保しますが、利用や改変などご自由にどうぞ。

;---------------------------------------------------------------------
;  クリスマス・オーナメント
;
;                                                      2020.11.20 naka
;  1. I/Oポート
;
;   (1). 出力ポート
;        GP0-2:  LEDに繋ぐ
;   (2). 入力ポート
;        GP3  : CDSと抵抗でVDDを分圧し明るさをセンス(sleepからの復帰割り込み)
;
;  2. 光り方
;    ・4段階(フル,1/2,1/4,消灯)でランダムに点灯する。
;    ・時々高速に点滅
;    ・時々回転表示
;
;  3. 暗くなると自動点灯
;     普段はsleepしていて、暗くなるとGPIOの変化による割り込みで
;     sleepから復帰して点灯する。
;---------------------------------------------------------------------
	LIST	P=PIC12F675
	INCLUDE	"P12F675.INC"
	__CONFIG _CPD_OFF & _CP_OFF & _BODEN_OFF & _MCLRE_OFF & _PWRTE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT
	ERRORLEVEL	-302	;アセンブル時のバンク警告メッセージ抑制
;---------------------------------------------------------------------
;  マクロ定義
;---------------------------------------------------------------------
BANK0	MACRO
	BCF	STATUS,RP0	;BANK0に切り替える
	ENDM
BANK1	MACRO
	BSF	STATUS,RP0	;BANK1に切り替える
	ENDM
;---------------------------------------------------------------------
;  変数レジスタの定義
;---------------------------------------------------------------------
CNT	EQU	20H	; カウンタ
CNT1	EQU	21H	; WAIT用カウンタ
CNT2	EQU	22H	; WAIT用カウンタ
LED_NO	EQU	23H	; 点灯するLED番号(0~9)
LEDBUF	EQU	24H	; LED表示バッファ(24-25H)
			; 各LED 2ビットで明るさ設定(00,01,10,11の順)
			; 6LEDなので24H、25Hの半分使用
LEDCNT	EQU	26H	; 割り込みで表示するLED番号カウンタ
PATADDR	EQU	27H	; 表示パターンのアドレスカウンタ
PATCNT	EQU	28H	; 表示パターンの表示繰り返しカウンタ
TMP	EQU	29H	; 一時作業用(割り込み内)
FLWAIT	EQU	2AH	; FLASHウエイト時間
PWMCNT	EQU	2BH	; 疑似PWMのためのカウンタ(0~3で変化)
DSPFLG	EQU	2CH	; 表示/非表示フラグ(0:非表示、1:表示)
;
TMP2	EQU	30H	; 一時作業(割り込み外)
RNDVAL	EQU	31H	; 乱数生成用
WK1	EQU	32H	; 乱数生成用
BLNKCNT	EQU	33H	; 高速点滅までのカウンタ
WCNT	EQU	34H	; 高速点滅回数カウンタ
INDEX	EQU	35H	; 回転表示時のパターンインデックス
RCNT	EQU	36H	; 回転表示カウンタ
;
BKUPW	EQU	40H	; 割り込み待避用
BKUPS	EQU	41H	; 割り込み待避用
BKUPFR	EQU	42H	; 割り込み待避用
BKUPPCL	EQU	43H	; 割り込み待避用
;
;---------------------------------------------------------------------
;  リセット・割り込み
;---------------------------------------------------------------------
	ORG	00H		; リセット時の飛び込み先
RESET
	GOTO	START		; 初期設定へ
	;
;---------------------------------------------------------------------
;  割り込み処理でダイナミック表示を行う。
;    (4回の割り込みで1LED分 ; 4段階PWM)
;---------------------------------------------------------------------
	ORG	04H		; 割り込み時の飛び込み先
INTRUPT
	;レジスタ待避
	MOVWF	BKUPW		;バックアップ(Wレジ)
	SWAPF	STATUS,W	;バックアップ(STATUSレジ)
	MOVWF	BKUPS
	MOVF	FSR,W		;バックアップ(FSRレジ)
	MOVWF	BKUPFR
	MOVF	PCLATH,W	;バックアップ(PCLATHレジ)
	MOVWF	BKUPPCL
	;
	BTFSS	INTCON,GPIF	; 外部割り込みか?
	GOTO	INT1
;	MOVF	GPIO,F		; 一度、空読みしないと割り込みが連続する
	BCF	DSPFLG,0
	BTFSC	GPIO,3		; LowならSleep,Highなら表示
	BSF	DSPFLG,0	; 表示
	BCF	INTCON,GPIF
	;
INT1
	;
	BCF	INTCON,T0IF	;割り込みフラグリセット
	;
	; 点灯するLEDの明るさを確認
	;
	MOVF	LEDCNT,W	; LED番号
	CALL	LEDBRT		; 0,1,2,4が返る
	SUBWF	PWMCNT,W	; PWMCNT - 明るさ > 0 なら点灯
	BTFSS	STATUS,C
	GOTO	DISP
	GOTO	UNDISP
	;
DISP
	MOVF	LEDCNT,W
	MOVWF	LED_NO		; 表示番号をLED_NOへ
	;
	; LED表示
	;
	CLRF	GPIO
	BSF	STATUS,RP0	; bank1 切り替え
	MOVLW	H'FF'
	MOVWF	TRISIO
	BCF	STATUS,RP0	; bank0に戻す
	;
	MOVF	LED_NO,W
	CALL	TABLE_TRIS
	BSF	STATUS,RP0	; bank1 切り替え
	MOVWF	TRISIO
	BCF	STATUS,RP0	; bank0に戻す
	MOVF	LED_NO,W
	CALL	TABLE_IO
	MOVWF	GPIO
	;
	GOTO	NEXTBIT
	;
UNDISP
	CLRF	GPIO		; LED非表示
	;
NEXTBIT
	INCF	PWMCNT,W
	ANDLW	H'03'
	MOVWF	PWMCNT
	BTFSS	STATUS,Z
	GOTO	RSTREG
	;
	INCF	LEDCNT,F	; 次の割り込みに備え、カウントアップ
	MOVF	LEDCNT,W
	SUBLW	D'6'		; LED:0~5
	BTFSC	STATUS,Z
	CLRF	LEDCNT
	;
RSTREG
	;レジスタ復元
	MOVF	BKUPPCL,W	;復元(PCLATHレジ)
	MOVWF	PCLATH
	MOVF	BKUPFR,W	;復元(FSRレジ)
	MOVWF	FSR
	SWAPF	BKUPS,W		;復元(STATUSレジ)
	MOVWF	STATUS
	SWAPF	BKUPW,F		;復元(Wレジ)LED_NO
	SWAPF	BKUPW,W
	;
	RETFIE			;割り込みから復帰
	;
;---------------------------------------------------------------------
;  初期設定
;---------------------------------------------------------------------
START
	BCF	INTCON,GIE	; 全割込み禁止
	;
	CLRF	GPIO
	MOVLW	B'00111111'	; GPIOをデジタルI/Oに設定
	MOVWF	CMCON		; デフォルトはコンパレータ
	BANK1
	MOVLW	B'00010111'	; GPIO3,5(空き→出力)
	MOVWF	TRISIO		;
	;TMR0割り込みタイマーセット
	MOVLW	H'88'		; プリスケーラを使わない
	MOVWF	OPTION_REG	; clock4MHz -> 1Mcycle
				; 1Mcycle/256/2=3,906Hz(=256usec毎)
				; 割り込み4回でひとつのLEDを点灯
				; 明るい  :割り込み4回とも点灯
				; 少し暗い:割り込み4回のうち2回のみ点灯
				; 暗い    :割り込み4回のうち1回のみ点灯
				; LED 12個x4回なので3,906/48=81Hzとなりチラチラしない
	; GPIO割り込み(明るさ検知)
	MOVLW	B'00001000' 	; GP3 Interrupt-on-change enabled
	MOVWF	IOC
	BANK0
	;
	CLRF	LEDCNT		; LEDカウンタクリア
	CLRF	LEDBUF		; LEDバッファクリア
	CLRF	LEDBUF+1	; LEDバッファクリア
	CLRF	DSPFLG
	;
	CLRF	PWMCNT
	CLRF	BLNKCNT
	;
;---------------------------------------------------------------------
;  メイン
;---------------------------------------------------------------------
MAIN
	BSF	INTCON,T0IE	; タイマー0割り込みイネーブル
	BSF	INTCON,PEIE	; 周辺割り込み許可
	BSF	INTCON,GPIE	; GPIO change割り込み許可
	BSF	INTCON,GIE	; 割り込み許可
	;
	CALL	DIAG		; 電源投入の動作確認のために表示
	CALL	RANDINT
MAINLP
	CALL	RNDBLINK
	BTFSS	DSPFLG,0	; 非表示ならSleep
	GOTO	MAINSLEEP
	;
	CALL	FASTBLINK
	BTFSS	DSPFLG,0	; 非表示ならSleep
	GOTO	MAINSLEEP
	;
	CALL	RNDBLINK
	BTFSS	DSPFLG,0	; 非表示ならSleep
	GOTO	MAINSLEEP
	;
	CALL	ROTATION
	BTFSS	DSPFLG,0	; 非表示ならSleep
	GOTO	MAINSLEEP
	;
	GOTO	MAINLP
	;
MAINSLEEP
	BCF	INTCON,T0IE	; タイマー0割り込み停止
	CLRF	GPIO
	SLEEP
	NOP
	;
	BSF	INTCON,T0IE	; タイマー0割り込みイネーブル
	GOTO	MAINLP

;---------------------------------------------------------------------
;  高速点滅
;---------------------------------------------------------------------
FASTBLINK
	MOVLW	D'30'
	MOVWF	BLNKCNT
FASTBLP
	CALL	RNDPAT		; ランダム点灯
	MOVLW	D'10'		; wait 40ms
	CALL	WBLINK
	DECFSZ	BLNKCNT,F
	GOTO	FASTBLP
	RETURN
	;
;---------------------------------------------------------------------
;  通常ランダム点滅
;---------------------------------------------------------------------
RNDBLINK
	MOVLW	D'30'
	MOVWF	BLNKCNT
RNDBLP
	CALL	RNDPAT		; ランダム点灯
	MOVLW	D'200'		; wait 800ms
	CALL	WBLINK
	DECFSZ	BLNKCNT,F
	GOTO	RNDBLP
	RETURN
	;
;---------------------------------------------------------------------
;  回転表示(点灯の明るさは1/2)
;---------------------------------------------------------------------
ROTATION
	MOVLW	D'10'		; 10回転
	MOVWF	WCNT
ROTLP1
	MOVLW	D'7'		; 7通りの表示パターン
	MOVWF	RCNT
	CLRF	INDEX
ROTLP2
	CALL	ROTGET
	MOVWF	LEDBUF
	INCF	INDEX,F
	CALL	ROTGET
	MOVWF	LEDBUF+1
	INCF	INDEX,F

	MOVLW	D'10'		; wait時間(40ms)
	CALL	WBLINK
	DECFSZ	RCNT,F
	GOTO	ROTLP2
	;
	DECFSZ	WCNT,F
	GOTO	ROTLP1
	RETURN
	;
ROTGET
	CLRF	PCLATH
	MOVF	INDEX,W
	ADDWF	PCL,F
ROTDT
	RETLW	B'00000011'	; 0
	RETLW	B'00000000'	;
	;
	RETLW	B'00001101'	; 1
	RETLW	B'00000000'	;
	;
	RETLW	B'00110100'	; 2
	RETLW	B'00000000'	;
	;
	RETLW	B'11010000'	; 3
	RETLW	B'00000000'	;
	;
	RETLW	B'01000000'	; 4
	RETLW	B'00000011'	;
	;
	RETLW	B'00000000'	; 5
	RETLW	B'00001101'	;
	;
	RETLW	B'00000000'	; 6
	RETLW	B'00000100'	;
	;
;---------------------------------------------------------------------
;  I/Oパターン
;---------------------------------------------------------------------
TABLE_IO
	CLRF	PCLATH
	ADDWF	PCL,F
	RETLW	B'00000001'	; LED 0
	RETLW	B'00000010'	; LED 1
	RETLW	B'00000010'	; LED 2
	RETLW	B'00000100'	; LED 3
	RETLW	B'00000001'	; LED 4
	RETLW	B'00000100'	; LED 5
	;
TABLE_TRIS
	CLRF	PCLATH
	ADDWF	PCL,F
	RETLW	B'00011100'	; LED 0
	RETLW	B'00011100'	; LED 1
	RETLW	B'00011001'	; LED 2
	RETLW	B'00011001'	; LED 3
	RETLW	B'00011010'	; LED 4
	RETLW	B'00011010'	; LED 5
	;
;---------------------------------------------------------------------
;  Wレジ値をビット位置にデコード
;---------------------------------------------------------------------
DECBIT
	CLRF	PCLATH
	ADDWF	PCL,F
DECBIT1
	RETLW	B'00000001'	;0
	RETLW	B'00000010'	;1
	RETLW	B'00000100'	;2
	RETLW	B'00001000'	;3
	RETLW	B'00010000'	;4
	RETLW	B'00100000'	;5
	RETLW	B'01000000'	;6
	RETLW	B'10000000'	;7
	;
;---------------------------------------------------------------------
;  LED番号からLEDBUFの値(明るさ)を取り出す(0,1,2,4)
;---------------------------------------------------------------------
LEDBRT
	BCF	STATUS,C
	RLF	LEDCNT,W	; LED番号を2倍しジャンプ先アドレスに変換
	CLRF	PCLATH
	ADDWF	PCL,F
	;
	CALL	LEDNO_0
	GOTO	LEDBRT_1
	CALL	LEDNO_1
	GOTO	LEDBRT_1
	CALL	LEDNO_2
	GOTO	LEDBRT_1
	CALL	LEDNO_3
	GOTO	LEDBRT_1
	CALL	LEDNO_4
	GOTO	LEDBRT_1
	CALL	LEDNO_5
	GOTO	LEDBRT_1
LEDBRT_1
	MOVWF	TMP
	SUBLW	D'3'
	BTFSC	STATUS,Z
	INCF	TMP,F
	MOVF	TMP,W
	RETURN
	;
LEDNO_0
	MOVF	LEDBUF,W
	ANDLW	B'00000011'	; LEDNO = 0
	RETURN
	;
LEDNO_1
	MOVF	LEDBUF,W
	ANDLW	B'00001100'	; LEDNO = 1
	MOVWF	TMP
	BCF	STATUS,C
	RRF	TMP,F
	RRF	TMP,W
	RETURN
	;
LEDNO_2
	SWAPF	LEDBUF,W
	ANDLW	B'00000011'	; LEDNO = 2
	RETURN
	;
LEDNO_3
	SWAPF	LEDBUF,W
	ANDLW	B'00001100'	; LEDNO = 3
	MOVWF	TMP
	BCF	STATUS,C
	RRF	TMP,F
	RRF	TMP,W
	RETURN
	;
LEDNO_4
	MOVF	LEDBUF+1,W
	ANDLW	B'00000011'	; LEDNO = 4
	RETURN
	;
LEDNO_5
	MOVF	LEDBUF+1,W
	ANDLW	B'00001100'	; LEDNO = 5
	MOVWF	TMP
	BCF	STATUS,C
	RRF	TMP,F
	RRF	TMP,W
	RETURN
	;
;---------------------------------------------------------------------
;  消灯
;---------------------------------------------------------------------
LEDOFF
	CLRF	LEDBUF
	CLRF	LEDBUF+1
	RETURN
	;
;---------------------------------------------------------------------
;  Waitルーチン(注)割り込みが入るので下記時間にはならない
;---------------------------------------------------------------------
W100US				; 約100usec
	MOVLW	D'32'
	MOVWF	CNT1
W100USLP
	DECFSZ	CNT1,F
	GOTO	W100USLP
	RETURN
	;
WAIT1MS				;1ミリ秒(998usec) CALLと合わせて1.000ms
	MOVLW	D'248'		;1cycle
	MOVWF	CNT1		;1cycle
W1MSLP
	NOP			;1cycle*248
	DECFSZ	CNT1,F		;1cycle*247+2cycle
	GOTO	W1MSLP		;2cycle*247
	GOTO	$+1		;2cycle
	NOP			;1cycle
	RETURN			;2cycle
	;
WBLINK
	; Wレジに待ち時間(単位4ms)を入れてCALL
	MOVWF	CNT2
WBLINKLP
	CALL	WAIT1MS
	CALL	WAIT1MS
	CALL	WAIT1MS
	CALL	WAIT1MS
	BTFSS	DSPFLG,0	; 非表示になったら即時リターン
	RETURN
	DECFSZ	CNT2,F
	GOTO	WBLINKLP
	RETURN
	;
;---------------------------------------------------------------------
;  電源投入時、全LED点灯
;---------------------------------------------------------------------
DIAG
	MOVLW	B'11111111'	;
	MOVWF	LEDBUF
	MOVLW	B'00001111'	;
	MOVWF	LEDBUF+1
	;
	MOVLW	D'250'		; 点灯時間
	CALL	WBLINK
	RETURN
	;
;---------------------------------------------------------------------
;  ランダム表示
;---------------------------------------------------------------------
RNDPAT
	CALL	RANDOM
	MOVWF	LEDBUF
	CALL	RANDOM
	MOVWF	LEDBUF+1
	;
	RETURN
;---------------------------------------------------------------------
;  M系列乱数(1~255)
;---------------------------------------------------------------------
RANDINT
	MOVLW	B'00101010'
	XORWF	TMR0,W
	MOVWF	RNDVAL
RANDOM
	MOVF	RNDVAL,W
	MOVWF	WK1
	RRF	WK1,F
	RRF	WK1,F
	XORWF	WK1,W
	RRF	WK1,F
	RRF	WK1,F
	XORWF	WK1,W
	RRF	WK1,F
	RRF	WK1,F
	RRF	WK1,F
	XORWF	WK1,F
	BCF	STATUS,C
	BTFSC	WK1,0
	BSF	STATUS,C
	RLF	RNDVAL,F
	MOVF	RNDVAL,W
	RETURN
	;
	END
;---------------------------------------------------------------------
;  終わり
;---------------------------------------------------------------------

0 件のコメント:

コメントを投稿