2023 年度 OSS リテラシ 3 : Raspberry Pi でのセンサー利用 (GROVE キット利用版)

はじめに

Grove Base Hat for Raspberry PiGROVE スターターキット を用いて,2 年生のマイコン実験 (Arduino) で行ったような内容をラズパイで行ってみる.

Grove とは,seeed 社が提供するモジュール化されたシステムであり, コネクタが共通化されていることが大きな特徴である. 試しに何か作ってみるときには,配線やケーブルの心配をしなくて良いので, Grove は大変便利である.

また,ラズパイは ADC (A/D コンバータ) 機能を持たないが, Grove Base Hat for Raspberry Pi には ADC 用のアナログポートが存在する. このハットのアナログポートは,ラズパイの機能を使うのではなく, ハットに組み込まれているチップ (STM32) を使っていることを把握しておいてほしい.

なお,教員の手元には他にも多くの I2C の GROVE センサ がある.もし,それらが使いたければ相談して欲しい.

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

seeed 社がラズパイ用に提供している python ライブラリ grove.py があるが, 試したところ最新の Raspberry Pi OS (bullseye) (Debian11 相当) では 動かないものがいくつかあった.そのため,本演習では seeed 社の提供する grove.py を基本として,grove.py が動作しないものについては 別のライブラリ (pigpio, RPi.GPIO) を利用することにする. なお,grove.py は裏で RPi.GPIO を利用している.

seeed 社のライブラリ (grove.py) のインストール

ライブラリの詳細はgrove.py の GitHub のリポジトリ を参照してほしい.

$ git clone https://github.com/Seeed-Studio/grove.py
$ cd grove.py
$ sudo pip install .    (末尾にピリオドが付されていることに注意)

なお,この grove.py をインストールすると, 各種外部機器を動作させるための コマンド群 も提供される.

pigpio

ライブラリの詳細は pigpio library の Web ページ を確認してほしい.

pip コマンドでインストールする.

$ sudo pip install pigpio

pigpio を利用する際は,管理者権限で pigpiod を起動する必要がある.

$ sudo pigpiod

RPi.GPIO

ライブラリの詳細は raspberry-gpio-python の Web ページ を確認してほしい.

pip コマンドでインストールする.

$ sudo pip install RPi.GPIO

I2C 規格のセンサーの利用

今回のキットに含まれる液晶モニタは I2C 規格である. それを使うためにはラズパイの設定が必要である. "メニュー" => "設定" => "Raspberry Pi の設定" を選択し, "インターフェイス" タブより I2C を有効にする

外部機器の利用例

[GPIO] Grove LED

LED を GROVE ハットのデジタルピン (先頭に D が付いているコネクタ) に接続する.以下では LED を D5 ピンに接続した場合の例を示す.

Pythonライブラリ grove.py を用いてプログラミングする. grove.gpio を用いて以下のように書ける.

from grove.gpio import GPIO
from time import sleep

pin = 5
led = GPIO(pin, GPIO.OUT)

while True:
    led.write(1)
    sleep(1)
    led.write(0)
    sleep(1)

上記のようにプログラムが書けることは /usr/local/lib/python3.9/dist-packages/grove/grove_led.py を見ると分かる. なお,この grove.gpio は内部で RPi.GPIO を用いている (/usr/local/lib/python3.9/dist-packages/grove/gpio/gpio_rpi.py を読めばわかる).

プログラムの作成と実行であるが,vi などの適当なエディタでファイルを作成し, それを python コマンドで実行することになる.

$ vi prog.py  (プログラム作成)


$ python prog.py   (実行)

実行を止める場合は Ctrl-c (Ctrl キーと c を一緒に押す) を打鍵すればよい.

[GPIO] Grove ミニファン

ファンを GROVE ハットのデジタルピン (先頭に D が付いているコネクタ) に接続する.以下では LED を D18 ピンに接続した場合の例を示す.

ピンの電圧を上げるとファンが回転し,ピンの電圧を下げるとファンが止まる. LED のオンオフと基本的に同じプログラムで動作させることができる. 以下のプログラムを実行すれば,1 秒おきにファンを回転・停止させることができる.

