Tanuki_Bayashin’s diary

電子工作を趣味としています。最近はラズベリーパイPicoというマイコンを使って楽しんでいます

においセンサの出力をLEDアレイを用いて表示する

※なにか気になる点がありましたらコメント欄からお伝えください。また、回路を製作する場合には電源を切るなど、注意を払って行うようお願いいたします。
(2021/10/11)

目次

1.はじめに

 以前、においセンサの出力(電圧値)をラズベリーパイPico(以下Picoと記述)を用いてPCの画面に文字で表示したが、より見やすくできないかと思い、複数のフルカラーLEDから構成されるWS2812Bを用いて表示することを試みた。

図1 製作した回路(電源は省略)
図2 においセンサ(TGS2450)(左:ブレッドボード上 右:拡大図)


秋月電子通商
※このHPの検索欄にて、においセンサ「TGS2450」あるいは通販コード「P-00989」と入力すれば、
においセンサTGS2450の情報を得ることができます。
(2023/10/03 変更:秋月電子通商の意向により)
akizukidenshi.com

ラズベリーパイPico
www.raspberrypi.org

WS2812B
www.adafruit.com

以前の記事:
【ラズベリーパイPico】においセンサにてにおいを検知する - Tanuki_Bayashin’s diary

【Raspberry Pi Pico 専用】WS2812B のためのライブラリの試作 - Tanuki_Bayashin’s diary

2.構成

 実体配線図を図3に示す。以前の臭気センサを用いた回路にWS2812Bを付け足した形となっている。(WS2812Bは実際では10x10のLEDアレイのものを選んだ)

図3 実体配線図

 においセンサ周りの回路は以前の記事と同じである。今回、臭気センサからの出力(0~5V)を0~9の整数に計算しなおし、WS2812B の高さとして出力した(簡易型のオシロスコープのような使い方をしている)。

※今回用いたにおいセンサは、においを感知すると出力する電圧が低下する。電圧が低下することでにおいを検出する仕組みになっている。このセンサは硫黄化合物に特に反応するとのことである。

3.コード

 リスト1にPico内のコードを載せる。ただし、自分用に製作したWS2812B用のライブラリを使用している。
WS2812B用のライブラリのコードへのリンク:
https://tanuki-bayashin.hatenablog.com/entry/2021/09/20/044930#%EF%BC%93%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA

3.1 リスト1

import array, utime
import machine
from machine import Pin
from Sep_2021 import Class_ws2812b    # 自作したWS2812B用のライブラリ

#Configure the number of WS2812 LEDs.
NUM_LEDS = 100

# においセンサーを用いるための準備
PinHeater = machine.Pin(0, machine.Pin.OUT) # センサのヒータを温める(GP0)
PinSensor = machine.Pin(1, machine.Pin.OUT) # センサへ電力を与える(GP1)
PinOutput = machine.ADC(26)     # センサの出力を読み取る(AD変換器:GP26)


# クラスClass_ws2812b からオブジェクトwsを取得している
ws = Class_ws2812b.Class_ws2812b()

# オブジェクトwsよりインスタンスsmを得ている
# StateMachine(0, ws2812, freq=8000000, sideset_base=Pin(16))
sm = ws.init_ws2812b(0, 8000000, 16)

# start the StateMachine, it will wait for data on its FIFO.
# 上で初期設定したsm(ステートマシン)を有効化している
sm.active(1)

# Display a pattern on the LEDs via an array of LED RGB values.
ar = array.array("I", [0 for _ in range(NUM_LEDS)])

# position の位置のLEDにred, green, blueの値をセットする
def ar_color(position, red, green, blue):
    ar[position] = (green<<16) + (red<<8) + blue

# すべてのLEDを消灯する
def clear_all():
    for i in range(NUM_LEDS):
        ar[i] = 0
    sm.put(ar,8)    # GP16(21番ピン)からWS2812Bに値を出力している

# retsu で示される列のLEDを消灯する
def clear_retsu(retsu):
    for i in range(10):
        j = retsu + i * 10
        ar[j] = 0

# retsu で示される列において、takasa の高さまで
# LEDを表示する。(一番上は白)
def colum(retsu, takasa):
    """display colum at retsu takasa."""
    # clear LEDs of retsu
    clear_retsu(retsu)
    # display LEDs of retsu
    for i in range(takasa):
        j = retsu + i*10
    #   ar_color(position, red, green, blue)
        ar_color(j, 0, 0, 80)  # -> week blue
    # Top of retsu is colored white
    ar_color(retsu + takasa * 10, 25, 25, 25)

    sm.put(ar,8)    # WS2812Bへ出力
    utime.sleep_ms(1)    # 1ms待機。念のため

# においセンサー ヒーター、センサーオフ
PinHeater.value(0)    # Heater OFF
PinSensor.value(1)    # Sencor Pullup OFF

# センサから値を読み取るための処理
def Keisoku_Shuuki():
    global voltage2
    utime.sleep(0.237)
    PinSensor.value(0)    # センサーへ給電
    utime.sleep(0.003)    # 250ms 中 3ms ON

    # センサーの電圧値を取得
    voltage = PinOutput.read_u16()
    voltage = voltage * 9.9 / 65535.0

    utime.sleep(0.002)    # 2ms ON (合計 5ms ON)
    PinSensor.value(1)    # センサー OFF

    PinHeater.value(1)    # 8ms Heater ON
    utime.sleep(0.008)
    PinHeater.value(0)    # Heater OFF
    voltage2 = min(int((voltage - 6.0) * 2 + 6.0), 9)

if __name__ == '__main__':
    # Process arguments
    print('Press Ctrl-C to quit.')

    try:
        while True:                          # メインループ
            for retsu in range(10):    # retsu 0~ 9
                global voltage2

        # においの計測
                Keisoku_Shuuki()
                takasa = voltage2
        # LEDを表示する
                colum(retsu, takasa)

    except KeyboardInterrupt:
        #### clear ws2812b
        clear_all()
        print('program is finished')

3.2 解説

 1~4行 ライブラリをインポートしている。
 7行目  WS2812BのLEDの数を指定
10~12行 においセンサ用の入出力ピンの割り当て
15~24行 コメントの通り。(WS2812B用のライブラリは自作なので、不具合が出る可能性あり。
 27行目 LED100個分のデータを格納するための変数。
29~60行 自作の関数4種。関数の内容はコメントの通り。
62~64行 においセンサの初期設定。ヒータ用の出力は正論理、
     センサの給電用の出力は負論理のため、このようになる
66~83行 においセンサから出力を得るための処理。以前の記事にも示したが、
     センサの購入元である秋月電子通商から得たコードである。
85~103行 メインルーチンである。if、try、except にてキーボードから’Ctrl-C’ が押されると、
      プログラムが終了する。プログラム終了時、LEDを消灯している。
      メインループのなかのKeisoku_Shuuki()にて出力を読み取り、
      colum(retsu, takasa)にてWS2812Bに結果を表示している。

4.動画

 実際にLEDが表示されるようすを動画で確認する。0列目から9列目にかけてそのときにおいセンサで読み取った値を高さで表し、再び0列目から表示している。
 調味料や薬品など、様々な物質について反応の様子を観察した。
youtu.be

5.まとめ

 以前においセンサを用いたとき、「表示に関して一目で様子が分かるものを考案する」としていたので、今回それに対応した形となっている。次は口臭チェッカーのようなものが作れたら面白いと思う。