Funpack3-1使用circuitpython读取XG24-EK2703A板卡温度信息
该项目使用了circuitpython,实现了读取XG24-EK2703A板卡内置的温度传感器,并通过蓝牙广播的设计,它的主要功能为:undefined。 该项目使用了Arduino在Wio终端上,实现了读取XG24-EK2703A蓝牙发送出来的温度信息的设计,它的主要功能为:undefined。
标签
Funpack活动
测试
显示
开发板
aramy
更新2024-03-05
114

硬件介绍:

XG24-EK2703A—EFR32xG24 Explorer套件是一个基于EFR32MG24片上系统的超低成本、小尺寸开发和评估平台,该套件专注于物联网应用的快速原型化和概念创建2.4 GHz无线协议的IoT应用程序,包括蓝牙LE、蓝牙Mesh、Zigbee、Thread 和 Matter。

板子上有两个LED和两个按钮,和一个SEGGER J-Link 调试器。支持在线调试。但是这么大个板子,没有集成什么传感器,只有内核上有一个测量芯片温度的传感器。不过编程方面除了可以使用C还能支持circuitpython编程。

任务选择:

芯科科技对这个XG24-EK2703A开发板提供了完整的编程IDE。但是安装很困难,需要在线安装,而且服务器基本都是在国外,安装缓慢,且安装后需要几十G的硬盘空间。仅仅是一个开发环境安装就困难重重。在群里老师的指导下,才了解到这个板卡还支持circuitpython编程,于是就决定选择任务1:使用芯片内部的温度检测外设,测量温度并通过蓝牙发送至上位机,在上位机中以“绘图”的形式对温度数据进行可视化。

任务实现:

定下了任务,选择了编程语言。下位机端就是读取温度传感器,然后写入蓝牙。这个板子的温度传感器是通过寄存器直接读取的。这里使用了群里老师提供的circuitpython的固件,能够支持uctypes读取寄存器。通过寄存器很容易就获得了温度信息。不得不说circuitpython在读取传感器方便,真的是快捷高效。

from uctypes import BF_POS, BF_LEN, UINT32,BFUINT32,BFUINT16, struct
from time import sleep
EMU_BASE = 0x50004000
#EMU_BASE = 0x50008000
EMU_LAYOUT = {
"EMU_TEMP": (0x88,{
"TEMP":2 << BF_POS|9 << BF_LEN|BFUINT32,
"TEMPLSB":0<< BF_POS |2 << BF_LEN|BFUINT32
})
}

def say(n):
temp="{:.2f}".format(n)
print(temp)
return temp

while True:
emu = struct(EMU_BASE,EMU_LAYOUT)
say(emu.EMU_TEMP.TEMP + emu.EMU_TEMP.TEMPLSB *0.25 -273.15)
sleep(0.5)

读取到了温度后,就是写入蓝牙。XG24-EK2703A开发板在这里是作为服务端。这里使用了adafruit_ble这个包。adafruit_ble这个包能够将蓝牙内容打包发送出去,类似于一个串口。这里自己建立了一个“CPY_TEMP”的蓝牙服务。

import time
import board
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService
from uctypes import BF_POS, BF_LEN, UINT32,BFUINT32,BFUINT16, struct
from time import sleep

EMU_BASE = 0x50004000
EMU_LAYOUT = {
"EMU_TEMP": (0x88,{
"TEMP":2 << BF_POS|9 << BF_LEN|BFUINT32,
"TEMPLSB":0<< BF_POS |2 << BF_LEN|BFUINT32
})
}

def say(n):
temp="{:.2f}".format(n)
print(temp)
return temp

ble = BLERadio()
uart = UARTService()
advertisement = ProvideServicesAdvertisement(uart)
advertisement.short_name = "CPY_TEMP"
advertisement.connectable = True

num=0
while True:
ble.start_advertising(advertisement)
print("Waiting to connect")
while not ble.connected:
pass
print("Connected")

