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

第4回 本体側の文字描画処理はどうなっているのか?

この記事を読むのに必要な時間:およそ 5 分

モータのPWM制御

その空きクロックを使って,モータのPWM制御を行ってしまいます。PWM制御というのは,スイッチのオン・オフをすばやく切り替え,アナログ的な出力を得る方法です。今回は35μsのタイマ処理で,256のカウントをおこないます。カウントと設定値を足してオーバーフローしたら,スイッチを入れます。これにより,0だとオフ,255だとオン,それ以外ではその中間という出力が得られます。

なお,今回はステッピングモータを使用しましたので,n相とn+1相の比率をPWMで切り替えています。PWMの周波数は,28800bpsの1/256で,約110Hzになります。

リスト2 モータのPWM制御処理

    movf    posll, 0
    addwf    pwmval, 0
    movlw    0
    btfsc    STATUS, C
    movlw    1
    addwf    poslh, 0
    
    call    getmotor
    andlw    0xf0
    movwf    work0
    
    movf    posrl, 0
    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
    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

次に,PWMのカウンタがラウンドしたところで,速度をステップ位置に加算します。これで,指定した速度でステッピングモータの相が進み,モータが回転するという仕組みです。モータの速度はライントレーサのセンサによって決めています。この処理は,もっと外側で行っています。

HTTPリクエストの生成

いちばん外側の処理は,サーバにリクエストを出してそのレスポンスを解析し,LEDを制御するという繰り返しです。LANモジュールには接続先のIPアドレスがセットしてあり,シリアルで文字を送ると,目的のサーバに自動的に接続します。ここに「GET / HTTP/1.0」のような文字列を入れておくことで,サーバにHTTPリクエストが送信されます。

リスト3 HTTPリクエスト生成

main
    call    traceproc
    
    movlw    0x47            ; 'G'
    call    sendrs
    movlw    0x45            ; 'E'
    call    sendrs
    movlw    0x54            ; 'T'
    call    sendrs
    movlw    0x20            ; ' '
    call    sendrs
    movlw    0x2f            ; '/'
    call    sendrs
    movlw    0x75            ; "u"
    call    sendrs
    movlw    0x76            ; "v"
    call    sendrs
    movlw    0x63            ; "c"
    call    sendrs
    movlw    0x61            ; "a"
    call    sendrs
    movlw    0x72            ; "r"
    call    sendrs
    
    call    traceproc
    
    movlw    0x2f            ; '/'
    call    sendrs
    movlw    0x3f            ; '?'
    call    sendrs
    movlw    0x6f            ; 'o'
    call    sendrs
    movlw    0x66            ; 'f'
    call    sendrs
    movlw    0x66            ; 'f'
    call    sendrs
    movlw    0x73            ; 's'
    call    sendrs
    movlw    0x65            ; 'e'
    call    sendrs
    movlw    0x74            ; 't'
    call    sendrs
    movlw    0x3d            ; '='
    call    sendrs
    movf    recvbuf, 0
    call    sendrs
    
    call    traceproc
    
    movf    recvbuf + 1, 0
    call    sendrs
    movf    recvbuf + 2, 0
    call    sendrs
    movf    recvbuf + 3, 0
    call    sendrs
    movf    recvbuf + 4, 0
    call    sendrs
    movf    recvbuf + 5, 0
    call    sendrs
    movf    recvbuf + 6, 0
    call    sendrs
    movf    recvbuf + 7, 0
    call    sendrs
    movlw    0x20            ; ' '
    call    sendrs
    movlw    0x48            ; 'H'
    call    sendrs
    movlw    0x54            ; 'T'
    call    sendrs
    
    call    traceproc
    
    movlw    0x54            ; 'T'
    call    sendrs
    movlw    0x50            ; 'P'
    call    sendrs
    movlw    0x2f            ; '/'
    call    sendrs
    movlw    0x31            ; '1'
    call    sendrs
    movlw    0x2e            ; '.'
    call    sendrs
    movlw    0x30            ; '0'
    call    sendrs
    movlw    0xd
    call    sendrs
    movlw    0xa
    call    sendrs
    movlw    0xd
    call    sendrs
    movlw    0xa
    call    sendrs
    
waitresp
    clrf    rxdata
