项目描述
项目介绍
很高兴参加由硬禾学堂和digikey联合发起的Funpack活动,本活动的初衷是让更多电子技术爱好者接触到来自世界各个厂商的开发板,完成指定任务就免费赠送开发板。
这是Funpack第三季第一期活动,本期活动开发板是一款来自芯科的高性能无线开发套件,其支持多种无线通讯协议。
硬件介绍
开发板的俯视图如图所示,板载USB J-link 调试器,USB接口为typec,开发板上还有2个用户按钮和2个用户LED灯,引出了拓展插座和焊盘,还有qwiic接口。qwiic接口由sparkfun开发,一种基于iic协议的接口,可连接外部传感器。
这次使用的开发板外设有按钮和led灯,点击按钮执行密集计算,尝试来升高CPU的温度。
设计思路
任务选择
我完成的任务是任务一,
(1)使用芯片内部的温度检测外设,测量温度并通过蓝牙发送至上位机,这一步就是发送数据
(2)在上位机中以“绘图”的形式对温度数据进行可视化,这一步就是接收蓝牙数据
软件流程图
流程图如图所示,一部分是蓝牙发送数据,这里采用circuitpython开发,创建service并读取芯片内部温度数据并发送,
另外一部分是电脑端通过蓝牙连接到开发板,使用python的bleak库获取并解析温度数据,然后使用matplotlib动态绘制出随时间变化的温度曲线。
发送蓝牙数据 接收蓝牙数据
功能展示
ble设备核心代码片段
温度服务特征值的uuid在CircuitPython中的python文件中定义,该特征值具有可读和通知的属性,会以字符串的形式提供温度数据:
# 开发板代码
# temperature_server.py
# 温度特征值
temperature_characteristic = StringCharacteristic(
uuid = VendorUUID('d2345a78-90ab-cdef-1234-567890abcdef'),
properties = (Characteristic.READ | Characteristic.NOTIFY),
write_perm = Attribute.NO_ACCESS,
)
在Circuitpython中,获取该芯片内部温度的语句为:
# 开发板代码
import microcontroller
microcontroller.cpu.temperature
具体实现细节可查阅此处官方实现:
float common_hal_mcu_processor_get_temperature(void) {
TEMPDRV_Init();
return (float)TEMPDRV_GetTemp();
}
在开发板中,点击按钮会对2000个随机数排序,此功能目的是使得芯片内部温度上升,可能效果不是不明显。
# 开发板代码
# 使得温度上升
def increase_temperature(self):
import random
dataset = [random.random() for _ in range(2000)]
dataset.sort()
return dataset
# 主函数
def main_function(self):
# ...
if not self.button1.value: # 按键按下时为Flase
self.led1.value = True
print("Button pressed, increasing temperature...")
self.increase_temperature() # 增加CPU温度
else:
self.led1.value = False
# ...
手机端连接开发板效果示意
为了获取开发板的物理地址,可以通过安卓手机端的EFR connect软件连接名称为Example的蓝牙设备。其中设备物理地址通过手机端查看,会在上位机连接蓝牙的程序中使用到。
上位机核心代码片段
上位机使用bleak库连接ble设备。
知道蓝牙地址 04:87:27:E9:A4:C6 和温度服务特征值的uuid d2345a78-90ab-cdef-1234-567890abcdef 后,上位机便可以连接指定的蓝牙服务,并接收来自开发板的实时温度数据。
# 上位机代码
device_address = "04:87:27:E9:A4:C6"
TEMPERATURE_CHARACTERISTIC_UUID = "d2345a78-90ab-cdef-1234-567890abcdef"
data_queue = queue.Queue()
# 连接并读取温度数据,存入队列中
async def connect_and_read(address):
async with BleakClient(address) as client:
if await client.is_connected():
print("Connected to BLE device!")
def callback(sender, data):
# 将数据放入队列
data_str = data.decode('utf-8') # 将bytearray转换为字符串
# 使用字符串分割或正则表达式提取温度值
temp_str = data_str.split(":")[1].strip().split(" ")[0]
try:
data = float(temp_str) # 转换为浮点数
except ValueError:
pass # 如果转换失败,跳过这个数据
data_queue.put(data)
await client.start_notify(TEMPERATURE_CHARACTERISTIC_UUID, callback)
while continue_running:
await asyncio.sleep(1)
await client.stop_notify(TEMPERATURE_CHARACTERISTIC_UUID)
并使用maplotlib库动态绘制温度曲线:
# 上位机代码
def update_plot(frame):
global flag
global x_data_start_time
global x_data_current_time
current_time = time.time() - start_time
while not data_queue.empty():
if flag:
flag = 0
x_data_start_time = time.time()
# 从队列中获取数据
temperature = data_queue.get()
x_data_current_time = time.time() - x_data_start_time
x_data.append(x_data_current_time)
y_data.append(temperature)
temp_text.set_text(f"Temperature: {y_data[-1]:.2f} °C")
# print(x_data_current_time, temperature)
if x_data_current_time >= continual_time-5:
ax.set_xlim(x_data_current_time - continual_time+5, x_data_current_time+5)
line.set_xdata(x_data)
line.set_ydata(y_data)
return line,
上位机温度数据可视化效果
上位机接收到开发板通过蓝牙传过来的温度数据,解析温度数据并可视化,时间轴会随时间不断变化,保证一直在显示最近一段时间内获取到的温度数据。具体动态效果可观看b站演示视频。
在可视化页面,点击q键会断开蓝牙连接并退出上位机程序。
心得体会
本次使用CircuitPython完成设计任务是受到微信群内大佬的启发,未来可以使用官方提供的Simplicity Studio进行更高级功能的实现。
最后,感谢Funpack活动的举办方提供了一个探索性的平台,感谢微信群中分享经验、答疑解惑的工程师们。