Funpack第九期:使用SensorTile.box 立方体较大的四个面,实现四个不同的功能
使用SensorTile.box 立方体较大的四个面,实现四个不同的功能
标签
嵌入式系统
wirano
更新2021-06-11
823

板卡介绍

本次funpack活动给我们带来的是来自ST的SensorTile.box。它是一个具有无线物联网和可穿戴传感器平台的即用型套件盒,具备丰富的传感器,包括:

  • 数字温度传感器STTS751
  • 六轴惯性测量单元LSM6DSOX
  • 三轴加速度计LIS2DW12和LIS3DHH
  • 三轴磁力计LIS2MDL
  • 压力传感器LPS22HH
  • 麦克风MP23ABS1
  • 温湿度传感器HTS221

其主控是STM32L4R9,具有DSP和FPU的超低功耗高性能ARM Cortex-M4微控制器,同时具备蓝牙应用处理器BlueNRG-M2模块。

任务介绍

本次我选择的是任务一:使用SensorTile.box 立方体较大的四个面,实现四个不同的功能。

需实现的功能如下:

  • 面1,测量桌面倾斜程度;
  • 面2,测量温度;
  • 面3,测量湿度;
  • 面4,测量气压;

任务分析

  • LSM6DSO 是系统级封装的 3D 数字加速度计和 3D 数字陀螺仪,经过配置,可利用硬件识别出6D 方向(在本次任务中只使用了4个面)并生成中断信号。
  • 桌面倾斜程度可通过LSM6DSO的加速度计数据经姿态解算出的欧拉角获得。
  • 温度通过温湿度传感器HTS221获得
  • 湿度通过温湿度传感器HTS221获得
  • 气压通过压力传感器LPS22HH获得

代码思路

这里我选择的是使用X-CUBE-MEMS1软件包进行开发。作为cube生态的一部分X-CUBE-MEMS1软件包以STM32CUBEMX拓展包的形式提供了ST MEMS传感器的驱动以及简单的应用demo。

任务中用到的传感器均由X-CUBE-MEMS1软件包自带的驱动程序驱动,6D识别使用了其中的MEMS1_Application,姿态解算使用了其中的STM32_MotionTL_Library。

任务数据的显示则是通过一个简单的QT上位机实现。

代码实现

 

传感器初始化

CUSTOM_ENV_SENSOR_Init(CUSTOM_HTS221_0, ENV_TEMPERATURE | ENV_HUMIDITY);
//HTS221初始化
CUSTOM_ENV_SENSOR_Enable(CUSTOM_HTS221_0, ENV_TEMPERATURE | ENV_HUMIDITY);
//HTS211使能温湿度输出
CUSTOM_ENV_SENSOR_Init(CUSTOM_LPS22HH_0, ENV_PRESSURE);
//LPS22HH初始化
CUSTOM_ENV_SENSOR_Enable(CUSTOM_LPS22HH_0, ENV_PRESSURE);
//LPS22HH使能气压输出
CUSTOM_MOTION_SENSOR_SetOutputDataRate(CUSTOM_LSM6DSO_0, MOTION_ACCELERO | MOTION_GYRO, 50);
//设置LSM6DSOX输出速率
CUSTOM_MOTION_SENSOR_GetFullScale(CUSTOM_LSM6DSO_0, MOTION_ACCELERO, &fullscale);

姿态解算配置

MotionTL_Initialize(MTL_MCU_STM32, aco);
//初始化MotionTL库
knobs.fullscale = fullscale;
//配置输入数据量程
knobs.k = 1;
//滤波器系数
knobs.mode = MODE_PITCH_ROLL_GRAVITY_INCLINATION;
//输出模式配置为欧拉角
MotionTL_SetKnobs(&knobs);
//应用配置

6D识别

    uint8_t xl = 0;
    uint8_t xh = 0;
    uint8_t yl = 0;
    uint8_t yh = 0;
    uint8_t zl = 0;
    uint8_t zh = 0;

    extern uint8_t surface;

    if (xl == 0U && yl == 0U && zl == 0U && xh == 0U && yh == 1U && zh == 0U) {
        surface = 4;
        //识别到面4
    } else if (xl == 1U && yl == 0U && zl == 0U && xh == 0U && yh == 0U && zh == 0U) {

    } else if (xl == 0U && yl == 0U && zl == 0U && xh == 1U && yh == 0U && zh == 0U) {

    } else if (xl == 0U && yl == 1U && zl == 0U && xh == 0U && yh == 0U && zh == 0U) {
        surface = 2;
        //识别到面2
    } else if (xl == 0U && yl == 0U && zl == 0U && xh == 0U && yh == 0U && zh == 1U) {
        surface = 1;
         //识别到面1
    } else if (xl == 0U && yl == 0U && zl == 1U && xh == 0U && yh == 0U && zh == 0U) {
        surface = 3;
        //识别到面3
    } else {

    }

//  printf("%s", dataOut);
}

数据获取与发送

