Funpack2-3——使用ESP32-E监测水质
Funpack2-3 ESP32-E TDS Arduino DS18S20 温度 百度物联网 水质
标签
Funpack活动
aramy
更新2023-01-03
769

硬件介绍:FireBeetle ESP32-E是一款基于ESP-WROOM-32E双核芯片的主控板,它专为IoT设计。它支持WIFI和蓝牙双模通信并具有体积小巧、超低功耗、板载充电电路、接口易用等特性。可灵活的用于家庭物联网改装、工业物联网改装、可穿戴设备等等。通过和IFTTT等物联网平台的连接,你可轻松制作出你独有的特色物联网智能家居系统。FireBeetle ESP32-E深度支持ArduinoIDE编程,并且即将支持Scratch图形化编程及MicroPython编程。
FpAFEjwbm37pbdE2EqJBlhx3cxTG
额外选了选了两个传感器。一个是TDS传感器,一个是DS18B20温度传感器。FireBeetle ESP32-E的板子设计上使用了排母,连接传感器会遇到点困难,需要把传感器导线接口设计成排针的方式才好连接。

任务选择:我选择了任务1,水质监控系统.用FireBeetle ESP32-E开发板作为控制单元,观察养殖水质参数(温度/浊度/tds/pH值/电位/溶解氧中两项指标以上)的变化,并能把数据上传到IoT网站上,可实时动态显示监测水质的变化情况。监控水体的tds和温度两项指标。物联网使用的是百度免费的物联网。
下位机编程使用Arduino,DFROBOT官网提供了相当丰富的例程,可以直接做参考。开发工具选择了VScode,这次摈弃了Arduino的官方工具,官方的Arduino编译工具,编译速度实在是太慢了。使用VScode简直是打开了新世界的大门。
上位机使用python,图形界面使用了Qt。工具使用的是pycharm。

任务实现:首先实现传感器的读取。DS18B20是一个单总线数字温度计,温度测量范围-55℃~+125℃。之前入门单片机时就玩过这款传感器,还自己DIY了一个DS18B20的温度探头,但是防水没能处理好,坏了。这次新买了个不锈钢探头的DS18B20。这里要注意FireBeetle ESP32-E的GPIO口没有做上拉,IIC的管脚也是没上拉。所以自己找了个10K欧的电阻将DS18B20的DQ脚做了个上拉。

// 读取DS18B20 的温度
float getTemp()
{
  // returns the temperature from one DS18S20 in DEG Celsius
  byte data[12];
  byte addr[8];
  if (!ds.search(addr))
  {
    // no more sensors on chain, reset search
    ds.reset_search();
    return -1000;
  }
  if (OneWire::crc8(addr, 7) != addr[7])
  {
    Serial.println("CRC is not valid!");
    return -1000;
  }
  if (addr[0] != 0x10 && addr[0] != 0x28)
  {
    Serial.print("Device is not recognized");
    return -1000;
  }
  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1); // start conversion, with parasite power on at the end
  delayMicroseconds(200);

  byte present = ds.reset();
  ds.select(addr);
  ds.write(0xBE); // Read Scratchpad

  for (int i = 0; i < 9; i++)
  { // we need 9 bytes
    data[i] = ds.read();
  }

  ds.reset_search();

  byte MSB = data[1];
  byte LSB = data[0];

  float tempRead = ((MSB << 8) | LSB); // using two's compliment
  float TemperatureSum = tempRead / 16;

  return TemperatureSum;
}


再者TDS传感器。第一次使用TDS传感器,参考DFROBOT官网的程序,自己理解这个TDS是个模拟传感器,输出的是个电压值。使用esp32的AD去读取电压值,读取多次(30次)取平均值,然后通过公式转换成TDS的数值。看代码TDS是和温度有关,感觉和水的导电率也有关系。

