RaspberryPi + Volumio + LCDを実現したプログラム説明
既にvolumioのバイナリにLCD表示機能も入れ込んだものをこちらで公開していますが、LCD表示のプログラムについて説明をしていませんでした。
今日は、そのあたりの説明をしようと思います。
使ったLCDはストロベリーリナックスさんのSB1602BWというI2C接続のものです。
実は、同じI2C接続で秋月電子で最近取り扱いを始めたI2C接続の有機ELディスプレイも、僅かにプログラム変更するだけで使用できます。
有機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)
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くらいの自然数)をお好みに調整してください。
にほんブログ村
ブログランキングに参加中です。 めざせ1位!
もしよろしければ「ぽちっと」お願いします。
« volumio + mpd-0.18.16 LCD バイナリ | トップページ | volumio + LCDの曲名の日本語文字化け対策(案) »
「Raspberry Pi」カテゴリの記事
- 来年からRapberryPiの供給が改善されるらしい。(2022.12.17)
- ラズパイオーディオお手軽インストーラー[MUTE](2022.07.08)
- 2022年版のRaspberry Pi OSではユーザー、パスワード設定が必須に(2022.05.05)
- あのオーディオデザインさんがラズパイオーディオを発売(2022.04.18)
- Volumio/MoodAudioに秋月電子のI2CタイプOLEDを接続して曲名などを表示するPython3版(2022.03.26)
コメント
« volumio + mpd-0.18.16 LCD バイナリ | トップページ | volumio + LCDの曲名の日本語文字化け対策(案) »
いつも参考にさせていただいています。
実はこの投稿を見る前から秋月OELに注目していたのですが、接続可能であることの情報と、スクリプトの修正箇所の解説について非常に有りがたく思います。
秋月OELには黄色のみ20行バージョンがありますが、対応させるには# line2を一部修正するだけで良いのでしょうか。
投稿: タナカ | 2014年10月11日 (土) 21時27分
タナカさん
おそらく、2行目スクロール処理の「sp + 16」 の16を20にすれば良いと思います。
1行目も16文字に収めるための間隔でvol値表示などをしていますから、適当に編集してください。
投稿: たかじん | 2014年10月11日 (土) 22時36分
たかじん様
たびたびの質問(お願い?)で恐縮です。
ダウンロードさせていただいたデーターは2GBのSDに入りきるサイズですが、
16GBとか64GBとかの巨大容量(爆)のSDを使い
音楽を保存する領域を目いっぱい増やしたい場合、
SDと表示されている領域を拡大する方法は難しいのでしょうか?
linuxを知っている人には簡単なのでしょうが、CP/MやMS-DOSの世代の私には難解です。
Netサーフィンしながら、チャレンジしたのですが勉強不足な私は、
何回もSDのデータを壊してしまい、そのたびに最初からイメージを書き込み、やり直しの連続です。
今のところ、成功しておりません。
一度アンマウントして、うんぬんかんぬん???のような気がしますが・・・ きっと違うんでしょうね。
投稿: イワン | 2014年10月12日 (日) 02時36分
イワンさん
https://nw-electric.way-nifty.com/blog/extsd.html
こちらにSDカードの余った領域を有効にする方法が書いてあります。
volumio v1.4用の設定済みバイナリでは、パーティションを作成してext4でフォーマットするところまで手動で行なって再起動させると、その領域を使えるように設定が済んでおります。
投稿: たかじん | 2014年10月12日 (日) 20時54分
たかじんさん
いまさらの質問で恐縮ですが秋月電子の有機ELディスプレイの
配線ってどのようにしてますかね?
投稿: tx2 | 2014年10月20日 (月) 07時26分
tx2さん
基本的にデータシート通りですが、近いうちに写真をUPいたします。
投稿: たかじん | 2014年10月20日 (月) 23時35分
秋月電子OLED・20桁について
・16桁を20桁対応に変更する具体的な方法を
解説して頂けないでしょうか。
《wget https://nw-electric.way-nifty.com/blog/files/oled_ctrl_s.pyを
Wクリック→テキストへ貼付け→16を20に変更→?》
よろしくお願いします。
投稿: fu103 | 2017年9月10日 (日) 08時37分
fu103さん
20文字のものは、文字数以外にも何か違っていたという話を聞いたことがあります。
秋月のDATAシートに書かれていないので、ちょっと不明でが、表示領域のアドレスなども違っている可能性があります。
16文字のものは、1行目の左端は0x80。 2行目は、0xC0です。
投稿: たかじん | 2017年9月10日 (日) 21時39分
おかげで、なんとか20桁ディスプレイに対応できました、
ありがとうございます。
・電源を入れた直後のスタンバイ画面に日付を表示したいと思い
《+ver+》を《date +"%Y/%m/%d"》に差し換えたり
試したのですが、うまくできません。
どのように入力すれば、良いでしょうか?
お手数かけます、よろしくお願いします。
投稿: fu103 | 2017年10月23日 (月) 20時01分
fu103さん
おめでとうございます。
日付は、RPi自体がリアルタイムクロックを持たないので、あやしいと思いますよ。
ネットが繋がってしばらくすると補正されますが、それまでは全然ちがう日付になる。
あとはpythonの使い方ですね。。。
投稿: たかじん | 2017年10月24日 (火) 08時31分