Select Your Language

免責事項

  • 本サイトの情報の利用、内容、サービスによって、利用者にいかなる損害、被害が生じても、著者は一切の責任を負いません。ユーザーご自身の責任においてご利用いただきますようお願いいたします。

    本サイトで頒布している基板およびキットは、技術者、またはそれに準ずる電気的知識をお持ちの電子工作ファンの方のためのものです。一般のオーディオファンの方のためのものではありません。
    また、頒布基板およびキットは、いかなる条件でも動作を保証するものではございませんので、あらかじめご了承ください。

    電子工作では、火傷、感電、火災などの可能性があります。十分に注意をして作業して下さい。

    営利目的のご使用は認めておりません。 記事の転載や、基板・キットの商用利用の方は、ご連絡ください。学生やサークルの学習目的でまとめてご購入する場合は特別価格でご提供させていただきます。
無料ブログはココログ

スポンサー

« volumio + mpd-0.18.16 LCD バイナリ | トップページ | volumio + LCDの曲名の日本語文字化け対策(案) »

2014年10月11日 (土)

RaspberryPi + Volumio + LCDを実現したプログラム説明

既にvolumioのバイナリにLCD表示機能も入れ込んだものをこちらで公開していますが、LCD表示のプログラムについて説明をしていませんでした。 

 

今日は、そのあたりの説明をしようと思います。 

使ったLCDはストロベリーリナックスさんのSB1602BWというI2C接続のものです。

実は、同じI2C接続で秋月電子で最近取り扱いを始めたI2C接続の有機ELディスプレイも、僅かにプログラム変更するだけで使用できます。 

Oled_i2c_

有機ELディスプレイは、残像がほぼ無いので、スクロール速度を上げても読みやすいとか、視野角もほぼ180度と視認性に優れています。 

寿命については、各所で色々いわれているようにあまり長くはない可能性があります。 これは、壊れるという意味ではなく輝度の低下です。 光らせたピクセルのみ輝度が低下していきますので、いわゆる焼き付きみたいにピクセル毎の輝度ムラが生じる可能性はあるかと思います。 

 

 

さてさて、プログラムの説明に入りたいと思います。 

プログラムはこちらlcd_ctrl.pyです。

 

冒頭部分

import RPi.GPIO as GPIO
import time
import commands
import smbus
import sys
from daemon import daemon
from daemon.pidlockfile import PIDLockFile 

ここは、おまじないと思ってください。 プログラムの中で使うライブラリなどをここに記述しています。 

次の

STOP = 0
PLAY = 1
PAUSE = 2
MSTOP = 1    # LCD Scroll motion stop time

の部分は、define(定数定義)のつもりなのですが、なんとpythonにはdefineがありません? ということで、普通に変数として定義しています。 
「MSTOP」は、曲名スクロール表示の最初に止まっている時間を指定しています。 

 

いよいよ、次からプログラム本体です。

i2cクラスのイニシャライズ部分。 LCDのアドレスとかコントラストを指定しています。 その他は、動作の初期値です。 

class i2c(object):

    def __init__(self):
        self.bus = smbus.SMBus(1)
        self.addr = 0x3e          # LCD i2s address
        self.contrast = 0x78      # LCD contrast
        self.state = STOP         # state
        self.shift = 0            # Scroll shift value
        self.retry = 20           # retry for init LCD
        self.old_line1 = " "      # old str 1
        self.old_line2 = " "      # old str 2
        self.init()

 

次に、I2C-LCDのイニシャライズ部です。 リトライは20回まで、0.5秒おきに繰り返すようにしています。  それでもアクセスできなかったときは、プログラムを終了させています。

# initialize LCD
    def init(self):
        while self.retry > 0:
            try:
                init_values = [0x39, 0x14, self.contrast, 0x56, 0x6c]

      ・・・・・略

            except IOError:
                self.retry = self.retry -1
                time.sleep(0.5)
            else:
                return 0
        else:
            sys.exit()

 

こちらは、1行目に表示する関数です。 同様に2行目用の関数もあり、そちらではスクロールするように作りました。 詳しくはプログラムソースをご覧下さい。 

# line1 send ascii data
    def line1(self, str):
        if str != self.old_line1:
            self.old_line1 = str
        else:
            return 0
        try:
            self.bus.write_byte_data(self.addr, 0, 0x80)
            vv = map(ord, list(str))
            self.bus.write_i2c_block_data(self.addr, 0x40, vv)
        except IOError:
            return -1

 

下のdisp関数が、動きを制御しています。 mpcにコマンドを出して、その戻りの文字列をみて、あれこれと画面に表示するものを決めています。 1行目に表示するもの。2行目に表示ものなど、ここで決めています。 関数が少し長いので詳細は割愛させて頂きます。

    def disp(self):
        # mpc command Send and Receive
        st = commands.getoutput('mpc')
        line_list = st.splitlines()       

        # stop
        if len(line_list) <= 1:
            if line_list[0].startswith(r"error:"):
                self.line1("  MPD shutdown  ")
                return 0
            else:
                self.state = STOP

        # play pause
        for line in range(0,len(line_list)):
            if line_list[line].startswith(r"[playing]"):
                self.state = PLAY
            elif line_list[line].startswith(r"[paused]"):
                self.state = PAUSE

      ・・・・略

次がメイン関数です。 0.5秒おきにdisp関数を呼び出しています。 スクロール速度を速くしたい場合は、この「0.5」を小さくすると速くなります。 LCDだと、0.2秒などに設定すると残像で文字がとても読みにくくなります。 