for (copyIndex = 0; copyIndex < SCOUNT; copyIndex++)
      analogBufferTemp[copyIndex] = analogBuffer[copyIndex];
    averageVoltage = getMedianNum(analogBufferTemp, SCOUNT) * (float)VREF / 1024.0;                                                                                                  // read the analog value more stable by the median filtering algorithm, and convert to voltage value
    float compensationCoefficient = 1.0 + 0.02 * (temperature - 25.0);                                                                                                               // temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.02*(fTP-25.0));
    float compensationVolatge = averageVoltage / compensationCoefficient;                                                                                                            // temperature compensation
    tdsValue = (133.42 * compensationVolatge * compensationVolatge * compensationVolatge - 255.86 * compensationVolatge * compensationVolatge + 857.39 * compensationVolatge) * 0.5; // convert voltage value to tds value

收集到传感器数据后就是要解决数据传输的问题了。这里使用了物联网的方式将数据上送到互联网,然后就可以在任何地方查看数据了。物联网部分官网的例程提供的是阿里云的物联网,我这里选择的是百度的物联网,操作都大同小异。
Fm-DK_my0PWqEXgK5p80NCZxFapX

//连接wifi
void connectWiFi()
{
  Serial.print("Connecting to ");
  Serial.println(WIFI_SSID);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected");
  Serial.print("IP Adderss: ");
  Serial.println(WiFi.localIP());
}

//这里就开始进行MQTT的回调
void callback(char *topic, byte *payload, unsigned int length)
{
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  Serial.println();
  Serial.println(String(length));
  for (int i = 0; i < length; i++)
  {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

void reconnect() //为防止MQTT服务器下线,当断开服务时尝试重新连接/
{
  while (!mqttClient.connected())
  {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (mqttClient.connect(client_id, mqtt_username, mqtt_password))
    {
      Serial.println("connected");
      // mqttClient.publish("outTopic", "hello world");
      if (mqttClient.subscribe(subTopic, 1))
      {
        Serial.println("subscribe success");
      }
      else
      {
        Serial.println("subscribe fail");
      }
    }
    else
    {
      Serial.print("failed, rc=");
      Serial.print(mqttClient.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

数据展示。上位机连接到物联网订阅数据,当有数据产生时,就在电脑屏幕上展示出来。上位机还是比较简单。 
Froh12fe6UU-lZYXrco6SdO5vp-r

import json
import random
import sys
import time

from PyQt5 import QtWidgets
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QPainter
from PyQt5.QtWidgets import QWidget
from QTUI.formmqtt import Ui_FormMqtt
from unit.data_deal import saveFile
from unit.mqtt_subprocess import GetMqttMsg


class MainWidget(QWidget):
    def __init__(self, parent=None):
        super(MainWidget, self).__init__(parent)
        self.ui = Ui_FormMqtt()
        self.ui.setupUi(self)

        #----------------------------
        #开启接收mqtt的线程
        self.getMqttMsgThread=GetMqttMsg()
        self.getMqttMsgThread.sinGetNewMsg.connect(self.reveiveMqttMsg)
        self.getMqttMsgThread.start()


    #时间中断
    def updateTime(self):
        print("时间中断")
        self.charview.show()
        self.drawPic()
        

    def reveiveMqttMsg(self,msg):
        print(msg)
        self.dealMsg(msg)
        self.ui.textBrowserMsg.append(time.strftime("%H/%M/%S", time.localtime())+" : "+msg)

    #处理接收到的消息
    def dealMsg(self,jsonmsg):
        #保存到文件
        saveFile(jsonmsg)
        #分解消息体
        objdict = json.loads(jsonmsg)
        print(objdict)
        print(objdict.get('temp'))
        if objdict.get('temp')!=None and objdict.get('tds')!=None :
            self.ui.lineEditTemp.setText(str(objdict.get('temp')))
            self.ui.lineEditTDS.setText((str(objdict.get('tds'))))



if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    appWindow = MainWidget()
    appWindow.show()
    sys.exit(app.exec_())


这里温度使用的是摄氏度。TDS使用的是ppm溶液百万分率浓度单位。指100万毫升溶液中含有溶质的毫升数或表明100万克溶液中含有溶质克数。自来水我测量的值是294左右,办公室饮水机过滤后的水测量的居然是0,很让我吃惊。

心得体会:感谢funpack带来的这期活动,ESP32开发板功能强大,价格低廉,真是DIY的好伙伴。

 

附件下载
water.zip
上位机.zip
团队介绍
瞎折腾小能手
团队成员
aramy
单片机业余爱好者,瞎捣鼓小能手。
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号