from grove.gpio import GPIO
from time import sleep

pin = 18
led = GPIO(pin, GPIO.OUT)

while True:
    led.write(1)
    sleep(1)
    led.write(0)
    sleep(1)

[GPIO] Grove リレー

リレーを GROVE ハットのデジタルピン (先頭に D が付いているコネクタ) に接続する.以下では LED を D22 ピンに接続した場合の例を示す.

リレーも GPIO で電圧の上げ下げで制御することができる.

from grove.gpio import GPIO
from time import sleep

pin = 22
led = GPIO(pin, GPIO.OUT)

while True:
    led.write(1)
    sleep(1)
    led.write(0)
    sleep(1)

なお,/usr/local/lib/python3.9/dist-packages/grove/grove_relay.py を見ると, GroveRelay 専用の grove.grove_relay が用意されており, それを用いると以下のようにプログラムが書けることが分かる. 実行できることがわかる.

import time
from grove.grove_relay import GroveRelay

PIN   = 22
relay = GroveRelay(PIN)

while True:
    relay.on()
    time.sleep(1)
    relay.off()
    time.sleep(1)

[GPIO] Grove ボタン

ボタンを GROVE ハットのデジタルピン (先頭に D が付いているコネクタ) に接続する.以下ではボタンを D16 ピンに接続した場合の例を示す.

Pythonライブラリ grove.py を用いてプログラミングする. LED と同じ grove.gpio を用いると以下のように書ける. GPIO の良く見るプログラムと準じた形になっていることがわかる.

from grove.gpio import GPIO
import time

pin = 16
switch = GPIO(pin, GPIO.IN)

while True:
    print (switch.read())
    time.sleep(1)

また,grove.py では,スイッチ専用の grove.grove_switch も用意されている. /usr/local/lib/python3.9/dist-packages/grove/grove_button.py を見ると,以下のようなプログラムを書いて実行すれば良いことが分かる.

from grove.grove_switch import GroveSwitch
import time

PIN = 16
swicth = GroveSwitch(PIN)

while True:
   if swicth.state:
      print("high")
   else:
      print("low")
   time.sleep(1)

[GPIO] モーションセンサー

モーションセンサーを GROVE ハットのデジタルピン (先頭に D が付いているコネクタ) に接続する.以下では LED を D18 ピンに接続した場合の例を示す.

基本的に GPIO で入力を取るセンサなので,ボタン (スイッチ) と同じプログラムが動く. 以下の例はピン番号を 16 から 18 へ変えただけである.

from grove.gpio import GPIO
import time

pin = 16
switch = GPIO(pin, GPIO.IN)

while True:
    print (switch.read())
    time.sleep(1)

実行してみると,反応がさほど良くないが, センサの前にものを置いた時に値が 1, センサの前に何もものが無い場合には値が 0 となることが確かめられる.

[PWM] Grove パッシブブザー

ラズパイで PWM を扱えるのは,ハットの PWM コネクタと D18 コネクタの 2 つである.そのため,ブザーは PWM か D18 コネクタのどちらかに 接続しないといけない. 以下ではブザーを PWM ピン (= 12 ピン) に接続した場合の例を示す.

Pythonライブラリ grove.py ではブザーを動かすためのメソッドが消えているので, Python ライブラリ pigpio で PWM 信号を扱うことにする.

pigpio を使う場合は,最初に pigpiod コマンドを実行する必要がある.

$ sudo pigpiod

以下のようなプログラムを作成して実行すれば良い.

import time
import pigpio

pi = pigpio.pi()

#PWMパラメータ
pwm_pin = 12 #PWM出力ピンを指定 (PWM ピン)
duty = 50 #デューティー比を%で指定
freq = 400 #PWM周波数をHzで指定

#パラメータ変換
cnv_dutycycle = int((duty * 1000000 / 100))

#PWMを出力
pi.hardware_PWM(pwm_pin, freq, cnv_dutycycle)

# 3 秒間鳴らす
time.sleep(3)

#PWMを止める. duty = 0 に.
pi.hardware_PWM(pwm_pin, freq, 0)

