Funpack5-4 - 基于FRDM-MCXN236实现环境数据采集与显示
该项目使用了FRDM-MCXN236,实现了环境数据采集与显示的设计,它的主要功能为:基于zephyr实现 环境数据的采集与显示 :通过 I2C 总线采集三轴加速度、温度、湿度等环境数据,经处理后实时显示在 OLED 屏上,并可通过按键切换显示界面。。
标签
嵌入式系统
Funpack活动
显示
zephyer
fly_lv
更新2026-10-19
5

一、项目介绍

本项目是一个以 NXP FRDM-MCXN236 开发板为平台,基于zephyr实现 环境数据的采集与显示 :通过 I2C 总线采集三轴加速度、温度、湿度等环境数据,经处理后实时显示在 OLED 屏上,并可通过按键切换显示界面。


二、硬件部分


FRDM-MCXN236:FRDM-MCXN236是一款紧凑且可扩展的开发板,可让您快速基于MCX N23x MCU开展原型设计。它们提供行业标准的接口,可轻松访问MCU的I/O、集成的开放标准串行接口、外部闪存和板载MCU-Link调试器。


image.png


0.96寸OLED:OLED是有机发光二极管,又称为有机电激光显示(Organic Electroluminescence Display, OLED)。OLED由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为是下一代的平面显示器新兴应用技术


image.png


sht45:SHT45 传感器是第四代产品(从 SHT10 起步,一路发展至巅峰)。SHT45 在 20% 至 70% 的相对湿度范围内具有出色的 ±1.0% 典型精度,在 5°C 至 60°C 范围内具有 ±0.1°C 的典型精度。

image.png



FXLS8974CFR3:FXLS8974CF是一款紧凑型3轴MEMS加速度计,适用于多种需要超低功耗运动唤醒的工业和医疗物联网应用,支持高性能和低功耗两种工作模式,可最大程度灵活满足不同应用场景对分辨率和功耗的需求。多种先进的集成数字功能可帮助设计人员降低整体系统功耗,简化主机数据采集工作。该产品采用2mm×2mm×0.95mm 10引脚DFN封装,引脚间距0.4mm,带可润湿侧翼,符合工业标准,可在-40℃至+105℃的扩展温度范围内工作,结合传感器性能、系统节能功能与宽温工作性能,适合物联网领域的运动感应应用。


image.png



三、软件部分

软件流程图

image.png


软件部分


开启了一个线程进行温湿度数据的获取,通过互斥锁保护数据的存储

static void env_thread(void *p1, void *p2, void *p3)
{
    ARG_UNUSED(p1);
    ARG_UNUSED(p2);
    ARG_UNUSED(p3);


    while (1) {
        struct sensor_value temp;
        struct sensor_value hum;


        if (sensor_sample_fetch(sht45) < 0) {
            printf("SHT45 sample fetch failed\n");
        } else if (sensor_channel_get(sht45, SENSOR_CHAN_AMBIENT_TEMP,
                         &temp) < 0 ||
               sensor_channel_get(sht45, SENSOR_CHAN_HUMIDITY, &hum) < 0) {
            printf("SHT45 channel get failed\n");
        } else {
            /* sensor_value_to_centi() 来自 sensor.h,返回 0.01 单位的 int64_t */
            int64_t t = sensor_value_to_centi(&temp);
            int64_t rh = sensor_value_to_centi(&hum);


            /* 串口打印:手工拆出整数位和两位小数,避免用 %f */
            int t_int = (int)(t / 100);
            int t_frac = (int)(t % 100);


            if (t_frac < 0) {
                t_frac = -t_frac;
            }


            printf("[env] T=%d.%02d C  RH=%d.%02d %%\n",
                   t_int, t_frac, (int)(rh / 100), (int)(rh % 100));


            k_mutex_lock(&state_lock, K_FOREVER);
            state.temp_c = (int16_t)CLAMP(t, (int64_t)INT16_MIN,
                              (int64_t)INT16_MAX);
            state.rh_pct = (uint16_t)CLAMP(rh, (int64_t)0,
                               (int64_t)UINT16_MAX);
            state.env_valid = true;
            k_mutex_unlock(&state_lock);
        }


        k_msleep(ENV_PERIOD_MS);
    }
}



