Arduino с датчиком TDS (датчик качества воды)
В этом руководстве вы узнаете, как использовать TDS-метр (Total Dissolved Solids — общее количество растворённых твёрдых веществ) с платой Arduino. TDS-метр показывает общее количество растворённых твёрдых веществ, таких как соли, минералы и металлы, в растворе. Этот параметр можно использовать для оценки качества воды и сравнения воды из разных источников. Одно из основных применений TDS-метра — мониторинг качества воды в аквариуме.
Мы будем использовать TDS-метр от keystudio и покажем простой пример измерения TDS в единицах ppm с помощью Arduino IDE.
В этом руководстве мы рассмотрим следующие темы:
Знакомство с TDS-метром
TDS-метр измеряет количество общих растворённых твёрдых веществ, таких как соли, минералы и металлы, в воде. По мере увеличения количества растворённых веществ в воде возрастает её проводимость, что позволяет вычислить общее количество растворённых веществ в ppm (мг/л).
Хотя это хороший индикатор для мониторинга качества воды, обратите внимание, что он не измеряет загрязняющие вещества в воде. Таким образом, вы не можете полагаться исключительно на этот индикатор для определения пригодности воды для употребления.
TDS-метр может быть полезен для мониторинга качества воды во многих приложениях, таких как бассейны, аквариумы, рыбные резервуары, гидропоника, водоочистители и т.д.
В этом руководстве мы будем использовать TDS-метр от keystudio, который поставляется с интерфейсным модулем и электродным зондом (см. изображение выше).
Для получения дополнительной информации о TDS-метре мы рекомендуем ознакомиться с официальной документацией.
Характеристики и спецификации
Данное руководство относится к TDS Meter V1.0 от keystudio. Вот параметры датчика:
TDS-метр:
Входное напряжение: DC 3.3 ~ 5.5 В
Выходное напряжение: 0 ~ 2.3 В
Рабочий ток: 3 ~ 6 мА
Диапазон измерения TDS: 0 ~ 1000 ppm
Точность измерения TDS: ± 10% F.S. (25 °C)
Интерфейс модуля: XH2.54-3P
Интерфейс электрода: XH2.54-2P
TDS зонд:
Количество игл: 2
Общая длина: 60 см
Интерфейс подключения: XH2.54-2P
Цвет: белый
Водонепроницаемый зонд
Где купить датчик TDS?
Вы можете найти датчик TDS по лучшей цене:
Подключение TDS-метра к Arduino
TDS-метр выдает аналоговый сигнал, который можно измерить с помощью аналоговых выводов Arduino (A0–A5).
Подключите датчик согласно следующей таблице:
Датчик TDS |
Arduino |
|---|---|
GND |
GND |
VCC |
3.3V |
Data |
A0 (или любой другой аналоговый вывод Arduino) |
Считывание TDS (качества воды) с Arduino – Код
Как мы упоминали ранее, датчик выдаёт аналоговый сигнал, который можно преобразовать в TDS в ppm. Мы используем код, предоставленный документацией датчика, с некоторыми модификациями.
Для получения более точных результатов вам, вероятно, потребуется откалибровать датчик с помощью раствора с известным значением TDS. Однако это может не потребоваться, если вас интересует не конкретное значение, а качественная оценка TDS.
Загрузите следующий код на вашу плату Arduino.
// Original source code: https://wiki.keyestudio.com/KS0429_keyestudio_TDS_Meter_V1.0#Test_Code
// Project details: https://RandomNerdTutorials.com/arduino-tds-water-quality-sensor/
#define TdsSensorPin A0
#define VREF 5.0 // analog reference voltage(Volt) of the ADC
#define SCOUNT 30 // sum of sample point
int analogBuffer[SCOUNT]; // store the analog value in the array, read from ADC
int analogBufferTemp[SCOUNT];
int analogBufferIndex = 0;
int copyIndex = 0;
float averageVoltage = 0;
float tdsValue = 0;
float temperature = 16; // current temperature for compensation
// median filtering algorithm
int getMedianNum(int bArray[], int iFilterLen){
int bTab[iFilterLen];
for (byte i = 0; i<iFilterLen; i++)
bTab[i] = bArray[i];
int i, j, bTemp;
for (j = 0; j < iFilterLen - 1; j++) {
for (i = 0; i < iFilterLen - j - 1; i++) {
if (bTab[i] > bTab[i + 1]) {
bTemp = bTab[i];
bTab[i] = bTab[i + 1];
bTab[i + 1] = bTemp;
}
}
}
if ((iFilterLen & 1) > 0){
bTemp = bTab[(iFilterLen - 1) / 2];
}
else {
bTemp = (bTab[iFilterLen / 2] + bTab[iFilterLen / 2 - 1]) / 2;
}
return bTemp;
}
void setup(){
Serial.begin(115200);
pinMode(TdsSensorPin,INPUT);
}
void loop(){
static unsigned long analogSampleTimepoint = millis();
if(millis()-analogSampleTimepoint > 40U){ //every 40 milliseconds,read the analog value from the ADC
analogSampleTimepoint = millis();
analogBuffer[analogBufferIndex] = analogRead(TdsSensorPin); //read the analog value and store into the buffer
analogBufferIndex++;
if(analogBufferIndex == SCOUNT){
analogBufferIndex = 0;
}
}
static unsigned long printTimepoint = millis();
if(millis()-printTimepoint > 800U){
printTimepoint = millis();
for(copyIndex=0; copyIndex<SCOUNT; copyIndex++){
analogBufferTemp[copyIndex] = analogBuffer[copyIndex];
// read the analog value more stable by the median filtering algorithm, and convert to voltage value
averageVoltage = getMedianNum(analogBufferTemp,SCOUNT) * (float)VREF / 1024.0;
//temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.02*(fTP-25.0));
float compensationCoefficient = 1.0+0.02*(temperature-25.0);
//temperature compensation
float compensationVoltage=averageVoltage/compensationCoefficient;
//convert voltage value to tds value
tdsValue=(133.42*compensationVoltage*compensationVoltage*compensationVoltage - 255.86*compensationVoltage*compensationVoltage + 857.39*compensationVoltage)*0.5;
//Serial.print("voltage:");
//Serial.print(averageVoltage,2);
//Serial.print("V ");
Serial.print("TDS Value:");
Serial.print(tdsValue,0);
Serial.println("ppm");
}
}
}
Как работает код
Давайте кратко рассмотрим код. Вы также можете сразу перейти к разделу Демонстрация.
Переменная TdsSensorPin сохраняет GPIO, с которого вы хотите получать показания. У ESP8266 есть только один аналоговый вывод — A0.
#define TdsSensorPin A0
Затем укажите аналоговое опорное напряжение для АЦП. Для Arduino это 5 В.
#define VREF 5.0 // analog reference voltage(Volt) of the ADC
Перед получением значения измерения мы применим алгоритм медианной фильтрации для получения более стабильного значения. Переменная SCOUNT указывает количество выборок, которые мы отфильтруем перед получением фактического значения.
#define SCOUNT 30 // sum of sample point
Затем нам нужны массивы для хранения показаний, а также индексные переменные, позволяющие перемещаться по массивам.
int analogBuffer[SCOUNT]; // store the analog value in the array, read from ADC
int analogBufferTemp[SCOUNT];
int analogBufferIndex = 0;
int copyIndex = 0;
Инициализируйте переменные averageVoltage и tdsValue как переменные с плавающей точкой.
float averageVoltage = 0;
float tdsValue = 0;
Переменная temperature сохраняет текущее значение температуры. Температура влияет на показания, поэтому существует алгоритм, компенсирующий колебания температуры. В этом примере эталонная температура составляет 25 °C, но вы можете изменить её в зависимости от вашей среды. Для более точных результатов вы можете добавить датчик температуры и получать фактическую температуру в момент считывания показаний датчика.
float temperature = 25; // current temperature for compensation
Следующая функция будет использоваться для получения стабильного значения TDS из массива показаний.
// median filtering algorithm
int getMedianNum(int bArray[], int iFilterLen){
int bTab[iFilterLen];
for (byte i = 0; i<iFilterLen; i++)
bTab[i] = bArray[i];
int i, j, bTemp;
for (j = 0; j < iFilterLen - 1; j++) {
for (i = 0; i < iFilterLen - j - 1; i++) {
if (bTab[i] > bTab[i + 1]) {
bTemp = bTab[i];
bTab[i] = bTab[i + 1];
bTab[i + 1] = bTemp;
}
}
}
if ((iFilterLen & 1) > 0){
bTemp = bTab[(iFilterLen - 1) / 2];
}
else {
bTemp = (bTab[iFilterLen / 2] + bTab[iFilterLen / 2 - 1]) / 2;
}
return bTemp;
}
В setup() инициализируйте Serial Monitor на скорости 115200 бод.
Serial.begin(115200);
Установите вывод датчика TDS как вход.
pinMode(TdsSensorPin,INPUT);
В loop() получайте новые показания TDS каждые 40 миллисекунд и сохраняйте их в буфере:
static unsigned long analogSampleTimepoint = millis();
if(millis()-analogSampleTimepoint > 40U){ //every 40 milliseconds,read the analog value from the ADC
analogSampleTimepoint = millis();
analogBuffer[analogBufferIndex] = analogRead(TdsSensorPin); //read the analog value and store into the buffer
analogBufferIndex++;
if(analogBufferIndex == SCOUNT){
analogBufferIndex = 0;
}
}
Затем каждые 800 миллисекунд он получает последние показания и вычисляет среднее напряжение, используя ранее созданный алгоритм фильтрации:
static unsigned long printTimepoint = millis();
if(millis()-printTimepoint > 800U){
printTimepoint = millis();
for(copyIndex=0; copyIndex<SCOUNT; copyIndex++){
analogBufferTemp[copyIndex] = analogBuffer[copyIndex];
// read the analog value more stable by the median filtering algorithm, and convert to voltage value
averageVoltage = getMedianNum(analogBufferTemp,SCOUNT) * (float)VREF / 1024.0;
Затем он вычисляет коэффициент температурной компенсации и рассчитывает значение TDS с учётом этого значения:
//temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.02*(fTP-25.0));
float compensationCoefficient = 1.0+0.02*(temperature-25.0);
//temperature compensation
float compensationVoltage=averageVoltage/compensationCoefficient;
//convert voltage value to tds value
tdsValue=(133.42*compensationVoltage*compensationVoltage*compensationVoltage- 255.86*compensationVoltage*compensationVoltage + 857.39*compensationVoltage)*0.5;
Наконец, он выводит значение TDS в ppm:
Serial.print("TDS Value:");
Serial.print(tdsValue,0);
Serial.println("ppm");
Демонстрация
После копирования кода в Arduino IDE загрузите его на вашу плату. Не забудьте выбрать правильную плату в Tools > Board и правильный COM-порт в Tools > Port.
После загрузки откройте Serial Monitor на скорости 115200 бод.
Если зонд не погружён в жидкость, будет отображаться значение приблизительно 0. Погрузите зонд в раствор, чтобы проверить его TDS. Вы можете попробовать с водопроводной водой и добавить немного соли, чтобы увидеть, как значения увеличиваются.
Я измерил значение TDS водопроводной воды в своём доме и получил значение около 100 ppm, что является хорошим показателем для питьевой воды.
Я также протестировал чай, и значение TDS увеличилось примерно до 230 ppm, что кажется разумным значением.
Наконец, я также измерил значение TDS бутилированной воды и получил значение около 25 ppm (такое же значение при использовании ESP8266).
Я также делюсь здесь результатами одного из наших читателей, чтобы вы могли сравнить:
водопроводная вода на ранчо: 125 ppm
пиво Corona: 384 ppm
уксус: 610 ppm
джин-тоник: 43 ppm
очищенная вода: 0 ppm
Заключение
TDS-метр может измерять общее количество растворённых твёрдых веществ в растворе. Он может использоваться как индикатор качества воды и позволяет характеризовать воду. Метр возвращает значение TDS в ppm (parts per million — миллионные доли, мг/л). Значение TDS имеет множество применений, но его нельзя использовать само по себе для определения, пригодна ли вода для питья или нет.
Отличное применение этого типа датчика — монитор качества воды в аквариуме. Вы можете использовать этот датчик вместе с водонепроницаемым датчиком температуры DS18B20 для мониторинга вашего аквариума, например.
У нас есть руководства по другим популярным датчикам для платы Arduino, которые могут вам понравиться: