Измеритель EC на основе Arduino

# Описание

Максимально дешевое и простое в изготовлении устройство для постоянного измерения электропроводности раствора с возможностью вести статистику.

# Оборудование

* Arduino UNO или любая другая модель с не менее чем двумя аналоговыми входами и не менее чем двумя цифровыми
* Кусок алюминиевого провода АВВГ (для изготовления электрода)
* Две тарированные литровые емкости (с меткой точно на 1 литр)
* Соль поваренная экстра (для изготовления калибровочных растворов)
* Весы с высокой точности не менее 0.01 грамма. Если таких нет, то потребуется кратно увеличить навески соли и воды.
* не менее 2 литров дистиллированной воды

# Теория

Для измерения проводимости раствора, необходимо обеспечить высокую частоту переменного тока не менее 1 кГц. Это необходимо для устранения эффекта поляризации электролита и для предотвращения разрушения электродов при длительном измерении.

Кроме того, важным моментом является необходимость термокомпенсации измерений. Поэтому, помимо подключения электрода, необходимо иметь в растворе измеритель температуры, например датчик 18b20 в герметичном корпусе.

# Схема подключения

Осуществляется прямое подключение по схеме:

A0---D11---->

A1---D10---->

]

# Электрод

Основные принципы при создании электрода:

* Использование материала, который не взаимодействует с раствором или делает это незначительно. Идеальный материал - платина. Минимально подходящий - алюминий или нержавеющая сталь.
* Электроды должны быть полностью погружены в раствор
* Расстояние между оголенными электродами не должны изменяться, любое нарушение положения электродов требует повторной калибровки.

Или как более доступный, но не очень удачный в плане точности вариант - использовать электрод из вилки сетевого шнура:
Возможно подключить один из вариантов готового электрода, например: &traffic\_analysisId=recommend\_3035\_null\_null\_null&scm=1007.13338.79672.000000000000000&pvid=7ecbdc77-d1ac-4ad3-8c9a-46092cd4c0ab&tpp=1 Water-quality-probe-TDS

Рассчитать параметры электрода можно по следующим формулам:

# Принцип работы

Измерение происходят следующим образом:

* Условно положительная фаза
	+ С цифровой порт D10 переводится в режим высокого уровня (1 HIGH), а D11 низкого.
	+ Ток напряжением 5В устремляется через раствор в сторону D11.
	+ При этом измеритель A1 возвращает значение падения напряжения на этом промежутке в цифровом виде.
	+ Затем уровень D10 снова переходит в состояние (0 LOW)
	+ Измерение на первой фазе завершено
* Условно отрицательная фаза
	+ С цифровой порт D11 переводится в режим высокого уровня (1 HIGH), а D10 низкого.
	+ Ток напряжением 5В устремляется через раствор в сторону D10.
	+ При этом измеритель A0 возвращает значение падения напряжения на этом промежутке в цифровом виде.
	+ Затем уровень D11 снова переходит в состояние (0 LOW)

Таким образом за 1 цикл измерений происходит полная смена полярности от +5В до 0 до -5В до 0

* Измерения выполняются максимальной скоростью (для arduino uno это ~3.5 КГц)
* Итоговые значения измеренные за период на положительной и отрицательной фазе усредняются, что повышает точность измерения, а затем усредняются между собой.

# Код сбора

Необходимо сначала скачать и добавить библиотеки:

* CyberLib
* OneWire
* DallasTemperature
* AM2320