[ADC] Grove 回転角度センサ

回転角度センサを GROVE ハットのアナログピンに接続する. 以下ではセンサを A0 に接続した場合の例を示す.

Pythonライブラリ grove.py を用いてプログラミングする. /usr/local/lib/python3.9/dist-packages/grove/adc.py を元に, ADC を用いたプログラムを作成すると以下のようになる.

import time
from grove.adc import ADC

adc = ADC()
while True:
    # Read channel 0 (Slot A0) voltage. Max 3300 mV
    # 右に回しきると 0 V,左に回し切ると 3.3 V なので,それを 0-1000 の数字に当てはめている
    print( int( adc.read_voltage( 0 ) / 3300 * 1000 ) )  # val 0-1000
    time.sleep(1)

/usr/local/lib/python3.9/dist-packages/grove/grove_rotary_angle_sensor.py から,回転角度センサ専用の grove.grove_rotary_angle_sensor が存在することがわかる. これは grove.adc のラッパーになっている. これを用いる場合は以下のようなプログラムを書いて実行すれば良い.

import time
from grove.grove_rotary_angle_sensor import GroveRotaryAngleSensor

PIN = 0
sensor = GroveRotaryAngleSensor(PIN)

while True:
    print('Rotary Value: {}'.format(sensor.value))
    time.sleep(.2)

[ADC] Grove サウンドセンサ

サウンドセンサを GROVE ハットのアナログピンに接続する. 以下ではセンサを A2 に接続した場合の例を示す.

Pythonライブラリ grove.py を用いてプログラミングする. ADC は電圧を見ているだけなので,回転角度センサと同じプログラム (ピン番号は 0 から 2 に変えている) が動く. 音量の正規化の係数 (/ 3300 * 1000 ) は適当に変更すれば, 出力する数値を適当に変更することができる.

import time
from grove.adc import ADC

adc = ADC()
while True:
    # Read channel 2 (Slot A2) voltage. Max 3300 mV
    print( int( adc.read_voltage( 2 ) / 3300 * 1000 ) )  # val 0-1000
    time.sleep(1)

また,/usr/local/lib/python3.9/dist-packages/grove/grove_sound_sensor.py から, 専用の grove.grove_sound_sensor が存在することが分かるので, それを用いたプログラムを以下のように書ける.

import time
from grove.grove_sound_sensor import GroveSoundSensor

PIN = 2
sensor = GroveSoundSensor(PIN)

print('Detecting sound...')
while True:
    print('Sound value: {0}'.format(sensor.sound))
    time.sleep(.3)

[ADC] Grove ライトセンサ

ライトセンサは反射光より色合い判断するのに使うことができる. 白いもの,黒いものに LED を近づけると, それぞれ大きな値,小さな値が表示される.

ライトセンサを GROVE ハットのアナログピンに接続する. 以下ではセンサを A4 に接続した場合の例を示す.

Pythonライブラリ grove.py を用いてプログラミングする. ADC は電圧を見ているだけなので,回転角度センサと同じプログラム (ピン番号は 0 から 4 に変えている) が動く. 音量の正規化の係数 (/ 3300 * 1000 ) は適当に変更すれば, 出力する数値を適当に変更することができる.

import time
from grove.adc import ADC

adc = ADC()
while True:
    # Read channel 2 (Slot A2) voltage. Max 3300 mV
    print( int( adc.read_voltage( 4 ) / 3300 * 1000 ) )  # val 0-1000
    time.sleep(1)

また,/usr/local/lib/python3.9/dist-packages/grove/grove_light_sensor_v1_2.py から, 専用の grove.grove_light_sensor_v1_2 が存在することが分かるので, それを用いたプログラムを以下のように書ける.

import time
from grove.grove_light_sensor_v1_2 import GroveLightSensor

PIN = 4
sensor = GroveLightSensor(PIN)

print('Detecting light...')
while True:
    print('Light value: {0}'.format(sensor.light))
    time.sleep(1)

Grove 温度湿度センサ DHT11

温湿度センサ DHT11 を GROVE ハットのデジタルピン (先頭に D が付いている コネクタ) に接続する.以下では LED を D26 ピンに接続した場合の例を示す.

