【得捷Follow me第3期】+ 寻找WiFi发射源的位置(任务综合帖)
[复制链接]
在此非常感谢EEworld和DigiKey举办的Follow me系列第3期活动,给我们学习机会。谢谢
【第一部分】3—5分钟短视频
【第二部分】任务/项目总结报告
任务1:使用MicroPython系统【对该任务的介绍、功能对应的主要代码片段及说明、功能展示及说明、心得体会建议】
此任务主要点是搭建Python开发环境,烧录Python固件并使用。
1.1 搭建Python环境
首先下载Thonny 工具安装,安装完成后建议使用English版本,若不使用English版本后面会对包管理造成影响,导致搜索不出来。
1.2 下载最新的python固件
https://micropython.org/download/esp32c3/
1.3 通过Thony下载python固件至ESP32C3中
1.4 参考python手册使用实时时钟RTC
from machine import RTC
rtc = RTC()
rtc.datetime((2023,12, 12, 1, 12, 48, 0, 0)) # set a specific date and time
print(rtc.datetime() )# get date and time
任务2:驱动扩展板上的OLED屏幕【对该任务的介绍、功能对应的主要代码片段及说明、功能展示及说明、心得体会建议】
这里需提前在Thonny下载好ssd1306的库。
note:在安装的时候需选择English版本,否则无法更新。
- import time
-
- from machine import Pin, SoftI2C
-
- import ssd1306
-
- import math
-
-
-
-
-
- i2c = SoftI2C(scl=Pin(7), sda=Pin(6))
-
- oled_width = 128
-
- oled_height = 64
-
- oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
-
-
-
- oled.fill(0)
-
- oled.text("I Love EEWORLD!", 10, 15)
-
- oled.text("/////", 30, 40)
-
- oled.text("(`3`)y", 30, 55)
-
- oled.show()
任务3:控制蜂鸣器播放音乐【对该任务的介绍、功能对应的主要代码片段及说明、功能展示及说明、心得体会建议】
3.1 蜂鸣器原理介绍
通过扩展板资料查找,确认蜂鸣器buzzer的引脚是A3,结合XIAO C3的引脚图得知使用的引脚是GPIO5。
3.2 任务开发
由以上蜂鸣器的驱动原理,可以确定蜂鸣器播放音乐步骤:
3.2.1 确认引脚
这里引入用户Button,当用户button按下后,蜂鸣器响起,我们先尝试将蜂鸣器驱动起来。
3.2.2 将引脚设置为PWM输出
- buzzer = machine.PWM(buzzer_pin)
-
- buzzer.freq(1047)
3.3.3 设定音乐频谱
我们主要是通过控制PWM频率来发出不同的声调,例如
3.3.4 循环执行音乐频谱
任务4:连接WiFi网络【对该任务的介绍、功能对应的主要代码片段及说明、功能展示及说明、心得体会建议】
4.1 ESP32C3 联网库分析
- import network
-
-
-
- wlan = network.WLAN(network.STA_IF)
-
- wlan.active(True)
-
- wlan.scan()
-
- wlan.isconnected()
-
- wlan.connect('ssid', 'key')
-
- wlan.config('mac')
-
- wlan.ifconfig()
-
-
-
- ap = network.WLAN(network.AP_IF)
-
- ap.config(ssid='ESP-AP')
-
- ap.config(max_clients=10)
-
- ap.active(True)
4.2 实现
连接到本地WIFI网络的一个有用的功能是:
- def do_connect():
-
- import network
-
- wlan = network.WLAN(network.STA_IF)
-
- wlan.active(True)
-
- if not wlan.isconnected():
-
- print('connecting to network...')
-
- wlan.connect('ssid', 'key')
-
- while not wlan.isconnected():
-
- pass
-
- print('network config:', wlan.ifconfig())
一旦网络建立起来,该socket模块就可以像往常一样创建和使用 TCP/UDP 套接字,并且该requests模块可以用于方便的 HTTP 请求。
调用 后,默认情况下,设备将永远wlan.connect()重试连接 ,即使身份验证失败或范围内没有 AP。 将返回此状态,直到连接成功或接口被禁用。这可以通过调用 来更改,其中 n 是所需的重新连接尝试次数(0 表示不会重试,-1 将恢复尝试永久重新连接的默认行为)。wlan.status()network.STAT_CONNECTINGwlan.config(reconnects=n)
任务5:使用外部传感器【对该任务的介绍、功能对应的主要代码片段及说明、功能展示及说明、心得体会建议】
5.1 ATH20温湿度传感器说明
5.2 光照传感器说明
光照传感器主要通过不同光照照射
5.3 功能实现
光照传感器主要通过ADC采样,通过python源码发现有类似的例子,通过Thonny修改下载后可读取ADC值。
AHT20 温湿度读取接口已在ahtx0.py有定义,可直接引用。
整体代码如下:
- from machine import Pin, SoftI2C, ADC
- import ssd1306
- import utime
- import time
- from ahtx0 import AHT20
-
-
- i2c = SoftI2C(scl=Pin(7), sda=Pin(6))
-
-
- oled = ssd1306.SSD1306_I2C(128, 64, i2c)
-
-
- oled.fill(0)
- oled.text("##EEWORLD Task##", 0, 0)
- oled.text("Temp:", 0, 16)
- oled.text("Humi:", 0, 32)
- oled.text("Light:", 0, 48)
- oled.show()
-
-
- aht = AHT20(i2c)
-
-
- adc = ADC(Pin(2))
- adc.atten(ADC.ATTN_11DB)
- adc.width(ADC.WIDTH_12BIT)
-
- while True:
- temp = aht.temperature
- humi = aht.relative_humidity
-
- light_adc = adc.read()
-
-
- light_lux = light_adc * 350 * 1.0 / 4095
-
-
- light_res = (4095 - light_adc) * 10.0 / light_adc
-
- print("Temp(°):\n");
- print('{:.2f}'.format(temp))
- print("Humi(%):\n");
- print('{:.2f}'.format(humi))
- print("Light(lux)\n");
- print('{:.2f}'.format(light_lux))
- print("Light(K)\n");
- print('{:.2f}'.format(light_res))
-
-
- oled.fill_rect(64,16,64,48,0)
- oled.text('{:.2f}'.format(temp), 64, 16)
- oled.text('{:.2f}'.format(humi), 64, 32)
- oled.text('{:.2f}'.format(light_lux), 64, 48)
- oled.show()
-
-
- time.sleep(1)
-
-
-
-
-
-
-
任务6:寻找WiFi发射源的位置
本期主线任务选择”寻找WIFI发射源位置“。
6.1 原理说明
WIFI信号的强弱主要由RSSI值体现,
RSSI的单位是DBm,dbm是一个表示功率绝对值的单位,他的计算公式为10lg(功率值/1mw)。例如如果接收到的功率为1mw,按照dbm单位进行折算后的值应该为10lg 1mw/1mw=0dbm。当然在实际传输过程中接收方是很难达到接收功率1mw的。因为还有接收端的天线增益,所以即使接收功率是0.00001mw(即-50db)时,RF射频的接收端也能很好地进行码元解码。
为什么测量出来的dbm值都是负数?
答:首先我们需要知道的是无线信号dbm都是负数,最大是0。因此测量出来的dbm值肯定都是负数。因为dbm值只在一种情况下为0,那就是在理想状态下经过实验测量的结果,一般我们认为dbm为0是其最大值,意味着接收方把发射方发射的所有无线信号都接收到了,即无线路由器发射多少功率,接收的无线网卡就获得多少功率。当然这是在理想状态下测量的,在实际中即使将无线网卡挨着无线路由器的发射天线也不会达到dbm为0的效果。所以说测量出来的dbm值都是负数,不要盲目的认为负数就是信号不好。
既然我们已经知道dbm是负数,那可以确定值越大,信号越好,越说明无线路由器发射的功率都被无线网卡接收到了。因此dbm值应该越大越好,-50dbm说明接收到的无线信号要好于-70dbm。
6.2 接口分析
而要想识别RSSI的强弱,涉及很多信号原理相关知识,但是在ESP32C3的代码库中已经有现成的函数可以直接返回WIFI信号强度,通过对network.pyi分析,我们可以知道status接口会返回WIFI信号强度。
通过以上预备知识的梳理,我们现在正式开始项目。
6.3 代码实现
6.3.1 需求
1、连接路由器
2、OLED需实时显示RSSI值
3、当RSSI处于-80至-60时显示信号LOW,[-60,-40)显示Middle,【-40,-20)显示High,大于-20显示Excellent。
4、信号越好蜂鸣器需鸣叫的越快,以便定位位置。
5、显示温湿度
6、获取网络最新时间并显示
6.3.2 实现
- import network
- import time
- from time import sleep
- import machine,ntptime
- from machine import Pin, SoftI2C,ADC
- import ssd1306
- import math
- from ahtx0 import AHT20
-
-
- i2c = SoftI2C(scl=Pin(7), sda=Pin(6))
-
- aht = AHT20(i2c)
-
-
- adc = ADC(Pin(2))
- adc.atten(ADC.ATTN_11DB)
- adc.width(ADC.WIDTH_12BIT)
-
-
- i2c = SoftI2C(scl=Pin(7), sda=Pin(6))
- oled_width = 128
- oled_height = 64
- oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
-
-
- wifi_ssid = "H3C_44671C"
- wifi_password = "wjly032623"
-
- oled.text("Starting up...", 0, 0)
- oled.show()
-
- station = network.WLAN(network.STA_IF)
- station.active(True)
- station.connect(wifi_ssid, wifi_password)
- time.sleep(1)
-
- while not station.isconnected():
- time.sleep(1)
-
- oled.fill(0)
- oled.text("Connecting to", 0, 0)
- oled.text(wifi_ssid, 0, 20)
- oled.show()
- time.sleep(2)
-
- oled.fill(0)
- ip_address = station.ifconfig()[0]
- oled.text("Connected! ", 0, 0)
- oled.text("IP Address:", 0, 20)
- oled.text(ip_address, 0, 40)
-
- oled.show()
- time.sleep(2)
-
-
- buzzer_pin = machine.Pin(5, machine.Pin.OUT)
- buzzer = machine.PWM(buzzer_pin)
- buzzer.freq(1047)
- buzzer.duty(0)
-
- center_x = oled_width // 2
- center_y = oled_height // 2
- square_size = 6
- num_squares = 12
- angle_increment = 2 * math.pi / num_squares
-
- x_pos = [12, 38, 64, 90]
- statuses = ["L", "M", "H", "Nice"]
-
- def calculate_block_count(rssi):
-
- if -80 <= rssi < -60:
- return 1
- elif -60 <= rssi < -40:
- return 2
- elif -40 <= rssi < -20:
- return 3
- elif -20 <= rssi <= 10:
- return 4
- def sync_ntp():
- """通过网络校准时间"""
- while True:
- try:
- ntptime.settime()
- break;
- except:
- print('time no')
- time.sleep(1)
-
- def ShowTime():
-
- NetWortime=time.localtime()
- NetWortime='%d-%d-%d %d:%d'%(NetWortime[0],NetWortime[1],NetWortime[2]+1,NetWortime[3]-16,NetWortime[4])
- oled.text(NetWortime,0,48)
-
-
-
- def Get_Sensor_Value():
- temp = aht.temperature
- humi = aht.relative_humidity
-
- light_adc = adc.read()
-
-
- light_lux = light_adc * 350 * 1.0 / 4095
- oled.text("T:", 0, 24)
- oled.text("H:", 64, 24)
- oled.text("L:", 0, 36)
- oled.text('{:.2f}'.format(temp), 16, 24)
- oled.text('{:.2f}'.format(humi), 80, 24)
- oled.text('{:.2f}'.format(light_lux), 16, 36)
- oled.show()
-
- while True:
- sync_ntp();
- NetWortime=time.localtime()
- print(type(NetWortime),NetWortime)
- NetWortime='%d-%d-%d %d:%d:%d'%(NetWortime[0],NetWortime[1],NetWortime[2],NetWortime[3]+8,NetWortime[4],NetWortime[5])
- print(NetWortime)
- oled.fill(0)
- station = network.WLAN(network.STA_IF)
- time.sleep(0.1)
- oled.text("##EEWORLD Task##", 0, 0)
- rssi = station.status('rssi')
- rssi_duty = 160 + 2 * int(rssi)
- rssi_duty_2 = int(rssi_duty / 2)
- rssi_abs = abs(int(rssi)) / 100
-
- block_count = calculate_block_count(rssi)
- status = statuses[block_count - 1]
-
- oled.text("RSSI:", 0, 12)
- oled.text(str(rssi), 40, 12)
- oled.text("SQ:",72,12)
- oled.text(status, 96, 12)
-
-
-
- Get_Sensor_Value()
- ShowTime()
- oled.text(ip_address, 0, 56)
-
-
- oled.show()
-
- buzzer.duty(rssi_duty)
- time.sleep(rssi_abs)
- buzzer.duty(0)
- time.sleep(rssi_abs)
- buzzer.duty(rssi_duty_2)
- time.sleep(rssi_abs)
- buzzer.duty(0)
- time.sleep(rssi_abs)
-
-
【第三部分】 源码
https://download.eeworld.com.cn/detail/jone5/630296
【第四部分】心得体会
我是第一次使用python对ESP32进行开发,因此此次任务对我来说还是具有很强的学习意义的,非常感谢EEWORLD联合得捷的此次任务,给了我们很多学习的机会。因为第一次接触用python去开发Esp32,由于工作繁忙,很多接口还不会使用,我会继续阅读学习Esp32 miceopython源码,以熟悉此中开发方式原理并进行分享。
最后再次感谢EEWorld提供此学习机会及分享的平台。非常感谢
【第五部分】参考资料
ESP32C3资料链接: https://wiki.seeedstudio.com/XIAO_ESP32C3_Getting_Started/
扩展板资料: https://wiki.seeedstudio.com/Seeeduino-XIAO-Expansion-Board/
Micropython资料链接; https://wiki.seeedstudio.com/XIAO_ESP32C3_MicroPython/
Micropython 参考手册: https://docs.micropython.org/en/latest/esp32/quickref.html
光照传感器手册:https://mm.digikey.com/Volume0/opasdata/d220001/medias/docus/2283/101020132_Web.pdf
温湿度传感器手册:https://mm.digikey.com/Volume0/opasdata/d220001/medias/docus/448/101990644_Web.pdf
|