Raspberry Pi で i2c対応 7セグディスプレイを制御

目的

  1. 可能な限り手軽に7セグディスプレイを制御する
  2. 最低でも4桁 2つ以上のデバイスを制御したい
  3. 利用するGPIOを最小限に抑えたい

利用した物

赤フグさんの下記キットを利用しました
http://www.akafugu.jp/ja/posts/products/twidisplay/

こちらを利用すると 複数デバイスをi2cプロトコルを用いて2線で制御できます。
(電源を入れると4線)

※複数デバイスのチェーン接続にあたってはRaspberryPiより流せる電流に気をつけるのはもちろんなのですが、下記を利用するのも安定動作のために良い方法という事を教えて頂きました。

http://akizukidenshi.com/catalog/g/gM-05452/

セットアップ

ハードウェア接続

GPIOピンの下記4つを利用し7セグ側の同名ピンに接続します。
ご利用のバージョンに合わせて下さい。

  • 3.3V (b+/2 では1)
  • i2c SDA (b+/2 では3)
  • i2C SCL (b+/2 では5)
  • GND (b+/2 では6)

Raspberry Pi側の設定

7セグディスプレイを接続すると、オンボードのマイコン起動に
15秒程掛かった後に、自分のアドレスが7セグに表示されます。

i2c利用のための準備

$ sudo apt-get install i2c-tools

/etc/modules

追記する

snd-bcm2835  
i2c-bcm2708  
i2c-dev  

/etc/modprobe.d/raspi-blacklist.conf

コメントアウトする

#blacklist i2c-bcm2708

/etc/modprobe.d/i2c.conf

ファイルを新しく作成の上、下記を追記

options i2c_bcm2708 baudrate=10000  

上記設定で反映しないケースがあり、下記設定を行いました。

/boot/config.txt

dtparam=i2c1_baudrate=10000  

※後述しますがbaudrateの記載が無いとハマりました

i2cスレーブアドレスの確認

pi@sseg-server ~ $ sudo i2cdetect -y 1  
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --  
10: 10 -- -- -- -- -- -- -- -- -- -- UU -- -- -- --  
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
30: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- --  
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  
70: -- -- -- -- -- -- -- --  

上記で10, 20と出ているのが認識されているデバイスのスレーブアドレスとなります。

ディスプレイをクリア

pi@sseg-server ~ $ sudo i2cset -y 1 0x10 0x82  

こちらで7セグディスプレイが反応すればOKです。

パラメータの意味

  • -y インタラクティブモードを無効にする
  • 1 i2cバスとして1を指定 (Raspberry Pi B+/2では1のみ)
  • 0x10 接続している機器のスレーブアドレス(7セグディスプレイ)
  • 0x82 ディスプレイクリア (詳細は赤フグさんキットのプロトコルドキュメントを参照)

サンプルプログラム

なんとなく動作が確認できたので早速 Pythonで制御してみます。

Python用ライブラリのインストール

$ sudo apt-get install python-smbus

test.pyを作成してみる

import smbus  
import time

bus = smbus.SMBus(1)

# init
bus.write_byte(0x10, 0x82)

def display(seg, num):  
    bus.write_byte(seg, 0x82)
    for i in list(str(num)):
        bus.write_byte(seg, int(i))
    time.sleep(0.01)

for i in range(0, 10000):  
    display(0x10, i)

1桁づつ表示命令を掛けるため、一度画面クリア後に大きい桁の数値から並べるようにして表示するようにしております。

はまった点

事象

高速で命令を出し続けていると下記のようなエラーがでました。

IOError: [Errno 5] Input/output error  

キットの説明に記載はありませんが、デフォルトのi2c通信速度では安定した通信ができません。

対策

手探りで色々と試していた所、i2cデバイスとの接続速度を baudrate=10000 とする事で安定して動作するようになりました。

i2c baudrate (before)

/etc/modprobe.d/i2c.conf にて設定無し

$ dmesg | grep i2c
[    5.850469] bcm2708_i2c_init_pinmode(1,2)
[    6.036941] bcm2708_i2c_init_pinmode(1,3)
[    6.228679] bcm2708_i2c bcm2708_i2c.1: BSC1 Controller at 0x20804000 (irq 79) (baudrate 100000)
[   13.466956] i2c /dev entries driver

i2c baudrate (after)

/etc/modprobe.d/i2c.conf にて設定あり (baudrate=10000)

$ dmesg | grep i2c
[    5.885741] bcm2708_i2c_init_pinmode(1,2)
[    6.077875] bcm2708_i2c_init_pinmode(1,3)
[    6.208788] bcm2708_i2c bcm2708_i2c.1: BSC1 Controller at 0x20804000 (irq 79) (baudrate 10000)
[   14.508370] i2c /dev entries driver
takashi