while ble.connected:
emu = struct(EMU_BASE,EMU_LAYOUT)
#temp=say(emu.EMU_TEMP.TEMP + emu.EMU_TEMP.TEMPLSB *0.25 -273.15)
temp=emu.EMU_TEMP.TEMP + emu.EMU_TEMP.TEMPLSB *0.25 -273.15
print("Temperature: %0.2f℃" % temp)
result = int(temp*100)
#num=num+1;
#uart.write(result.encode("utf-8"))
#uart.write(str(num).encode("utf-8"))
uart.write(str(result))
time.sleep(0.5)

接下来是上位机的部分。在电脑上使用gatttool能够很容易地连上XG24-EK2703A的“CPY_TEMP”蓝牙服务,但是却不知道如何来读取数据,使用char-read-hnd始终是读取不到数据。使用手机APP,通过Notify的方式就能正确读取广播数据。

最终决定使用手头的Wio Terminal通过Arduino编程来实现上位机功能。

Wio Terminal支持蓝牙,并且官方提供了Line Charts库,专门用于绘制折线图,但是Line Charts库和蓝牙库应该是有冲突,两个库同时使用,屏幕就无法点亮。所以这里绘图部分仅仅使用TFT_eSPI库手工绘制温度变化曲线。

#include "rpcBLEDevice.h"
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include "TFT_eSPI.h"
TFT_eSPI tft;
#define MAX_SIZE 40 // maximum size of data
float queue[MAX_SIZE] = {0};
uint8_t queuesize = 0;