创建一个线程先进行加速度计的初始化,然后通过i2c获取加速度数据,同样通过互斥锁存储数据

static void accel_thread(void *p1, void *p2, void *p3)
{
    ARG_UNUSED(p1);
    ARG_UNUSED(p2);
    ARG_UNUSED(p3);


    while (1) {
        struct sensor_value x;
        struct sensor_value y;
        struct sensor_value z;


        if (sensor_sample_fetch(accel) < 0) {
            printf("accel sample fetch failed\n");
        } else if (sensor_channel_get(accel, SENSOR_CHAN_ACCEL_X, &x) < 0 ||
               sensor_channel_get(accel, SENSOR_CHAN_ACCEL_Y, &y) < 0 ||
               sensor_channel_get(accel, SENSOR_CHAN_ACCEL_Z, &z) < 0) {
            printf("accel channel get failed\n");
        } else {
            int x_mg = accel_to_mg(&x);
            int y_mg = accel_to_mg(&y);
            int z_mg = accel_to_mg(&z);


            /* 串口打印:printf 未开浮点支持,这里用整数 mg 输出 */
            printf("[accel] X=%+5d mg  Y=%+5d mg  Z=%+5d mg\n",
                   x_mg, y_mg, z_mg);


            k_mutex_lock(&state_lock, K_FOREVER);
            state.x_mg = x_mg;
            state.y_mg = y_mg;
            state.z_mg = z_mg;
            state.accel_valid = true;
            k_mutex_unlock(&state_lock);
        }


        k_msleep(ACCEL_PERIOD_MS);
    }
}


下面代码把获取到的x,y,z数据映射到屏幕的圆点,达到倾斜开发板,对应屏幕上的小球也会进行相应的运动

static void draw_bubble_screen(const struct sensor_state *st)
{
    const struct cfb_position center = { .x = CENTER_X, .y = CENTER_Y };
    const struct cfb_position h_start = { .x = CENTER_X - BUBBLE_RADIUS, .y = CENTER_Y };
    const struct cfb_position h_end = { .x = CENTER_X + BUBBLE_RADIUS, .y = CENTER_Y };
    const struct cfb_position v_start = { .x = CENTER_X, .y = CENTER_Y - BUBBLE_RADIUS };
    const struct cfb_position v_end = { .x = CENTER_X, .y = CENTER_Y + BUBBLE_RADIUS };
    int limit = BUBBLE_RADIUS - DOT_RADIUS - 1;
    /* +X 向右、+Y 向上,屏幕坐标 y 轴朝下所以要取反 */
    int dx = CLAMP(st->x_mg * BUBBLE_RADIUS / TILT_FULL_SCALE_MG, -limit, limit);
    int dy = CLAMP(-st->y_mg * BUBBLE_RADIUS / TILT_FULL_SCALE_MG, -limit, limit);


    cfb_print(oled, "BUBBLE 1/3", 0, 0);
    cfb_draw_circle(oled, &center, BUBBLE_RADIUS);
    cfb_draw_line(oled, &h_start, &h_end);
    cfb_draw_line(oled, &v_start, &v_end);
    draw_filled_dot(CENTER_X + dx, CENTER_Y + dy, DOT_RADIUS);
}





四、项目展示

可以通过sw2按键进行界面的切换

水平仪界面:倾斜开发板,中间的小球会随着移植

image.png


加速度界面:会实时显示获取的加速度

image.png


温湿度数据界面,通过iic获取sht45的温湿度数据,然后显示再oled屏幕上面

image.png


串口输出数据

image.png



五、心得体会

通过这次活动让我更加深入的体会到了zephyr的便捷性,不需要更改上层代码,只需要更改对应的设备树就能完成项目的移植,也让体会到mcxn236这颗芯片的性能。



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