TDS(総溶解固形分)センサーを使って液肥の濃度を計測したいと思い、DFRobotのTDSセンサーを買ってみました。
当初ESP32で計測するつもりでしたが、どうしてもうまく計測できなかったのでArduino UNOを使って計測してみました。
まずはTDSとはどういったものか?ちょっと調べてみました。
TDSとは?
TDSはTotal Dissolved Solid=総溶解固形分でカルシウム、マグネシウム、カリウム、ナトリウムなど、水に溶けている物質の総量を濃度で表した数値。
ECとTDSは以下のように計算できるようです。
- EC(mS/cm) X 1000 / 2 = TDS(ppm)
- TDS(ppm) x 2 / 1000 = EC(mS/cm)
水道水や水耕栽培に適したTDS値など調べてまとめてみました。
| PH | EC(電気伝導度) 1mS/cm=1000μS/cm |
TDS(総溶解固形分) PPM |
|
|---|---|---|---|
| 純水 | 5.4-5.7 | 1μS/cm | 0.5ppm |
| 水道水 | 6.8-8.1 | 100~200μS/cm | 40ppm |
| 水耕栽培 | 5.5-7.0 | 基準2.4mS/cm | 1250ppm |
| レタス | 5.5-6.5 | 0.8-1.2 | 560-840ppm |
| キャベツ | 6.5-7.0 | 2.5-3.0 | 1750-2100ppm |
| ブロッコリ | 6.0-6.5 | 2.8-3.5 | 1960-2450ppm |
TDS以外のPHやECは次回、センサーを使ってEC値を取得してサーバーにデータをアップするところまでテストしてみます。
以下のページを参考に表にしてみました。

ハイポニカでは500倍に薄めた濃度なので、TDSは500ppm前後になっていて、上の表よりもちょっと薄い濃度ですが季節や温度・植物によって吸収する養分が違うので薄めでも良いそうです。ただ、大体的に厳密に育てるにはTDS・EC値を測って液肥の濃度を変えていく必要がありそうですが、
今のところテスト的に育てているだけなのでセンサーで計測できていれば気にしないことにして、ハイポニカは500倍に薄めて育てています。
TDSについてちょっとだけ分かったところで実際にTDSを計測して、データをサーバにアップするテストをしていきます。
TDSセンサー + Arduino UNO WIFI Rev2でデータ取得成功
いろいろとテストした結果、Arduino UNO WIFI Rev2を使ってうまくTDS計測ができました。以下のページにArduino UNO WIFI Rev2でWifi接続、サーバーのInfluxDBにTDSデータ送信するまでは以下で書いてますので参考にしてくださると嬉しいです。
今回はその前段階として、Wifiが無いArduino UNOとESP32でTDSセンサーでうまく計測できるか実験している様子をメモ的に書いておきます。
成功したArduino IDE スケッチ
以下のようにしてラズパイのサーバーのInfluxDBにデータをアップできました。
現在は温度を計測してないので、後ほど温度計も導入してより正確にTDS値を取得できるようにしていきます。
#include <SPI.h>
//Wifi接続
#include <WiFiNINA.h>
#include "arduino_secrets.h"
char ssid[] = "Xiaomi_wifi";//Wifi SSIDを変更する
char pass[] = "xxxxxxxx"; //Wifiパスワード
//サーバにアクセスPOST送信
#include <ArduinoHttpClient.h>
//InfluxDB
#define PLACE "reef-TDS"
#define MEASUREMENT "air5"
#define HOST "UNO-Wifi-Rev2"
String influxUrl = "/write?db=sensor";
String influxUser = "root";
String influxPassword = "xxxxxxxx";
const char serverName[] = "192.168.31.53";
int port = 8086;
WiFiClient wifi;
HttpClient client = HttpClient(wifi, serverName, port);
int status = WL_IDLE_STATUS;
//サーバー ラズパイに接続
void postToInfluxDB(int tdsValue) {
String influxData = MEASUREMENT;
influxData += ",place=" PLACE ",host=" HOST;
influxData += " tds=";
influxData += tdsValue;
String contentType = "application/x-www-form-urlencoded";
client.beginRequest();
client.sendBasicAuth(influxUser, influxPassword);//Basic認証
client.post(influxUrl, contentType, influxData);
int statusCode = client.responseStatusCode();
Serial.print("Status code: ");
Serial.println(statusCode);
String response = client.responseBody();
Serial.print("Response: ");
Serial.println(response);
}
//TDS計測
#include <EEPROM.h>
#include "GravityTDS.h"
#define TdsSensorPin A1
GravityTDS gravityTds;
//温度 本当は温度も計測するとなお正確にTDS値が取得できる。
float temperature = 25,tdsValue = 0;
void setup() {
Serial.begin(115200);
while (status != WL_CONNECTED) {
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
delay(10000);
}
//TDS計測
gravityTds.setPin(TdsSensorPin);
gravityTds.setAref(5);
gravityTds.setAdcRange(1024);
gravityTds.begin();
}
void loop() {
//temperature = readTemperature();
gravityTds.setTemperature(temperature);
gravityTds.update();
tdsValue = gravityTds.getTdsValue();
Serial.print(tdsValue,0);
Serial.println("ppm");
if (WiFi.status() == WL_CONNECTED) {
delay(600000);//10分おきにInfluxDBにアップする
postToInfluxDB(tdsValue);
}
delay(1000);
}
サーバー(ラズパイ)のInfluxDBにアップしてGrafanaでグラフ表示したところ↓徐々にPPMが上がってきた?ようです。小さなコップに液肥を入れて実験しているからかもしれません。