waitresp0
    call    traceproc
    movf    rxdata, 0
    btfsc    STATUS, Z
    goto    waitresp0
    
    xorlw    0xd
    btfss    STATUS, Z
    goto    waitresp
    
    clrf    rxdata
waitresp1
    call    traceproc
    movf    rxdata, 0
    btfsc    STATUS, Z
    goto    waitresp1
    
    xorlw    0xa
    btfss    STATUS, Z
    goto    waitresp
    
    clrf    rxdata
waitresp2
    call    traceproc
    movf    rxdata, 0
    btfsc    STATUS, Z
    goto    waitresp2
    
    xorlw    0xd
    btfss    STATUS, Z
    goto    waitresp
    
    clrf    rxdata
waitresp3
    call    traceproc
    movf    rxdata, 0
    btfsc    STATUS, Z
    goto    waitresp3
    
    xorlw    0xa
    btfss    STATUS, Z
    goto    waitresp
    
    clrf    rxdata
    movlw    recvbuf
    movwf    bufpos
recvbody
    call    traceproc
    movf    rxdata, 0
    btfsc    STATUS, Z
    goto    recvbody
    
    andlw    0xf0
    xorlw    0x30
    btfsc    STATUS, Z
    goto    recvbody0
    xorlw    0x70
    btfsc    STATUS, Z
    goto    recvbody0
    xorlw    0x20
    btfss    STATUS, Z
    goto    putchar
recvbody0
    movf    bufpos, 0
    movwf    FSR
    movf    rxdata, 0
    movwf    INDF
    incf    bufpos, 1
    
    clrf    rxdata
    movf    bufpos, 0
    xorlw    recvbuf_end
    btfss    STATUS, Z
    goto    recvbody
putchar
    movlw    recvbuf + 8
    movwf    FSR
    movlw    4
    movwf    work2
putchar0
    call    traceproc
    btfsc    posrh, 0
    goto    putchar0
    
    movf    INDF, 0
    btfsc    INDF, 6
    addlw    9            ; 0x61 -> 0x6a
    andlw    0xf
    movwf    work1
    swapf    work1, 1
    
    incf    FSR, 1
    movf    INDF, 0
    btfsc    INDF, 6
    addlw    9            ; 0x61 -> 0x6a
    andlw    0xf
    iorwf    work1, 0
    xorlw    0xff
    movwf    PORTB
    
    incf    FSR, 1
putchar1
    call    traceproc
    btfss    posrh, 0
    goto    putchar1
    
    movlw    0xff
    movwf    PORTB
    
    decfsz    work2, 1
    goto    putchar0
    
    goto    main

サーバはHTTPリクエストを受け取ると,レスポンスを返します。マイコン側ではこれを受信してメモリに格納しておきます。そのあと,受信したデータを順次LEDに出力していきます。出力がおわったら,次の文字のHTTPリクエストを送信します。今回は内側のステッピングモータの回転に合わせてLED出力を変えるようにしました。これにより,蓄光テープを見失って180°回転しているところでは文字の描画がストップします。

全体としては,まずシリアルにリクエストを出力する処理の中で,シリアルの35μsタイミング待ちが発生します。ここでPWM処理が定期的に呼ばれます。そのあと,シリアルの受信待ちがありますが,ここでもタイミング待ちが定期的に呼ばれます。このように,何をやるにしてもループの中でシリアルのタイミング待ちを呼ぶことで,シリアル受信やPWM処理を途切れさせないようになっています。ちなみにシリアル受信は,シリアルの35μsタイミング待ちを30回呼び出して1文字受信ですから,受信した文字を毎回チェックする必要はありません。

おわりに

というわけで,ソースをざっと追ってみましたが,いかがでしたでしょうか。割り込みベースの処理に慣れている方だと,見なれないやり方で不思議に思われたかも知れません。クロック数を正確に読めるアセンブラならではのやり方として,心に留めていただければと思います。

最後までおつき合いいただき,ありがとうございました。

今回のプログラムソース全体はこちらからダウンロードできます。

著者プロフィール

木元峰之(きもとみねゆき)

独立系ソフトハウスに8年間勤務,パッケージソフトの開発や記事執筆などを行う。現在はフリーのコンサルタント。SWESTなどのワークショップで分科会のコーディネータを務める。デジタル回路設計歴30年,プログラミング歴27年。

きもと特急電子設計
URL:http://business.pa-i.org/