
Raspberry Pi のセンシングにハマっているgoldear@goldear820です。
今回はTDS(Total Dissolved Solids 総溶解固形物)をラズパイで測定するのですが、しっかり意味を理解していないと全く意味のない代物です。
アクアリウム初心者の私がTDSを気にする必要は無いのですが、技術的に測定してみたいということで実施してみます。
目次
TDSについて
TDSとは Total Dissolved Solids 総溶解固形物 の略語で、一言でいうと水中に含まれる不純物を測定して、数値化します。
※今回は技術的に測定してみたいだけなので、詳細は割愛します。
水質検査用品を取り扱っているセラジャパンのコラムに以下のようなものがあります。
全体図

簡易的な全体図になります。
スマートアクアリウムはRaspberry Piをベースに実装していきます。
Raspberry Piの持つGPIO経由で各種センサと接続してセンサ情報を収集、Raspberry Pi自身にセンサ情報を処理させます。
今回はTDSセンサ KS0429、ADC MCP3008 を使って、機能を追加していきます。
今後、機能拡張を行うごとに全体図は更新していきます。現時点で実装予定の機能は以下のとおりです。
【実装済み】
・水温測定
・室温/湿度測定
【未実装】
・TDS(Total Dissolved Solids)測定 ← 今回実装
・pH測定
・CO2測定
・センサ情報のOLED表示
・映像ストリーミング
・Webサーバにセンサ情報公開
準備物
TDSセンサ KS0429

今回使用するのもAmazonで購入可能な中華製KEYESTUDIO TDSセンサーです。
公式wikiに仕様や使い方がまとめられており、Arduino用C言語ですがサンプルコードがあるのも親切で好印象。
今回はサンプルコードをRaspberry Pi用pythonに書き換えて利用させてもらいます。
ADC MCP3008

TDSセンサはアナログ出力のため、そのままではラズパイに入力することができません。
今回はMCP3008(ADC 8チャネル・分解能10bit・SPI)を用いて、アナログ出力をデジタル出力に変換してからラズパイに入力します。
Raspberry Pi

今回もRaspberry Pi ZERO WHを使用します。
設定
MCP3008はラズパイとSPIで通信するため、あらかじめらSPIを有効化しておく必要があります。
pi@raspberry:~ $ sudo raspi-config
上記コマンドを実行することで、設定画面が表示されます。

「3 Interface Options」を選択します。
※ Debian 12ベースのRaspberry Pi OS「Bookworm」の設定画面です。バージョン違いで設定項目が異なる可能性があります。

「I3 SPI」を選択します。

「はい」を選択すると、SPIが有効化されます。
SPIについては上記のページが詳細に説明されています。
実装
全体の流れは、以下の通り
① 水温センサーで取得した値をログ記録
② TDSセンサで取得した電圧値を取得
③ ①で取得した最新の水温値を用いて、電圧値を温度補正
④ 補正済み電圧値をTDS値に変換
1秒ごとに水温値を取得して、ログ記録を行うコードです。※実用ではもっと低頻度で取得
#!/usr/bin/env python3
import datetime
from time import sleep
from w1thermsensor import W1ThermSensor
OUTPUT = "/home/goldear/temp/log/ds18b20.log"
def get_water_temp():
while True:
# Create instance
temp_sensor = W1ThermSensor()
# Get time
dt_now = datetime.datetime.now()
timestamp = dt_now.strftime("%Y-%m-%d %H:%M:%S")
try:
# Get water temperature
temp = temp_sensor.get_temperature()
except SensorNotReadyError as e:
pass
#print("Reading from DHT failure: ", e.args)
# Write log
with open(OUTPUT, mode="a") as log:
log.str = timestamp + "," + f'{temp:.2f}' + "\n"
log.write(log.str)
# Debug
print(str(temp))
sleep(1)
return
if __name__ == "__main__":
get_water_temp()
TDSセンサが取得した電圧値を取得して、温度補正、TDS値変換を行うコードです。
#!/usr/bin/env python3
from gpiozero import MCP3008
from time import sleep
import numpy as np
AVE_NUM = 128
def get_tds():
# Get Newest Water temperature from log file
date, w_temp = np.loadtxt(
fname = "/home/goldear/temp/log/ds18b20.log"
,delimiter = ","
,dtype = "unicode"
,unpack = "True"
)
# Convert data type
date = date.astype(np.datetime64)
w_temp = w_temp.astype(np.float64)
newest_w_temp = w_temp[-1]
# Calc voltage compensation coefficient
vcf = 1.0 + 0.02 * (newest_w_temp - 25.0);
# Get ADC Voltage from MCP3008
Vref = 3.301
adc = MCP3008(channel=0, differential=False)
## Calc median value
l_buf_vol = []
for i in range(AVE_NUM):
l_buf_vol.append(adc.value)
np_buf_vol = np.array(l_buf_vol)
## Calc coefficient value
c_vol = np.median(np_buf_vol) * Vref / vcf
# Calc TDS value
tds_val = ( 133.42 * c_vol * c_vol * c_vol
- 255.86 * c_vol * c_vol
+ 857.39 * c_vol) * 0.5
# Debug
print("TDS Value: " + f'{tds_val:.2f}' + "ppm")
return
if __name__ == "__main__":
get_tds()
動作確認

水槽内の水にセンサを浸けます。
25.0
25.0625
25.0625
25.0
25.0625
水温記録のpythonプログラムを実行して、1秒毎に水温を出力していること、指定ファイルにログ記録されていることを確認。
TDS Value: 362.77ppm
続けてTDS測定のpythonプログラムを実行して、TDS値がコンソール上に出力されたことを確認。
まとめ
素人の私にはあまり必要性がないTDS値を確認できるようにしました。
実際に使用してみた印象としては、餌を与えれば上がり、バクテリアを添加すれば上がり、指を水に漬ければ上がる。唯一下げる方法は水換えのみ。
やはり私には必要なさそうです。。。
・水温測定の実装

・室温・湿度測定の実装



コメント