void service_4d(void){
    MTL_input_t input_data;
    MTL_output_t output_data;
    CUSTOM_MOTION_SENSOR_AxesRaw_t raw_data;

    float temp,hum,press;

    char buffer[23];
    f2u8 f2u8;

    buffer[0] = 0xaa;
    buffer[22] = 0x55;

    switch (surface) {
        case 0:

            break;
        case 1:
            CUSTOM_MOTION_SENSOR_GetAxesRaw(CUSTOM_LSM6DSO_0, MOTION_ACCELERO, &raw_data);
            input_data.acc_x = raw_data.x / 65535.0 * fullscale * 1.0;
            input_data.acc_y = raw_data.y / 65535.0 * fullscale * 1.0;
            input_data.acc_z = raw_data.z / 65535.0 * fullscale * 1.0;
            MotionTL_Update(&input_data, HAL_GetTick(), &output_data);
            //获取欧拉角
            buffer[1] = 1;
            f2u8.f = output_data.roll_3x;
            buffer[2] = f2u8.u8[3];
            buffer[3] = f2u8.u8[2];
            buffer[4] = f2u8.u8[1];
            buffer[5] = f2u8.u8[0];
            f2u8.f = output_data.pitch_3x;
            buffer[6] = f2u8.u8[3];
            buffer[7] = f2u8.u8[2];
            buffer[8] = f2u8.u8[1];
            buffer[9] = f2u8.u8[0];

//            sprintf(buffer,"%f %f\n", output_data.pitch_3x, output_data.roll_3x);
            break;
        case 2:
            CUSTOM_ENV_SENSOR_GetValue(CUSTOM_HTS221_0,ENV_TEMPERATURE,&temp);
            //获取温度
            buffer[1] = 2;
            f2u8.f = temp;
            buffer[10] = f2u8.u8[3];
            buffer[11] = f2u8.u8[2];
            buffer[12] = f2u8.u8[1];
            buffer[13] = f2u8.u8[0];
//            sprintf(buffer,"temp:%f\n",temp);
            break;
        case 3:
            CUSTOM_ENV_SENSOR_GetValue(CUSTOM_HTS221_0,ENV_HUMIDITY,&hum);
            //获取湿度
            buffer[1] = 3;
            f2u8.f = hum;
            buffer[14] = f2u8.u8[3];
            buffer[15] = f2u8.u8[2];
            buffer[16] = f2u8.u8[1];
            buffer[17] = f2u8.u8[0];
//            sprintf(buffer,"hum:%f\n",hum);
            break;
        case 4:
            CUSTOM_ENV_SENSOR_GetValue(CUSTOM_LPS22HH_0,ENV_PRESSURE,&press);
            //获取气压
            buffer[1] = 4;
            f2u8.f = press;
            buffer[18] = f2u8.u8[3];
            buffer[19] = f2u8.u8[2];
            buffer[20] = f2u8.u8[1];
            buffer[21] = f2u8.u8[0];
//            sprintf(buffer,"press:%f\n",press);
            break;
        default:
            break;
    }

    if(surface != 0) {
        CDC_Transmit_FS(buffer, 23);
        //通过USB虚拟串口发送至上位机
    }
}

上位机实现

import sys
import serial.threaded
import struct

from PyQt5.QtWidgets import QApplication, QMainWindow
from Funpack9_UI import *

from qt_material import apply_stylesheet


# 通信协议实现
class MCUTrans(serial.threaded.FramedPacket):
    START = b'\xaa'
    STOP = b'\x55'

    def handle_packet(self, packet):
        if len(packet) == 21:
            rec_data = struct.unpack('>Bfffff', packet)
            if rec_data[0] == 1:
                funpack.label.setText("面1:桌面倾斜程度")
                funpack.label_2.setText(
                    'rol:' + str(round(rec_data[1], 2)) + '° pit:' + str(round(rec_data[2], 2)) + '°')
            elif rec_data[0] == 2:
                funpack.label.setText("面2:温度")
                funpack.label_2.setText(str(round(rec_data[3], 2)) + '℃')
            elif rec_data[0] == 3:
                funpack.label.setText("面3:湿度")
                funpack.label_2.setText(str(round(rec_data[4], 2)) + '%')
            elif rec_data[0] == 4:
                funpack.label.setText("面4:气压")
                funpack.label_2.setText(str(round(rec_data[5], 2)) + 'hPa')

    def handle_out_of_packet_data(self, data):
        print('out of packet')

# UI类
class FunpackQt(QMainWindow, Ui_MainWindow):

    def __init__(self, parent=None):
        super(FunpackQt, self).__init__(parent)
        self.setupUi(self)

    def clicked(self):
        print("click")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    apply_stylesheet(app, theme='light_red.xml', invert_secondary=True)
    funpack = FunpackQt()
    funpack.show()
    ser = serial.Serial("/dev/ttyACM0", 115200)
    t = serial.threaded.ReaderThread(ser, MCUTrans)
    t.start()
    sys.exit(app.exec_()

结果演示 面1:桌面倾斜程度

FiI9RHdfLdrU3WfG0cifevWrJxuF

面2:温度

FuZEj_bdibWWmwDnkWKxvc2Srlek

面3:湿度

FmatvfoiRSl6WVf5jJokl3CCvmQ1

面4:气压

Fqa7SsJ17NV7BpXMpy0ONXrCEqH-

心得体会

这是我第一次通过ST的评估套件进行开发,不同于以往的通过MCU进行开发。ST强大的生态大大得简化了开发步骤,完善的cube软件包提供了BSP,让我省去了板卡适配环节,MotionTL库节省了姿态解算算法的实现时间。让我再次感受到了ST生态的强大。

十分感谢硬禾,能够提供机会让我们接触到如此优秀的板卡,也希望Funpack能继续办下去,让广大爱好者既能学到东西,又能接触到优秀的硬件。

附件下载
box.zip
Funpack9_UI.zip
团队介绍
团队成员
wirano
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号