1、硬件的实现:

(1)esp01s

           esp32是一款自带WIFI和BLE的模组,可以通过mircoypython的方式对其进行开发,引脚资源做一般的项目也是足够用了。网上基本有卖,价格大概在20元左右,建议入手安信可的质量可能会比较好一点。

ESP32 TTS 语音播报 esp32语音控制_智能家居

(2)DHT11

           DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,内部由一个 8 位单片机控制一个电阻式感湿元件和一个 NTC 测温元件,DHT11 采用单总线协议。 既能检测温度又能检测湿度,只需要将 DATA引脚连接单片机的一个 I/O 即可,其中的协议和数据格式以及时序原理在这里就不仔细提了,有兴趣了解更多的可自行百度。

ESP32 TTS 语音播报 esp32语音控制_智能家居_02

(3)继电器

           继电器的作用简单点理解就是用小信号去控制大负载,因为一些负载例如水泵、门锁模块等都需要较大的功率,而单片机的引脚那微弱的电流是不足以驱动这些模块的正常运转的。这时候就需要用到继电器,将单片机IO引脚接到信号触发端、电源正负极分别接入DC+、DC-、负载的正负极接入COM和NO端即可实现弱电流驱动大电流负载的开关。

ESP32 TTS 语音播报 esp32语音控制_python_03

(4)水位传感器

           水位传感器是一款简单易用的水位/水滴识别检测传感器,其是通过具有一系列的暴露的平行导线线迹测量其水滴/水量大小从而判断水位。轻松完成水量到模拟信号的转换,达到水位报警的功效。

ESP32 TTS 语音播报 esp32语音控制_mqtt_04

(5)12v门锁模块

           通过设置引脚的高低电平通过继电器来控制门锁模块的闭合,门锁模块的电压需要12V,因为只是个简单的演示,所以有需要的也可以用更好的模块。

ESP32 TTS 语音播报 esp32语音控制_mqtt_05

(6)水泵模块

           使用微型水泵模拟鱼缸中换水的实现

ESP32 TTS 语音播报 esp32语音控制_mqtt_06

(7)其他模块

           还需要用到的模块可能就是LED模块、和风扇模块等模块,其实加入其他模块使用上也是一样的。因为我买的风扇模块自带放大电路,就不需要用到继电器了,直接将电源的DC+和DC-与风扇的VCC、GND相连、单片机IO脚与其S进行相连就可以正常驱动了。

2.编程实现

           IDE:uPyCraft_v1.1。
           esp32 mircopython固件:esp32-micropython
           连接esp32的电脑驱动:CP210x_Windows10_Drivers

(1)刷入esp32-mircopython固件

           1)将esp32通过数据线进行连接,在uPyCraft中连接识别到的串口4(每台计算机不一定一样,看自身情况)。

ESP32 TTS 语音播报 esp32语音控制_mqtt_07


(2)点击BurnFirmware 后选择burn_addr为0x1000,erase_flash为yes、选择好串口最后选择下载好的mircopython固件刷入即可。

ESP32 TTS 语音播报 esp32语音控制_ESP32 TTS 语音播报_08

ESP32 TTS 语音播报 esp32语音控制_单片机_09


(3)代码的实现

  1)导入需要用到的包

import network  
import time
import machine
import _thread
from machine import UART
from umqtt  import simple as mqtt
import dht
from machine import Pin
from machine import ADC

  2)定义需要用到的变量
    wlan是连接网络的一个对象、client是MQTT连接MQTT代理服务器的一个对象、ssid、password分别是你的路由器名称和密码、server是我阿里云服务器的外网IP地址,因为我在阿里云搭建好了mosquitto(MQTT代理服务器),clientid是客户端标识符,用来区别不同设备的接入,所以安卓端或者是其他调试助手啥的不能跟esp32的clientid相同。
       

wlan=None 
client=None
ssid='TP-LINK_0138'
password='88807570'
server='101.200.***.***'
clientid='lwhesp32'

