エンジニアの夏休み:蓄光テープで「省エネディスプレイ」を作る

第2回文字描画のループを作る

前回、蓄光テープにLEDで像が描けることを確認しました。蓄光テープはLEDの光を当てた直後は明るく、時間が経つにつれて暗くなっていきます。暗くなったところにもう一度LEDの光を当てれば、1回目とは違う像を描くことができますね。このためには、テープを環状にして、光が弱くなったころにLEDが戻ってくるようにすると良さそうです。今回は、これに挑戦してみます。

テープ上にあるかどうかを光センサで判別

テープを環状にするので、LEDがテープをたどる方法を考えないといけません。今回は簡単に、光センサを使うことにしました。黒い紙の上に蓄光テープを貼り、反射光を見て、蓄光テープ上にいるかどうかを判断します。進行方向に対して左前方にセンサを置き、テープの上に来たら左に、テープから外れたら右に向きを変えます。これによって、センサがテープの縁をたどるようになります。テープの最後を過ぎるとセンサがテープから外れ、右方向に回り続けます。その結果180°回転して、反対側のテープをたどることになります。このテープを渡りきると、また180°回転して、最初のテープに戻るという仕組みです。さて、はたして考えた通りに行くでしょうか。

やってみると、とりあえず期待通りに動いてくれているようです。ケーブルがからまるという問題はありますが、エンドレスに描いていくことができるようになりました。あとは、PCから文字イメージをもらえば、好きなテキストがどこまでも描けることになります。というわけで、次回はこれに挑戦してみましょう。

ハードとソフトの構成

自分でも作ってみたいという方のために、もう少し詳しく見ていきましょう。

まずセンサですが、フォトリフレクタと呼ばれる、反射型の光センサを使いました。データシートを見ると、フォトトランジスタ側は、1V印加時の電流が最大2mAくらいです。2kΩの抵抗を直列に入れて5Vの電源を用意すると、この抵抗に4Vが現れ、センサに1V残ることになります。これをマイコンのADコンバータに入力します。

このセンサは赤外線タイプで外乱光の影響を受けにくいということになっていますが、せっかくなのでLEDもマイコンで制御するようにしました。LEDオン時の数値と、LEDオフ時の数値の差を反射光と判断することで、外の明るさの変化に強くなります。

図1 前回の基板と今回の比較。こちらは前回。PICのチップと紫外線LEDが並んでいるだけです。
図1 前回の基板と今回の比較。こちらは前回。PICのチップと紫外線LEDが並んでいるだけです。
図2 今回は車輪の車輪(モーター)の位置を変え、LEDの反対側に光センサを配置しました。これがテープの位置を判別します。
図2 今回は車輪の車輪(モーター)の位置を変え、LEDの反対側に光センサを配置しました。これがテープの位置を判別します。

ソフト側ですが、反射光の強さに応じてモーターの速度が連続的に変わるようにしました。今回使ったのはステッピングモーターですから、なめらかに回転させるためのPWM制御も必要です。次回の範囲まで考えると、シリアル通信も必要です。どう組むのがいいでしょうか。

これは私のやり方ですが、まずシリアル通信に必要なクロックを基準にしました。9600bpsの場合、3倍のクロックは約35μsになります(なぜ3倍にするかについては、⁠組込みプレス』Vol.18 p.133に詳しい記事があります⁠⁠。これを256分周してPWMに使うと、約110HzのPWM出力が得られます。同時に、速度を位置に反映させる計算もおこないます。ここまでがシリアルクロックごとの処理です。

リスト1 モーター処理
waitrx3
	call	waitrx
	call	waitrx
waitrx
	movf	posll, 0		; 左モーターPWM処理
	addwf	pwmval, 0
	movlw	0
	btfsc	STATUS, C
	movlw	1
	addwf	poslh, 0
	
	call	getmotor
	andlw	0xf0
	movwf	work0
	
	movf	posrl, 0		; 右モーターPWM処理
	addwf	pwmval, 0
	movlw	0
	btfsc	STATUS, C
	movlw	1
	addwf	posrh, 0
	
	call	getmotor
	andlw	0xf
	iorwf	work0, 0
	
	movwf	PORTC
	
	incf	pwmval, 1		; PWM位相送り・256分周
	btfss	STATUS, Z
	goto	waitrx1
	
	movf	vell, 0			; 速度を位置に反映
	addwf	posll, 1
	btfsc	STATUS, C
	incf	poslh, 1
	
	movf	velr, 0
	addwf	posrl, 1
	btfsc	STATUS, C
	incf	posrh, 1
	
waitrx1
	movlw	0x55			; (87clk - 2)
	subwf	TMR0, 1
waitrx0
	btfsc	TMR0, 7
	goto	waitrx0
	
		; シリアル受信処理
	
	retlw	0

光センサの処理とシリアル送受信、LED出力の処理は、これとは独立して行います。今回はシリアル送受信はやりませんが、LEDを出力して、センサのAD変換を行い、結果を速度に反映させる処理を行います。シリアル送受信中にセンサ処理が一瞬だけ遅れても、問題ないだろうという判断です。

リスト2 センサ読み取り処理
traceproc
	bcf	val_ra, PORTA_LED	; LED off
	movf	val_ra, 0
	movwf	PORTA
	
	call	waitrx3
	call	waitrx3
	call	waitrx3
	call	waitrx3
	call	waitrx3
	
	bsf	ADCON0, 2		; AD変換
	call	waitrx3
	movf	ADRESH, 0
	movwf	work1
	
	bsf	val_ra, PORTA_LED	; LED on
	movf	val_ra, 0
	movwf	PORTA
	
		; このあとAD値を速度に反映

センサの動作確認ですが、せっかくLEDが8つあるので、ここにAD変換した8bitをそのまま出力してしまいました。反射させたときにどんな値がが出るかがわかれば、それを速度に変換するときの参考になります。今回は、LEDオン時とLEDオフ時の差が0x20以下であればテープ外、0x40以上であればテープ上と判断し、この間であればなめらかにモーター速度に反映されるようにしました。

ぜひ、みなさんが作るときの参考にしてください。

おすすめ記事

記事・ニュース一覧