// The remote service we wish to connect to.
static BLEUUID serviceUUID("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
// The characteristic of the remote service we are interested in.
static BLEUUID charUUID("6e400003-b5a3-f393-e0a9-e50e24dcca9e");

static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic *pRemoteCharacteristic;
static BLEAdvertisedDevice *myDevice;
uint8_t bd_addr[6] = {0xa9, 0xad, 0xe9, 0x27, 0x87, 0x04};
BLEAddress BattServer(bd_addr);


//--图形------------------------------
void addval(float val)
{
    if (queuesize < MAX_SIZE)
    { // 队列未满
        queue[queuesize] = val;
        queuesize++;
    }
    else
    { // 队列已满
        for (uint8_t i = 1; i < MAX_SIZE; i++)
        {
            queue[i - 1] = queue[i];
        }
        queue[MAX_SIZE - 1] = val;
    }
}

// 绘制坐标轴 和显示温度值
void drawaxis(float val)
{
    tft.setFreeFont(&FreeSansBoldOblique9pt7b); // select Free, Sans, Bold, Oblique, 12pt.
    tft.drawString(String(val, 2)+" `C", 5, 2);       // prints string at (70,80)
    tft.drawLine(0, 120, 320, 120, TFT_RED);
}
// 绘制曲线  范围 从 10~50摄氏度(映射到0~240)
void drawwave(uint16_t color)
{
    int x0, y0, x1, y1;
    float val;
    for (uint8_t i = 1; i < queuesize; i++)
    {
        val = queue[i - 1];
        if (val < 10)
            val = 10.0;
        if (val > 50)
            val = 50.0;
        y0 = int((val - 10.0) * 6);
        x0 = (i - 1) * 320 / (queuesize - 1);
        val = queue[i];
        if (val < 10)
            val = 10.0;
        if (val > 50)
            val = 50.0;
        y1 = int((val - 10) * 6);
        x1 = (i) * 320 / (queuesize - 1);
        // Serial.printf("i=%d ,queuesize=%d ,%.2f,%.2f,    %d,%d  ,  %d,%d\n",i,queuesize,queue[i-1],queue[i],x0,y0,x1,y1);
        tft.drawLine(x0, 240-y0, x1, 240-y1, color);
    }
}

// 蓝牙----------------------------------------------
static void notifyCallback(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify)
{
    char temp[6]; // 定义缓冲,用来存放串口传来的数据
    float blu_temp;
    if (length > 0 && length < 6)
    { // 使用字符串来存放温度,温度扩大了100倍。
        memset(temp, 0, sizeof(char) * 6);
        for (uint8_t i = 0; i < length; i++)
        {
            temp[i] = pData[i];
        }
        blu_temp = float(String(temp).toInt()) / 100.00;
        // data.push(blu_temp);
        Serial.println(blu_temp);
        drawwave(TFT_WHITE);
        addval(blu_temp);
        drawaxis(blu_temp);
        drawwave(TFT_BLUE);
    }
}

class MyClientCallback : public BLEClientCallbacks
{
    void onConnect(BLEClient *pclient)
    {
    }

    void onDisconnect(BLEClient *pclient)
    {
        connected = false;
        Serial.println("onDisconnect");
    }
};

bool connectToServer()
{
    Serial.println("+++++++++++++++++++++++++++++++++++++++++++++");
    Serial.print("Forming a connection to ");
    Serial.println(myDevice->getAddress().toString().c_str());

    BLEClient *pClient = BLEDevice::createClient();
    Serial.println(" - Created client");

    pClient->setClientCallbacks(new MyClientCallback());

    // Connect to the remove BLE Server.
    pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
    Serial.println(" - Connected to server");

    // Obtain a reference to the service we are after in the remote BLE server.
    BLERemoteService *pRemoteService = pClient->getService(serviceUUID);
    Serial.println(serviceUUID.toString().c_str());
    if (pRemoteService == nullptr)
    {
        Serial.print("Failed to find our service UUID: ");
        Serial.println(serviceUUID.toString().c_str());
        pClient->disconnect();
        return false;
    }
    Serial.println(" - Found our service");

    // Obtain a reference to the characteristic in the service of the remote BLE server.
    pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
    if (pRemoteCharacteristic == nullptr)
    {
        Serial.print("Failed to find our characteristic UUID: ");
        Serial.println(charUUID.toString().c_str());
        pClient->disconnect();
        return false;
    }
    Serial.println(" - Found our characteristic");

    // Read the value of the characteristic.
    if (pRemoteCharacteristic->canRead())
    {
        Serial.println(" -  can  read  start");
        std::string value = pRemoteCharacteristic->readValue();
        Serial.print("The characteristic value was: ");
        Serial.println(value.c_str());
    }

    if (pRemoteCharacteristic->canNotify())
        pRemoteCharacteristic->registerForNotify(notifyCallback);

    connected = true;
    return true;
}

/**
 * Scan for BLE servers and find the first one that advertises the service we are looking for.
 */
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
{
    /**
     * Called for each advertising BLE server.
     */
    void onResult(BLEAdvertisedDevice advertisedDevice)
    {
        Serial.print("BLE Advertised Device found: ");
        Serial.println(advertisedDevice.toString().c_str());

        // We have found a device, let us now see if it contains the service we are looking for.
        if (memcmp(advertisedDevice.getAddress().getNative(), BattServer.getNative(), 6) == 0)
        {
            Serial.print("BATT Device found: ");
            Serial.println(advertisedDevice.toString().c_str());
            BLEDevice::getScan()->stop();
            Serial.println("new BLEAdvertisedDevice");
            myDevice = new BLEAdvertisedDevice(advertisedDevice);
            Serial.println("new BLEAdvertisedDevice done");
            doConnect = true;
            doScan = true;
        } // onResult
    }
}; // MyAdvertisedDeviceCallbacks


void setup()
{
    Serial.begin(115200);
    while (!Serial)
    {
    };
    delay(2000);
    Serial.println("Starting Arduino BLE Client application...");

     tft.begin();
    tft.setRotation(3);
    tft.fillScreen(TFT_WHITE); // Green background

    BLEDevice::init("");

    BLEScan *pBLEScan = BLEDevice::getScan();
    pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
    pBLEScan->setInterval(1349);
    pBLEScan->setWindow(449);
    pBLEScan->setActiveScan(true);
    pBLEScan->start(5, false);
} // End of setup.

// This is the Arduino main loop function.
void loop()
{
    if (doConnect == true)
    {
        if (connectToServer())
        {
            Serial.println("We are now connected to the BLE Server.");
        }
        else
        {
            Serial.println("We have failed to connect to the server; there is nothin more we will do.");
        }
        doConnect = false;
    }
    delay(500);
} // End of loop

心得体会:非常荣幸参加funpack的这期活动。XG24-EK2703A板子很优秀,可惜板子上的传感器太少了,玩起来不过瘾,而且他家的开发工具安装起来真有点秃头。感谢群里的各位老师,在老师们的指导下,终于玩起来啦!

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