Raspberry PiとI2C接続のキャラクタ・ディスプレイ その2 Pythonでプログラム

I2Cはバイト単位の入出力

 前回、i2c-toolsを使って、OLE(有機EL)表示器のSO1602Aの動作を確認しました。アドレスは0x3cでした。smbusのPythonライブラリもインストールしました。smbusはI2Cとほとんど同じ規格ですが、策定はフィリップスではなくインテルです。PCの電源管理や温度管理のために使っています。PCなので、マスタは一つだけという特殊事情があります。I2Cはマルチマスタを考慮したプロトコルです。

Pythonでプログラミング

 次の一覧表が、smbusライブラリのファンクションです。表示器は書き込みだけをします。したがって、単独の書き込みは、次の2種類があります。

  • write_byte_data(アドレス, コマンド, 1バイトの値)
  • write_word_data(アドレス, コマンド, 1ワードの値)

 複数のデータをまとめて書き込みときは、次の二つのいずれかを使います。

  • write_block_data(アドレス, コマンド, 1個以上の1バイトの値)
  • write_i2c_block_data(アドレス, コマンド,  1個以上の1バイトの値)

   (※最大32バイトまで)

 二つの関数で、送っているデータを見たのが次の図です。アドレスを送った後の状態が異なります。SO1602Aは、write_block_data() では、先頭に間違ったキャラクタを表示したので、write_i2c_block_data()を使うことにしました。なお、次回に予定しているAQM1602では、どちらも正しい表示ができました。

ファンクション SMBus

  • long write_quick(int addr)
  • long read_byte(int addr)
  • long write_byte(int addr,char val)
  • long read_byte_data(int addr,char cmd)
  • long write_byte_data(int addr,char cmd,char val)
  • long read_word_data(int addr,char cmd)
  • long write_word_data(int addr,char cmd,int val)
  • long process_call(int addr,char cmd,int val)
  • long[] read_block_data(int addr,char cmd)
  • write_block_data(int addr,char cmd,long vals[])
  • long[] block_process_call(int addr,char cmd,long vals[])
ファンクション I2C

  • long[] read_i2c_block_data(int addr,char cmd,byte)
  • write_i2c_block_data(int addr,char cmd,long vals[])

(※)2018/10/27 long[] read_block_data(int addr,char cmd)のパラメータが一つ多かったので削除した。

画面の初期化

#!usr/bin/env python
# -*- coding: utf-8 -*-
import smbus
import time
i2c = smbus.SMBus(1)  #1 : bus number
addr01=0x3c #OLED
_command=0x00
_data=0x40
_clear=0x01
_home=0x02
display_On=0x0f
OLED_2ndline=0x20+0x80

# 画面初期化 OLED SO1602
i2c.write_byte_data(addr01, _command, _clear)
time.sleep(0.2)
i2c.write_byte_data(addr01, _command, _home)
time.sleep(0.1)
i2c.write_byte_data(addr01, _command, display_On)
time.sleep(0.1)

 実行すると、カーソルが左上で点滅します。

 画面の初期化は、

i2c.write_i2c_block_data(addr01, _data, [_clear,_home,display_On])

でも動作しました。time.sleep()を入れないと正常にコマンドが受け付けられないときは、1命令ずつ書き込みましょう。

書き込み

 左上から"1234"と表示します。

i2c.write_i2c_block_data(addr01, _data, [0x31,0x32,0x33,0x34])

 つづけて"aX"と表示します。

i2c.write_i2c_block_data(addr01, _data, [ord('a'),ord('X')])

 2行目の先頭から、"1234"と表示します。

i2c.write_byte_data(addr01, _command, OLED_2ndline)
i2c.write_i2c_block_data(addr01, _data, [0x31,0x32,0x33,0x34])

 文字列”Temp: ”を表示して、下の行に移動後”109”と表示します。

message1="Temp : "
mojilist=[]
for moji in message1:
        mojilist.append(ord(moji))

i2c.write_i2c_block_data(addr01, _data, mojilist)

i2c.write_byte_data(addr01, _command, OLED_2ndline)

i2c.write_i2c_block_data(addr01, _data, [0x31,0x30,0x39])

 初期設定と上記のプログラムを一つのファイルにして、i2c.pyというファイル名で保存します。sudo chmod 755 i2c.pyで実行権を付けます。python i2c.pyと入力して実行すると次のように表示されました。

 コラム I2Cの転送速度

 Standard-mode では最大100kbit/s、Fast-mode では最大400kbit/s、Fast-mode Plus では最大 1Mbit/s、High-speedでは最大 3.4Mbit/s のデータ転送が可能です。

 SO1602Aのデータシートにはクロックが最小2.5us=400kHzとなっているので、/boot/config.txtに、デフォルトの100kHzから400kHzへ変更しても動作するかもしれません。

dtparam=i2c_baudrate=400000