Pythonライブラリ grove.py で提供されるコマンドが動かないので, DHT11 用に seeed 社が公開している Python ライブラリを用いる.

$ sudo pip install seeed-python-dht

プログラムは以下のように書ける.

import time
import seeed_dht

# DHT11 type
dht11 = seeed_dht.DHT("11", 26)

while True:
    humi, temp = dht11.read()
    print('humidity {0:.1f}%, temperature {1:.1f}*'.format(humi, temp))
    time.sleep(1)

[I2C] Grove 16x2 LCD

LCD を GROVE ハットの I2C ピンに接続する.

<URL:https://wiki.seeedstudio.com/Grove-LCD_RGB_Backlight/#play-with-raspberry-pi> を参考にプログラムを作成する. GrovePigrove_rgb_lcd を元にプログラムを作成する. 実行すると,setText 関数で指定した文字列が表示されるはずである.

import time,sys
import smbus

bus = smbus.SMBus(1)

# this device has two I2C addresses
DISPLAY_TEXT_ADDR = 0x3e

# send command to display (no need for external use)
def textCommand(cmd):
    bus.write_byte_data(DISPLAY_TEXT_ADDR,0x80,cmd)

# set display text \n for second line(or auto wrap)
def setText(text):
    textCommand(0x01) # clear display
    time.sleep(.05)
    textCommand(0x08 | 0x04) # display on, no cursor
    textCommand(0x28) # 2 lines
    time.sleep(.05)
    count = 0
    row = 0
    for c in text:
        if c == '\n' or count == 16:
            count = 0
            row += 1
            if row == 2:
                break
            textCommand(0xc0)
            if c == '\n':
                continue
        count += 1
        bus.write_byte_data(DISPLAY_TEXT_ADDR,0x40,ord(c))

# main
setText("Hello world?? \nThis is an LCD test")

課題

課題 3 は必須とする.課題 4-1 ~ 4-4 については 1 つ選ぶこと.

課題 3

上記演習で用いた機器を 4 個以上を用いたシステムを構築して動作させよ. 但し,利用シーンを定め,何らかの目的を実現するためのシステムとすること.

  • 教員に動作確認してもらうこと.
  • 作成したプログラム,システムの利用シーンや目的を簡単にまとめた文書を提出すること.

課題 4-1

PWM のパッシブブザーのサンプルプログラムを改良して, LED の明るさと音の高さを同期変化させるプログラムを作成せよ. 段階的に明るく/高音にしていき,明るさが最大になった後は段階的に暗く/低音にすること.

  • 教員に動作確認してもらうこと.
  • 作成したプログラムを提出すること.

課題 4-2

パッシブブザーを PWM ではなく,GPIO (電圧の ON/OFF) で 「ドレミファソラシド」と音を鳴らすこと. これは 2 年生のマイコン実験の課題と同じである.

  • 教員に動作確認してもらうこと.
  • 作成したプログラムを提出すること.

課題 4-3

ADC のサウンドセンサもしくはライトセンサについて, /usr/local/lib/python3.9/dist-packages/grove/adc.py 内で定義されている ADC クラスを用いてプログラムを作成せよ. すなわち,サンプルスクリプト 21-rotary_angle-2.py と同様な プログラムをサウンドセンサもしくはライトセンサについて作成すること.

  • 教員に動作確認してもらうこと.
  • 作成したプログラムを提出すること.

課題 4-4

LCD のデータシート の p.14-15 を参考に,カタカナ文字を液晶ディスプレイに表示させよ.

  • 教員に動作確認してもらうこと.
  • 作成したプログラムを提出すること.

[参考] Ruby で L チカ

Ruby ライブラリ pi_piper を用いても,Lチカなど実行することができる.

$ sudo apt install ruby-dev libssl-dev
$ gem install pi_piper

$ vi led.rb

  require "pi_piper"
  pin_a = PiPiper::Pin.new(:pin => 5, :direction => :out)
  loop do
    pin_a.on
    sleep 1
    pin_a.off
    sleep 1
  end

$ ruby led.rb