Arduino 水質檢測儀(濁度、TDS、溫度、電導率、吸光度、硬度)帶18b20溫度補償。

原文鏈接:https://blog.csdn.net/qq_40987215/article/details/90708893

1、arduino代碼如下:

可直接進行串口打印或者oled顯示(spi)

 

#include <SPI.h>

#include <Wire.h>

#include <math.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

#include <Fonts/FreeSerif9pt7b.h>

#include <MsTimer2.h> 

#include "TSL2581.h"

//---------------------------TDS-----------------------------------

#include <OneWire.h>

#include <DallasTemperature.h>

//-----------------------------------------------------------------

#include <SoftwareSerial.h>      //開啓軟串口

 

 

SoftwareSerial mySerial(2 , 3); //第2= RX,第3= TX   //開啓軟串口

WaveShare_TSL2581 tsl = WaveShare_TSL2581();

 

#define SCREEN_WIDTH 128 // OLED display width, in pixels

#define SCREEN_HEIGHT 32 // OLED display height, in pixels

 

// Declaration for SSD1306 display connected using software SPI (default case):

#define OLED_MOSI   9

#define OLED_CLK   10

#define OLED_DC    11

#define OLED_CS    12

#define OLED_RESET 13

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,

  OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

 

#define NUMFLAKES     10 // Number of snowflakes in the animation example

 

#define Blank_KEY      7

#define Dark_KEY_INT   1

#define LED_Control    8

 

//************************* User Defined Variables for TDS********************************************************//

 

 

//##################################################################################

//-----------  Do not Replace R1 with a resistor lower than 300 ohms    ------------

//##################################################################################

 

 

int R1= 1000;

int Ra=25; //Resistance of powering Pins

int ECPin= A0;

int ECGround=A1;

int ECPower =A3;

 

 

//*********** Converting to ppm [Learn to use EC it is much better**************//

// Hana      [USA]        PPMconverion:  0.5

// Eutech    [EU]          PPMconversion:  0.64

//Tranchen  [Australia]  PPMconversion:  0.7

// Why didnt anyone standardise this?

 

 

float PPMconversion=0.7;

 

 

//*************Compensating for temperature ************************************//

//The value below will change depending on what chemical solution we are measuring

//0.019 is generaly considered the standard for plant nutrients [google "Temperature compensation EC" for more info

float TemperatureCoef = 0.019; //this changes depending on what chemical we are measuring

 

 

 

 

//********************** Cell Constant For Ec Measurements *********************//

//Mine was around 2.9 with plugs being a standard size they should all be around the same

//But If you get bad readings you can use the calibration script and fluid to get a better estimate for K

float K=2.88;

 

 

 

 

//************ Temp Probe Related *********************************************//

#define ONE_WIRE_BUS 6          // Data wire For Temp Probe is plugged into pin 6 on the Arduino

const int TempProbePossitive =5;  //Temp Probe power connected to pin 5

const int TempProbeNegative=4;    //Temp Probe Negative connected to pin 4

 

 

 

 

//***************************** END Of Recomended User Inputs *****************************************************************//

 

void read2581_id(void);

void displayValue(void);

 

unsigned long TSL2581_CH0=0,TSL2581_CH1=0;

float Absorbance=0.0;

float Turbidity=0.0;

unsigned int dark=0;

unsigned int blank=0;

int inCOMdate=0;

volatile int darkState = LOW;

volatile int timerState = LOW;

//----------------------------------------------TDS-------------------------------------------------------------

OneWire oneWire(ONE_WIRE_BUS);// Setup a oneWire instance to communicate with any OneWire devices

DallasTemperature sensors(&oneWire);// Pass our oneWire reference to Dallas Temperature.

 

 

float Temperature=10;

float EC=0;// EC

float EC25 =0;// EC for 25oC

int ppm =0;//  TDS

float GH=0;// hardness of water

 

 

float raw= 0;

float Vin= 5;

float Vdrop= 0;

float Rc= 0;

float buffer=0;

int timeCount=0;

//-------------------------------------------------------------------------------------------------------------

 

