Автор Тема: EC-метр на базе ардуино  (Прочитано 3438 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Пресвятой_ДжимБим

  • Ветеран
  • *****
  • Сообщений: 504

  • Активность на форуме
    18%
EC-метр на базе ардуино
« : 28 Июня 2017, 20:17:15 »
Не выдержала душа поэта.. Не могу я зырить на потуги некоторых гениев.

Итак, готовое простое устройство для измерения электропроводности. С экранчиком, термокомпенсацией  и калибровкой.

Поскольку в качестве электрода все дружно ненавидят вилку шнура, то её и будем использовать :D

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




Номиналы и запчасти:
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

P.s. Тех кого мучает вопрос телеметрии - флаг в руки. Делается все элементарно на уровне 5-го класса среднеобразовательной школы.
P.p.s. Устройство ваще никак не претендует на суперточность. Для домашней гидропоники. Не более.
« Последнее редактирование: 28 Июня 2017, 20:48:10 от Пресвятой_ДжимБим »

Оффлайн Borodach1

  • Ветеран
  • *****
  • Сообщений: 2048
  • Ну... почти всё, что нажито непосильным трудом.)))

  • Активность на форуме
    3.4%
EC-метр на базе ардуино
« Ответ #1 : 28 Июня 2017, 20:54:48 »
Схема подключения порадовала.)))
Интересно,  сколько человек воткнёт вилку в розетку?  ;)
))))))))))))))))))))))))))

Оффлайн Пресвятой_ДжимБим

  • Ветеран
  • *****
  • Сообщений: 504

  • Активность на форуме
    18%
EC-метр на базе ардуино
« Ответ #2 : 28 Июня 2017, 21:03:58 »
Ай мля. Забыл питание к экрану пририсовать.
Да и пофиг. Кто знает - разберётся.
А чё со схемой не так? :D ;D ;D

Оффлайн Vad

  • Ветеран
  • *****
  • Сообщений: 6345
  • Мой аватар вырос.. на гидропонике :)

  • Активность на форуме
    6.4%
    • Email
EC-метр на базе ардуино
« Ответ #3 : 28 Июня 2017, 21:16:21 »
Схема подключения порадовала.)))
Интересно,  сколько человек воткнёт вилку в розетку?  ;)
))))))))))))))))))))))))))
спецом плоская вилка!
чеб не втыкнули  :D

Пресвятой_ДжимБим, наведи порядок с переменными, нельзя так жестоко разбрасываться памятью..
всю статику загоняй в #define (номера кнопок, пинов, коэффициенты,  резисторы )
какого черта он будет всю жизьнь держать в голове  то, что требовалось 1 раз при старте.. и то для удобства писателю! ;)

это что за переменные?
int i = 0;
int j = 0;
они нигде не используются

да и вообще, все временные переменные объявляй внутри функции...
меньше путаницы будет..

Спасибо!

Не буду изготовлять автоматику для ваших гидропонных установок. Ленивый стал. Если не теряете надежду уговорить.. обращайтесь:



Оффлайн Пресвятой_ДжимБим

  • Ветеран
  • *****
  • Сообщений: 504

  • Активность на форуме
    18%
EC-метр на базе ардуино
« Ответ #4 : 28 Июня 2017, 21:22:27 »
Схема подключения порадовала.)))
Интересно,  сколько человек воткнёт вилку в розетку?  ;)
))))))))))))))))))))))))))
спецом плоская вилка!
чеб не втыкнули  :D

Пресвятой_ДжимБим, наведи порядок с переменными, нельзя так жестоко разбрасываться памятью..
всю статику загоняй в #define (номера кнопок, пинов, коэффициенты,  резисторы )
какого черта он будет всю жизьнь держать в голове  то, что требовалось 1 раз при старте.. и то для удобства писателю! ;)

это что за переменные?
int i = 0;
int j = 0;
они нигде не используются

да и вообще, все временные переменные объявляй внутри функции...
меньше путаницы будет..
Переменные i и j используются. В операторе for, и далее.
А код такой сделал, Штобе чайникам понятнее было.
Да и не интересен мне данный код в целом.. это просто работающий пример.
Эдакая фиговина с меандром в 10кГц.
Просто Сив устал уже это устройство рожать. Я в роли акушера..

Оффлайн Пресвятой_ДжимБим

  • Ветеран
  • *****
  • Сообщений: 504

  • Активность на форуме
    18%
EC-метр на базе ардуино
« Ответ #5 : 28 Июня 2017, 21:25:44 »
Ой, да. i и j объявлены внутри for))))
Исправлю))

Оффлайн Vad

  • Ветеран
  • *****
  • Сообщений: 6345
  • Мой аватар вырос.. на гидропонике :)

  • Активность на форуме
    6.4%
    • Email
EC-метр на базе ардуино
« Ответ #6 : 28 Июня 2017, 21:31:49 »
Исправлю))