Arduino UNO
Arduino UNOは互換機を買いました。コレでも普通にArduino UNOとして使えるようです。
それと、以下のUNOにESP8266が合体してWifiも使えるというのも買ってみましたがArduino IDEでボードでたしか「Generic ESP8266 Module」を選ばなければいけなかったのでこちらではTDSセンサーは使えない。

UNOは全部で3台になった。
ESP32
できればESP32でTDSセンサーを使いたかったのですがうまく計測できず断念。
TDSメーターを用意する
こちらでTDSセンサーをキャリブレーションするときに同じ値にするために使う。激安であまり信用はできないメーターですが、無いよりはましそうなので使ってみます。(実際に使ってみたら全く問題ありませんでした。)
DFRobot Gravity Analog TDS Sensor Meter For Arduinoを用意
Mouserで購入
TDSセンサーは1464円ほどで非常に安かったです。6000円分買うと送料無料になるのも素晴らしいところ。
DFRobot Gravity Analog TDS Sensorの使い方ページ
使い方やArduino IDEのスケッチもこちらにありました。
ブログで地下水のような水の水質調査していました。↓
Arduino UNOでは以下のように配線すればよさそうです。UNOだと迷うことは無いのですが、ESP32ではどうすればいいのか不明。
出展:DFRobot
やはりArduino UNOを使ったほうが無難かもしれません。
Arduino UNO でTDSセンサー動作テスト
まずはノーマルなArduino UNO Rev3でTDSセンサーでちゃんと計測できるかやってみます。
Arduino IDEでボードを「Arduino/Genuino Uno」を選びました。

PIN
上の図のようにデータをA1にしました。
| TDS | Arduino UNO |
|---|---|
| + | VIN |
| – | GND |
| A | A1 |
サンプルスケッチは2通りあって、ライブラリあり・なしのスケッチがありますので、それぞれ試してみます。
ライブラリありのスケッチ
ライブラリはDFRobot Gravity Analog TDS Sensor Meter For Arduino)このページ(DFRobot Gravity Analog TDS Sensor Meter For Arduino)の以下のリンクにあります。

ダウンロードできたら以下のようにスケッチ > ライブラリをインクルード > ZIP形式のライブラリをインストールを選択してダウンロードした GravityTDS-master.zipを選択する。

キャリブレーションする
まずはこちらのサンプルコードをArduino UNOに書き込む。
#include <EEPROM.h>
#include "GravityTDS.h"
#define TdsSensorPin A1
GravityTDS gravityTds;
float temperature = 25,tdsValue = 0;
void setup()
{
Serial.begin(115200);
gravityTds.setPin(TdsSensorPin);
gravityTds.setAref(5.0); //reference voltage on ADC, default 5.0V on Arduino UNO
gravityTds.setAdcRange(1024); //1024 for 10bit ADC;4096 for 12bit ADC
gravityTds.begin(); //initialization
}
void loop()
{
//temperature = readTemperature(); //add your temperature sensor and read it
gravityTds.setTemperature(temperature); // set the temperature and execute temperature compensation
gravityTds.update(); //sample and calculate
tdsValue = gravityTds.getTdsValue(); // then get the value
Serial.print(tdsValue,0);
Serial.println("ppm");
delay(1000);
}
シリアルモニタで「enter」を押してキャリブレーションモードに、↓

液肥が入った水につけて「cal:474」で調整

