1947浏览
查看: 1947|回复: 0

[ESP8266/ESP32] Beetle ESP32 C3 物联网亮板载灯

[复制链接]
上一次我们对Beetle ESP32 C3进行了亮灯操作,初试尝试了对该主控板进行MicroPython编程。
这次我们将在原来点灯的基础上,增加一点点难度,利用物联网控制板载LED灯的开关。
Beetle ESP32 C3 物联网亮板载灯图1

通过上图我们发现,行空板作为物联网服务器,发送开关灯指令,然后将指令通过无线网络发送给ESP32 C3,从而实现板载灯的开或关。

一、物联网服务器的选择
本例采用行空板自带的Siot服务器,因上次测试云雀气象仪,已经将行空板上的Siot版本升级成V2,当然也可以利用一台电脑作为Siot服务器。此外,由于已经使用Siot V2,因此适于用MicroPython的siot.py文件可能会出现一些差异。

行空板通过USB连接电脑,在电脑上打开浏览器,地址栏输入10.1.2.3,然后单击左侧的**应用开关**,在右侧确定将SIoT服务打开,然后单击**打开页面**按钮进入SIoT服务器管理界面。Beetle ESP32 C3 物联网亮板载灯图2

输入账号和密码,默认是siot和dfrobot,单击登录。
Beetle ESP32 C3 物联网亮板载灯图3

然后创建一个名为**c3**的主题,设备名称为siot,注意在编程时,需要输入"**siot/c3**"
Beetle ESP32 C3 物联网亮板载灯图4

单击**查看详情**进入该主题,通过输入信息字符串,勾选**保存到数据库**,然后单击**发送**按钮将消息发送。后面我们可以通过发送1来点灯,发送0实现灭灯。
Beetle ESP32 C3 物联网亮板载灯图5

二、无线AP
由于ESP32对无线和蓝牙的支持,因此本例通过无线网络进行物联网数据交换,我们可以直接使用家庭无线网络,将行空板(所在电脑)与Beetle ESP32 C3接入同一网络,如没有网络环境,也可以打开手机热点,将行空板和ESP32 C3连上手机热点。
1. 行空板连接无线网络
行空板通过USB连接电脑,在电脑上打开浏览器,地址栏输入10.1.2.3,然后单击左侧的**网络设置**,在右侧通过选择无线网络的名称,并输入密码进行连接,连接成功后,WiFi状态会显示相关信息,需要将IP地址记下来,供后面使用。
Beetle ESP32 C3 物联网亮板载灯图6

2. ESP32 C3连接无线网络
MicroPython中默认提供了network模块用于无线网络的通信,我们Python程序中定义一个函数用于无线网络连接。
  1. def WIFIconnect():
  2.     import network
  3.     ssid='Mi10'  #无线网络名称
  4.     password='********'  #填写自己的无线网络密码
  5.     station=network.WLAN(network.STA_IF)
  6.     if station.isconnected() == True:
  7.         print("WiFi already connected")
  8.         print(station.ifconfig())  #这里显示一下ESP C3连接无线网络后的动态IP地址
  9.         return
  10.     station.active(True)
  11.     station.connect(ssid,password)
  12.     while station.isconnected() == False:
  13.         pass
  14.     print("Connection successful")
  15.     print(station.ifconfig())
复制代码