Приучай чайников к основным правилам..
ведь чайники до сих пор не знают очень много  ;)
должны начинать учиться *???*
Спасибо!

Не буду изготовлять автоматику для ваших гидропонных установок. Ленивый стал. Если не теряете надежду уговорить.. обращайтесь:



Оффлайн Vad

  • Ветеран
  • *****
  • Сообщений: 6345
  • Мой аватар вырос.. на гидропонике :)

  • Активность на форуме
    6.4%
    • Email
EC-метр на базе ардуино
« Ответ #7 : 28 Июня 2017, 21:34:28 »
int buttonState = 0;

обьявлена как целая, а используется как булева
обьяви ее boolean
Спасибо!

Не буду изготовлять автоматику для ваших гидропонных установок. Ленивый стал. Если не теряете надежду уговорить.. обращайтесь:



Оффлайн Пресвятой_ДжимБим

  • Ветеран
  • *****
  • Сообщений: 504

  • Активность на форуме
    18%
EC-метр на базе ардуино
« Ответ #8 : 28 Июня 2017, 21:39:36 »
Исправлю))

Приучай чайников к основным правилам..
ведь чайники до сих пор не знают очень много  ;)
должны начинать учиться *???*
Да по большому счету я и сам чайник ещё.  Ничо. Учусь потихоньку.
Устройство работает, как ни странно. И даже показывает что-то  :D
Так-что обычному пользователю только останется повторить схему и залить скетч в дуину.
Но опять же.
И даже этот вариант я читаю микроскопом для забивания гвоздей.

Оффлайн Пресвятой_ДжимБим

  • Ветеран
  • *****
  • Сообщений: 504

  • Активность на форуме
    18%
EC-метр на базе ардуино
« Ответ #9 : 28 Июня 2017, 21:41:07 »
int buttonState = 0;

обьявлена как целая, а используется как булева
обьяви ее boolean
Оу.. точно. На автомате воткнул. Можно было и без этой переменной обойтись..

Оффлайн Vad

  • Ветеран
  • *****
  • Сообщений: 6345
  • Мой аватар вырос.. на гидропонике :)

  • Активность на форуме
    6.4%
    • Email
EC-метр на базе ардуино
« Ответ #10 : 28 Июня 2017, 21:55:58 »
И даже этот вариант я читаю микроскопом для забивания гвоздей.
кто-то решит к этому  микроскопу ручку деревянную приделать, обточить до  удобной формы, и тут..  неожиданно закончится память :D
она всегда неожиданно заканчивается :D
особенно когда вот так, int buf[140],temp; "глобально" выкинули 140 байт  ;)
Спасибо!

Не буду изготовлять автоматику для ваших гидропонных установок. Ленивый стал. Если не теряете надежду уговорить.. обращайтесь:



Оффлайн allex_step

  • Старожил
  • ****
  • Сообщений: 484
  • Хомячина

  • Активность на форуме
    5.4%
    • Email
EC-метр на базе ардуино
« Ответ #11 : 28 Июня 2017, 21:58:02 »
а как ЭТО интегрировать в Mega2560 для добавления в автоматизацию функции контроля ЕС? (а дальше - регулирование)

Оффлайн Пресвятой_ДжимБим

  • Ветеран
  • *****
  • Сообщений: 504

  • Активность на форуме
    18%
EC-метр на базе ардуино
« Ответ #12 : 28 Июня 2017, 21:59:53 »
И даже этот вариант я читаю микроскопом для забивания гвоздей.
кто-то решит к этому  микроскопу ручку деревянную приделать, обточить до  удобной формы, и тут..  неожиданно закончится память :D
она всегда неожиданно заканчивается :D
особенно когда вот так, int buf[140],temp; "глобально" выкинули 140 байт  ;)
А 140 значений - это жЫрный троллинг ващет))
Кому нужно 140 значений?))) Хватило бы и 10-ти.
Но так веселее. Этож микроскоп и гвозди.
« Последнее редактирование: 28 Июня 2017, 22:02:18 от Пресвятой_ДжимБим »

Оффлайн Vad

  • Ветеран
  • *****
  • Сообщений: 6345
  • Мой аватар вырос.. на гидропонике :)

  • Активность на форуме
    6.4%
    • Email
EC-метр на базе ардуино
« Ответ #13 : 28 Июня 2017, 22:00:50 »
лучше никак, это  стендалон версия..
гальванически не развязано..  по сути  игрушечно-настольный вариант *???*
Спасибо!

Не буду изготовлять автоматику для ваших гидропонных установок. Ленивый стал. Если не теряете надежду уговорить.. обращайтесь:



Оффлайн ...Andrew...

  • Постоялец
  • ***
  • Сообщений: 197

  • Активность на форуме
    0%
EC-метр на базе ардуино
« Ответ #14 : 28 Июня 2017, 22:03:11 »
А какая повторяемость показаний получилась?
raw-замеров и очищенных с помощью медианного фильтра?