スマートアクアリウムのススメ③ Raspberry Pi で TDS測定【KS0429】

Raspberry Pi のセンシングにハマっているgoldear@goldear820です。

今回はTDS(Total Dissolved Solids 総溶解固形物)をラズパイで測定するのですが、しっかり意味を理解していないと全く意味のない代物です。

アクアリウム初心者の私がTDSを気にする必要は無いのですが、技術的に測定してみたいということで実施してみます。

スポンサーリンク

TDSについて

TDSとは Total Dissolved Solids 総溶解固形物 の略語で、一言でいうと水中に含まれる不純物を測定して、数値化します。

※今回は技術的に測定してみたいだけなので、詳細は割愛します。

水質検査用品を取り扱っているセラジャパンのコラムに以下のようなものがあります。

TDSってなに?? | 株式会社セラジャパン
TDSメーターは水中に含まれる不純物を測定するようです。不純物とは何なのか?アクアリウムの不純物とは有害物質の事なのでしょうか?実際に飲料水やRO水、アクアリウムの水槽の飼育水を測定し、TDS値の違いを検証してみます。
アクアリウムのTDS値 | 株式会社セラジャパン
アクアリウムのTDS測定は推奨しません。正しい使用方法と測定内容を理解すれば、飼育水の汚れやミネラルを測定することは困難な事が分かります。TDS値は水に溶け込んだ色々な物の総量に反応し、単一物質に特化した測定には不向きな事が分かりました。飼...

全体図

簡易的な全体図になります。

スマートアクアリウムはRaspberry Piをベースに実装していきます。

Raspberry Piの持つGPIO経由で各種センサと接続してセンサ情報を収集、Raspberry Pi自身にセンサ情報を処理させます。

今回はTDSセンサ KS0429、ADC MCP3008 を使って、機能を追加していきます。

今後、機能拡張を行うごとに全体図は更新していきます。現時点で実装予定の機能は以下のとおりです。

【実装済み】
・水温測定
・室温/湿度測定


【未実装】
・TDS(Total Dissolved Solids)測定 ← 今回実装
・pH測定
・CO2測定
・センサ情報のOLED表示
・映像ストリーミング
・Webサーバにセンサ情報公開

準備物

TDSセンサ KS0429

今回使用するのもAmazonで購入可能な中華製KEYESTUDIO TDSセンサーです。

KS0429 keyestudio TDS Meter V1.0 - Keyestudio Wiki

公式wikiに仕様や使い方がまとめられており、Arduino用C言語ですがサンプルコードがあるのも親切で好印象。

今回はサンプルコードをRaspberry Pi用pythonに書き換えて利用させてもらいます。

ADC MCP3008

TDSセンサはアナログ出力のため、そのままではラズパイに入力することができません。

今回はMCP3008(ADC 8チャネル・分解能10bit・SPI)を用いて、アナログ出力をデジタル出力に変換してからラズパイに入力します。

10bit 8ch ADコンバーター MCP3008-I/P: 半導体 秋月電子通商-電子部品・ネット通販
電子部品,通販,販売,半導体,IC,LED,マイコン,電子工作10bit 8ch ADコンバーター MCP3008-I/P秋月電子通商 電子部品通信販売

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通信インターフェースの基本を学ぶ(入門編) - 通信回路、プロトコルなど | Analog Devices
SPI通信インターフェース(Serial Peripheral Interface)は、マイクロコントローラとその周辺ICの間でよく使用される同期式シリアル通信インターフェースの1つです。センサー、A/Dコンバータ、D/Aコンバータ、シフト...

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()


動作確認

水槽内の水にセンサを浸けます。

pi@raspberrypi:~/temp/src $ python ds18b20.py
25.0
25.0625
25.0625
25.0
25.0625

水温記録のpythonプログラムを実行して、1秒毎に水温を出力していること、指定ファイルにログ記録されていることを確認。

pi@raspberrypi:~/temp/src $ python ks0429.py
TDS Value: 362.77ppm

続けてTDS測定のpythonプログラムを実行して、TDS値がコンソール上に出力されたことを確認。

まとめ

素人の私にはあまり必要性がないTDS値を確認できるようにしました。

実際に使用してみた印象としては、餌を与えれば上がり、バクテリアを添加すれば上がり、指を水に漬ければ上がる。唯一下げる方法は水換えのみ。

やはり私には必要なさそうです。。。

・水温測定の実装

スマートアクアリウムのススメ① Raspberry Pi で 水温測定【DS18B20】
北海道で買ってきたまりもをこぢんまりと育てるつもりが、どんどんアクアリウムにハマって後戻りできない状態のgoldear@goldear820です。 アクアリウムで非常に重要になってくるのが「水温管理」ですが、我が家はNASが24時間稼働して...

・室温・湿度測定の実装

スマートアクアリウムのススメ② Raspberry Pi で 室温&湿度測定【DHT22】
冬場はPC暖房で過ごすgoldear@goldear820です。 前回ススメ①で水槽の水温を測定できるようにしましたが、今回は水槽を配置している部屋の温度・湿度を測定できるようにします。 私の水槽は25x17x21cmの小型水槽なので、特に...

コメント