そうすると、水道水で45くらいなのに90くらいになる・・・?うまくいかない?
Arduino UNO WIFI Rev2でもう一度キャリブレーションして試したところ、正確な数値が出たのでコチラのライブラリありのスケッチを使っています。
ライブラリ無しのスケッチ
ライブラリ使わないのだと液肥432、水道水43くらいで近い値になる。
TDS Value:432ppm
TDS Value:432ppm
TDS Value:432ppm
TDS Value:430ppm
TDS Value:428ppm
TDS Value:104ppm
TDS Value:23ppm
TDS Value:0ppm
TDS Value:0ppm
TDS Value:0ppm
TDS Value:2ppm
TDS Value:76ppm
TDS Value:76ppm
TDS Value:76ppm
TDS Value:76ppm
TDS Value:659ppm
TDS Value:1147ppm ←コップの金属の部分に触れた時
TDS Value:1147ppm
TDS Value:1147ppm
TDS Value:1147ppm
TDS Value:1147ppm
TDS Value:1147ppm
TDS Value:43ppm
TDS Value:41ppm
以下、ESP32でテストしたところうまくTDSデータを取得できませんでした。
失敗メモとして書いておきますので必要なければ読み飛ばしてくださいね。
ESP32(ESP-WROOM-32)でテスト
Arduino UNOでうまくいったので、本番環境で使いたいESP32で試してみる。
ボードをESP32 Dev Moduleを選ぶ。

ESP32はスケッチを書き込む時にBOOTボタンを押す。
PIN
データはGPIO13ピンにする。
| TDS | ESP32 |
|---|---|
| + | VIN |
| – | GND |
| A | GPIO13 |
ライブラリ使わないスケッチ
Anarog PinをGPIO13に変更(左下から3番目D13のPIN)
#define TdsSensorPin 13
液肥につけると12293と高い値が出る。水道水だと0になる。
TDS Value:12293ppm
TDS Value:12293ppm
TDS Value:12382ppm
以下の行を1024→4096に変更
averageVoltage = getMedianNum(analogBufferTemp,SCOUNT) * (float)VREF / 4096.0;
これで、上のほうにある行を5Vから3.3V↓にしても変わらずうまくいかない・・・
#define VREF 3.3
ライブラリありのスケッチ
同様にPINをGPIO13にする。ライブラリもA1→13に直さないといけない。以下のライブラリのあるパスのGravityTDS.cppファイルを編集する。
C:\Users\User名\Documents\Arduino\libraries\GravityTDS-master\GravityTDS.cpp
以下の行を13に変更
this->pin = 13;
キャリブレーションする。

Calで値を送信しても受け付けてくれず・・・ESP32をリセットしてもダメだった。ううん
以下の行を5→3.3に、1024→4096にして再度試すとキャリブレーションで「cal:474」を送信したら成功したが、水道水だとまだ0ppmのまま・・・
gravityTds.setAref(3.3); //reference voltage on ADC, default 5.0V on Arduino UNO
gravityTds.setAdcRange(4096); //1024 for 10bit ADC;4096 for 12bit ADC
ESP32のADCは12BITらしい。なので4096にする。4094で3.3V・5Vにしてもダメだった。
ということで、残念ながら現状ではESP32でTDSセンサーを使えませんでした。
Arduino UNO Wifi Rev2で試してみる
Arduino UNOでWifi接続してデータ送信
WifiがついたArduino UNOを買って、計測したTDSデータをWifiで送信できるようにしました。
Arduino UNO Wifi Rev2でWifiやデータをInfluxDBに投げるまでは書いてありますので省略します。
ライブラリありのスケッチで再度テスト
- 水道水:TDSテスター・TDSセンサーともに38ppmで同じ。
- 液肥:TDSテスターでの計測は577ppmの時にTDSセンサーだと538ppm。少し誤差はありますが許容範囲といったところでしょうか?
温度も一緒に計測すればより値が正確になりそうです。
以上、最終的にTDSセンサーとArduino UNO WIFI Rev2でデータ取得成功しました。




コメント
貴殿のサイトがとても参考になります、ありがとうございます。
TDSセンサーとESP32の組み合わせについて次の様に変更しましたら
おおよそのTDS値が取得できましたので参考になれば幸いです。
#define VREF 5 // analog reference voltage(Volt) of the ADCの
VREFを3.3V->1.1Vに変更、
分解能を1024->4096に変更、
analogSetAttenuation(ADC_6db); //アッテネータを設定
おお!ありがとうございますm(_ _)m
参考になります。