前回のSONY非接触型カードリーダーRC-S380とraspberry pi(読み取り編)で最低限のセットアップをしました。
カードリーダーと連携させるつもりでDisplay-O-Tron HATを使って簡単にディスプレイとして表示させようと思ったら・・・。
なんと! i2cが認識しない?!

購入時にサンプルは動作したのに、保管していて破損させたのか・・・、なんだかお亡くなりになられていたので、チープなLCDキャラクタディスプレイに変更してお届けします!
(もしかしたら現在はZero系は未対応のようで、もしかしたら3B系なら動くかも知れません。ちょっと手持ちがないので、それはまた後日に検証します)
急遽、こいつの出番です。使わずに置いておいたのが功を奏しましたね。
計画変更 LCDディスプレイの変更

※前回の記事も修正しておきました。
「DC 5V HD44780 1602 LCD 16×2キャラクタ」
というらしいです。1602というのは1行に16文字表示でき2行あるからみたいですね。色々入った3000円のセット物にありました。元はArduino向けで作られたようで、私の所持しているLCDは、裏に追加の部品でI2cに接続できるようになっていて、輝度の調整がプラスドライバーでできるものでした。
Raspberry Pi とは5Vで繋ぎます。ネットでも情報がいっぱいあり、3.3V対応だから壊れる危険もあるという書込と、最大で5Vまで大丈夫だという記述とあって本当の所は分かりません。でも、単体では数百円で買えるようですから気にしません。
こういったボードだと動かすのにライブラリの情報が欲しいところ、一応販売業者のサイトにありました。それでやってみようとなり、プログラムが苦手な中年オヤジの奮闘をまとめてみます。
そういうことで、中級者が故になんちゃってプログラミングの常套手段である「ネットからかき集めてきたコードを読み解いて、それなりに仕上げる」というやり方でいきます!
ネットよ、そして上級者のみんな……… このオラに ほんのちょっとずつだけコードをわけてくれ!
今回の環境
前回のSONY非接触型カードリーダーRC-S380とraspberry pi(読み取り編)でセットアップ済みです。
- Raspberry Pi Zero WH
- ソニー SONY 非接触ICカードリーダー/ライター PaSoRi RC-S380"
- 電子工作キット
- サンワサプライ NFCタグ(10枚入り)
動作確認
これ、プログラムしないと表示出来ないので、安易にHATで済ませうようと思ったのがいけなかったのか、ノンプログラマーな中年オヤジには大変でした。
とにかくケーブル繋いで動作確認します。
通電しただけで光ります。眩しい。通電はOKです。
接続の仕方は購入した公式サイトにありました。
http://osoyoo.com/ja/2016/06/01/drive-i2c-lcd-screen-with-raspberry-pi/
なにやら口コミみてもネットで調べても、コードやら間違いだらけらしいのでアテにしないでいたんですけど、サンプルがそのまま動いたわー。
実際には認識しなかったDisplay-O-TRONを導入させるため、Pimoroniからライブラリ一式をインストール済みだったため、以下の点だけ追記して動きました。
sudo nano /etc/modules
モジュールファイルで下記の内容を追加して下さい:
i2c-bcm2708
i2c-dev
Ctrl+Xボダンを押して、Yを入力して、ファイルを保存して下さい。
- 他に必要な環境も記載しておきます。
- sudo raspi-config でI2cを有効にします。
そして上記のmoduleを追記します。(i2c-bcm2708じゃなくて今のラズパイってBM2835とかじゃないのか〜??) - sudo apt-get install -y python-smbus i2c-toolsでsmbusとtoolsを追加します。
- lsmod | grep i2c_ でBM2708が見えればOKです。
- sudo i2cdetect -y 1で出てくる番号を控えます。今回は27です。(=0x027)
もしも表示された全行例が”-”だけなら認識されていません。 - サンプルをダウンロードする
wget http://osoyoo.com/driver/i2clcda.py sudo python i2clcda.py
いや、サンプルはほぼそのまま動いたわー。
もし、エラーもなく、LCDに何も表示されない場合は、LCD裏のプラスのつまみを調整すると映ることがあります。輝度の調整がアナログなんです。実際に私も最高輝度になっていたので、右に回すと落ちて、左に回すと白い光が増します。やはり真ん中くらいですね。
では、前回のNFCの動作と同時にディスプレイに表示するやり方をご紹介します。
ゴール設定
では、元気玉・・・いや古今東西の各方面の上級者から寄せ集めた・・・参考にしたコードの中で、ほぼ基本としたコードはこちらのサイトの物です。ありがとうございます。
参考にしたプログラムコード
https://qiita.com/nofrmm/items/96eba75085ea2987e28e
このブログでPythonの勉強を一部公開し始めました。まだ全然まとめきれていませんが、参考本は読んでいます。そこの知識も含めて考えてみました。
NFCにはメッセージも入ります。しかし、読み書きはまだテストしていません。また、元々ユニークなIDが振られています。
そのIDをキーにして何かを制御したいので、ここでのゴールは、読み込んだNFCタグのIDを2行LCDに表示することにします。
目標:読み込んだNFCタグのIDを2行LCDに表示する
サンプル通りに習う
LCDの公式サイトといっても不確かな部分もあるので、疑ってかかります。そのため、先ずは用意する文字列が表示できるかどうかから実施しました。同時に動きを知ることができるので、次のステップでも有効です。
サンプルはそちらのサイトで確認してください。
公式:http://osoyoo.com/ja/2016/06/01/drive-i2c-lcd-screen-with-raspberry-pi/
ここで唯一確認したのは、I2cのアドレスです。
I2C_ADDR = 0x27 # I2C device address, if any error, change this address to 0x3f
元々27でした。(0x27)コメントにはエラーが出たら3Fに変えろとあります。恐らくバージョン違いなんでしょう。
そしてメッセージ部分を見ると・・・。
# Send some test lcd_string("Created by <",LCD_LINE_1) lcd_string("Osoyoo.com <",LCD_LINE_2)
lcd_stringの関数?でダブルコーテーションで囲われた16文字と分かりました。表示場所はカンマで区切ってLINE番号です。
変更する
最終的にはNFCを読み込んだIDを入れたいので、次のようにしてみます。
# messに代入 mess1 = "TestTest90123456" mess2 = "id = xxxxxxxxxxx" # Send some test lcd_string(mess1,LCD_LINE_1) lcd_string(mess2,LCD_LINE_2)
messという変数を作り、そこに仮のIDを入れてみます。実際にはNFCで取得した変数を割り当てますが、今はデータがないのでテキストで入れます。
問題なく表示されました。
プログラムやPythonに慣れていないので、どういう方式かも分かりません。昔ながらの方法で表示できればと思って文字列を変数に変えてみただけです。
ここで覚えられることとして、実は変数をmessという名前にしましたが、変数として宣言したり定義したりしなくていいのかー?といいことでした。
しかし、Pythonでは自動的に判別してくれるので、きちんと文字列として認識できています。便利!
おまじない
追記した物にPythonの環境定義とコーディング方式を記述します。
#!/usr/bin/env python # -*- coding: utf-8 -*-
コマンドでsudo python〜としなくても良い?らしいので、追記しておきました。無くても良いんだなーという感想です。書籍とかだと書いてありますよね。
コメントアウトする
NFCと連携させるのに、2行の表示で良くて、サンプルみたいに続けて次の2行は必要ありません。また、他の部分でもそういう箇所があれば、積極的にその行をコメントアウトしていきます。
そうすれば実行されませんから、単純な動きが見られるのと、もしも必要な部分までコメントアウトすればエラーが出ますから、何をしているのか分かり易いんですよね。
ここまでテキストベースで作業しています。
Mac OSXでの作業です。これを別のRaspberry Pi でやるのも乙ですね。Pythonは簡単に扱えますからもっと便利でしょう。
クロスプラットフォームなら専用エディッタも活躍します。Muがリリースされたばかりです。
英文字しか表示できない?
アプリケーション側でできるのか分かりませんけど、試しに半角カタカナで表示させてみてください。文字化けします。当然です。アスキーコードが違いますからね。
で、その時のエラーメッセージの中で、128byteだからとありました。
カタカナまで表示するには256byte無いとダメなんですよね。どうやらハード側で対応していない?? でも、表示している事例もあったので、16進数で指定すれば良いのか、そもそも同じような外観でも中身が違うのか、よく分かりません。
今回は英字だけでも問題ないので、スルーします。ご存じの方は教えてくださーい!
トライしてみて
サンプルがハマるかと想像していたけれど大丈夫でした。単に表示させることはOKです。また、文字列を変数に変えてもOKです。簡単でした。
表示の仕方もなんとなく理解できて満足です。
写真のように数字を入れているのは文字数のカウント用です。特に意味はありません。
では、次はNFCとLCDの2つを実装させます。
前回の記事と実装編
変更したコード全文
コード全文 !/usr/bin/env python -- coding: utf-8 -- import smbus import time Define some device parameters I2C_ADDR = 0x27 # I2C device address, if any error, change this address to 0x3f LCD_WIDTH = 16 # Maximum characters per line Define some device constants LCD_CHR = 1 # Mode - Sending data LCD_CMD = 0 # Mode - Sending command LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line LCD_LINE_3 = 0x94 # LCD RAM address for the 3rd line LCD_LINE_4 = 0xD4 # LCD RAM address for the 4th line LCD_BACKLIGHT = 0x08 # On LCD_BACKLIGHT = 0x00 # Off ENABLE = 0b00000100 # Enable bit Timing constants E_PULSE = 0.0005 E_DELAY = 0.0005 Open I2C interface bus = smbus.SMBus(0) # Rev 1 Pi uses 0 bus = smbus.SMBus(1) # Rev 2 Pi uses 1 def lcd_init(): Initialise display lcd_byte(0x33,LCD_CMD) # 110011 Initialise lcd_byte(0x32,LCD_CMD) # 110010 Initialise lcd_byte(0x06,LCD_CMD) # 000110 Cursor move direction lcd_byte(0x0C,LCD_CMD) # 001100 Display On,Cursor Off, Blink Off lcd_byte(0x28,LCD_CMD) # 101000 Data length, number of lines, font size lcd_byte(0x01,LCD_CMD) # 000001 Clear display def lcd_byte(bits, mode): Send byte to data pins bits = the data mode = 1 for data 0 for command bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT bits_low = mode | ((bits<<4) & 0xF0) | LCD_BACKLIGHT High bits bus.write_byte(I2C_ADDR, bits_high) lcd_toggle_enable(bits_high) Low bits bus.write_byte(I2C_ADDR, bits_low) lcd_toggle_enable(bits_low) def lcd_toggle_enable(bits): Toggle enable time.sleep(E_DELAY) bus.write_byte(I2C_ADDR, (bits | ENABLE)) time.sleep(E_PULSE) bus.write_byte(I2C_ADDR,(bits & ~ENABLE)) time.sleep(E_DELAY) def lcd_string(message,line): Send string to display message = message.ljust(LCD_WIDTH," ") lcd_byte(line, LCD_CMD) for i in range(LCD_WIDTH): lcd_byte(ord(message[i]),LCD_CHR) def main(): Main program block Initialise display lcd_init() while True: messに代入 mess1 = "TestTest90123456" mess2 = "id = xxxxxxxxxxx" Send some test lcd_string(mess1,LCD_LINE_1) lcd_string(mess2,LCD_LINE_2) lcd_string("Created by <",LCD_LINE_1) lcd_string("Osoyoo.com <",LCD_LINE_2) time.sleep(3) Send some more text lcd_string("> Tutorial Url:",LCD_LINE_1) lcd_string("> http://osoyoo.com",LCD_LINE_2) time.sleep(3) if name == 'main': try: main() except KeyboardInterrupt: pass finally: LCD_BACKLIGHT = 0x00 lcd_byte(0x01, LCD_CMD)
この記事のコメント(承認後に公開)