```
// Библиотека работы с DS18b20
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE\_WIRE\_BUS 12
OneWire oneWire(ONE\_WIRE\_BUS);
DallasTemperature sensors(&oneWire);
// Библиотека для датчика AM2320
#include <AM2320.h>
#include <Wire.h>
// Глобальные переменные
float po;
float ap\_raw;
float an\_raw;

void setup() {
 ADCSRA &= B11111000;
 ADCSRA |= B00000100;
 Serial.begin(9600);
 Wire.begin();
}

void loop() {
int d1,d2,a1,tr;
long n;
float x,x0,x1,x2,ec,ec0,ec1,ec2,t,tk,k,l,lev;
String gp;

String tstring = "tparse="; // Метка начала строки для парсинга
String tstring\_end = "="; // Метка окончания строки
String pstring = ""; // Метка строки вывода колонку
//////////////////////////////////////////////////////////////////////////
// Общая температура и влажность воздуха с AM2320 через i2c
AM2320 th;
th.Read();
// Заполнение строкового вывода для машинного парсинга
 tstring +=fFTS(th.t,1) + ";" + fFTS(th.h,1) + ";" + fFTS(fAbsoluteHumidity(th.t,th.h),1) + ";";
// Человекочитаемый вывод
 pstring += "Air temperature=";
 pstring += fFTS(th.t,2);
 pstring += "\n";
 pstring += "Relative humidity=";
 pstring += fFTS(th.h,2);
 pstring += "\n";
 pstring += "Absolute air humidity=";
 pstring += fFTS(fAbsoluteHumidity(th.t,th.h),2);
 pstring += "\n";

///////////////////////////// Раствор 1 ////////////////////////////////////////////
gp="container 1"; // Номер группы измерения

// Измеритель ЕС1
// Схема подключения
// d1----a1----->
// d2----------->
d1=10; // Цифровой порт соединенный с аналоговым портом и электродом измерения
d2=11; // Цифровой порт соединенный с электродом противофазы
a1=0; // Аналоговый порт измерения
n=50000;// Колличество измерений для усреднения
// Калибровка ЕС
ec1= 0.01; // Фактическое значение ЕС при нижнем пределе
x1=16; // Показания АЦП при нижнем значении ЕС
ec2= 3; // Фактическое значение ЕС при верхнем пределе
x2=160; // Показания АЦП при верхнем значении ЕС
// Температура раствора
tr=0; // Порядковый номер датчика 18b20 в растворе
tk=0.02; // Коэффициент влияния температуры на проводимость раствора

// Измерение температуры
sensors.requestTemperatures();
t=sensors.getTempCByIndex(tr);
// Измерение RAW проводимости
x=fConductivity(d1,d2,a1,n);

 pstring += gp +" RAW Solution polarization ADC = ";
 pstring += fFTS(po,2);
 pstring += "\n";
// Расчет ЕС
ec0=fCalibration(x1,ec1,x2,ec2,x);
// Термокомпенсация ЕС
ec=fECTemp(tk,ec0,t);

// Измеритель уровня 1
d1=9; // Цифровой порт соединенный с аналоговым портом и электродом измерения
d2=11; // Цифровой порт соединенный с электродом противофазы
a1=0; // Аналоговый порт измерения
n=500; // Колличество измерений для усреднения
k=0.835; // Коэффициент компенсации электропроводности
// Измерение проводимости
l=fConductivity(d1,d2,a1,n);
lev=x/pow(l,k);
// Заполнение строкового вывода для машинного парсинга
 tstring +=fFTS(t,2) + ";" + fFTS(x,4) + ";" + fFTS(l,2) + ";"+ fFTS(ec0,4) + ";";
// Человекочитаемый вывод
 pstring += gp +" Solution temperature = ";
 pstring += fFTS(t,2);
 pstring += "\n";
 pstring += gp +" RAW EC ADC = ";
 pstring += fFTS(x,4);
 pstring += "\n";
 pstring += gp +" RAW Level ADC = ";
 pstring += fFTS(l,2);
 pstring += "\n";
 pstring += gp +" EC = ";
 pstring += fFTS(ec0,4);
 pstring += "\n";
 pstring += gp +" Level = ";
 pstring += fFTS(lev,4);
 pstring += "\n";
/////////////////////////////////////////////////////////////////////////////////////

///////////////////////////// Раствор 2 ////////////////////////////////////////////
gp="container 2"; // Номер группы измерения

// Измеритель ЕС1
// Схема подключения
// d1----a1----->
// d2----------->
d1=7; // Цифровой порт соединенный с аналоговым портом и электродом измерения
d2=8; // Цифровой порт соединенный с электродом противофазы
a1=1; // Аналоговый порт измерения
n=50000;// Колличество измерений для усреднения
// Калибровка ЕС
ec1= 0.01; // Фактическое значение ЕС при нижнем пределе
x1=16; // Показания АЦП при нижнем значении ЕС
ec2= 3; // Фактическое значение ЕС при верхнем пределе
x2=160; // Показания АЦП при верхнем значении ЕС
// Температура раствора
tr=1; // Порядковый номер датчика 18b20 в растворе
tk=0.02; // Коэффициент влияния температуры на проводимость раствора

// Измерение температуры
sensors.requestTemperatures();
t=sensors.getTempCByIndex(tr);
// Измерение RAW проводимости
x=fConductivity(d1,d2,a1,n);

 pstring += gp +" RAW Solution polarization ADC = ";
 pstring += fFTS(po,2);
 pstring += "\n";
// Расчет ЕС
ec0=fCalibration(x1,ec1,x2,ec2,x);
// Термокомпенсация ЕС
ec=fECTemp(tk,ec0,t);

// Измеритель уровня 1
d1=6; // Цифровой порт соединенный с аналоговым портом и электродом измерения
d2=8; // Цифровой порт соединенный с электродом противофазы
a1=1; // Аналоговый порт измерения
n=500; // Колличество измерений для усреднения
k=0.835; // Коэффициент компенсации электропроводности
// Измерение проводимости
l=fConductivity(d1,d2,a1,n);
lev=x/pow(l,k);
// Заполнение строкового вывода для машинного парсинга
 tstring +=fFTS(t,2) + ";" + fFTS(x,4) + ";" + fFTS(l,2) + ";"+ fFTS(ec0,4) + ";";
// Человекочитаемый вывод
 pstring += gp +" Solution temperature = ";
 pstring += fFTS(t,2);
 pstring += "\n";
 pstring += gp +" RAW EC ADC = ";
 pstring += fFTS(x,4);
 pstring += "\n";
 pstring += gp +" RAW Level ADC = ";
 pstring += fFTS(l,2);
 pstring += "\n";
 pstring += gp +" EC = ";
 pstring += fFTS(ec0,4);
 pstring += "\n";
 pstring += gp +" Level = ";
 pstring += fFTS(lev,4);
 pstring += "\n";
/////////////////////////////////////////////////////////////////////////////////////

// Передача в терминал
 tstring += tstring\_end;
 Serial.println(tstring);
 Serial.print("\n");
 Serial.print(pstring);
 Serial.print("\n --------\n");
}

//////////////////////////////////////////////////////////////////////
// ФУНКЦИИ
// Функция калибровки
float fCalibration(float x1, float ec1, float x2, float ec2, float x){
 float b=(-log(ec1/ec2))/log(x2/x1);
 float a=((pow(x1,-b))\*ec1);
 float ec0 = a \* pow(x,b);
 return ec0;
}

// Функция термокомпенсации ЕС
float fECTemp(float k, float ec0, float t){
 return ec0/(1+k\*(t-25));
}

//Функция замера электропроводности в RAW
float fConductivity(int d1, int d2, int a1, long cnt){

 pinMode(d1, OUTPUT);
 pinMode(d2, OUTPUT);
 long var=1;
 unsigned long ap=0;
 unsigned long an=0;
 while(var < cnt){

 digitalWrite(d2, HIGH);
 ap=0+analogRead(a1)+ap;
 digitalWrite(d2, LOW);

 digitalWrite(d1, HIGH);
 an=1023-analogRead(a1)+an;
 digitalWrite(d1, LOW);
 var++;
 }
 pinMode(d1, INPUT);
 pinMode(d2, INPUT);
 // Усреднение АЦП при положительной фазе
 ap\_raw=(float)ap/var;
 // Усреднение АЦП при отрицательной фазе
 an\_raw=(float)an/var;
 // Расчет поляризации раствора
 po = ap\_raw-an\_raw;
 // Исключение влияние поляризаци
 return (((float)ap+(float)an)/var/2);

}

// Функция преобразования чисел с плавающей запятой в текст
String fFTS(float x, byte precision) {
 char tmp[50];
 dtostrf(x, 0, precision, tmp);
 return String(tmp);
}

// Функция конвертации относительной влажности в абсолютную
float fAbsoluteHumidity(float tt, float rh){
 return (4.579\*pow(2.71828,((17.14\*tt)/(235.3+tt))))\*rh/100;
}

```

