Не выдержала душа поэта.. Не могу я зырить на потуги некоторых гениев.
Итак, готовое простое устройство для измерения электропроводности. С экранчиком, термокомпенсацией и калибровкой.
Поскольку в качестве электрода все дружно ненавидят вилку шнура, то её и будем использовать

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

Номиналы и запчасти:
R1 = 510 Ом
R2 = 510 Ом
R3 = 4,7 Ком
S1 - обычная кнопка без фиксатора.
Ардуино Про Мини.
Экран с I2C шиной.
Датчик DS18b20.
Провода всякие

Шнур с американской вилкой с дырочками на электродах(бывают и без дырочек, и они сделаны из крутой нержавки!).
Код:
#include <OneWire.h> //данная библиотека отредактирована для подключения температурного датчика ds18b20 напрямую(без резисторов). Ссылка на скачивание: [url]https://yadi.sk/d/osXYOMSI3KEThp[/url]
#include <DallasTemperature.h>
#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3f,16,2); //У меня адрес экрана на кв.шине 0x3f, но бывает еще и 0x27, т.е. строка будет выглядеть так 'LiquidCrystal_I2C lcd(0x27,16,2);'
int button = 5;// пин кнопки
int buttonState = 0;
int R1 = 510; // R1=510 ом
int R2 = 510;// R2=510 ом
int Ra = 25; //Даже не спрашивайте! Rа=V/I(замеряйте, если хотите, сами)
int ECPin = A0;
float TemperatureCoef = 0.019;//темп.коэфф. ~ 2% на градус.
float K = 1.88;//константа первоначальной работы(для американской вилки с дырочками)
float CalibrationEC=2.19; // Здесь Вы задаете EC калибровочного раствора. У меня вода равна 0.19. плюс 1гр соли на 1 литр воды =2ЕС, итого = 2.19
//***********************Остальные переменные**********************************************//
int i = 0;
int j = 0;
int buf[140],temp;
unsigned long int avgValue;
float Temperature=10;
float EC = 0;
float EC25 = 0;
int ppm = 0;
float raw = 0;
float Vin = 5;
float Vdrop = 0;
float Rc = 0;
//**************************Переменные для Калибровки ******************************************//
float TemperatureFinish=0;
float TemperatureStart=0;
float Kt=0;
//*********************** Настройки eeprom ******************//
int value;
int addresCalibration=0;
float PPMconversion=0.5;
#define ONE_WIRE_BUS 9 // Сигнальный провод темп. датчика на 9 пине
const int TempProbePossitive =8; // Плюсовой провод темп.датчика на пине 8
const int TempProbeNegative=7; //Минусовой провод темп.датчика на пине 7
OneWire oneWire(ONE_WIRE_BUS);// Настраиваем шину
DallasTemperature sensors(&oneWire);//
void setup() {
Serial.begin(9600);
ADCSRA &= B11111000; //Ускоряем АЦП до 1мГц
ADCSRA |= B00000100; //-------------//---------------
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(button, INPUT);
pinMode(ECPin, INPUT);
pinMode(TempProbeNegative , OUTPUT );
digitalWrite(TempProbeNegative , LOW );
pinMode(TempProbePossitive , OUTPUT );
digitalWrite(TempProbePossitive , HIGH );
delay(100);// даем сенсору время на активацию
sensors.begin();
delay(100);
R1=(R1+Ra);
value = EEPROM.read(addresCalibration);
if (value <=254) K=value*0.02;
lcd.init();
lcd.backlight();
}
void loop() {
GetEC();
Calibration();
}
void GetEC(){
sensors.requestTemperatures();// Запрос от датчика температуры
Temperature=sensors.getTempCByIndex(0); //Запись значений в переменные
for(int i=0;i<140;i++) //берем 140 значений с АЦП
{
PORTD = B00000100;
delayMicroseconds(83); // 83 микросекунды+ускоренный analoread() в течении 17 микросекунд=100микросекунд, что означает 10кГц работы устройства.
raw = analogRead(ECPin);
buf[i] = raw;
PORTD = B00001000;
delayMicroseconds(100); //Противофаза, дабы исключить поляризацию.
}
PORTD = B00000000;
for(int i=0;i<130;i++)
{
for(int j=i+1;j<140;j++)
{
if(buf[i]>buf[j])
{
temp=buf[i];
buf[i]=buf[j];
buf[j]=temp;
}
}
}
avgValue=0;
for(int i=20;i<100;i++) // 80 средних значений
avgValue+=buf[i];
float ECValue=(float)avgValue/80;
Vdrop = (Vin*ECValue)/1024.0; // перевод аналог.значений в милливольты
Rc = (Vdrop*R1)/(Vin-Vdrop); //Вычисляем сопротивление воды
Rc = Rc-Ra-R2; // вычитаем лишнее
EC = 1000/(Rc*K); //получение чистого ЕС
//*************Компенсация температуры********************//
EC25 = EC/ (1+ TemperatureCoef*(Temperature-25.0));
ppm = (EC25)*(PPMconversion*1000); // Переводим получившийся EC в ppm@0,5
//******************Вывод на Экран************************//
lcd.setCursor(0,0);
lcd.print("Arduino EC-PPM ");
lcd.setCursor(0,1);
lcd.print("EC: ");
lcd.setCursor(3,1);
lcd.print(EC25);
lcd.setCursor(9,1);
lcd.print(Temperature);
lcd.print("'C");
//*****************Информация для отладки******************//
Serial.print("EC: ");
Serial.print(EC);
Serial.print(" raw: ");
Serial.print(raw);
Serial.print(" Rc: ");
Serial.print(Rc);
Serial.print(" EC: ");
Serial.print(EC25);
Serial.print(" Simens ");
Serial.print(ppm);
Serial.print(" ppm ");
Serial.print(Temperature);
Serial.println(" *C ");
//}
}
void Calibration(){
buttonState = digitalRead(button);
if(buttonState!=HIGH) return;
lcd.setCursor(0,0);
lcd.print("Calibrating ");
lcd.setCursor(0,1);
lcd.print("EC: ");
lcd.setCursor(3,1);
lcd.print(CalibrationEC);
sensors.requestTemperatures();
TemperatureStart=sensors.getTempCByIndex(0);
i = 0;
j= 0;
for(int i=0;i<140;i++)
{
PORTD = B00000100;
delayMicroseconds(83); // 83 микросекунды+ускоренный analoread() в течении 17 микросекунд=100микросекунд, что означает 10кГц работы устройства.
raw = analogRead(ECPin);
buf[i] = raw;
PORTD = B00001000;
delayMicroseconds(100); //Противофаза, дабы исключить поляризацию.
}
PORTD = B00000000;
for(int i=0;i<130;i++) //Сортируем аналоговые значения от меньшего к бОльшему.
{
for(int j=i+1;j<140;j++)
{
if(buf[i]>buf[j])
{
temp=buf[i];
buf[i]=buf[j];
buf[j]=temp;
}
}
}
avgValue=0;
for(int i=20;i<100;i++)
avgValue+=buf[i];
float ECValue=(float)avgValue/80;
sensors.requestTemperatures();
TemperatureFinish=sensors.getTempCByIndex(0);
//*************Компенсация температуры********************//
EC = CalibrationEC*(1+(TemperatureCoef*(TemperatureFinish-25.0))) ;
//***************** Вычисление Сопротивления Калибровочного раствора **************************//
Vdrop= (((Vin)*(ECValue))/1024.0);
Rc=(Vdrop*R1)/(Vin-Vdrop);
Rc=Rc-Ra-R2; // вычитаем лишнее
Kt= 1000/(Rc*EC);
if (TemperatureStart==TemperatureFinish){
Serial.println(" Results are Trustworthy");
Serial.print("Calibration Fluid EC: ");
Serial.print(CalibrationEC);
Serial.print(" S "); //add units here
Serial.print("Cell Constant K");
Serial.print(K);
lcd.setCursor(0,0);
lcd.print("GoodResults ");
lcd.setCursor(0,1);
lcd.print("EC: ");
lcd.setCursor(3,1);
lcd.print(CalibrationEC);
lcd.setCursor(9,1);
lcd.print("K:");
lcd.setCursor(11,1);
lcd.print(Kt);
while (1) {
if (buttonState==HIGH){
K=Kt; //записываем новую константу
//********Запись нового значения в EEPROM**********//
value=K/0.02;
EEPROM.write(addresCalibration, value);
lcd.setCursor(0,0);
lcd.print("Saved Calibration ");
lcd.setCursor(0,1);
lcd.print("K: ");
lcd.setCursor(3,1);
lcd.print(Kt);
delay(5000);
return;
}
}
}
else{
Serial.println(" Error Wait For Temperature To settle");
lcd.setCursor(0,0);
lcd.print("Bad Results ");
delay(5000);
Calibration();
}
}
Электрод можно использовать любой двухконтактный.(Любой!!1111)
Калибруется просто. В коде находите строчку "float CalibrationEC=", и после знака "равно" прописываете цифрами ваш калибровочный раствор(например: 1.14, 1.38 или 2), далее после заливки скетча в ардуину нажимаете большую красную кнопку(предварительно макнув электрод с датчиком температуры в калибровочный раствор), и всё.
При надписи "Bad result" нажимаем кнопку повторно, и так до тех пор, пока экранчик Вас не поздравит с тем, что все прошло удачно и записалось в eeprom.
Вот.
И теперь живите с этим как хотите.

P.s. Тех кого мучает вопрос телеметрии - флаг в руки. Делается все элементарно на уровне 5-го класса среднеобразовательной школы.
P.p.s. Устройство ваще никак не претендует на суперточность. Для домашней гидропоники. Не более.