├── python └── raspberrypi │ ├── example │ ├── ecdata.txt │ ├── phdata.txt │ ├── demo_EC_reset.py │ ├── demo_PH_reset.py │ ├── demo_PH_calibration.py │ ├── demo_EC_calibration.py │ ├── demo_PH_read.py │ └── demo_PH_EC.py │ ├── README_CN.md │ ├── README.md │ ├── DFRobot_EC.py │ ├── DFRobot_PH.py │ └── DFRobot_ADS1115.py ├── resources ├── images │ └── SEN0161-V2.png └── [SEN0161-V2](V2.0) Layout.pdf ├── library.properties ├── keywords.txt ├── LICENSE ├── example ├── DFRobot_PH_Test │ └── DFRobot_PH_Test.ino └── DFRobot_PH_EC │ └── DFRobot_PH_EC.ino ├── README_CN.md ├── DFRobot_PH.h ├── README.md └── DFRobot_PH.cpp /python/raspberrypi/example/ecdata.txt: -------------------------------------------------------------------------------- 1 | kvalueLow=1.0 2 | kvalueHigh=1.0 -------------------------------------------------------------------------------- /python/raspberrypi/example/phdata.txt: -------------------------------------------------------------------------------- 1 | neutralVoltage=1500.0 2 | acidVoltage=2032.44 3 | -------------------------------------------------------------------------------- /resources/images/SEN0161-V2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DFRobot/DFRobot_PH/HEAD/resources/images/SEN0161-V2.png -------------------------------------------------------------------------------- /resources/[SEN0161-V2](V2.0) Layout.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DFRobot/DFRobot_PH/HEAD/resources/[SEN0161-V2](V2.0) Layout.pdf -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=DFRobot_PH 2 | version=1.0.0 3 | author=DFRobot 4 | maintainer=Jiawei Zhang 5 | sentence=DFRobot Standard library(SKU:SEN0161-V2). 6 | paragraph=Analog pH Sensor. 7 | category=Sensors 8 | url=https://github.com/DFRobot/DFRobot_PH 9 | architectures=* 10 | depends=DFRobot_EC 11 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring DFRobot_PH 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | DFRobot_PH KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | readPH KEYWORD2 15 | calibration KEYWORD2 -------------------------------------------------------------------------------- /python/raspberrypi/example/demo_EC_reset.py: -------------------------------------------------------------------------------- 1 | 2 | '''! 3 | @file demo_EC_reset.py 4 | @brief This example ues to reset ecdata.txt to default value 5 | @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 6 | @license The MIT License (MIT) 7 | @author [Jiawei Zhang](jiawei.zhang@dfrobot.com) 8 | @version V1.0 9 | @date 2018-11-06 10 | @url https://github.com/DFRobot/DFRobot_PH 11 | ''' 12 | import sys 13 | sys.path.append('../') 14 | import time 15 | 16 | from DFRobot_EC import DFRobot_EC 17 | ec = DFRobot_EC() 18 | 19 | ec.reset() 20 | time.sleep(0.5) 21 | sys.exit(1) -------------------------------------------------------------------------------- /python/raspberrypi/example/demo_PH_reset.py: -------------------------------------------------------------------------------- 1 | '''! 2 | @file demo_PH_reset.py 3 | @brief This example ues to reset phdata.txt to default value 4 | @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 5 | @license The MIT License (MIT) 6 | @author [Jiawei Zhang](jiawei.zhang@dfrobot.com) 7 | @version V1.0 8 | @date 2018-11-06 9 | @url https://github.com/DFRobot/DFRobot_PH 10 | ''' 11 | 12 | import sys 13 | sys.path.append('../') 14 | import time 15 | 16 | from DFRobot_PH import DFRobot_PH 17 | ph = DFRobot_PH() 18 | 19 | ph.reset() 20 | time.sleep(0.5) 21 | sys.exit(1) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2010 DFRobot Co.Ltd 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /python/raspberrypi/example/demo_PH_calibration.py: -------------------------------------------------------------------------------- 1 | '''! 2 | @file demo_PH_calibration.py 3 | @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 4 | @license The MIT License (MIT) 5 | @author [Jiawei Zhang](jiawei.zhang@dfrobot.com) 6 | @version V1.0 7 | @date 2018-11-06 8 | @url https://github.com/DFRobot/DFRobot_PH 9 | ''' 10 | import sys 11 | sys.path.append('../') 12 | import time 13 | ADS1115_REG_CONFIG_PGA_6_144V = 0x00 # 6.144V range = Gain 2/3 14 | ADS1115_REG_CONFIG_PGA_4_096V = 0x02 # 4.096V range = Gain 1 15 | ADS1115_REG_CONFIG_PGA_2_048V = 0x04 # 2.048V range = Gain 2 (default) 16 | ADS1115_REG_CONFIG_PGA_1_024V = 0x06 # 1.024V range = Gain 4 17 | ADS1115_REG_CONFIG_PGA_0_512V = 0x08 # 0.512V range = Gain 8 18 | ADS1115_REG_CONFIG_PGA_0_256V = 0x0A # 0.256V range = Gain 16 19 | 20 | from DFRobot_ADS1115 import ADS1115 21 | from DFRobot_PH import DFRobot_PH 22 | 23 | ads1115 = ADS1115() 24 | ph = DFRobot_PH() 25 | 26 | ph.begin() 27 | while True : 28 | temperature = 25 29 | #Set the IIC address 30 | ads1115.setAddr_ADS1115(0x48) 31 | #Sets the gain and input voltage range. 32 | ads1115.setGain(ADS1115_REG_CONFIG_PGA_6_144V) 33 | #Get the Digital Value of Analog of selected channel 34 | adc0 = ads1115.readVoltage(0) 35 | print "A0:%dmV "%(adc0['r']) 36 | #Calibrate the calibration data 37 | ph.calibration(adc0['r']) 38 | time.sleep(1.0) -------------------------------------------------------------------------------- /python/raspberrypi/example/demo_EC_calibration.py: -------------------------------------------------------------------------------- 1 | '''! 2 | @file demo_EC_calibration.py 3 | @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 4 | @license The MIT License (MIT) 5 | @author [Jiawei Zhang](jiawei.zhang@dfrobot.com) 6 | @version V1.0 7 | @date 2018-11-06 8 | @url https://github.com/DFRobot/DFRobot_PH 9 | ''' 10 | 11 | import sys 12 | sys.path.append('../') 13 | import time 14 | ADS1115_REG_CONFIG_PGA_6_144V = 0x00 # 6.144V range = Gain 2/3 15 | ADS1115_REG_CONFIG_PGA_4_096V = 0x02 # 4.096V range = Gain 1 16 | ADS1115_REG_CONFIG_PGA_2_048V = 0x04 # 2.048V range = Gain 2 (default) 17 | ADS1115_REG_CONFIG_PGA_1_024V = 0x06 # 1.024V range = Gain 4 18 | ADS1115_REG_CONFIG_PGA_0_512V = 0x08 # 0.512V range = Gain 8 19 | ADS1115_REG_CONFIG_PGA_0_256V = 0x0A # 0.256V range = Gain 16 20 | 21 | from DFRobot_ADS1115 import ADS1115 22 | from DFRobot_EC import DFRobot_EC 23 | 24 | ads1115 = ADS1115() 25 | ec = DFRobot_EC() 26 | 27 | ec.begin() 28 | while True : 29 | #Read your temperature sensor to execute temperature compensation 30 | temperature = 25 31 | #Set the IIC address 32 | ads1115.setAddr_ADS1115(0x48) 33 | #Sets the gain and input voltage range. 34 | ads1115.setGain(ADS1115_REG_CONFIG_PGA_6_144V) 35 | #Get the Digital Value of Analog of selected channel 36 | adc0 = ads1115.readVoltage(0) 37 | print "A0:%dmV "%(adc0['r']) 38 | #Calibrate the calibration data 39 | ec.calibration(adc0['r'],temperature) 40 | time.sleep(3.0) -------------------------------------------------------------------------------- /python/raspberrypi/example/demo_PH_read.py: -------------------------------------------------------------------------------- 1 | '''! 2 | @file demo_PH_read.py 3 | @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 4 | @license The MIT License (MIT) 5 | @author [Jiawei Zhang](jiawei.zhang@dfrobot.com) 6 | @version V1.0 7 | @date 2018-11-06 8 | @url https://github.com/DFRobot/DFRobot_PH 9 | ''' 10 | import sys 11 | sys.path.append('../') 12 | import time 13 | ADS1115_REG_CONFIG_PGA_6_144V = 0x00 # 6.144V range = Gain 2/3 14 | ADS1115_REG_CONFIG_PGA_4_096V = 0x02 # 4.096V range = Gain 1 15 | ADS1115_REG_CONFIG_PGA_2_048V = 0x04 # 2.048V range = Gain 2 (default) 16 | ADS1115_REG_CONFIG_PGA_1_024V = 0x06 # 1.024V range = Gain 4 17 | ADS1115_REG_CONFIG_PGA_0_512V = 0x08 # 0.512V range = Gain 8 18 | ADS1115_REG_CONFIG_PGA_0_256V = 0x0A # 0.256V range = Gain 16 19 | 20 | from DFRobot_ADS1115 import ADS1115 21 | from DFRobot_PH import DFRobot_PH 22 | 23 | ads1115 = ADS1115() 24 | ph = DFRobot_PH() 25 | 26 | ph.begin() 27 | while True : 28 | #Read your temperature sensor to execute temperature compensation 29 | temperature = 25 30 | #Set the IIC address 31 | ads1115.setAddr_ADS1115(0x48) 32 | #Sets the gain and input voltage range. 33 | ads1115.setGain(ADS1115_REG_CONFIG_PGA_6_144V) 34 | #Get the Digital Value of Analog of selected channel 35 | adc0 = ads1115.readVoltage(0) 36 | #Convert voltage to PH with temperature compensation 37 | PH = ph.read_PH(adc0['r'],temperature) 38 | print "Temperature:%.1f ^C PH:%.2f" %(temperature,PH) 39 | time.sleep(1.0) 40 | -------------------------------------------------------------------------------- /python/raspberrypi/example/demo_PH_EC.py: -------------------------------------------------------------------------------- 1 | '''! 2 | @file demo_PH_EC.py 3 | @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 4 | @license The MIT License (MIT) 5 | @author [Jiawei Zhang](jiawei.zhang@dfrobot.com) 6 | @version V1.0 7 | @date 2018-11-06 8 | @url https://github.com/DFRobot/DFRobot_PH 9 | ''' 10 | 11 | import sys 12 | sys.path.append('../') 13 | import time 14 | ADS1115_REG_CONFIG_PGA_6_144V = 0x00 # 6.144V range = Gain 2/3 15 | ADS1115_REG_CONFIG_PGA_4_096V = 0x02 # 4.096V range = Gain 1 16 | ADS1115_REG_CONFIG_PGA_2_048V = 0x04 # 2.048V range = Gain 2 (default) 17 | ADS1115_REG_CONFIG_PGA_1_024V = 0x06 # 1.024V range = Gain 4 18 | ADS1115_REG_CONFIG_PGA_0_512V = 0x08 # 0.512V range = Gain 8 19 | ADS1115_REG_CONFIG_PGA_0_256V = 0x0A # 0.256V range = Gain 16 20 | 21 | from DFRobot_ADS1115 import ADS1115 22 | from DFRobot_EC import DFRobot_EC 23 | from DFRobot_PH import DFRobot_PH 24 | 25 | ads1115 = ADS1115() 26 | ec = DFRobot_EC() 27 | ph = DFRobot_PH() 28 | 29 | ec.begin() 30 | ph.begin() 31 | while True : 32 | #Read your temperature sensor to execute temperature compensation 33 | temperature = 25 34 | #Set the IIC address 35 | ads1115.setAddr_ADS1115(0x48) 36 | #Sets the gain and input voltage range. 37 | ads1115.setGain(ADS1115_REG_CONFIG_PGA_6_144V) 38 | #Get the Digital Value of Analog of selected channel 39 | adc0 = ads1115.readVoltage(0) 40 | adc1 = ads1115.readVoltage(1) 41 | #Convert voltage to EC with temperature compensation 42 | EC = ec.readEC(adc0['r'],temperature) 43 | PH = ph.read_PH(adc1['r'],temperature) 44 | print "Temperature:%.1f ^C EC:%.2f ms/cm PH:%.2f " %(temperature,EC,PH) 45 | time.sleep(1.0) 46 | -------------------------------------------------------------------------------- /example/DFRobot_PH_Test/DFRobot_PH_Test.ino: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file DFRobot_PH_Test.h 3 | * @brief This is the sample code for Gravity: Analog pH Sensor / Meter Kit V2, SKU:SEN0161-V2. 4 | * @n In order to guarantee precision, a temperature sensor such as DS18B20 is needed, to execute automatic temperature compensation. 5 | * @n You can send commands in the serial monitor to execute the calibration. 6 | * @n Serial Commands: 7 | * @n enterph -> enter the calibration mode 8 | * @n calph -> calibrate with the standard buffer solution, two buffer solutions(4.0 and 7.0) will be automaticlly recognized 9 | * @n exitph -> save the calibrated parameters and exit from calibration mode 10 | * 11 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 12 | * @license The MIT License (MIT) 13 | * @author [Jiawei Zhang](jiawei.zhang@dfrobot.com) 14 | * @version V1.0 15 | * @date 2018-11-06 16 | * @url https://github.com/DFRobot/DFRobot_PH 17 | */ 18 | 19 | #include "DFRobot_PH.h" 20 | #include 21 | 22 | #define PH_PIN A1 23 | float voltage,phValue,temperature = 25; 24 | DFRobot_PH ph; 25 | 26 | void setup() 27 | { 28 | Serial.begin(115200); 29 | ph.begin(); 30 | } 31 | 32 | void loop() 33 | { 34 | static unsigned long timepoint = millis(); 35 | if(millis()-timepoint>1000U){ //time interval: 1s 36 | timepoint = millis(); 37 | //temperature = readTemperature(); // read your temperature sensor to execute temperature compensation 38 | voltage = analogRead(PH_PIN)/1024.0*5000; // read the voltage 39 | phValue = ph.readPH(voltage,temperature); // convert voltage to pH with temperature compensation 40 | Serial.print("temperature:"); 41 | Serial.print(temperature,1); 42 | Serial.print("^C pH:"); 43 | Serial.println(phValue,2); 44 | } 45 | ph.calibration(voltage,temperature); // calibration process by Serail CMD 46 | } 47 | 48 | float readTemperature() 49 | { 50 | //add your code here to get the temperature from your temperature sensor 51 | } 52 | -------------------------------------------------------------------------------- /python/raspberrypi/README_CN.md: -------------------------------------------------------------------------------- 1 | # DFRobot_PH 2 | 3 | - [English Version](./README.md) 4 | 5 | 这是 Gravity 的示例代码:模拟 pH 传感器/仪表套件 V2,SKU:SEN0161-V2 6 | 7 | ![产品效果图](../../resources/images/SEN0161-V2.png) 8 | 9 | 10 | ## 产品链接([https://www.dfrobot.com.cn/goods-1828.html](https://www.dfrobot.com.cn/goods-1828.html)) 11 | SKU: SEN0161-V2 12 | 13 | ## 目录 14 | 15 | * [概述](#概述) 16 | * [库安装](#库安装) 17 | * [方法](#方法) 18 | * [兼容性](#兼容性) 19 | * [历史](#历史) 20 | * [创作者](#创作者) 21 | 22 | ## 概述 23 | 24 | 模拟pH计V2专门用于测量溶液的pH,衡量溶液的酸碱程度,常用于鱼菜共生、水产养殖、环境水检测等领域。 25 | 26 | ## 库安装 27 | 1. 下载库至树莓派,要使用这个库,首先要将库下载到Raspberry Pi,命令下载方法如下:
28 | ```python 29 | sudo git clone https://github.com/DFRobot/DFRobot_PH 30 | ``` 31 | 2. 打开并运行例程,要执行一个例程demo_x.py,请在命令行中输入python demo_x.py。例如,要执行 demo_PH_read.py例程,你需要输入:
32 | 33 | ```python 34 | python demo_PH_read.py 35 | 或 36 | python2 demo_PH_read.py 37 | ``` 38 | 39 | ## 方法 40 | 41 | ```python 42 | '''! 43 | @brief 初始化模拟 pH 传感器. 44 | ''' 45 | def begin(self): 46 | 47 | '''! 48 | @brief 通过温度补偿将电压转换为 PH值 49 | @param voltage 电压值 50 | @param temperature 环境温度值 51 | @return PH值 52 | ''' 53 | def read_PH(self,voltage,temperature): 54 | 55 | '''! 56 | @brief 使用校准参数校准PH计 57 | @param voltage 电压值 58 | ''' 59 | def calibration(self,voltage): 60 | 61 | '''! 62 | @brief 将校准数据设置为默认值。 63 | ''' 64 | def reset(self): 65 | ``` 66 | 67 | ## 兼容性 68 | 69 | | 主板 | 通过 | 未通过 | 未测试 | 备注 | 70 | | ------------ | :--: | :----: | :----: | :--: | 71 | | RaspberryPi2 | | | √ | | 72 | | RaspberryPi3 | | | √ | | 73 | | RaspberryPi4 | √ | | | | 74 | 75 | * Python 版本 76 | 77 | | Python | 通过 | 未通过 | 未测试 | 备注 | 78 | | ------- | :--: | :----: | :----: | ---- | 79 | | Python2 | √ | | | | 80 | | Python3 | | | √ | | 81 | 82 | ## 历史 83 | 84 | - 2018/11/06 - 1.0.0 版本 85 | 86 | ## 创作者 87 | 88 | Written by Jiawei Zhang(jiawei.zhang@dfrobot.com), 2018. (Welcome to our [website](https://www.dfrobot.com/)) 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /README_CN.md: -------------------------------------------------------------------------------- 1 | # DFRobot_PH 2 | 3 | * [English Version](./README.md) 4 | 5 | 这是 Gravity 的示例代码:模拟 pH 传感器/仪表套件 V2,SKU:SEN0161-V2 6 | 7 | ![产品效果图](./resources/images/SEN0161-V2.png) 8 | 9 | 10 | ## 产品链接([https://www.dfrobot.com.cn/goods-1828.html](https://www.dfrobot.com.cn/goods-1828.html)) 11 | SKU: SEN0161-V2 12 | 13 | ## 目录 14 | 15 | * [概述](#概述) 16 | * [库安装](#库安装) 17 | * [方法](#方法) 18 | * [兼容性](#兼容性) 19 | * [历史](#历史) 20 | * [创作者](#创作者) 21 | 22 | ## 概述 23 | 24 | 模拟pH计V2专门用于测量溶液的pH,衡量溶液的酸碱程度,常用于鱼菜共生、水产养殖、环境水检测等领域。 25 | 26 | ## 库安装 27 | 28 | 这里有2种安装方法: 29 | 1. 使用此库前,请首先下载库文件,将其粘贴到\Arduino\libraries目录中,然后打开examples文件夹并在该文件夹中运行演示。 30 | 2. 直接在Arduino软件库管理中搜索下载 DFRobot_AHT20 库
31 | 在运行此库的demo之前,你需要下载关联库: https://github.com/DFRobot/DFRobot_EC 32 | 33 | ## 方法 34 | 35 | ```C++ 36 | /** 37 | * @fn calibration 38 | * @brief 使用校准参数校准PH计 39 | * 40 | * @param voltage : 电压值 41 | * @param temperature : 环境温度值 42 | * @param cmd : enterph -> 进入PH计校准模式 43 | * @n calph -> 用标准缓冲液校准,自动识别两种缓冲液(4.0和7.0) 44 | * @n exitph -> 保存校准参数并退出 PH 校准模式 45 | */ 46 | void calibration(float voltage, float temperature,char* cmd); 47 | void calibration(float voltage, float temperature); 48 | /** 49 | * @fn readPH 50 | * @brief 通过温度补偿将电压转换为 PH值 51 | * 52 | * @param voltage : 电压值 53 | * @param temperature : 环境温度值 54 | * @return PH值 55 | */ 56 | float readPH(float voltage, float temperature); 57 | /** 58 | * @fn begin 59 | * @brief 初始化模拟 pH 传感器 60 | */ 61 | void begin(); 62 | ``` 63 | 64 | ## 兼容性 65 | 66 | MCU | Work Well | Work Wrong | Untested | Remarks 67 | ------------------ | :----------: | :----------: | :---------: | ----- 68 | Arduino Uno | √ | | | 69 | Leonardo | √ | | | 70 | Meag2560 | √ | | | 71 | esp32 series | | x | | 72 | 73 | ## 历史 74 | 75 | - 2018/11/06 - 1.0.0 版本 76 | 77 | ## 创作者 78 | 79 | Written by Jiawei Zhang(jiawei.zhang@dfrobot.com), 2018. (Welcome to our [website](https://www.dfrobot.com/)) 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /DFRobot_PH.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file DFRobot_PH.h 3 | * @brief Arduino library for Gravity: Analog pH Sensor / Meter Kit V2, SKU: SEN0161-V2 4 | * 5 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 6 | * @license The MIT License (MIT) 7 | * @author [Jiawei Zhang](jiawei.zhang@dfrobot.com) 8 | * @version V1.0 9 | * @date 2018-11-06 10 | * @url https://github.com/DFRobot/DFRobot_PH 11 | */ 12 | 13 | #ifndef _DFROBOT_PH_H_ 14 | #define _DFROBOT_PH_H_ 15 | 16 | #if ARDUINO >= 100 17 | #include "Arduino.h" 18 | #else 19 | #include "WProgram.h" 20 | #endif 21 | 22 | #define ReceivedBufferLength 10 //length of the Serial CMD buffer 23 | 24 | class DFRobot_PH 25 | { 26 | public: 27 | DFRobot_PH(); 28 | ~DFRobot_PH(); 29 | /** 30 | * @fn calibration 31 | * @brief Calibrate the calibration data 32 | * 33 | * @param voltage : Voltage value 34 | * @param temperature : Ambient temperature 35 | * @param cmd : enterph -> enter the PH calibration mode 36 | * @n calph -> calibrate with the standard buffer solution, two buffer solutions(4.0 and 7.0) will be automaticlly recognized 37 | * @n exitph -> save the calibrated parameters and exit from PH calibration mode 38 | */ 39 | void calibration(float voltage, float temperature,char* cmd); //calibration by Serial CMD 40 | void calibration(float voltage, float temperature); 41 | /** 42 | * @fn readPH 43 | * @brief Convert voltage to PH with temperature compensation 44 | * @note voltage to pH value, with temperature compensation 45 | * 46 | * @param voltage : Voltage value 47 | * @param temperature : Ambient temperature 48 | * @return The PH value 49 | */ 50 | float readPH(float voltage, float temperature); 51 | /** 52 | * @fn begin 53 | * @brief Initialization The Analog pH Sensor 54 | */ 55 | void begin(); 56 | 57 | private: 58 | float _phValue; 59 | float _acidVoltage; 60 | float _neutralVoltage; 61 | float _voltage; 62 | float _temperature; 63 | 64 | char _cmdReceivedBuffer[ReceivedBufferLength]; //store the Serial CMD 65 | byte _cmdReceivedBufferIndex; 66 | 67 | private: 68 | boolean cmdSerialDataAvailable(); 69 | void phCalibration(byte mode); // calibration process, wirte key parameters to EEPROM 70 | byte cmdParse(const char* cmd); 71 | byte cmdParse(); 72 | char* strupr(char* str); 73 | }; 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /python/raspberrypi/README.md: -------------------------------------------------------------------------------- 1 | ## DFRobot_PH 2 | 3 | * [中文版](./README_CN.md) 4 | 5 | This is the sample code for Gravity: Analog pH Sensor / Meter Kit V2, SKU:SEN0161-V2 6 | 7 | ![产品效果图](../../resources/images/SEN0161-V2.png) 8 | 9 | ## Product Link ([https://www.dfrobot.com/product-1782.html](https://www.dfrobot.com/product-1782.html)) 10 | SKU: SEN0161-V2 11 | 12 | ## Table of Contents 13 | 14 | * [Summary](#summary) 15 | * [Installation](#installation) 16 | * [Methods](#methods) 17 | * [Compatibility](#compatibility) 18 | * [History](#history) 19 | * [Credits](#credits) 20 | 21 | ## Summary 22 | 23 | Analog pH meter V2 is specifically designed to measure the pH of the solution and reflect the acidity or alkalinity. DFRobot ph sensor is commonly used in various applications such as aquaponics, aquaculture, and environmental water testing. 24 | 25 | 26 | ## Installation 27 | 1. To use this library, first download the library file
28 | ```python 29 | sudo git clone https://github.com/DFRobot/DFRobot_PH 30 | ``` 31 | 2. Open and run the routine. To execute a routine demo_x.py, enter python demo_x.py in the command line. For example, to execute the demo_read_aht20.py routine, you need to enter :
32 | 33 | ```python 34 | python demo_PH_read.py 35 | or 36 | python2 demo_PH_read.py 37 | ``` 38 | 39 | ## Methods 40 | 41 | ```python 42 | '''! 43 | @brief Initialization The Analog pH Sensor. 44 | ''' 45 | def begin(self): 46 | 47 | '''! 48 | @brief Convert voltage to PH with temperature compensation. 49 | @note voltage to pH value, with temperature compensation 50 | @param voltage Voltage value 51 | @param temperature Ambient temperature 52 | @return The PH value 53 | ''' 54 | def read_PH(self,voltage,temperature): 55 | 56 | '''! 57 | @brief Calibrate the calibration data. 58 | @param voltage Voltage value 59 | ''' 60 | def calibration(self,voltage): 61 | 62 | '''! 63 | @brief Reset the calibration data to default value. 64 | ''' 65 | def reset(self): 66 | 67 | ``` 68 | ## Compatibility 69 | 70 | | 主板 | 通过 | 未通过 | 未测试 | 备注 | 71 | | ------------ | :--: | :----: | :----: | :--: | 72 | | RaspberryPi2 | | | √ | | 73 | | RaspberryPi3 | | | √ | | 74 | | RaspberryPi4 | √ | | | | 75 | 76 | * Python 版本 77 | 78 | | Python | 通过 | 未通过 | 未测试 | 备注 | 79 | | ------- | :--: | :----: | :----: | ---- | 80 | | Python2 | √ | | | | 81 | | Python3 | | | √ | | 82 | ## History 83 | 84 | - 2018/11/06 - Version 1.0.0 released. 85 | 86 | ## Credits 87 | 88 | Written by Jiawei Zhang(jiawei.zhang@dfrobot.com), 2018. (Welcome to our [website](https://www.dfrobot.com/)) 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## DFRobot_PH 2 | 3 | * [中文版](./README_CN.md) 4 | 5 | This is the sample code for Gravity: Analog pH Sensor / Meter Kit V2, SKU:SEN0161-V2 6 | 7 | ![产品效果图](./resources/images/SEN0161-V2.png) 8 | 9 | ## Product Link ([https://www.dfrobot.com/product-1782.html](https://www.dfrobot.com/product-1782.html)) 10 | SKU: SEN0161-V2 11 | 12 | ## Table of Contents 13 | 14 | * [Summary](#summary) 15 | * [Installation](#installation) 16 | * [Methods](#methods) 17 | * [Compatibility](#compatibility) 18 | * [History](#history) 19 | * [Credits](#credits) 20 | 21 | ## Summary 22 | 23 | Analog pH meter V2 is specifically designed to measure the pH of the solution and reflect the acidity or alkalinity. DFRobot ph sensor is commonly used in various applications such as aquaponics, aquaculture, and environmental water testing. 24 | 25 | ## Installation 26 | 27 | To use this library, first download the library file, paste it into the \Arduino\libraries directory, then open the examples folder and run the demo in the folder.
28 | Depends library: https://github.com/DFRobot/DFRobot_EC 29 | 30 | 31 | ## Methods 32 | 33 | ```C++ 34 | /** 35 | * @fn calibration 36 | * @brief Calibrate the calibration data 37 | * 38 | * @param voltage : Voltage value 39 | * @param temperature : Ambient temperature 40 | * @param cmd : enterph -> enter the PH calibration mode 41 | * @n calph -> calibrate with the standard buffer solution, two buffer solutions(4.0 and 7.0) will be automaticlly recognized 42 | * @n exitph -> save the calibrated parameters and exit from PH calibration mode 43 | */ 44 | void calibration(float voltage, float temperature,char* cmd); //calibration by Serial CMD 45 | void calibration(float voltage, float temperature); 46 | /** 47 | * @fn readPH 48 | * @brief Convert voltage to PH with temperature compensation 49 | * @note voltage to pH value, with temperature compensation 50 | * 51 | * @param voltage : Voltage value 52 | * @param temperature : Ambient temperature 53 | * @return The PH value 54 | */ 55 | float readPH(float voltage, float temperature); 56 | /** 57 | * @fn begin 58 | * @brief Initialization The Analog pH Sensor 59 | */ 60 | void begin(); 61 | ``` 62 | 63 | ## Compatibility 64 | 65 | MCU | Work Well | Work Wrong | Untested | Remarks 66 | ------------------ | :----------: | :----------: | :---------: | ----- 67 | Arduino Uno | √ | | | 68 | Leonardo | √ | | | 69 | Meag2560 | √ | | | 70 | esp32 series | | x | | 71 | 72 | ## History 73 | 74 | - 2018/11/06 - Version 1.0.0 released. 75 | 76 | ## Credits 77 | 78 | Written by Jiawei Zhang(jiawei.zhang@dfrobot.com), 2018. (Welcome to our [website](https://www.dfrobot.com/)) 79 | -------------------------------------------------------------------------------- /python/raspberrypi/DFRobot_EC.py: -------------------------------------------------------------------------------- 1 | '''! 2 | @file DFRobot_EC.py 3 | @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 4 | @license The MIT License (MIT) 5 | @author [Jiawei Zhang](jiawei.zhang@dfrobot.com) 6 | @version V1.0 7 | @date 2018-11-06 8 | @url https://github.com/DFRobot/DFRobot_PH 9 | ''' 10 | 11 | import time 12 | import sys 13 | 14 | _kvalue = 1.0 15 | _kvalueLow = 1.0 16 | _kvalueHigh = 1.0 17 | _cmdReceivedBufferIndex = 0 18 | _voltage = 0.0 19 | _temperature = 25.0 20 | 21 | class DFRobot_EC(): 22 | def begin(self): 23 | global _kvalueLow 24 | global _kvalueHigh 25 | try: 26 | with open('ecdata.txt','r') as f: 27 | kvalueLowLine = f.readline() 28 | kvalueLowLine = kvalueLowLine.strip('kvalueLow=') 29 | _kvalueLow = float(kvalueLowLine) 30 | kvalueHighLine = f.readline() 31 | kvalueHighLine = kvalueHighLine.strip('kvalueHigh=') 32 | _kvalueHigh = float(kvalueHighLine) 33 | except : 34 | print "ecdata.txt ERROR ! Please run DFRobot_EC_Reset" 35 | sys.exit(1) 36 | def readEC(self,voltage,temperature): 37 | global _kvalueLow 38 | global _kvalueHigh 39 | global _kvalue 40 | rawEC = 1000*voltage/820.0/200.0 41 | valueTemp = rawEC * _kvalue 42 | if(valueTemp > 2.5): 43 | _kvalue = _kvalueHigh 44 | elif(valueTemp < 2.0): 45 | _kvalue = _kvalueLow 46 | value = rawEC * _kvalue 47 | value = value / (1.0+0.0185*(temperature-25.0)) 48 | return value 49 | def calibration(self,voltage,temperature): 50 | rawEC = 1000*voltage/820.0/200.0 51 | if (rawEC>0.9 and rawEC<1.9): 52 | compECsolution = 1.413*(1.0+0.0185*(temperature-25.0)) 53 | KValueTemp = 820.0*200.0*compECsolution/1000.0/voltage 54 | round(KValueTemp,2) 55 | print ">>>Buffer Solution:1.413us/cm" 56 | f=open('ecdata.txt','r+') 57 | flist=f.readlines() 58 | flist[0]='kvalueLow='+ str(KValueTemp) + '\n' 59 | f=open('ecdata.txt','w+') 60 | f.writelines(flist) 61 | f.close() 62 | print ">>>EC:1.413us/cm Calibration completed,Please enter Ctrl+C exit calibration in 5 seconds" 63 | time.sleep(5.0) 64 | elif (rawEC>9 and rawEC<16.8): 65 | compECsolution = 12.88*(1.0+0.0185*(temperature-25.0)) 66 | KValueTemp = 820.0*200.0*compECsolution/1000.0/voltage 67 | print ">>>Buffer Solution:12.88ms/cm" 68 | f=open('ecdata.txt','r+') 69 | flist=f.readlines() 70 | flist[1]='kvalueHigh='+ str(KValueTemp) + '\n' 71 | f=open('ecdata.txt','w+') 72 | f.writelines(flist) 73 | f.close() 74 | print ">>>EC:12.88ms/cm Calibration completed,Please enter Ctrl+C exit calibration in 5 seconds" 75 | time.sleep(5.0) 76 | else: 77 | print ">>>Buffer Solution Error Try Again<<<" 78 | def reset(self): 79 | _kvalueLow = 1.0; 80 | _kvalueHigh = 1.0; 81 | try: 82 | f=open('ecdata.txt','r+') 83 | flist=f.readlines() 84 | flist[0]='kvalueLow=' + str(_kvalueLow) + '\n' 85 | flist[1]='kvalueHigh='+ str(_kvalueHigh) + '\n' 86 | f=open('ecdata.txt','w+') 87 | f.writelines(flist) 88 | f.close() 89 | print ">>>Reset to default parameters<<<" 90 | except: 91 | f=open('ecdata.txt','w') 92 | #flist=f.readlines() 93 | flist ='kvalueLow=' + str(_kvalueLow) + '\n' 94 | flist +='kvalueHigh='+ str(_kvalueHigh) + '\n' 95 | #f=open('data.txt','w+') 96 | f.writelines(flist) 97 | f.close() 98 | print ">>>Reset to default parameters<<<" -------------------------------------------------------------------------------- /python/raspberrypi/DFRobot_PH.py: -------------------------------------------------------------------------------- 1 | '''! 2 | @file DFRobot_PH.py 3 | @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 4 | @license The MIT License (MIT) 5 | @author [Jiawei Zhang](jiawei.zhang@dfrobot.com) 6 | @version V1.0 7 | @date 2018-11-06 8 | @url https://github.com/DFRobot/DFRobot_PH 9 | ''' 10 | 11 | import time 12 | import sys 13 | 14 | _temperature = 25.0 15 | _acidVoltage = 2032.44 16 | _neutralVoltage = 1500.0 17 | class DFRobot_PH(): 18 | def begin(self): 19 | '''! 20 | @brief Initialization The Analog pH Sensor. 21 | ''' 22 | global _acidVoltage 23 | global _neutralVoltage 24 | try: 25 | with open('phdata.txt','r') as f: 26 | neutralVoltageLine = f.readline() 27 | neutralVoltageLine = neutralVoltageLine.strip('neutralVoltage=') 28 | _neutralVoltage = float(neutralVoltageLine) 29 | acidVoltageLine = f.readline() 30 | acidVoltageLine = acidVoltageLine.strip('acidVoltage=') 31 | _acidVoltage = float(acidVoltageLine) 32 | except : 33 | print "phdata.txt ERROR ! Please run DFRobot_PH_Reset" 34 | sys.exit(1) 35 | def read_PH(self,voltage,temperature): 36 | '''! 37 | @brief Convert voltage to PH with temperature compensation. 38 | @note voltage to pH value, with temperature compensation 39 | @param voltage Voltage value 40 | @param temperature Ambient temperature 41 | @return The PH value 42 | ''' 43 | global _acidVoltage 44 | global _neutralVoltage 45 | slope = (7.0-4.0)/((_neutralVoltage-1500.0)/3.0 - (_acidVoltage-1500.0)/3.0) 46 | intercept = 7.0 - slope*(_neutralVoltage-1500.0)/3.0 47 | _phValue = slope*(voltage-1500.0)/3.0+intercept 48 | round(_phValue,2) 49 | return _phValue 50 | def calibration(self,voltage): 51 | '''! 52 | @brief Calibrate the calibration data. 53 | @param voltage Voltage value 54 | ''' 55 | if (voltage>1322 and voltage<1678): 56 | print ">>>Buffer Solution:7.0" 57 | f=open('phdata.txt','r+') 58 | flist=f.readlines() 59 | flist[0]='neutralVoltage='+ str(voltage) + '\n' 60 | f=open('phdata.txt','w+') 61 | f.writelines(flist) 62 | f.close() 63 | print ">>>PH:7.0 Calibration completed,Please enter Ctrl+C exit calibration in 5 seconds" 64 | time.sleep(5.0) 65 | elif (voltage>1854 and voltage<2210): 66 | print ">>>Buffer Solution:4.0" 67 | f=open('phdata.txt','r+') 68 | flist=f.readlines() 69 | flist[1]='acidVoltage='+ str(voltage) + '\n' 70 | f=open('phdata.txt','w+') 71 | f.writelines(flist) 72 | f.close() 73 | print ">>>PH:4.0 Calibration completed,Please enter Ctrl+C exit calibration in 5 seconds" 74 | time.sleep(5.0) 75 | else: 76 | print ">>>Buffer Solution Error Try Again<<<" 77 | def reset(self): 78 | '''! 79 | @brief Reset the calibration data to default value. 80 | ''' 81 | 82 | _acidVoltage = 2032.44 83 | _neutralVoltage = 1500.0 84 | try: 85 | f=open('phdata.txt','r+') 86 | flist=f.readlines() 87 | flist[0]='neutralVoltage='+ str(_neutralVoltage) + '\n' 88 | flist[1]='acidVoltage='+ str(_acidVoltage) + '\n' 89 | f=open('phdata.txt','w+') 90 | f.writelines(flist) 91 | f.close() 92 | print ">>>Reset to default parameters<<<" 93 | except: 94 | f=open('phdata.txt','w') 95 | #flist=f.readlines() 96 | flist ='neutralVoltage='+ str(_neutralVoltage) + '\n' 97 | flist +='acidVoltage='+ str(_acidVoltage) + '\n' 98 | #f=open('data.txt','w+') 99 | f.writelines(flist) 100 | f.close() 101 | print ">>>Reset to default parameters<<<" -------------------------------------------------------------------------------- /example/DFRobot_PH_EC/DFRobot_PH_EC.ino: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file DFRobot_PH_EC.h 3 | * @brief This is the sample code for The Mixed use of two sensors: 4 | * @n 1. Gravity: Analog pH Sensor / Meter Kit V2, SKU:SEN0161-V2 5 | * @n 2. Analog Electrical Conductivity Sensor / Meter Kit V2 (K=1.0), SKU: DFR0300. 6 | * @n In order to guarantee precision, a temperature sensor such as DS18B20 is needed, to execute automatic temperature compensation. 7 | * @n Serial Commands: 8 | * @n PH Calibration: 9 | * @n enterph -> enter the calibration mode 10 | * @n calph -> calibrate with the standard buffer solution, two buffer solutions(4.0 and 7.0) will be automaticlly recognized 11 | * @n exitph -> save the calibrated parameters and exit from calibration mode 12 | * @n EC Calibration: 13 | * @n enterph -> enter the PH calibration mode 14 | * @n calph -> calibrate with the standard buffer solution, two buffer solutions(4.0 and 7.0) will be automaticlly recognized 15 | * @n exitph -> save the calibrated parameters and exit from PH calibration mode 16 | * 17 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 18 | * @license The MIT License (MIT) 19 | * @author [Jiawei Zhang](jiawei.zhang@dfrobot.com) 20 | * @version V1.0 21 | * @date 2018-11-06 22 | * @url https://github.com/DFRobot/DFRobot_PH 23 | */ 24 | 25 | #include "DFRobot_PH.h" 26 | #include "DFRobot_EC.h" 27 | #include 28 | 29 | #define PH_PIN A1 30 | #define EC_PIN A2 31 | float voltagePH,voltageEC,phValue,ecValue,temperature = 25; 32 | DFRobot_PH ph; 33 | DFRobot_EC ec; 34 | 35 | void setup() 36 | { 37 | Serial.begin(115200); 38 | ph.begin(); 39 | ec.begin(); 40 | } 41 | 42 | void loop() 43 | { 44 | char cmd[10]; 45 | static unsigned long timepoint = millis(); 46 | if(millis()-timepoint>1000U){ //time interval: 1s 47 | timepoint = millis(); 48 | //temperature = readTemperature(); // read your temperature sensor to execute temperature compensation 49 | voltagePH = analogRead(PH_PIN)/1024.0*5000; // read the ph voltage 50 | phValue = ph.readPH(voltagePH,temperature); // convert voltage to pH with temperature compensation 51 | Serial.print("pH:"); 52 | Serial.print(phValue,2); 53 | voltageEC = analogRead(EC_PIN)/1024.0*5000; 54 | ecValue = ec.readEC(voltageEC,temperature); // convert voltage to EC with temperature compensation 55 | Serial.print(", EC:"); 56 | Serial.print(ecValue,2); 57 | Serial.println("ms/cm"); 58 | } 59 | if(readSerial(cmd)){ 60 | toUpperCase(cmd); 61 | if(strstr(cmd,"PH")){ 62 | ph.calibration(voltagePH,temperature,cmd); //PH calibration process by Serail CMD 63 | } 64 | if(strstr(cmd,"EC")){ 65 | ec.calibration(voltageEC,temperature,cmd); //EC calibration process by Serail CMD 66 | } 67 | } 68 | } 69 | 70 | int i = 0; 71 | bool readSerial(char result[]){ 72 | while(Serial.available() > 0){ 73 | char inChar = Serial.read(); 74 | if(inChar == '\n'){ 75 | result[i] = '\0'; 76 | Serial.flush(); 77 | i=0; 78 | return true; 79 | } 80 | if(inChar != '\r'){ 81 | result[i] = inChar; 82 | i++; 83 | } 84 | delay(1); 85 | } 86 | return false; 87 | } 88 | 89 | float readTemperature() 90 | { 91 | //add your code here to get the temperature from your temperature sensor 92 | } 93 | 94 | void toUpperCase(char* str) 95 | { 96 | if (str == NULL) return; 97 | for (int i = 0; str[i] != '\0'; i++) 98 | { 99 | str[i] = toupper(str[i]); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /python/raspberrypi/DFRobot_ADS1115.py: -------------------------------------------------------------------------------- 1 | '''! 2 | @file DFRobot_ADS1115.py 3 | @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 4 | @license The MIT License (MIT) 5 | @author [Jiawei Zhang](jiawei.zhang@dfrobot.com) 6 | @version V1.0 7 | @date 2018-11-06 8 | @url https://github.com/DFRobot/DFRobot_PH 9 | ''' 10 | 11 | import smbus 12 | import time 13 | 14 | # Get I2C bus 15 | bus = smbus.SMBus(1) 16 | 17 | # I2C address of the device 18 | ADS1115_IIC_ADDRESS0 = 0x48 19 | ADS1115_IIC_ADDRESS1 = 0x49 20 | 21 | # ADS1115 Register Map 22 | ADS1115_REG_POINTER_CONVERT = 0x00 # Conversion register 23 | ADS1115_REG_POINTER_CONFIG = 0x01 # Configuration register 24 | ADS1115_REG_POINTER_LOWTHRESH = 0x02 # Lo_thresh register 25 | ADS1115_REG_POINTER_HITHRESH = 0x03 # Hi_thresh register 26 | 27 | # ADS1115 Configuration Register 28 | ADS1115_REG_CONFIG_OS_NOEFFECT = 0x00 # No effect 29 | ADS1115_REG_CONFIG_OS_SINGLE = 0x80 # Begin a single conversion 30 | ADS1115_REG_CONFIG_MUX_DIFF_0_1 = 0x00 # Differential P = AIN0, N = AIN1 (default) 31 | ADS1115_REG_CONFIG_MUX_DIFF_0_3 = 0x10 # Differential P = AIN0, N = AIN3 32 | ADS1115_REG_CONFIG_MUX_DIFF_1_3 = 0x20 # Differential P = AIN1, N = AIN3 33 | ADS1115_REG_CONFIG_MUX_DIFF_2_3 = 0x30 # Differential P = AIN2, N = AIN3 34 | ADS1115_REG_CONFIG_MUX_SINGLE_0 = 0x40 # Single-ended P = AIN0, N = GND 35 | ADS1115_REG_CONFIG_MUX_SINGLE_1 = 0x50 # Single-ended P = AIN1, N = GND 36 | ADS1115_REG_CONFIG_MUX_SINGLE_2 = 0x60 # Single-ended P = AIN2, N = GND 37 | ADS1115_REG_CONFIG_MUX_SINGLE_3 = 0x70 # Single-ended P = AIN3, N = GND 38 | ADS1115_REG_CONFIG_PGA_6_144V = 0x00 # +/-6.144V range = Gain 2/3 39 | ADS1115_REG_CONFIG_PGA_4_096V = 0x02 # +/-4.096V range = Gain 1 40 | ADS1115_REG_CONFIG_PGA_2_048V = 0x04 # +/-2.048V range = Gain 2 (default) 41 | ADS1115_REG_CONFIG_PGA_1_024V = 0x06 # +/-1.024V range = Gain 4 42 | ADS1115_REG_CONFIG_PGA_0_512V = 0x08 # +/-0.512V range = Gain 8 43 | ADS1115_REG_CONFIG_PGA_0_256V = 0x0A # +/-0.256V range = Gain 16 44 | ADS1115_REG_CONFIG_MODE_CONTIN = 0x00 # Continuous conversion mode 45 | ADS1115_REG_CONFIG_MODE_SINGLE = 0x01 # Power-down single-shot mode (default) 46 | ADS1115_REG_CONFIG_DR_8SPS = 0x00 # 8 samples per second 47 | ADS1115_REG_CONFIG_DR_16SPS = 0x20 # 16 samples per second 48 | ADS1115_REG_CONFIG_DR_32SPS = 0x40 # 32 samples per second 49 | ADS1115_REG_CONFIG_DR_64SPS = 0x60 # 64 samples per second 50 | ADS1115_REG_CONFIG_DR_128SPS = 0x80 # 128 samples per second (default) 51 | ADS1115_REG_CONFIG_DR_250SPS = 0xA0 # 250 samples per second 52 | ADS1115_REG_CONFIG_DR_475SPS = 0xC0 # 475 samples per second 53 | ADS1115_REG_CONFIG_DR_860SPS = 0xE0 # 860 samples per second 54 | ADS1115_REG_CONFIG_CMODE_TRAD = 0x00 # Traditional comparator with hysteresis (default) 55 | ADS1115_REG_CONFIG_CMODE_WINDOW = 0x10 # Window comparator 56 | ADS1115_REG_CONFIG_CPOL_ACTVLOW = 0x00 # ALERT/RDY pin is low when active (default) 57 | ADS1115_REG_CONFIG_CPOL_ACTVHI = 0x08 # ALERT/RDY pin is high when active 58 | ADS1115_REG_CONFIG_CLAT_NONLAT = 0x00 # Non-latching comparator (default) 59 | ADS1115_REG_CONFIG_CLAT_LATCH = 0x04 # Latching comparator 60 | ADS1115_REG_CONFIG_CQUE_1CONV = 0x00 # Assert ALERT/RDY after one conversions 61 | ADS1115_REG_CONFIG_CQUE_2CONV = 0x01 # Assert ALERT/RDY after two conversions 62 | ADS1115_REG_CONFIG_CQUE_4CONV = 0x02 # Assert ALERT/RDY after four conversions 63 | ADS1115_REG_CONFIG_CQUE_NONE = 0x03 # Disable the comparator and put ALERT/RDY in high state (default) 64 | 65 | mygain=0x02 66 | coefficient=0.125 67 | addr_G=ADS1115_IIC_ADDRESS0 68 | class ADS1115(): 69 | def setGain(self,gain): 70 | global mygain 71 | global coefficient 72 | mygain=gain 73 | if mygain == ADS1115_REG_CONFIG_PGA_6_144V: 74 | coefficient = 0.1875 75 | elif mygain == ADS1115_REG_CONFIG_PGA_4_096V: 76 | coefficient = 0.125 77 | elif mygain == ADS1115_REG_CONFIG_PGA_2_048V: 78 | coefficient = 0.0625 79 | elif mygain == ADS1115_REG_CONFIG_PGA_1_024V: 80 | coefficient = 0.03125 81 | elif mygain == ADS1115_REG_CONFIG_PGA_0_512V: 82 | coefficient = 0.015625 83 | elif mygain == ADS1115_REG_CONFIG_PGA_0_256V: 84 | coefficient = 0.0078125 85 | else: 86 | coefficient = 0.125 87 | def setAddr_ADS1115(self,addr): 88 | global addr_G 89 | addr_G=addr 90 | def setChannel(self,channel): 91 | global mygain 92 | """Select the Channel user want to use from 0-3 93 | For Single-ended Output 94 | 0 : AINP = AIN0 and AINN = GND 95 | 1 : AINP = AIN1 and AINN = GND 96 | 2 : AINP = AIN2 and AINN = GND 97 | 3 : AINP = AIN3 and AINN = GND 98 | For Differential Output 99 | 0 : AINP = AIN0 and AINN = AIN1 100 | 1 : AINP = AIN0 and AINN = AIN3 101 | 2 : AINP = AIN1 and AINN = AIN3 102 | 3 : AINP = AIN2 and AINN = AIN3""" 103 | self.channel = channel 104 | while self.channel > 3 : 105 | self.channel = 0 106 | 107 | return self.channel 108 | 109 | def setSingle(self): 110 | global addr_G 111 | if self.channel == 0: 112 | CONFIG_REG = [ADS1115_REG_CONFIG_OS_SINGLE | ADS1115_REG_CONFIG_MUX_SINGLE_0 | mygain | ADS1115_REG_CONFIG_MODE_CONTIN, ADS1115_REG_CONFIG_DR_128SPS | ADS1115_REG_CONFIG_CQUE_NONE] 113 | elif self.channel == 1: 114 | CONFIG_REG = [ADS1115_REG_CONFIG_OS_SINGLE | ADS1115_REG_CONFIG_MUX_SINGLE_1 | mygain | ADS1115_REG_CONFIG_MODE_CONTIN, ADS1115_REG_CONFIG_DR_128SPS | ADS1115_REG_CONFIG_CQUE_NONE] 115 | elif self.channel == 2: 116 | CONFIG_REG = [ADS1115_REG_CONFIG_OS_SINGLE | ADS1115_REG_CONFIG_MUX_SINGLE_2 | mygain | ADS1115_REG_CONFIG_MODE_CONTIN, ADS1115_REG_CONFIG_DR_128SPS | ADS1115_REG_CONFIG_CQUE_NONE] 117 | elif self.channel == 3: 118 | CONFIG_REG = [ADS1115_REG_CONFIG_OS_SINGLE | ADS1115_REG_CONFIG_MUX_SINGLE_3 | mygain | ADS1115_REG_CONFIG_MODE_CONTIN, ADS1115_REG_CONFIG_DR_128SPS | ADS1115_REG_CONFIG_CQUE_NONE] 119 | 120 | bus.write_i2c_block_data(addr_G, ADS1115_REG_POINTER_CONFIG, CONFIG_REG) 121 | 122 | def setDifferential(self): 123 | global addr_G 124 | if self.channel == 0: 125 | CONFIG_REG = [ADS1115_REG_CONFIG_OS_SINGLE | ADS1115_REG_CONFIG_MUX_DIFF_0_1 | mygain | ADS1115_REG_CONFIG_MODE_CONTIN, ADS1115_REG_CONFIG_DR_128SPS | ADS1115_REG_CONFIG_CQUE_NONE] 126 | elif self.channel == 1: 127 | CONFIG_REG = [ADS1115_REG_CONFIG_OS_SINGLE | ADS1115_REG_CONFIG_MUX_DIFF_0_3 | mygain | ADS1115_REG_CONFIG_MODE_CONTIN, ADS1115_REG_CONFIG_DR_128SPS | ADS1115_REG_CONFIG_CQUE_NONE] 128 | elif self.channel == 2: 129 | CONFIG_REG = [ADS1115_REG_CONFIG_OS_SINGLE | ADS1115_REG_CONFIG_MUX_DIFF_1_3 | mygain | ADS1115_REG_CONFIG_MODE_CONTIN, ADS1115_REG_CONFIG_DR_128SPS | ADS1115_REG_CONFIG_CQUE_NONE] 130 | elif self.channel == 3: 131 | CONFIG_REG = [ADS1115_REG_CONFIG_OS_SINGLE | ADS1115_REG_CONFIG_MUX_DIFF_2_3 | mygain | ADS1115_REG_CONFIG_MODE_CONTIN, ADS1115_REG_CONFIG_DR_128SPS | ADS1115_REG_CONFIG_CQUE_NONE] 132 | 133 | bus.write_i2c_block_data(addr_G, ADS1115_REG_POINTER_CONFIG, CONFIG_REG) 134 | 135 | def readValue(self): 136 | """Read data back from ADS1115_REG_POINTER_CONVERT(0x00), 2 bytes 137 | raw_adc MSB, raw_adc LSB""" 138 | global coefficient 139 | global addr_G 140 | data = bus.read_i2c_block_data(addr_G, ADS1115_REG_POINTER_CONVERT, 2) 141 | 142 | # Convert the data 143 | raw_adc = data[0] * 256 + data[1] 144 | 145 | if raw_adc > 32767: 146 | raw_adc -= 65535 147 | raw_adc = int(float(raw_adc)*coefficient) 148 | return {'r' : raw_adc} 149 | 150 | def readVoltage(self,channel): 151 | self.setChannel(channel) 152 | self.setSingle() 153 | time.sleep(0.1) 154 | return self.readValue() 155 | 156 | def ComparatorVoltage(self,channel): 157 | self.setChannel(channel) 158 | self.setDifferential() 159 | time.sleep(0.1) 160 | return self.readValue() -------------------------------------------------------------------------------- /DFRobot_PH.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file DFRobot_PH.cpp 3 | * @brief Arduino library for Gravity: Analog pH Sensor / Meter Kit V2, SKU: SEN0161-V2 4 | * 5 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 6 | * @license The MIT License (MIT) 7 | * @author [Jiawei Zhang](jiawei.zhang@dfrobot.com) 8 | * @version V1.0 9 | * @date 2018-11-06 10 | * @url https://github.com/DFRobot/DFRobot_PH 11 | */ 12 | 13 | 14 | #if ARDUINO >= 100 15 | #include "Arduino.h" 16 | #else 17 | #include "WProgram.h" 18 | #endif 19 | 20 | #include "DFRobot_PH.h" 21 | #include 22 | 23 | #define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp[i]);} 24 | #define EEPROM_read(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp[i]=EEPROM.read(address+i);} 25 | 26 | #define PHVALUEADDR 0x00 //the start address of the pH calibration parameters stored in the EEPROM 27 | 28 | char* DFRobot_PH::strupr(char* str) { 29 | if (str == NULL) return NULL; 30 | char *ptr = str; 31 | while (*ptr != ' ') { 32 | *ptr = toupper((unsigned char)*ptr); 33 | ptr++; 34 | } 35 | return str; 36 | } 37 | 38 | DFRobot_PH::DFRobot_PH() 39 | { 40 | this->_temperature = 25.0; 41 | this->_phValue = 7.0; 42 | this->_acidVoltage = 2032.44; //buffer solution 4.0 at 25C 43 | this->_neutralVoltage = 1500.0; //buffer solution 7.0 at 25C 44 | this->_voltage = 1500.0; 45 | } 46 | 47 | DFRobot_PH::~DFRobot_PH() 48 | { 49 | 50 | } 51 | 52 | void DFRobot_PH::begin() 53 | { 54 | EEPROM_read(PHVALUEADDR, this->_neutralVoltage); //load the neutral (pH = 7.0)voltage of the pH board from the EEPROM 55 | //Serial.print("_neutralVoltage:"); 56 | //Serial.println(this->_neutralVoltage); 57 | if(EEPROM.read(PHVALUEADDR)==0xFF && EEPROM.read(PHVALUEADDR+1)==0xFF && EEPROM.read(PHVALUEADDR+2)==0xFF && EEPROM.read(PHVALUEADDR+3)==0xFF){ 58 | this->_neutralVoltage = 1500.0; // new EEPROM, write typical voltage 59 | EEPROM_write(PHVALUEADDR, this->_neutralVoltage); 60 | } 61 | EEPROM_read(PHVALUEADDR+4, this->_acidVoltage);//load the acid (pH = 4.0) voltage of the pH board from the EEPROM 62 | //Serial.print("_acidVoltage:"); 63 | //Serial.println(this->_acidVoltage); 64 | if(EEPROM.read(PHVALUEADDR+4)==0xFF && EEPROM.read(PHVALUEADDR+5)==0xFF && EEPROM.read(PHVALUEADDR+6)==0xFF && EEPROM.read(PHVALUEADDR+7)==0xFF){ 65 | this->_acidVoltage = 2032.44; // new EEPROM, write typical voltage 66 | EEPROM_write(PHVALUEADDR+4, this->_acidVoltage); 67 | } 68 | } 69 | 70 | float DFRobot_PH::readPH(float voltage, float temperature) 71 | { 72 | float slope = (7.0-4.0)/((this->_neutralVoltage-1500.0)/3.0 - (this->_acidVoltage-1500.0)/3.0); // two point: (_neutralVoltage,7.0),(_acidVoltage,4.0) 73 | float intercept = 7.0 - slope*(this->_neutralVoltage-1500.0)/3.0; 74 | //Serial.print("slope:"); 75 | //Serial.print(slope); 76 | //Serial.print(",intercept:"); 77 | //Serial.println(intercept); 78 | this->_phValue = slope*(voltage-1500.0)/3.0+intercept; //y = k*x + b 79 | return _phValue; 80 | } 81 | 82 | 83 | void DFRobot_PH::calibration(float voltage, float temperature,char* cmd) 84 | { 85 | this->_voltage = voltage; 86 | this->_temperature = temperature; 87 | String sCmd = String(cmd); 88 | sCmd.toUpperCase(); 89 | phCalibration(cmdParse(sCmd.c_str())); // if received Serial CMD from the serial monitor, enter into the calibration mode 90 | } 91 | 92 | void DFRobot_PH::calibration(float voltage, float temperature) 93 | { 94 | this->_voltage = voltage; 95 | this->_temperature = temperature; 96 | if(cmdSerialDataAvailable() > 0){ 97 | phCalibration(cmdParse()); // if received Serial CMD from the serial monitor, enter into the calibration mode 98 | } 99 | } 100 | 101 | boolean DFRobot_PH::cmdSerialDataAvailable() 102 | { 103 | char cmdReceivedChar; 104 | static unsigned long cmdReceivedTimeOut = millis(); 105 | while(Serial.available()>0){ 106 | if(millis() - cmdReceivedTimeOut > 500U){ 107 | this->_cmdReceivedBufferIndex = 0; 108 | memset(this->_cmdReceivedBuffer,0,(ReceivedBufferLength)); 109 | } 110 | cmdReceivedTimeOut = millis(); 111 | cmdReceivedChar = Serial.read(); 112 | if (cmdReceivedChar == '\n' || this->_cmdReceivedBufferIndex==ReceivedBufferLength-1){ 113 | this->_cmdReceivedBufferIndex = 0; 114 | strupr(this->_cmdReceivedBuffer); 115 | return true; 116 | }else{ 117 | this->_cmdReceivedBuffer[this->_cmdReceivedBufferIndex] = cmdReceivedChar; 118 | this->_cmdReceivedBufferIndex++; 119 | } 120 | } 121 | return false; 122 | } 123 | 124 | byte DFRobot_PH::cmdParse(const char* cmd) 125 | { 126 | byte modeIndex = 0; 127 | if(strstr(cmd, "ENTERPH") != NULL){ 128 | modeIndex = 1; 129 | }else if(strstr(cmd, "EXITPH") != NULL){ 130 | modeIndex = 3; 131 | }else if(strstr(cmd, "CALPH") != NULL){ 132 | modeIndex = 2; 133 | } 134 | return modeIndex; 135 | } 136 | 137 | byte DFRobot_PH::cmdParse() 138 | { 139 | byte modeIndex = 0; 140 | if(strstr(this->_cmdReceivedBuffer, "ENTERPH") != NULL){ 141 | modeIndex = 1; 142 | }else if(strstr(this->_cmdReceivedBuffer, "EXITPH") != NULL){ 143 | modeIndex = 3; 144 | }else if(strstr(this->_cmdReceivedBuffer, "CALPH") != NULL){ 145 | modeIndex = 2; 146 | } 147 | return modeIndex; 148 | } 149 | 150 | void DFRobot_PH::phCalibration(byte mode) 151 | { 152 | char *receivedBufferPtr; 153 | static boolean phCalibrationFinish = 0; 154 | static boolean enterCalibrationFlag = 0; 155 | switch(mode){ 156 | case 0: 157 | if(enterCalibrationFlag){ 158 | Serial.println(F(">>>Command Error<<<")); 159 | } 160 | break; 161 | 162 | case 1: 163 | enterCalibrationFlag = 1; 164 | phCalibrationFinish = 0; 165 | Serial.println(); 166 | Serial.println(F(">>>Enter PH Calibration Mode<<<")); 167 | Serial.println(F(">>>Please put the probe into the 4.0 or 7.0 standard buffer solution<<<")); 168 | Serial.println(); 169 | break; 170 | 171 | case 2: 172 | if(enterCalibrationFlag){ 173 | if((this->_voltage>1322)&&(this->_voltage<1678)){ // buffer solution:7.0{ 174 | Serial.println(); 175 | Serial.print(F(">>>Buffer Solution:7.0")); 176 | this->_neutralVoltage = this->_voltage; 177 | Serial.println(F(",Send EXITPH to Save and Exit<<<")); 178 | Serial.println(); 179 | phCalibrationFinish = 1; 180 | }else if((this->_voltage>1854)&&(this->_voltage<2210)){ //buffer solution:4.0 181 | Serial.println(); 182 | Serial.print(F(">>>Buffer Solution:4.0")); 183 | this->_acidVoltage = this->_voltage; 184 | Serial.println(F(",Send EXITPH to Save and Exit<<<")); 185 | Serial.println(); 186 | phCalibrationFinish = 1; 187 | }else{ 188 | Serial.println(); 189 | Serial.print(F(">>>Buffer Solution Error Try Again<<<")); 190 | Serial.println(); // not buffer solution or faulty operation 191 | phCalibrationFinish = 0; 192 | } 193 | } 194 | break; 195 | 196 | case 3: 197 | if(enterCalibrationFlag){ 198 | Serial.println(); 199 | if(phCalibrationFinish){ 200 | if((this->_voltage>1322)&&(this->_voltage<1678)){ 201 | 202 | EEPROM_write(PHVALUEADDR, this->_neutralVoltage); 203 | }else if((this->_voltage>1854)&&(this->_voltage<2210)){ 204 | EEPROM_write(PHVALUEADDR+4, this->_acidVoltage); 205 | } 206 | Serial.print(F(">>>Calibration Successful")); 207 | }else{ 208 | Serial.print(F(">>>Calibration Failed")); 209 | } 210 | Serial.println(F(",Exit PH Calibration Mode<<<")); 211 | Serial.println(); 212 | phCalibrationFinish = 0; 213 | enterCalibrationFlag = 0; 214 | } 215 | break; 216 | } 217 | } 218 | --------------------------------------------------------------------------------