3)引脚设置
    lock是python多线程新的锁对象,因为温湿度变量会会出现在读取线程没有使用完又被推送线程给访问的时候是一个临界资源所以需要用到多线程和线程锁对变量进行上锁解锁再给其他线程使用进行互斥的操作。

    实例化DHT11类并将引脚设置为pin4。DHT11测量并返回温湿度数据:dht.measure()、dht.temperature()、dht.humidity()。

    水位测量模块需要进行模拟信号转换为数字信号,adc.atten(db)设置衰减比,adc.width(bit)设置数据宽度。

    剩下的就是风扇引脚的设置,因为我的风扇有除VCC、GND外还有 INA,INB 俩个引脚,用来控制风扇的转动方向,其中一个给高电平一个给低电平就行。

lock = _thread.allocate_lock()
d = dht.DHT11(machine.Pin(4))
led=Pin(13,Pin.OUT)#外接LED
led1=Pin(2,Pin.OUT)#开发板LED
adc_pin = Pin(34)# 水位测量
adc = ADC(adc_pin)
adc.atten(ADC.ATTN_11DB)
adc.width(ADC.WIDTH_10BIT)

fan1=Pin(25,Pin.OUT)#风扇INA
fan2=Pin(26,Pin.OUT)#风扇INB
door=Pin(18,Pin.OUT)#
shuibeng=Pin(15,Pin.OUT)#

4)温湿度和水位深度获取
    获取DHT11和水位深度函数,通过lock.acquire()对message和value进行上锁操作。通过adc.read()获取水位深度,通过d.temperature()获取温度,d.humidity()获取湿度后在进行解锁操作给其他函数使用,如果捕获到异常则延时俩秒后进行重启操作。

def getmessage():
  global message
  global value
  try:
   while True:
    lock.acquire()
    time.sleep(5)
    d.measure()
    value = adc.read()
    message=("temp:{} hum:{} level:{}".format(d.temperature(),d.humidity(),value))
    lock.release()
  except:
    time.sleep(2)
    machine.reset()

5)网络连接

def ConnectWifi():
  global wlan
  wlan=network.WLAN(network.STA_IF)
  wlan.active(True)
  wlan.connect(ssid,password)
  while wlan.isconnected() == False:
    time.sleep(2)
  print('Connected to wifi successfully!')

def ConnectMqtt():
  global client
  client=mqtt.MQTTClient(clientid,server,port=3881,user='***',password='***')
  client.connect()

    将模块设置为sta模式(WIFI模块作为连接路由功能)
    通过ssid,password直接连接wifi
    通过clientid server IP地址 端口 用户名和密码实现MQTT的连接
6)对软件层消息的订阅
    接收到软件层消息后对消息进行处理然后进行相应的处理

def getrecmsg(topic,payload):
   global recmsg
   print('msg: {}'.format(payload))
   recmsg=payload
   if(recmsg==b'0101'):
    led.value(1) 
   if(recmsg==b'0100'):
    led.value(0)
   if(recmsg==b'0201'): 
    led1.value(1) 
   if(recmsg==b'0200'):
    led1.value(0)   
   if(recmsg==b'0501'):
    fan1.value(1) 
    fan2.value(0) 
   if(recmsg==b'0500'):
    fan1.value(0)
    fan2.value(0) 
   if(recmsg==b'0301'):
    door.value(1) 
   if(recmsg==b'0300'):
    door.value(0)
   if(recmsg==b'0401'):
    shuibeng.value(1) 
   if(recmsg==b'0400'):
    shuibeng.value(0)

7)等待消息缓冲
    等待服务器消息。订阅消息将通过set_callback()传递给回调集,任何其他消息都将在内部处理。

def receiveMessage():
  try:
    while True:
      client.wait_msg()
  except:
    time.sleep(2)
    machine.reset()

8)消息的发布
    通过publish()第一个参数为主题、第二个为数据将温湿度和水位高度推送到软件层,软件层订阅相同的主题即可接收。