Данный код является примером замера и выводит в com порт сырые усредненные данные с АЦП. Для расчета ЕС необходимо выполнить калибровку электрода и расчет термокомпенсации.

* Arduino UNO выполняет обеспечивает измерения с частотой ~ 12-13 кГц

# Калибровка

Калибровка электрода необходима для перевода значений с АЦП в электропроводность ЕС выраженную в мСи/см. Для этого необходимо изготовить калибровочные растворы. Самый доступный способ, но позволяющий получить достаточную точность, это калибровка по поваренной соли качества экстра с содержанием хлорида натрия не менее 99.7%. Как правило она доступна в любом продуктовом магазине.

## Подготовка к калибровке

1. Необходимо выполнить тарирование емкости в 1 литр, если такой нет. Для этого понадобятся весы с точностью не менее чем в 1 грамм.
2. Необходимо влить в емкость 1000 грамм дистиллированной воды при температурой 25 градусов и отметить уровень. Это будет 1 литр.
3. Нужно изготовить не менее двух емкостей, лучше 3

## Изготовление растворов

Раствор изготавливается путем всыпания в тарированную емкость расчетного веса соли с точностью до 0.01 грамма (потребуются соответствующие весы). Наиболее точно процедуру можно выполнять так:

1. Ставим на весы тару с некоторым количеством соли.
2. Сбрасываем весы на 0
3. Сухой мелкой ложечкой или лопаткой берем из тары соль и пересыпаем мелкими порциями в калибровочную тару, весы будут показывать, какое количество соли уже выбрано из тары и продолжаем, пока не будет отвешен точный вес.
4. Вливаем дистиллированную воду в калибровочную тару до половины объема и тщательно перемешиваем соль
5. Доводим уровень до метки 1 литр.

