Raspberry Pi Zero 2 W(以下、Zero 2 W)にRaspberry Pi OS 32bit版をセットアップしました。メモリ(SDRAM)搭載量が512MBと少ないのでRaspberry Pi OSが満足に動作するか心配していましたが、OSのGUI操作や軽いアプリケーションであれば拍子抜けするくらい普通に動作します。
Zero 2 Wには無線LAN機能が加わったので、同じSSIDの無線LANに接続しているPCからVNC Vewerで遠隔操作できます。時計も正確です。
USBブートのRaspberry Pi 4 Model B(以下、4B)の快適さに慣れてしまうとアプリの起動など遅いのですが、Python 3でI2CやSPI接続したモジュール制御には問題なく対応できました。
Zero 2 WとI2C接続したSCD30、BME280センサ、SPI接続した2.8インチTFT液晶で動作確認した際のメモです。
Zero 2 Wの仕様
Zero 2 WはCPU性能が向上し、WiFiがついたのでIoT用途にも向いています。メモリ(SDRAM)搭載量が512MBと少ないので重いアプリを動かすのは難しいですが、Raspberry Pi OS上のPython3から各種センサモジュールを制御できるので使い勝手が良いです。
もうすぐRaspberry Pi PicoにInfineon CYW43439無線チップを追加搭載したRaspberry Pi pico Wの国内販売が始まるようです。値段も安いので登場が待ちどおしいです。
項目 | Raspberry Pi 4 Model B | Raspberry Pi Zero2 W | Raspberry Pi pico W |
SoC プロセッサ | Broadcom BCM2711 ARM v8 Cortex-A72 Quad core 1.5GHz or 1.8GHz | Broadcom BCM2710A1 ARM v8 Cortex-A53 Quad core 1GHz | RP2040 ARM Cortex-M0+ Dual-core 133 MHz |
メモリー | 1GB, 2GB, 4GB or 8GB LPDDR4-3200 SDRAM | 512MB LPDDR2 SDRAM | 264kB on-chip SRAM |
ネットワーク | • 2.4 GHz and 5.0 GHz IEEE 802.11.b/g/n/ac wireless •Gigabit Ethernet | 2.4GHz IEEE 802.11b/g/n wireless | 2.4GHz 802.11n wireless |
GPIO | •40-pin GPIO header | • 40-pin I/O header footprint ※GPIO端子の半田付け必要 | 26 multifunction GPIO pins |
代表的な コネクタ | •2×USB 3.0 ports、 2×USB 2.0 ports • microSD card slot •2×micro-HDMI ports •MIPI DSI display port | • USB 2.0 port • microSD card slot • mini HDMI port | • USB 1.1 controller • BOOTSEL button |
電源 | USB-C connector 5V DC 3A | microUSB connector 5V DC 2.5A | micro USB power port |
参考:
・Raspberry Pi 4 Model B specifications – Raspberry Pi
・Raspberry Pi Zero 2 W specifications – Raspberry Pi
・Raspberry Pi Pico and Pico W – Raspberry Pi Documentation
・Raspberry Pi Pico W – Raspberry Pi
・Operating system images – Raspberry Pi OS
Raspberry Pi OSのセットアップ、モジュールとの結線
Zero 2 WとI2C接続したSCD30センサとBME280センサモジュールの測定データをSPI接続した2.8インチTFT液晶(240×320、ILI9341)モジュールに日本語フォントで表示して動作確認しました。
4Bと同じ構成、手順で動作させることができました。
Raspberry Pi OSのセットアップ
Zero 2 Wのmini HDMI portにはHDMI接続のディスプレイを、micro USB(USBと印字の)コネクタにはキーボードとマウスを、micro USB(PWR INと印字の)コネクタにはACアダプタをつなぎます。
セットアップ手順は4Bと同じです。PCにインストールしたRaspberry Pi Imagerを使ってmicroSDカードにRaspberry Pi OSのセットアップイメージを書込みます。書き込んだmicroSDカードをZero 2 Wのスロットに挿し込んで電源ON(ACアダプタをmicro USBコネクタに接続)です。
Raspberry Pi OSのI2CとSPIを有効化
I2CとSPIの設定 はデフォルトでは無効です。
苺メニューの「設定」—>「Raspberry Piの設定」を開いて—>「インターフェース」でI2CとSPIを有効にチェック。
再起動するとSoC内蔵の I2C(ハードウエア I2C)とSPI通信が使えるようになります。
Zero 2WにSCD30センサとBME280センサを結線した後、LXTerminalで下記コマンドを投入すると、i2c-1(バス番号1)にBME280のアドレス(0x76)とSCD30のアドレス(0x61)が見えます。
i2cdetect -y 1
結線図
2.8インチTFT液晶(240×320)モジュールをSPIで、SCD30センサとBME280センサモジュールをSoC内蔵の I2C(ハードウエア I2C)で接続する結線図です。2.8インチTFT液晶(240×320)モジュールは4線式のSPIです。
Zero 2 Wと4BのGPIOのピン構成は同じです。Zero 2 WのmicroSDカードスロット側がGPIOの1番ピン側になります。
2.8インチTFT液晶モジュールとGPIOとのピン接続の詳細は下記ページに纏めました。本記事ではライブラリのインストールなど必要事項のみの記載です。
Python3プログラムを実行
SCD30センサ、BME280センサでCO2濃度、気圧、気温、湿度を測定して、SPI接続の2.8インチTFTに表示するPython3プログラムをZero 2で実行しました。
このPython3プログラムは4Bで実行した実績があります。
ライブラリのインストール
ライブラリのインストールにはpipを使います。pipは、Pythonパッケージのインストールなどを行うユーティリティで、Raspberry Pi OS with desktop(bullseye)にはPython3とともにインストールされています。
現時点のバージョンはPythonが3.9.2、pipが20.3.4。
構築したRaspberry Pi OSにはPython3のみなので、コマンドではpipとpip3を区別していません。
smbus2
未インストールであればi2C通信を行うためにsmbus2をインストールします。smbus2パッケージは「smbus2-0.4.2」でした。
sudo pip install smbus2
https://pypi.org/project/smbus2/
2.8インチTFT液晶ライブラリ
2.8インチTFT液晶 (240×320)モジュールの液晶コントローラLSIはILI9341。Adafruitのライブラリ「Adafruit_CircuitPython_RGB_Display」を利用させていただきました。
sudo pip install adafruit-circuitpython-rgb-display
https://github.com/adafruit/Adafruit_CircuitPython_RGB_Display
SCD30ライブラリ
SCD30のライブラリには「scd30_i2c」を利用させていただきました。ライブラリ「scd30_i2c」のバージョンは「scd30-i2c-0.0.6」でした。利用には、Pythonバージョン >=3.7.3が必要です。
sudo pip install scd30-i2c
https://pypi.org/project/scd30-i2c/
BME280ライブラリ
BME280のライブラリには「RPi.bme280 0.2.4」を利用させていただきました。Python3コード上でI2Cアドレスとポート番号を指定できるで使い勝手が良いです。
sudo pip install RPi.bme280
https://pypi.org/project/RPi.bme280/
BME280、SCD30センサの測定データを2.8インチTFT液晶に表示するプログラムコード
Adafruitライブラリ付属のサンプルプログラム「rgb_display_pillow_stats.py」を参考にして、SCD30センサでCO2濃度、BME280センサで気圧、気温、湿度の測定結果の出力先として2.8インチTFT液晶を加えたプログラムコード「bme280_scd30_sample_TFT_csv.py」を作りました。
日本語を表示するために、独立行政法人情報処理推進機構 (IPA) が提供している日本語フォント「IPAex フォント」をインストール。「ipaexfont-gothic」を使っています。
sudo apt install fonts-ipaexfont
Python3プログラムの実行環境には、Raspberry Pi OS with desktop(bullseye)にプリインストール されているThonny Python IDEを使って動作確認しました。
Thonny Python IDEのshell部分にCSV形式で連続表示するとともに、2.8インチTFT液晶にも2秒間隔で表示します。
CSV表示は、先頭から日時(曜日)、SCD30データ(CO2濃度、気温、湿度)、BME280データ(気圧、気温、湿度)。2.8インチTFT液晶表示は、上からBME280データ(気温)、SCD30データ(CO2濃度)、BME280データ(気圧、湿度)、日時(曜日)です。
Thonny Python IDEのshell部分へのCSV表示が不要な場合は117行目を#でコメントアウトします。
bme280_scd30_sample_TFT_csv.py
※ここをクリックするとコード表示を開閉できます。
#bme280_scd30_sample_TFT_csv.py
#coding: utf-8
#---TFT-ili9341 init-----rgb_display_pillow_stats.py---
import time
import subprocess
import digitalio
import board
from PIL import Image, ImageDraw, ImageFont
from adafruit_rgb_display import ili9341
# Configuration for CS and DC pins (these are PiTFT defaults):
cs_pin = digitalio.DigitalInOut(board.CE0)
dc_pin = digitalio.DigitalInOut(board.D25)
reset_pin = digitalio.DigitalInOut(board.D24)
# Config for display baudrate (default max is 24mhz):
BAUDRATE = 24000000
# Setup SPI bus using hardware SPI:
spi = board.SPI()
# pylint: disable=line-too-long
# Create the display:
disp = ili9341.ILI9341(
spi,
rotation=90, # 2.2", 2.4", 2.8", 3.2" ILI9341
cs=cs_pin,
dc=dc_pin,
rst=reset_pin,
baudrate=BAUDRATE,
)
# pylint: enable=line-too-long
# Create blank image for drawing.
# Make sure to create image with mode 'RGB' for full color.
if disp.rotation % 180 == 90:
height = disp.width # we swap height/width to rotate it to landscape!
width = disp.height
else:
width = disp.width # we swap height/width to rotate it to landscape!
height = disp.height
image = Image.new("RGB", (width, height))
# Get drawing object to draw on image.
draw = ImageDraw.Draw(image)
# Draw a black filled box to clear the image.
draw.rectangle((0, 0, width, height), outline=0, fill=(0, 0, 0))
disp.image(image)
# First define some constants to allow easy positioning of text.
padding = -2
x = 0
# Load a ipaexfont-gothic font.
font1 = ImageFont.truetype("/usr/share/fonts/opentype/ipaexfont-gothic/ipaexg.ttf", 50)
font2 = ImageFont.truetype("/usr/share/fonts/opentype/ipaexfont-gothic/ipaexg.ttf", 20)
font3 = ImageFont.truetype("/usr/share/fonts/opentype/ipaexfont-gothic/ipaexg.ttf", 15)
#---BME280 init---------------bme280_sample.py------------
import smbus2
import bme280
port = 1
address = 0x76
bus = smbus2.SMBus(port)
calibration_params = bme280.load_calibration_params(bus, address)
# the sample method will take a single reading and return a
# compensated_reading object
data = bme280.sample(bus, address, calibration_params)
#---SCD30 init-----------------scd30_sample.py------------
from scd30_i2c import SCD30
scd30 = SCD30()
scd30.set_measurement_interval(2)
scd30.start_periodic_measurement()
time.sleep(2)
while True:
#---csv out ------------------------------------------
if scd30.get_data_ready():
m = scd30.read_measurement()
if m is not None:
dtd = time.strftime('%Y年%m月%d日', time.localtime())
dtt = time.strftime('%H時%M分%S秒', time.localtime())
dta = time.strftime('%a', time.localtime())
if dta == "Mon":
jdta = dta.replace("Mon", "(月)")
elif dta == "Tue":
jdta = dta.replace("Tue", "(火)")
elif dta == "Wed":
jdta = dta.replace("Wed", "(水)")
elif dta == "Thu":
jdta = dta.replace("Thu", "(木)")
elif dta == "Fri":
jdta = dta.replace("Fri", "(金)")
elif dta == "Sat":
jdta = dta.replace("Sat", "(土)")
elif dta == "Sun":
jdta = dta.replace("Sun", "(日)")
else:
jdta="ー"
data = bme280.sample(bus, address, calibration_params)
pbme280 = f"{data.pressure:.1f},{data.temperature:.1f},{data.humidity:.1f}"
pscd30 = f"{m[0]:.1f},{m[1]:.1f},{m[2]:.1f}"
P_csv = dtd + jdta + " " + dtt + "," + pscd30 + "," + pbme280
print(P_csv)
#---TFT-ili9341- Draw ---------------------------------
# Draw a black filled box to clear the image.
draw.rectangle((0, 0, width, height), outline=0, fill=(0, 0, 0))
draw.text((50, 192), dtd, font=font2, fill="#00ff00")
draw.text((50, 212), dtt, font=font2, fill="#00ff00")
draw.text((220, 192), jdta, font=font2, fill="#00ff00")
draw.text((20, 3), "温度:", font=font2, fill="#ffffff")
draw.text((24, 25), "( ℃ )", font=font3, fill="#ffffff")
temp =format(float(data.temperature), '.1f')
draw.text((90, 0), temp, font=font1, fill="#ffffff")
draw.text((14, 50), "CO :", font=font2, fill="#FFFF00")
draw.text((47, 58), "2", font=font3, fill="#FFFF00")
draw.text((14, 70), "( ppm )", font=font3, fill="#FFFF00")
co2 =format(float(m[0]), '.1f')
draw.text((90, 47), co2, font=font1, fill="#FFFF00")
draw.text((20, 97), "気圧:", font=font2, fill="#ffffff")
draw.text((18, 117), "( hpa )", font=font3, fill="#ffffff")
pres =format(float(data.pressure), '.1f')
draw.text((90, 93), pres, font=font1, fill="#ffffff")
draw.text((20, 143), "湿度:", font=font2, fill="#ffffff")
draw.text((24, 165), "( % )", font=font3, fill="#ffffff")
humi =format(float(data.humidity), '.1f')
draw.text((90, 140), humi, font=font1, fill="#ffffff")
disp.image(image)
time.sleep(2)
else:
time.sleep(0.2)
SCD30センサのセルフキャリブレーション
SCD30センサは換気の良い場所で電源を入れたままで一定時間連続測定してセルフキャリブレーションします。400ppm台の数値に落ち着くと思います。
SparkFun SCD30 CO₂ センサー ライブラリ
注: SCD30 には、自動セルフキャリブレーション ルーチンがあります。Sensirion は、セルフキャリブレーションを完了するために、少なくとも 1 日 1 時間の「新鮮な空気」で 7 日間の連続測定を推奨しています。Note: The SCD30 has an automatic self-calibration routine. Sensirion recommends 7 days of continuous readings with at least 1 hour a day of ‘fresh air’ for self-calibration to complete.
https://github.com/sparkfun/SparkFun_SCD30_Arduino_Library
Interface Description Sensirion SCD30 Sensor Module p.13/21
1.4.6 自動セルフキャリブレーション (ASC) の (非) アクティブ化
継続的な自動セルフキャリブレーションは、次のコマンドで (非) アクティブにすることができます。 初めてアクティブ化する場合、アルゴリズムが ASC の初期パラメーター セットを見つけることができるように、最低 7 日間必要です。 センサーは、毎日少なくとも 1 時間は新鮮な空気にさらす必要があります。 また、その間、センサーを電源から切り離すことはできません。そうしないと、キャリブレーション パラメータを見つける手順が中止され、最初からやり直す必要があります。 正常に計算されたパラメータは SCD30 の不揮発性メモリに保存され、再起動後も以前に見つかった ASC のパラメータが引き続き存在するという効果があります。1.4.6 (De-)Activate Automatic Self-Calibration (ASC)
https://sensirion.com/media/documents/D7CEEF4A/6165372F/Sensirion_CO2_Sensors_SCD30_Interface_Description.pdf
Continuous automatic self-calibration can be (de-)activated with the following command. When activated for the first time a period of minimum 7 days is needed so that the algorithm can find its initial parameter set for ASC. The sensor has to be exposed to fresh air for at least 1 hour every day. Also during that period, the sensor may not be disconnected from the power supply, otherwise the procedure to find calibration parameters is aborted and has to be restarted from the beginning. The successfully calculated parameters are stored in non-volatile memory of the SCD30 having the effect that after a restart the previously found parameters for ASC are still present.