void setup() {

    //------------------------------------Serial----------------------

  Serial.begin(115200);

  mySerial.begin(115200);   //  設置虛擬串口波特率

  //---------------------------------LED and KEY---------------------

  pinMode(Blank_KEY, INPUT_PULLUP);

  pinMode(LED_Control,OUTPUT);

  digitalWrite(LED_Control, LOW);//led ON

  attachInterrupt(Dark_KEY_INT, dark_KEY, LOW);

  //-------------------------------18B20 and EC------------------------

  pinMode(TempProbeNegative , OUTPUT ); //seting ground pin as output for tmp probe

  digitalWrite(TempProbeNegative , LOW );//Seting it to ground so it can sink current

  pinMode(TempProbePossitive , OUTPUT );//ditto but for positive

  digitalWrite(TempProbePossitive , HIGH );

  pinMode(ECPin,INPUT);

  pinMode(ECPower,OUTPUT);//Setting pin for sourcing current

  pinMode(ECGround,OUTPUT);//setting pin for sinking current

  digitalWrite(ECGround,LOW);//We can leave the ground connected permanantly

  //-----------------------------18B20 one wire-----------------------------------

  delay(100);// gives sensor time to settle

  sensors.begin();

  delay(100);

  //** Adding Digital Pin Resistance to [25 ohm] to the static Resistor *********//

  // Consule Read-Me for Why, or just accept it as true

  R1=(R1+Ra);// Taking into acount Powering Pin Resitance

  

  //---------------------------------SSD1306 OLED-------------------

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally

  if(!display.begin(SSD1306_SWITCHCAPVCC)) {

    //Serial.println(F("SSD1306 allocation failed"));

    for(;;); // Don't proceed, loop forever

  }

  display.display();

  display.clearDisplay();

  displayValue();

  //------------------------------------TSL2581---------------------

  Wire.begin(); //i2c config

  read2581_id();

  /* Setup the sensor power on */

  tsl.TSL2581_power_on();

  delay(2000);

  //  /* Setup the sensor gain and integration time */

  tsl.TSL2581_config();

  //----------------------------------------------------------------

  MsTimer2::set(250, acquireData);        // 中斷設置函數,每 500ms 進入一次中斷

  MsTimer2::start();

}

 

void loop() {

  if(timerState)//採集數據

  {

    timeCount++;// add 1 of 500ms

    tsl.TSL2581_Read_Channel();

    TSL2581_CH0 = tsl.calculateLux(1, NOM_INTEG_CYCLE);

    TSL2581_CH1 = tsl.calculateLux(2, NOM_INTEG_CYCLE);

  }

  if(timeCount >= 10)//每5秒執行一次電導率採集,不能小於5秒

  {

    timeCount =0;

    GetEC(); 

    PrintReadings();

    

    mySerial.write(ppm);

    mySerial.write(ppm);

    mySerial.write(Temperature); 

    mySerial.write(Temperature);

 

 

  }

  if (Serial.available() > 0)//串口接收到數據

  {

    inCOMdate = Serial.read();//獲取串口接收到的數據

  }

  switch(inCOMdate){

    case 'T':{inCOMdate =0;Serial.println(Turbidity,1);};break;// output the Turbidity

    case 'E':{inCOMdate =0;Serial.println(EC25,2);};break;// output the EC

    case 'S':{inCOMdate =0;Serial.println(ppm);};break;// output the TDS

    case 'G':{inCOMdate =0;Serial.println(GH,1);};break;// output the Hardness

    case 'W':{inCOMdate =0;Serial.println(Temperature,1);};break;// output the Temperature

    default:break;

  }

  

  if((!digitalRead(Blank_KEY)) || (inCOMdate == 'B'))//KEY1 or COM=D

  {

    inCOMdate =0;

    blank = TSL2581_CH0;

  }

  

  if(darkState || (inCOMdate == 'D'))//採集暗電流

  {

    inCOMdate =0;

    digitalWrite(LED_Control, HIGH);//led OFF

    delay(500);

    tsl.TSL2581_Read_Channel();

    TSL2581_CH0 = tsl.calculateLux(1, NOM_INTEG_CYCLE);

    TSL2581_CH1 = tsl.calculateLux(2, NOM_INTEG_CYCLE);

    dark = TSL2581_CH0;

    darkState = LOW;

    digitalWrite(LED_Control, LOW);//led ON

  }

  calculate();//計算吸光度和濁度

  displayValue();//display data

  

}

 