def main():
    lcd = i2c()

    while True:
        lcd.disp()
        time.sleep(0.5)

 

最後に、メイン関数を呼んでいる箇所です。 daemon化するおまじないも含んでいます。 

if __name__ == '__main__':
    with daemon.DaemonContext(pidfile=PIDLockFile('/var/run/lcd_ctrl.pid')):
        main()

 

以上がI2C-LCDにデータを転送するプログラムです。

 

最終的には、ほぼフルスクラッチ状態になりましたが大したことないプログラムです。 コメント行や空白行を除くと、正味100行程度です。 期待した方には申し訳ないですが、特別なテクニックなども使用していません。 工夫した点としてはtryとmap()を使っている所でしょうか。

でも、たったこれだけのプログラムで、エラー対策も含めて所定の動作をすることができるのはpythonの凄いところだと思います。 

 

 

************************ 

さて、秋月電子の有機ELディスプレイに対応させるには、下記の変更が必要です。

I2Cのアドレスを0x3cに変更

  self.addr = 0x3c          # i2s address

 

イニシャライズ方法の変更

# initialize OLED
    def init(self):
        while self.retry > 0:
            try:
                self.bus.write_byte_data(self.addr, 0, 0x0c) # Display ON
            except IOError:
                self.retry = self.retry -1
                time.sleep(0.5)
            else:
                return 0
        else:
            sys.exit()

 

2行目の先頭位置は0xC0ではなく、0xA0とします。 

# line2 send ascii data and Scroll
    def line2(self, str, sp):
        try:
            self.bus.write_byte_data(self.addr, 0, 0xA0)
            self.maxlen = len(str) +MSTOP

 

あとは、スクロール速度(0.15-0.5秒程度)やMSTOP値(1-5くらいの自然数)をお好みに調整してください。

 

 

 

にほんブログ村 PC家電ブログ PCオーディオへ にほんブログ村
ブログランキングに参加中です。 めざせ1位! 
もしよろしければ「ぽちっと」お願いします。 



« volumio + mpd-0.18.16 LCD バイナリ | トップページ | volumio + LCDの曲名の日本語文字化け対策(案) »

Raspberry Pi」カテゴリの記事

コメント

いつも参考にさせていただいています。
実はこの投稿を見る前から秋月OELに注目していたのですが、接続可能であることの情報と、スクリプトの修正箇所の解説について非常に有りがたく思います。
秋月OELには黄色のみ20行バージョンがありますが、対応させるには# line2を一部修正するだけで良いのでしょうか。

タナカさん

おそらく、2行目スクロール処理の「sp + 16」 の16を20にすれば良いと思います。

1行目も16文字に収めるための間隔でvol値表示などをしていますから、適当に編集してください。

たかじん様
 たびたびの質問(お願い?)で恐縮です。
 ダウンロードさせていただいたデーターは2GBのSDに入りきるサイズですが、
16GBとか64GBとかの巨大容量(爆)のSDを使い
音楽を保存する領域を目いっぱい増やしたい場合、
SDと表示されている領域を拡大する方法は難しいのでしょうか?
linuxを知っている人には簡単なのでしょうが、CP/MやMS-DOSの世代の私には難解です。
Netサーフィンしながら、チャレンジしたのですが勉強不足な私は、
何回もSDのデータを壊してしまい、そのたびに最初からイメージを書き込み、やり直しの連続です。
今のところ、成功しておりません。
一度アンマウントして、うんぬんかんぬん???のような気がしますが・・・ きっと違うんでしょうね。

イワンさん

https://nw-electric.way-nifty.com/blog/extsd.html

こちらにSDカードの余った領域を有効にする方法が書いてあります。
volumio v1.4用の設定済みバイナリでは、パーティションを作成してext4でフォーマットするところまで手動で行なって再起動させると、その領域を使えるように設定が済んでおります。

たかじんさん

いまさらの質問で恐縮ですが秋月電子の有機ELディスプレイの
配線ってどのようにしてますかね?

tx2さん

基本的にデータシート通りですが、近いうちに写真をUPいたします。

秋月電子OLED・20桁について

・16桁を20桁対応に変更する具体的な方法を
解説して頂けないでしょうか。

《wget https://nw-electric.way-nifty.com/blog/files/oled_ctrl_s.py
Wクリック→テキストへ貼付け→16を20に変更→?》
よろしくお願いします。

fu103さん

20文字のものは、文字数以外にも何か違っていたという話を聞いたことがあります。

秋月のDATAシートに書かれていないので、ちょっと不明でが、表示領域のアドレスなども違っている可能性があります。

16文字のものは、1行目の左端は0x80。 2行目は、0xC0です。

おかげで、なんとか20桁ディスプレイに対応できました、
ありがとうございます。
・電源を入れた直後のスタンバイ画面に日付を表示したいと思い
《+ver+》を《date +"%Y/%m/%d"》に差し換えたり
試したのですが、うまくできません。
どのように入力すれば、良いでしょうか?
お手数かけます、よろしくお願いします。

fu103さん

おめでとうございます。
日付は、RPi自体がリアルタイムクロックを持たないので、あやしいと思いますよ。
ネットが繋がってしばらくすると補正されますが、それまでは全然ちがう日付になる。

あとはpythonの使い方ですね。。。

コメントを書く

(ウェブ上には掲載しません)

トラックバック


この記事へのトラックバック一覧です: RaspberryPi + Volumio + LCDを実現したプログラム説明:

« volumio + mpd-0.18.16 LCD バイナリ | トップページ | volumio + LCDの曲名の日本語文字化け対策(案) »

サイト内検索(new)

2023年6月
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30