## Значения калибровочных навесок

Значения с учетом ЕС воды ~0.01 мСи/см

* ЕС=1 мСи/см 0,49 гр/литр NaCl
* ЕС=2 мСи/см 1 гр/литр NaCl
* ЕС=3 мСи/см 1.53 гр/литр NaCl
* ЕС=4 мСи/см 2.06 гр/литр NaCl
* ЕС=5 мСи/см 2.61 гр/литр NaCl

### Калибровка без весов подручными средствами

Нам понадобится:

* пластиковая бутлка 0,5 из под Sprite для отмера 0,5 литра воды
* аптечный кальция хлорид 10% в ампулах (100 мг/мл) по 5 мл в ампуле
* емкость для смешивания и измерений.

Ход измерений

* Наливаем в промытую бутылку из под спрайта воду до метки под горлышком, желательно осмос, но не критично. Температура должна быть комнатной.
* переливаем в емкость для смешивания и измеряем значение АЦП. Это будет x0
* Вливаем в эту емкость одну ампулу.

*В ампулах содержится 5 мл раствора CaCl2\*6H2O высокой чистоты*

* Одна ампула + 500 мл воды дают ЕС=1,094 мСи/см
* Две ампулы + 500 мл воды дают ЕС=2,084 мСи/см
* Три ампулы + 500 мл воды дают ЕС=3,013 мСи/см

если ампулы по 10 мл, то объем воды необходимо увеличить до 1 литра.

Измеряем значение АЦП предварительно при одной ампуле x1=x, ec1=1,094 и при трех ампулах x2=x, ec2=3,013

* Для поправки на воду, делаем несколько пересчетов, добавляя к измеренным результатам ЕС, расчетное значение ЕС воды.

Можно приготовить три калибровочных раствора 1, 2 и 5 ампул растворить в полулитре дистиллята с ЕС 0.01

Получим там где:

* одна ампула ЕС = 1.114 мсм/см
* две апулы ЕС = 2.132 мсм/см
* три ампуы ЕС = 3.107 мсм/см
* четыре ЕС = 4.057 мсм/см
* пять ЕС = 4.988 мсм/см
* шесть ЕС = 5.909 мсм/см

## Перевод значений с АЦП в ЕС

* Для перевода значений лучше брать среднее за несколько измерений в одном растворе или построить график и выбрать точку из него: https://youtu.be/qVoSLE-npMU

Упрощенно, значения с измерителя АЦП можно перевести в ЕС по следужей формуле:

```

 e
 c
 =
 a
 ∗

 x

 b

 {\displaystyle ec=a\*x^{b}}

```

```
где x - значение полученное с АЦП в сыром виде
    а,b коэффициенты наклона и коэффициент нелинейности учитывающие потери в цепи измерения.

```

Калибровка с приемлемой точностью должна осуществляться не менее чем по двум точкам. Поэтому для нахождения значений коэффициентов a и b нам необходимо решить систему уравнений:

```
где x1 - показания АЦП ардуины в калибровочном растворе с электропроводностью ec1
    x2 - показания АЦП ардуины в калибровочном растворе с электропроводностью ec2

```

* **Все измерения необходимо проводить при температуре 25 градусов цельсия**

# Термокомпенсация

Расчет термокомпинсации можно выполнить только эмпирическим путем, так как состав измеряемого раствора не известен, а какждая соль имеет свои характеристики изменения проводимости её растворов при разных температурах. Компенсация выполняется по следующей формуле:

```

 E
 C
 k
 =
 e
 c

 /

 (
 1
 k
 ∗
 (
 t
 −
 25
 )
 )

 {\displaystyle ECk=ec/(1+k\*(t-25))}

```

```
где ECk - термокомпенсированное значение электропроводности
    ec - расчитанное выше значение ec при температуре 25 градусов
    t - температура раствора
    k - эмпирический коэффициент влияния температуры на электропроводность конкретного раствора, определяется по графикам влияния и равен примерно 0.01 - 0.03

```