void dark_KEY(){

  darkState = HIGH;

}

void acquireData(){

  timerState = !timerState;

}

 

void read2581_id(void)

{

  int   id;

  int a;

  id = tsl.TSL2581_Read_ID();

  a = id & 0xf0;      //The lower four bits are the silicon version number

  if (!(a == 144))    //ID = 90H = 144D

  {

    //Serial.println("false....... ");

    display.clearDisplay();

    display.setCursor(0,10);

    display.print(F("false....... "));

    display.display();

    delay(500);

  } else {

    //Serial.print("I2C DEV is working ,id = ");

    //Serial.println(id);

    display.clearDisplay();

    display.setCursor(0,0);

    display.println(F("I2C DEV is working "));

    display.print(F("id = "));

    display.println(id);

    display.display();

    delay(500);

  }

}

void calculate(void){

  float temp1 = blank - dark;

  float temp2 = TSL2581_CH0 - dark;

  Absorbance = log10(temp1/temp2);

  Turbidity = (Absorbance - 0.0029)/0.004;//根據工作曲線計算斜率和截距

}

 

void displayValue(void) {

  display.clearDisplay();

  display.setFont(&FreeSerif9pt7b);

//  display.setTextSize(1);

  display.setTextColor(WHITE);

//  display.setTextColor(BLACK,WHITE); // Draw 'inverse' text

 

  display.setCursor(10,12);

  display.print(Absorbance,4);

  display.println(F(" A"));

  display.setFont();

  display.setCursor(89,4);

  display.print(TSL2581_CH0);

  display.setCursor(0,16);

  display.print(F("Dark  = "));

  display.print(dark);

  display.println(F(";"));

  display.print(F("Blank = "));

  display.print(blank);

  display.display();

}

 

//************ This Loop Is called From Main Loop************************//

void GetEC(){

 

 

//*********Reading Temperature Of Solution *******************//

sensors.requestTemperatures();// Send the command to get temperatures

Temperature=sensors.getTempCByIndex(0); //Stores Value in Variable

 

 

 

 

//************Estimates Resistance of Liquid ****************//

digitalWrite(ECPower,HIGH);

raw= analogRead(ECPin);

raw= analogRead(ECPin);// This is not a mistake, First reading will be low beause if charged a capacitor

digitalWrite(ECPower,LOW);

 

 

 

 

//***************** Converts to EC **************************//

Vdrop= (Vin*raw)/1024.0;

Rc=(Vdrop*R1)/(Vin-Vdrop);

Rc=Rc-Ra; //acounting for Digital Pin Resitance

EC = 1000/(Rc*K);

 

 

//*************Compensating For Temperaure********************//

EC25  =  EC/ (1+ TemperatureCoef*(Temperature-25.0));

ppm=(EC25)*(PPMconversion*1000);

 

//--------------GH value---------------------------------

if(ppm < 160)

{

  GH = ppm / 20.0;

}

else

{

  GH = ppm / 18.2;

}

 

}

//************************** End OF EC Function ***************************//

 

//***This Loop Is called From Main Loop- Prints to serial usefull info ***//

void PrintReadings(){

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 ");

 

};
 

/*開啓軟串口的目的是使用藍牙傳輸數據給Android上位機,便於用戶進行查看*/

#include <SoftwareSerial.h>      //開啓軟串口
SoftwareSerial mySerial(2 , 3); //第2= RX,第3= TX   //開啓軟串口

mySerial.begin(115200);   //  設置虛擬串口波特率

mySerial.write(ppm);
mySerial.write(ppm);
mySerial.write(Temperature); 
mySerial.write(Temperature);

 

2.電路圖:

 

 

3.串口輸出:

 

 

 

 

 
--------------------- 
作者:CHEN Q X 
來源:CSDN 
原文:https://blog.csdn.net/qq_40987215/article/details/90708893 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章