■動機
いつかRaspberry Piで遊んでみたいなと思っていたのですが、最近やっと触り始めて最初に躓いた点についてニーズがあるかわかりませんが、備忘録として残したいと思い、記載
■やろうとした事
趣味のアクアリウムで、仕事で行っているデータ分析を何か絡められないかと思い、生き物を長生きさせるための水質指標の可視化・分析でもしようかなと思い立ちました
■目的設定
とりあえず、pHあたりは必須かなと何となく思っていましたが、アクアリウムをやる人なら一度は買ったことのある試験紙タイプで測れる指標(こんなの↓)をターゲットに考えました
テトラ テスト 6in1 試験紙

ただ、調べると水温、pHは入手しやすいセンサーで測れそうでしたが、それ以外は結構難しそうだったので一旦、やれそうなものから始めてみることにしました。以下は指標とセンサーの入手性を考えた時のものです
| 指標 | 観点 | 入手性 | 実現性 |
|---|---|---|---|
| pH | 酸性・アルカリ性。生体の種類で好みがある | 容易:(4000円程度) | 可能 |
| 水温 | 熱帯魚なら必須 | 容易:(1000円程度) | 可能 |
| 亜硝酸$$NO^{-}_{2}$$ | 生物ろ過が効いているかの確認。水替えに重要な指標 | 困難:研究用用途しかない(5万以上) | 不可 |
| 硝酸$$NO^{-}_{3}$$ | 亜硝酸がさらに分解されるとこれになる。溜まりすぎると良くない | 同上 | 不可 |
| EC(導電率) | 化学反応的に見る試験紙の指標は測るのが難しそうなので、代替の指標。水の汚れ具合を見るための指標 | 買えなくは無い(1万) | 可能 |
■構成
ハード面
・Raspberry Pi(最新はPi5。もはやちょっとしたパソコンくらいの性能あり。安いPi4にした)
・ブレッドボード(Raspberry Piと線をつなぐために間のボード)
・ジャンパー線(Raspberry PiはGPIOというセンサーとのI/Fがあるのでそこに線をつなぐ)
・水温センサー(DS18B20)
・pHセンサー(Analog pH Sensor kit)
・ECセンサー(Analog Electrical Conductivity Sensor Kit)※今後購入予定
水槽 ← センサー ← ジャンパー線 ← Raspberry Pi という構成
※出典:https://www.souichi.club/raspberrypi/rasppi-ds18b20/
ソフト面
・Python
・Streamlit
・プログラム
水温を取得するプログラム
import time
import csv
from datetime import datetime
from pathlib import Path
INTERVAL = 60.0
def read_temp():
device_file = '/sys/bus/w1/devices/28-000000783735/w1_slave'
with open(device_file, 'r') as f:
lines = f.readlines()
temp_pos = lines[1].find('t=')
temp_string = lines[1][temp_pos+2:]
temp_c = float(temp_string) / 1000.0
return temp_c
def main():
log_paht = Path('temp_log.csv')
newfile = not log_paht.exists()
next_time = time.monotonic()
while True:
now = time.monotonic()
sleep_sec = next_time - now
if sleep_sec > 0:
time.sleep(sleep_sec)
try:
temp_c = read_temp()
ts = datetime.now().isoformat(timespec='seconds')
print(f'{ts} {temp_c:.2f} ℃')
with log_paht.open('a', newline='') as f:
writer = csv.writer(f)
if newfile:
writer.writerow(['timestamp', 'temp_c'])
newfile = False
writer.writerow([ts, f'{temp_c:.3f}'])
except Exception as e:
print('Error', e)
next_time += INTERVAL
if __name__ == '__main__':
main()
ログファイルをStreamlitで可視化するプログラム
# temp_dashboard.py
import pandas as pd
import streamlit as st
from pathlib import Path
LOG_FILE = Path("temp_log.csv")
st.set_page_config(page_title="水温モニタ", layout="wide")
st.title("水温モニタリング ダッシュボード")
if not LOG_FILE.exists():
st.warning("まだ temp_log.csv がありません。先に temp_logger.py を動かしてください。")
st.stop()
df = pd.read_csv(LOG_FILE)
df["timestamp"] = pd.to_datetime(df["timestamp"])
st.sidebar.header("表示設定")
hours = st.sidebar.slider("表示する時間範囲(時間)", 1, 168, 24)
latest_time = df["timestamp"].max()
threshold_time = latest_time - pd.Timedelta(hours=hours)
df_show = df[df["timestamp"] >= threshold_time].copy()
st.subheader(f"直近 {hours} 時間の水温")
st.line_chart(
df_show.set_index("timestamp")[["temp_c"]],
height=300,
)
latest = df.iloc[-1]
st.subheader("最新の値")
col1, col2 = st.columns(2)
with col1:
st.metric("水温 (℃)", f"{latest['temp_c']:.2f}")
with col2:
st.write("記録時刻:", latest["timestamp"])
with st.expander("生データを表示"):
st.dataframe(df_show.sort_values("timestamp", ascending=False))
やっと本題
楽しく電子工作を夜、家族が寝静まった後に行って、簡単なプログラムを書いた後にStreamlitを実行したら以下エラーが出て、解決に時間がかかりました。

ネットで調べてもあまりいい情報が簡単には見つからなかったのですが、生成AI(GPT5.1)に聞きながら、解消ができました。ほんと生成AIすごいですねぇ、、、もはや自分の調査能力を軽く超えていることに気づきました。
■直接原因
pipでStreamlitをインストールした際に依存関係で入るNumpy/Pandasは、Raspberry PiのCPUと合っておらず、不正命令(Illegal instruction)が発生してしまう。
・Raspberry PiのCPUは、Cortex-A72(Pi4)
→このCPUに汎用バイナリのNumpy2.3.5が合っていない
■対策
公式がRaspberry PiのARM CPU向けにビルドしているapt版のNumpy/Pandasを利用する
手順①
Raspberry Pi OS用のNumpy/Pandasをインストールする
sudo apt-get install -y python3-numpy python3-pandas
手順②
venv を --system-site-packagesで作り、Raspberry Pi向けにビルドされているインストール済のNumpy/Pandasを使うようにする
python3.11 -m venv --system-site-packages ~/venv_XXX
手順③
pip でStreamlitをインストールするが、Numpy/Pandasを新たに入れないように--no-depsで実施
pip install --no-deps streamlit
手順④
Streamlitを起動して、No moduleで怒られたら、個別に必要なパッケージを地道にインストールする。なお、パッケージ(altairなど)によってはNumpy/Pandasと依存関係があって、pipが勝手に新しいバージョンを入れないように--no-depsで実施する
pip install --no-deps altair などなど
これでエラーが解消しました♪