三、ESP32 C3上编程
使用Thonny为ESP32 C3编写程序,用于接收SIoT服务器发送过来的消息,并根据消息实现开灯和关灯。要使ESP32 C3能使用SIoT,我们需要将soit.py库文件上传到ESP32 C3上去。
在Thonny中新建文件,并将下面的代码复制到Thonny中,保存时选择**保存到MicroPython设备**。
Beetle ESP32 C3 物联网亮板载灯图7
  1. # file siot.py
  2. # brief         download into mpython and run the demo
  3. # Copyright     Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
  4. # licence       The MIT License (MIT)
  5. # author        [LuoYufeng](yufeng.luo@dfrobot.com)
  6. # version       V1.0
  7. # date          2019-10-8
  8. '''
  9. import usocket as socket
  10. import ustruct as struct
  11. from machine import Timer
  12. #from ubinascii import hexlify
  13. class MQTTException(Exception):
  14.     pass
  15. tim = None
  16. _sock = None
  17. _pid = 0
  18. _cb = None
  19. lw_topic = None
  20. lw_msg = None
  21. lw_qos = 0
  22. lw_retain = False
  23. def init(client_id, server, port=0, user=None, password=None, keepalive=0,ssl=False, ssl_params={}):
  24.   global _client_id, _addr, _ssl, _ssl_params, _user, _pswd, _keepalive
  25.   if port == 0:
  26.     port = 8883 if ssl else 1883
  27.   _client_id = client_id
  28.   _addr = socket.getaddrinfo(server, port)[0][-1]
  29.   _ssl = ssl
  30.   _ssl_params = ssl_params
  31.   _user = user
  32.   _pswd = password
  33.   _keepalive = keepalive
  34. def _send_str(s):
  35.   global _sock
  36.   _sock.write(struct.pack("!H", len(s)))
  37.   _sock.write(s)
  38. def _recv_len():
  39.   global _sock
  40.   n = 0
  41.   sh = 0
  42.   while 1:
  43.     b = _sock.read(1)[0]
  44.     n |= (b & 0x7f) << sh
  45.     if not b & 0x80:
  46.       return n
  47.     sh += 7
  48.    
  49. def set_callback(f):
  50.   global _cb
  51.   _cb = f
  52. def subscribe(topic, callback):
  53.   global _cb
  54.   _cb = callback
  55.   getsubscribe(topic)
  56. def loop():
  57.   global tim
  58.   if tim !=None:
  59.     tim.deinit()
  60.   tim = Timer(1)
  61.   tim.init(period=50,mode=Timer.PERIODIC, callback=check_msg)
  62. def set_last_will(topic, msg, retain=False, qos=0):
  63.   global lw_topic, lw_msg, lw_qos, lw_retain
  64.   assert 0 <= qos <= 2
  65.   assert topic
  66.   lw_topic = topic
  67.   lw_msg = msg
  68.   lw_qos = qos
  69.   lw_retain = retain
  70. def connect(clean_session=True):
  71.   global _sock, _ssl, _user, _keepalive, lw_topic
  72.   _sock = socket.socket()
  73.   _sock.connect(_addr)
  74.   if _ssl:
  75.     import ussl
  76.     _sock = ussl.wrap_socket(_sock, **_ssl_params)
  77.   msg = bytearray(b"\x10\0\0\x04MQTT\x04\x02\0\0")
  78.   msg[1] = 10 + 2 + len(_client_id)
  79.   msg[9] = clean_session << 1
  80.   if _user is not None:
  81.     msg[1] += 2 + len(_user) + 2 + len(_pswd)
  82.     msg[9] |= 0xC0
  83.   if _keepalive:
  84.     assert _keepalive < 65536
  85.     msg[10] |= _keepalive >> 8
  86.     msg[11] |= _keepalive & 0x00FF
  87.   if lw_topic:
  88.     msg[1] += 2 + len(lw_topic) + 2 + len(lw_msg)
  89.     msg[9] |= 0x4 | (lw_qos & 0x1) << 3 | (lw_qos & 0x2) << 3
  90.     msg[9] |= lw_retain << 5
  91.   _sock.write(msg)
  92.   #print(hex(len(msg)), hexlify(msg, ":"))
  93.   _send_str(_client_id)
  94.   if lw_topic:
  95.     _send_str(lw_topic)
  96.     _send_str(lw_msg)
  97.   if _user is not None:
  98.     _send_str(_user)
  99.     _send_str(_pswd)
  100.   resp = _sock.read(4)
  101.   assert resp[0] == 0x20 and resp[1] == 0x02
  102.   if resp[3] != 0:
  103.     raise MQTTException(resp[3])
  104.   return resp[2] & 1
  105. def stop():
  106.   global _sock, tim
  107.   _sock.write(b"\xe0\0")
  108.   _sock.close()
  109.   if tim !=None:
  110.     tim.deinit()
  111. def ping():
  112.   global _sock
  113.   _sock.write(b"\xc0\0")
  114. def publish(topic, msg, retain=False, qos=0):
  115.   global _sock, _pid
  116.   pkt = bytearray(b"\x30\0\0\0")
  117.   pkt[0] |= qos << 1 | retain
  118.   sz = 2 + len(topic) + len(msg)
  119.   if qos > 0:
  120.     sz += 2
  121.   assert sz < 2097152
  122.   i = 1
  123.   while sz > 0x7f:
  124.     pkt[i] = (sz & 0x7f) | 0x80
  125.     sz >>= 7
  126.     i += 1
  127.   pkt[i] = sz
  128.   #print(hex(len(pkt)), hexlify(pkt, ":"))
  129.   _sock.write(pkt, i + 1)
  130.   _send_str(topic)
  131.   if qos > 0:
  132.     _pid += 1
  133.     pid = _pid
  134.     struct.pack_into("!H", pkt, 0, pid)
  135.     _sock.write(pkt, 2)
  136.   _sock.write(msg)
  137.   if qos == 1:
  138.     while 1:
  139.       op = wait_msg()
  140.       if op == 0x40:
  141.         sz = _sock.read(1)
  142.         assert sz == b"\x02"
  143.         rcv_pid = _sock.read(2)
  144.         rcv_pid = rcv_pid[0] << 8 | rcv_pid[1]
  145.         if pid == rcv_pid:
  146.           return
  147.   elif qos == 2:
  148.     assert 0
  149. def getsubscribe(topic, qos=0):
  150.   global _sock, _pid
  151.   assert _cb is not None, "getsubscribe callback is not set"
  152.   pkt = bytearray(b"\x82\0\0\0")
  153.   _pid += 1
  154.   struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, _pid)
  155.   #print(hex(len(pkt)), hexlify(pkt, ":"))
  156.   _sock.write(pkt)
  157.   _send_str(topic)
  158.   _sock.write(qos.to_bytes(1, "little"))
  159.   while 1:
  160.     op = wait_msg()
  161.     if op == 0x90:
  162.       resp = _sock.read(4)
  163.       #print(resp)
  164.       assert resp[1] == pkt[2] and resp[2] == pkt[3]
  165.       if resp[3] == 0x80:
  166.         raise MQTTException(resp[3])
  167.       return
  168. # Wait for a single incoming MQTT message and process it.
  169. # Subscribed messages are delivered to a callback previously
  170. # set by .set_callback() method. Other (internal) MQTT
  171. # messages processed internally.
  172. def wait_msg():
  173.   global _sock
  174.   res = _sock.read(1)
  175.   _sock.setblocking(True)
  176.   if res is None:
  177.     return None
  178.   if res == b"":
  179.     raise OSError(-1)
  180.   if res == b"\xd0":  # PINGRESP
  181.     sz = _sock.read(1)[0]
  182.     assert sz == 0
  183.     return None
  184.   op = res[0]
  185.   if op & 0xf0 != 0x30:
  186.     return op
  187.   sz = _recv_len()
  188.   topic_len = _sock.read(2)
  189.   topic_len = (topic_len[0] << 8) | topic_len[1]
  190.   topic = _sock.read(topic_len)
  191.   sz -= topic_len + 2
  192.   if op & 6:
  193.     pid = _sock.read(2)
  194.     pid = pid[0] << 8 | pid[1]
  195.     sz -= 2
  196.   msg = _sock.read(sz)
  197.   _cb(topic, msg)
  198.   if op & 6 == 2:
  199.     pkt = bytearray(b"\x40\x02\0\0")
  200.     struct.pack_into("!H", pkt, 2, pid)
  201.     _sock.write(pkt)
  202.   elif op & 6 == 4:
  203.     assert 0
  204. # Checks whether a pending message from server is available.
  205. # If not, returns immediately with None. Otherwise, does
  206. # the same processing as wait_msg.
  207. def check_msg(msg = ""):
  208.   global _sock
  209.   _sock.setblocking(False)
  210.   return wait_msg()
复制代码




下面是ESP32 C3上保存的main.py程序代码:
  1. import time
  2. from machine import Pin
  3. import siot #导入同目录下的siot.py
  4. led=Pin(10,Pin.OUT)
  5. SERVER="192.168.75.163"  #行空板的IP地址
  6. CLIENT_ID=""
  7. IOT_pubTopic='siot/c3'
  8. IOT_UserName='siot'
  9. IOT_PassWord='dfrobot'
  10. siot.init(CLIENT_ID,SERVER,user=IOT_UserName,password=IOT_PassWord)
  11. def WIFIconnect(): #无线链接
  12.     import network
  13.     ssid='Mi10'  #无线名称
  14.     password='********'  #修改为无线密码
  15.     station=network.WLAN(network.STA_IF)
  16.     if station.isconnected() == True:
  17.         print("WiFi already connected")
  18.         print(station.ifconfig())
  19.         return
  20.     station.active(True)
  21.     station.connect(ssid,password)
  22.     while station.isconnected() == False:
  23.         pass
  24.     print("Connection successful")
  25.     print(station.ifconfig())
  26. def sub_cp(topic,msg):   # 回调函数
  27.     s=msg.decode()  #对接收到的信息解码
  28.     print(s)   
  29.     if s=='1':  #接收的消息1就亮灯
  30.         led.value(1)
  31.     else:
  32.         led.value(0)
  33. WIFIconnect()
  34. siot.connect()
  35. siot.set_callback(sub_cp)
  36. siot.subscribe(IOT_pubTopic,sub_cp)
  37. while True:
  38.     time.sleep(1)
  39.     siot.check_msg()
复制代码

此时,我们可能通过向行空板上的SIoT发送1或0,实现ESP32 C3板载灯的亮或灭。我们也可以进一步在行空板上编写一个控制程序,如设置2个按钮,一个按钮是亮灯,另一个是关灯,实现消息的发送。[/md]

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail