Arduino 水质检测仪(浊度、TDS、温度、电导率、吸光度、硬度)带18b20温度补偿。

 

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.串口输出:

 

 

 

 

  • 5
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
无需任何TDS/pH计,即可构建自己的基于IoT的水质监测系统! 硬件部件: Arduino UNO×1个 公/母跳线×1个 HC-05蓝牙模块×1个 RGB扩散普通阴极×1个 电阻330欧姆×3 旋转电位器(通用)×1个 RGB LCD屏蔽套件,16x2字符显示×1个 电阻1k欧姆×1个 软件应用程序和在线服务:ArduinoIDEArdutooth 手动工具和制造机: 剥线钳和切割器,26-14 AWG单芯和绞线 什么是TDSTDS代表总溶解固体。顾名思义,它可以使我们溶解在一定量的水中的固体数量,以ppm(百万分之一)为单位。TDS是根据电导率[S / m]计算的。电导率越高,TDS值越高。以下是不同类型的水的TDS值的列表: 纯净水:80-150 自来水:250-350 地下水:500-1000 海水:约30000 根据世界卫生组织(世界卫生组织)的建议,饮用水的TDS低于300。但是,TDS低于100的水不能食用,因为它缺乏必需的矿物质。高于300的水被认为过于“坚硬”,因为其中所含的矿物质过多。 通常,我们使用TDS笔来测量水的TDS。但是,我们无法将笔与Arduino集成在一起。因此,有可以与Arduino集成的特殊TDS仪表。但是,我决定在不使用TDS笔的情况下进行此项目。 Arduino的电路 将Arduino的5V连接到面包板的一个电源轨 将Arduino的地面连接到面包板的另一个电源导轨 将1k欧姆电阻的一端连接到地面,另一端连接到面包板。将Arduino上的模拟引脚A0连接到电阻器。最后,将一根线连接到电阻器,将另一根线连接到5V。将这些电线的自由端连接到鳄鱼夹。 液晶显示 将VSS引脚连接到接地轨 将VDD引脚连接到5V电源轨 将V0连接到电位计的中心引脚 将电位计的两端连接到5V并接地 将RS引脚连接到Arduino引脚7 将R / W引脚连接到Arduino引脚8 将D4连接到Arduino引脚10 将D5连接到Arduino引脚11 将D6连接到Arduino引脚12 将D7连接到Arduino引脚13 HC-05蓝牙模块 将VCC引脚连接到5V电源轨 将GND引脚接地 将TX引脚连接到Arduino引脚3(用作RX) 将RX引脚连接到Arduino引脚2(用作TX) RGB LED 将公共阴极(最长的引脚)接地 通过330欧姆电阻将红色引脚(阴极引脚的右侧)连接到Arduino的PWM引脚9 通过330欧姆电阻将绿色引脚(阴极引脚的左侧)连接到Arduino上的PWM引脚6 通过330欧姆电阻将蓝色引脚(最左侧)连接到Arduino上的PWM引脚5

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蜻蜓队长c

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值