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