def threadPublish():
  try:
    while True:
      lock.acquire()
      client.publish('liwenhui',message)
      time.sleep(10)
      lock.release()
  except:
    time.sleep(2)
    machine.reset()

9)

def main():  
  ConnectWifi()  
  try:
    ConnectMqtt()
    client.set_callback(getrecmsg)
    client.subscribe('liwenhui')
  except:
    time.sleep(2)
    machine.reset()
    
  _thread.start_new_thread(getuartmessage,())
  _thread.start_new_thread(receiveMessage,())
  _thread.start_new_thread(threadPublish,())

main()

完整代码

import network
import time
import machine
import _thread
from machine import UART
from umqtt  import simple as mqtt
import dht
from machine import Pin
from machine import ADC


wlan=None 
client=None
ssid='替换'
password='替换'
server='替换'
clientid='lwhesp32'
lock = _thread.allocate_lock()
d = dht.DHT11(machine.Pin(4))
led=Pin(13,Pin.OUT)#外接LED
led1=Pin(2,Pin.OUT)#开发板LED
adc_pin = Pin(34)# 水位测量
adc = ADC(adc_pin)
adc.atten(ADC.ATTN_11DB)
adc.width(ADC.WIDTH_10BIT)

fan1=Pin(25,Pin.OUT)#风扇INA
fan2=Pin(26,Pin.OUT)#风扇INB
door=Pin(18,Pin.OUT)#
shuibeng=Pin(15,Pin.OUT)#

def getmessage():
  global message
  global value
  try:
   while True:
    lock.acquire()
    time.sleep(5)
    d.measure()
    value = adc.read()
    message=("temp:{} hum:{} level:{}".format(d.temperature(),d.humidity(),value))
    lock.release()
  except:
    time.sleep(2)
    machine.reset()
def ConnectWifi():
  global wlan
  wlan=network.WLAN(network.STA_IF)
  wlan.active(True)
  wlan.connect(ssid,password)
  while wlan.isconnected() == False:
    time.sleep(2)
  print('Connected to wifi successfully!')

def ConnectMqtt():
  global client
  client=mqtt.MQTTClient(clientid,server,port=3881,user='替换',password='替换')
  client.connect()
  
def getrecmsg(topic,payload):
   global recmsg
   print('msg: {}'.format(payload))
   recmsg=payload
   if(recmsg==b'0101'):
    led.value(1) 
   if(recmsg==b'0100'):
    led.value(0)
   if(recmsg==b'0201'): 
    led1.value(1) 
   if(recmsg==b'0200'):
    led1.value(0)   
   if(recmsg==b'0501'):
    fan1.value(1) 
    fan2.value(0) 
   if(recmsg==b'0500'):
    fan1.value(0)
    fan2.value(0) 
   if(recmsg==b'0301'):
    door.value(1) 
   if(recmsg==b'0300'):
    door.value(0)
   if(recmsg==b'0401'):
    shuibeng.value(1) 
   if(recmsg==b'0400'):
    shuibeng.value(0)   
    
def receiveMessage():
  try:
    while True:
      client.wait_msg()
  except:
    time.sleep(2)
    machine.reset()
    
    
def threadPublish():
  try:
    while True:
      lock.acquire()
      client.publish('liwenhui',message)
      time.sleep(10)
      lock.release()
  except:
    time.sleep(2)
    machine.reset()
   
def main():  
  ConnectWifi()  
  try:
    ConnectMqtt()
    client.set_callback(getrecmsg)
    client.subscribe('liwenhui')
  except:
    time.sleep(2)
    machine.reset()
    
  _thread.start_new_thread(getuartmessage,())
  _thread.start_new_thread(receiveMessage,())
  _thread.start_new_thread(threadPublish,())

main()

结尾

       最后就可以通过MQTT调试助手、通信猫、mqtt-fx等其他工具去测试系统是否正常,阿里云的搭建在我的博客中有些,不会搭建的也可以去看看。