基于STM32的智能防久坐与健康办公系统

举报
DS小龙哥 发表于 2025/12/25 11:57:00 2025/12/25
【摘要】 项目开发背景随着现代办公环境的普及和信息技术的快速发展,越来越多的人群需要长时间在办公桌前工作,导致久坐成为日常生活中的普遍现象。研究表明,持续久坐不仅会引发颈椎和腰椎疾病,还可能增加肥胖、心血管问题及代谢综合征的风险,严重影响工作效率与个人健康。传统的健康提醒方式往往依赖于简单的定时器或手动设置,缺乏智能化和实时性,用户容易因工作专注而忽略提醒,无法有效改善坐姿习惯。此外,单一传感器监测...

项目开发背景

随着现代办公环境的普及和信息技术的快速发展,越来越多的人群需要长时间在办公桌前工作,导致久坐成为日常生活中的普遍现象。研究表明,持续久坐不仅会引发颈椎和腰椎疾病,还可能增加肥胖、心血管问题及代谢综合征的风险,严重影响工作效率与个人健康。

传统的健康提醒方式往往依赖于简单的定时器或手动设置,缺乏智能化和实时性,用户容易因工作专注而忽略提醒,无法有效改善坐姿习惯。此外,单一传感器监测的局限性难以全面反映用户的在位状态和坐姿变化,亟需一种集成多传感器与智能提醒的综合解决方案。

为此,本项目基于STM32微控制器开发智能防久坐与健康办公系统,通过超声波模块实时监测用户与桌面的距离,结合压力传感器检测坐姿持续时间,并集成温湿度传感器提供环境健康数据。系统能够在用户久坐超时后,自动触发灯光和语音提醒,同时通过OLED显示屏直观展示关键信息,旨在以低成本、高效率的方式帮助用户养成健康办公习惯。

该系统不仅提升了健康监测的精准性和用户体验,还通过多模态交互增强提醒效果,预期能有效降低久坐带来的健康风险,促进办公环境的智能化与人性化改进。

设计实现的功能

(1) 使用超声波模块监测用户与桌面的距离,判断用户是否在位。
(2) 通过压力传感器检测用户是否长时间保持坐姿。
(3) 用户久坐超过设定时间(如1小时),系统通过灯光和语音进行提醒。
(4) 通过OLED屏幕显示在座时长、环境温湿度等健康信息。

项目硬件模块组成

(1)主控芯片:STM32F103C8T6单片机。
(2)传感模块:HC-SR04超声波模块、HX711压力传感器模块、DHT11温湿度传感器。
(3)显示与提醒:0.96英寸OLED显示屏、WS2812 RGB灯带、SYN6288语音模块。

设计意义

该系统设计旨在通过智能监测和提醒机制,有效帮助办公人群避免因长时间久坐而引发的健康问题,如颈椎劳损、腰椎疾病和血液循环不畅等,从而提升整体工作效率和生活质量。通过集成超声波模块和压力传感器,系统能够准确判断用户是否在位及坐姿持续时间,并在超过设定阈值时自动触发灯光和语音提醒,引导用户适时活动身体,减少久坐带来的潜在风险。

此外,系统通过OLED显示屏实时展示在座时长和环境温湿度数据,使用户能够直观了解自身办公状态和周围条件,促进健康意识的养成。这种集成化的设计不仅体现了嵌入式系统在健康领域的实用价值,还为现代办公环境提供了一种低成本、高效的解决方案,有助于培养良好的工作习惯。

设计思路

本系统以STM32F103C8T6单片机为核心控制器,通过集成多种传感器和执行模块实现智能防久坐与健康办公功能。系统首先利用HC-SR04超声波模块持续监测用户与桌面的距离,当距离在一定范围内时判定用户处于在位状态;同时,HX711压力传感器模块检测座椅压力变化,确认用户是否保持坐姿。这些传感器数据由STM32实时采集和处理,用于综合判断用户行为状态。

在用户状态判断基础上,系统通过内部计时器累计用户连续坐姿时间。如果坐姿持续时间超过预设阈值(例如1小时),STM32会触发提醒机制:一方面控制WS2812 RGB灯带发出特定颜色的光效作为视觉提示,另一方面驱动SYN6288语音模块播放定制语音内容,提醒用户起身活动,从而避免久坐带来的健康风险。

此外,系统集成DHT11温湿度传感器采集环境数据,并结合在位时长等信息,通过0.96英寸OLED显示屏实时显示。OLED屏幕以清晰界面展示当前在座时长、环境温度和湿度等健康相关参数,方便用户随时查看,增强办公环境的健康管理意识。

整个系统设计注重模块间的协同工作,STM32负责统一调度传感器数据采集、状态判断、提醒触发和显示更新,确保各硬件模块高效稳定运行。所有功能均基于实际需求实现,无需额外添加,最终形成一个完整的防久坐与健康办公解决方案。

框架图

+----------------+    +----------------+    +----------------+
|   传感模块     |    |   处理模块     |    |   输出模块     |
|                |    |                |    |                |
| - HC-SR04      |--->| - STM32        |--->| - OLED         |
|   超声波       |    |   F103C8T6     |    |   显示屏       |
| - HX711        |    |                |    | - WS2812       |
|   压力传感器   |    |                |    |   RGB灯带      |
| - DHT11        |    |                |    | - SYN6288      |
|   温湿度       |    |                |    |   语音模块     |
+----------------+    +----------------+    +----------------+

系统总体设计

本系统基于STM32F103C8T6单片机作为核心控制器,旨在实现智能防久坐与健康办公功能。系统通过集成多种传感器和输出模块,实时监测用户状态并提供健康提醒,以促进办公环境的健康管理。

系统采用HC-SR04超声波模块检测用户与桌面的距离,从而判断用户是否在位;同时,HX711压力传感器模块用于监测用户坐姿压力,以识别长时间保持坐姿的情况。这些传感器数据由STM32主控芯片实时采集和处理,结合DHT11温湿度传感器获取的环境数据,形成全面的用户状态监测。

主控芯片对采集的数据进行分析,当检测到用户久坐时间超过预设阈值(如1小时)时,系统会触发提醒机制。提醒通过WS2812 RGB灯带发出灯光信号,并利用SYN6288语音模块播放语音提示,以引导用户适时活动。

系统还集成0.96英寸OLED显示屏,用于实时显示用户在座时长、环境温湿度等健康信息,方便用户随时查看。整个设计注重实用性和可靠性,各硬件模块协同工作,确保系统稳定运行并有效达成防久坐目标。

系统功能总结

功能名称 功能描述 相关硬件模块
用户在位监测 使用超声波模块监测用户与桌面的距离,判断用户是否在位。 HC-SR04超声波模块
坐姿检测 通过压力传感器检测用户是否长时间保持坐姿。 HX711压力传感器模块
久坐提醒 用户久坐超过设定时间(如1小时),系统通过灯光和语音进行提醒。 WS2812 RGB灯带、SYN6288语音模块
健康信息显示 通过OLED屏幕显示在座时长、环境温湿度等健康信息。 0.96英寸OLED显示屏、DHT11温湿度传感器

设计的各个功能模块描述

STM32F103C8T6单片机作为系统的核心控制器,负责协调和处理所有传感器数据及输出设备的控制。它通过内部程序逻辑实现数据的采集、分析和决策,确保系统稳定运行,并执行防久坐与健康办公的自动化功能。

HC-SR04超声波模块用于监测用户与桌面的距离,通过发射和接收超声波信号来计算实际距离值,从而判断用户是否在位。当检测到用户离开座位时,系统会暂停或重置久坐计时,以准确反映用户状态。

HX711压力传感器模块安装在座椅上,通过检测压力变化来判断用户是否长时间保持坐姿。该模块将压力数据转换为电信号,供主控芯片分析,并与计时功能结合,识别久坐行为。

DHT11温湿度传感器用于采集办公环境的温度和湿度数据,提供实时环境信息。这些数据被传输到主控芯片,用于后续显示和健康监测,帮助用户了解周围条件。

0.96英寸OLED显示屏用于直观显示用户的在座时长、环境温湿度等健康信息。它通过清晰的文本和图形界面,为用户提供实时反馈,方便随时查看系统状态。

WS2812 RGB灯带作为视觉提醒装置,当用户久坐超过设定时间时,会通过改变灯光颜色或闪烁模式发出警示。这种视觉信号能有效吸引用户注意,促使其起身活动。

SYN6288语音模块用于生成语音提醒,在检测到久坐行为时播放预设的语音消息,如“请起身休息”。该模块通过音频输出增强提醒效果,确保用户及时响应系统提示。

上位机代码设计

#include <windows.h>
#include <iostream>
#include <string>
#include <sstream>
#include <thread>
#include <chrono>

// 串口配置
HANDLE hSerial;
const int BAUD_RATE = 9600;
const int DATA_BITS = 8;
const int STOP_BITS = ONESTOPBIT;
const int PARITY = NOPARITY;

// 健康数据存储结构
struct HealthData {
    float distance;
    float pressure;
    float temperature;
    float humidity;
    int presence;
    int sittingTime;
};

// 打开串口
bool openSerialPort(const char* portName) {
    hSerial = CreateFileA(portName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hSerial == INVALID_HANDLE_VALUE) {
        std::cerr << "Error opening serial port!" << std::endl;
        return false;
    }

    DCB dcbSerialParams = {0};
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
    if (!GetCommState(hSerial, &dcbSerialParams)) {
        std::cerr << "Error getting serial port state!" << std::endl;
        return false;
    }

    dcbSerialParams.BaudRate = BAUD_RATE;
    dcbSerialParams.ByteSize = DATA_BITS;
    dcbSerialParams.StopBits = STOP_BITS;
    dcbSerialParams.Parity = PARITY;
    if (!SetCommState(hSerial, &dcbSerialParams)) {
        std::cerr << "Error setting serial port state!" << std::endl;
        return false;
    }

    COMMTIMEOUTS timeouts = {0};
    timeouts.ReadIntervalTimeout = 50;
    timeouts.ReadTotalTimeoutConstant = 50;
    timeouts.ReadTotalTimeoutMultiplier = 10;
    timeouts.WriteTotalTimeoutConstant = 50;
    timeouts.WriteTotalTimeoutMultiplier = 10;
    if (!SetCommTimeouts(hSerial, &timeouts)) {
        std::cerr << "Error setting timeouts!" << std::endl;
        return false;
    }

    return true;
}

// 读取串口数据
std::string readSerialData() {
    char buffer[256];
    DWORD bytesRead;
    std::string data;
    if (ReadFile(hSerial, buffer, sizeof(buffer) - 1, &bytesRead, NULL)) {
        buffer[bytesRead] = '\0';
        data = buffer;
    }
    return data;
}

// 解析数据
HealthData parseData(const std::string& data) {
    HealthData hd = {0};
    std::stringstream ss(data);
    std::string token;

    while (std::getline(ss, token, ',')) {
        size_t colonPos = token.find(':');
        if (colonPos != std::string::npos) {
            std::string key = token.substr(0, colonPos);
            std::string value = token.substr(colonPos + 1);

            if (key == "DIST") hd.distance = std::stof(value);
            else if (key == "PRESS") hd.pressure = std::stof(value);
            else if (key == "TEMP") hd.temperature = std::stof(value);
            else if (key == "HUM") hd.humidity = std::stof(value);
            else if (key == "PRESENCE") hd.presence = std::stoi(value);
            else if (key == "SITTING") hd.sittingTime = std::stoi(value);
        }
    }
    return hd;
}

// 语音提醒(使用Windows Beep)
void voiceAlert() {
    Beep(1000, 500); // 频率1000Hz,持续时间500ms
    Beep(1500, 500);
}

// 灯光提醒(改变控制台颜色)
void lightAlert() {
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hConsole, BACKGROUND_RED); // 红色背景
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    SetConsoleTextAttribute(hConsole, BACKGROUND_GREEN); // 绿色背景
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    SetConsoleTextAttribute(hConsole, BACKGROUND_BLUE); // 蓝色背景
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    SetConsoleTextAttribute(hConsole, 7); // 恢复默认
}

// 显示健康信息
void displayHealthInfo(const HealthData& hd) {
    system("cls"); // 清屏
    std::cout << "=== 智能防久坐与健康办公系统 ===" << std::endl;
    std::cout << "在座时长: " << hd.sittingTime << " 秒" << std::endl;
    std::cout << "环境温度: " << hd.temperature << " °C" << std::endl;
    std::cout << "环境湿度: " << hd.humidity << " %" << std::endl;
    std::cout << "用户距离: " << hd.distance << " cm" << std::endl;
    std::cout << "压力值: " << hd.pressure << std::endl;
    std::cout << "在位状态: " << (hd.presence ? "在位" : "离位") << std::endl;
    std::cout << "===============================" << std::endl;
}

int main() {
    const char* portName = "COM3"; // 根据实际串口修改
    const int SITTING_THRESHOLD = 3600; // 久坐阈值(秒)

    if (!openSerialPort(portName)) {
        return -1;
    }

    std::cout << "串口打开成功,开始监控..." << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(2));

    while (true) {
        std::string data = readSerialData();
        if (!data.empty()) {
            HealthData hd = parseData(data);
            displayHealthInfo(hd);

            // 久坐提醒
            if (hd.sittingTime >= SITTING_THRESHOLD) {
                std::cout << "警告:您已久坐超过1小时,请起身活动!" << std::endl;
                std::thread voiceThread(voiceAlert);
                std::thread lightThread(lightAlert);
                voiceThread.join();
                lightThread.join();
            }
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // 每秒更新
    }

    CloseHandle(hSerial);
    return 0;
}

模块代码设计

#include "stm32f10x.h"

// 引脚定义
#define ULTRASONIC_TRIG_PIN    GPIO_Pin_0
#define ULTRASONIC_ECHO_PIN    GPIO_Pin_1
#define ULTRASONIC_PORT        GPIOA

#define HX711_SCK_PIN          GPIO_Pin_2
#define HX711_DOUT_PIN         GPIO_Pin_3
#define HX711_PORT             GPIOA

#define DHT11_PIN              GPIO_Pin_4
#define DHT11_PORT             GPIOA

#define WS2812_PIN             GPIO_Pin_0
#define WS2812_PORT            GPIOB

#define OLED_SCL_PIN           GPIO_Pin_6
#define OLED_SDA_PIN           GPIO_Pin_7
#define OLED_PORT              GPIOB

#define SYN6288_TX_PIN         GPIO_Pin_2
#define SYN6288_RX_PIN         GPIO_Pin_3
#define SYN6288_PORT           GPIOA

// 全局变量
volatile uint32_t ultrasonic_distance = 0;
volatile uint32_t pressure_value = 0;
volatile uint8_t temperature = 0;
volatile uint8_t humidity = 0;
volatile uint32_t sit_time = 0;
volatile uint8_t user_present = 0;

// 延时函数
void delay_us(uint32_t us)
{
    us *= 8;
    while(us--)
    {
        __NOP();
    }
}

void delay_ms(uint32_t ms)
{
    while(ms--)
    {
        delay_us(1000);
    }
}

// 超声波模块HC-SR04
void ultrasonic_init(void)
{
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
    
    // TRIG输出模式
    ULTRASONIC_PORT->CRL &= ~(0xF << (0*4));
    ULTRASONIC_PORT->CRL |= (0x3 << (0*4));
    
    // ECHO输入模式
    ULTRASONIC_PORT->CRL &= ~(0xF << (1*4));
    ULTRASONIC_PORT->CRL |= (0x4 << (1*4));
}

uint32_t ultrasonic_get_distance(void)
{
    uint32_t timeout = 0;
    uint32_t time_high = 0;
    
    // 发送10us高电平触发信号
    ULTRASONIC_PORT->BSRR = ULTRASONIC_TRIG_PIN;
    delay_us(10);
    ULTRASONIC_PORT->BRR = ULTRASONIC_TRIG_PIN;
    
    // 等待回响信号变高
    timeout = 10000;
    while(!(ULTRASONIC_PORT->IDR & ULTRASONIC_ECHO_PIN))
    {
        if(--timeout == 0) return 0;
    }
    
    // 测量高电平时间
    time_high = 0;
    while(ULTRASONIC_PORT->IDR & ULTRASONIC_ECHO_PIN)
    {
        delay_us(1);
        time_high++;
        if(time_high > 30000) break; // 超时
    }
    
    // 计算距离 (cm) = 时间(us) / 58
    return time_high / 58;
}

// HX711压力传感器
void hx711_init(void)
{
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
    
    // SCK输出模式
    HX711_PORT->CRL &= ~(0xF << (2*4));
    HX711_PORT->CRL |= (0x3 << (2*4));
    
    // DOUT输入模式
    HX711_PORT->CRL &= ~(0xF << (3*4));
    HX711_PORT->CRL |= (0x4 << (3*4));
    
    HX711_PORT->BRR = HX711_SCK_PIN;
}

uint32_t hx711_read(void)
{
    uint32_t count = 0;
    uint8_t i;
    
    // 等待DOUT变低
    while(HX711_PORT->IDR & HX711_DOUT_PIN);
    
    for(i=0; i<24; i++)
    {
        HX711_PORT->BSRR = HX711_SCK_PIN;
        delay_us(1);
        count = count << 1;
        HX711_PORT->BRR = HX711_SCK_PIN;
        delay_us(1);
        
        if(HX711_PORT->IDR & HX711_DOUT_PIN)
            count++;
    }
    
    // 第25个脉冲选择通道和增益
    HX711_PORT->BSRR = HX711_SCK_PIN;
    delay_us(1);
    HX711_PORT->BRR = HX711_SCK_PIN;
    delay_us(1);
    
    return count ^ 0x800000;
}

// DHT11温湿度传感器
void dht11_init(void)
{
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
    
    // 开漏输出模式
    DHT11_PORT->CRL &= ~(0xF << (4*4));
    DHT11_PORT->CRL |= (0x6 << (4*4));
}

uint8_t dht11_read_byte(void)
{
    uint8_t i, data = 0;
    
    for(i=0; i<8; i++)
    {
        while(!(DHT11_PORT->IDR & DHT11_PIN));
        delay_us(40);
        
        data <<= 1;
        if(DHT11_PORT->IDR & DHT11_PIN)
            data |= 1;
            
        while(DHT11_PORT->IDR & DHT11_PIN);
    }
    
    return data;
}

uint8_t dht11_read_data(uint8_t *temp, uint8_t *humi)
{
    uint8_t buf[5];
    uint8_t i;
    
    // 主机发送开始信号
    DHT11_PORT->BRR = DHT11_PIN;
    delay_ms(18);
    DHT11_PORT->BSRR = DHT11_PIN;
    delay_us(30);
    
    // 切换为输入模式
    DHT11_PORT->CRL &= ~(0xF << (4*4));
    DHT11_PORT->CRL |= (0x4 << (4*4));
    
    // 等待DHT11响应
    if(DHT11_PORT->IDR & DHT11_PIN) return 0;
    delay_us(80);
    if(!(DHT11_PORT->IDR & DHT11_PIN)) return 0;
    delay_us(80);
    
    // 读取40位数据
    for(i=0; i<5; i++)
        buf[i] = dht11_read_byte();
    
    // 切换回输出模式
    DHT11_PORT->CRL &= ~(0xF << (4*4));
    DHT11_PORT->CRL |= (0x6 << (4*4));
    DHT11_PORT->BSRR = DHT11_PIN;
    
    // 校验数据
    if(buf[4] == (buf[0] + buf[1] + buf[2] + buf[3]))
    {
        *humi = buf[0];
        *temp = buf[2];
        return 1;
    }
    
    return 0;
}

// WS2812 RGB灯带
void ws2812_init(void)
{
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
    
    // 推挽输出
    WS2812_PORT->CRL &= ~(0xF << (0*4));
    WS2812_PORT->CRL |= (0x3 << (0*4));
}

void ws2812_send_bit(uint8_t bit_val)
{
    if(bit_val)
    {
        WS2812_PORT->BSRR = WS2812_PIN;
        delay_us(0.9);
        WS2812_PORT->BRR = WS2812_PIN;
        delay_us(0.35);
    }
    else
    {
        WS2812_PORT->BSRR = WS2812_PIN;
        delay_us(0.35);
        WS2812_PORT->BRR = WS2812_PIN;
        delay_us(0.9);
    }
}

void ws2812_send_byte(uint8_t byte_val)
{
    uint8_t i;
    for(i=0; i<8; i++)
    {
        ws2812_send_bit(byte_val & 0x80);
        byte_val <<= 1;
    }
}

void ws2812_set_color(uint8_t red, uint8_t green, uint8_t blue)
{
    ws2812_send_byte(green);
    ws2812_send_byte(red);
    ws2812_send_byte(blue);
    delay_us(50);
}

// OLED显示 (SSD1306, I2C)
void oled_i2c_init(void)
{
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
    
    // PB6-SCL, PB7-SDA 复用开漏输出
    OLED_PORT->CRL &= ~(0xFF << (6*4));
    OLED_PORT->CRL |= (0x66 << (6*4));
    
    // I2C1配置
    I2C1->CR1 &= ~I2C_CR1_PE;
    I2C1->CR2 = 36; // 36MHz
    I2C1->CCR = 180; // 100kHz
    I2C1->TRISE = 37;
    I2C1->CR1 |= I2C_CR1_PE;
}

void oled_i2c_write(uint8_t addr, uint8_t *data, uint16_t len)
{
    // 发送起始条件
    I2C1->CR1 |= I2C_CR1_START;
    while(!(I2C1->SR1 & I2C_SR1_SB));
    
    // 发送设备地址
    I2C1->DR = addr;
    while(!(I2C1->SR1 & I2C_SR1_ADDR));
    (void)I2C1->SR2;
    
    // 发送数据
    while(len--)
    {
        while(!(I2C1->SR1 & I2C_SR1_TXE));
        I2C1->DR = *data++;
    }
    
    // 发送停止条件
    while(!(I2C1->SR1 & I2C_SR1_BTF));
    I2C1->CR1 |= I2C_CR1_STOP;
}

void oled_write_cmd(uint8_t cmd)
{
    uint8_t buf[2] = {0x00, cmd};
    oled_i2c_write(0x78, buf, 2);
}

void oled_write_data(uint8_t data)
{
    uint8_t buf[2] = {0x40, data};
    oled_i2c_write(0x78, buf, 2);
}

void oled_init(void)
{
    oled_i2c_init();
    delay_ms(100);
    
    oled_write_cmd(0xAE); // 关闭显示
    oled_write_cmd(0x20); // 内存地址模式
    oled_write_cmd(0x10);
    oled_write_cmd(0xB0);
    oled_write_cmd(0xC8);
    oled_write_cmd(0x00);
    oled_write_cmd(0x10);
    oled_write_cmd(0x40);
    oled_write_cmd(0x81);
    oled_write_cmd(0xFF);
    oled_write_cmd(0xA1);
    oled_write_cmd(0xA6);
    oled_write_cmd(0xA8);
    oled_write_cmd(0x3F);
    oled_write_cmd(0xA4);
    oled_write_cmd(0xD3);
    oled_write_cmd(0x00);
    oled_write_cmd(0xD5);
    oled_write_cmd(0xF0);
    oled_write_cmd(0xD9);
    oled_write_cmd(0x22);
    oled_write_cmd(0xDA);
    oled_write_cmd(0x12);
    oled_write_cmd(0xDB);
    oled_write_cmd(0x20);
    oled_write_cmd(0x8D);
    oled_write_cmd(0x14);
    oled_write_cmd(0xAF); // 开启显示
}

void oled_clear(void)
{
    uint8_t i, j;
    for(i=0; i<8; i++)
    {
        oled_write_cmd(0xB0 + i);
        oled_write_cmd(0x00);
        oled_write_cmd(0x10);
        for(j=0; j<128; j++)
            oled_write_data(0x00);
    }
}

void oled_show_string(uint8_t x, uint8_t y, char *str)
{
    // 简化实现 - 实际需要字库
    oled_write_cmd(0xB0 + y);
    oled_write_cmd(((x & 0xF0) >> 4) | 0x10);
    oled_write_cmd(x & 0x0F);
    
    while(*str)
    {
        oled_write_data(*str++);
    }
}

// SYN6288语音模块
void syn6288_init(void)
{
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
    
    // USART1 TX推挽输出,RX浮空输入
    SYN6288_PORT->CRL &= ~(0xFF << (2*4));
    SYN6288_PORT->CRL |= (0x4B << (2*4));
    
    // USART1配置
    USART1->BRR = 0x1D4C; // 9600 @36MHz
    USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
}

void syn6288_speak(char *text)
{
    while(*text)
    {
        while(!(USART1->SR & USART_SR_TXE));
        USART1->DR = *text++;
    }
}

// 系统定时器
void systick_init(void)
{
    SysTick->LOAD = 9000 - 1; // 1ms中断
    SysTick->VAL = 0;
    SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | 
                   SysTick_CTRL_TICKINT_Msk | 
                   SysTick_CTRL_ENABLE_Msk;
}

void SysTick_Handler(void)
{
    static uint32_t timer_1s = 0;
    
    timer_1s++;
    if(timer_1s >= 1000) // 1秒
    {
        timer_1s = 0;
        if(user_present)
        {
            sit_time++;
        }
    }
}

// 主函数
int main(void)
{
    // 系统时钟配置
    SystemInit();
    
    // 初始化各模块
    ultrasonic_init();
    hx711_init();
    dht11_init();
    ws2812_init();
    oled_init();
    syn6288_init();
    systick_init();
    
    oled_clear();
    oled_show_string(0, 0, "Health Monitor");
    
    while(1)
    {
        // 检测用户是否在位
        ultrasonic_distance = ultrasonic_get_distance();
        if(ultrasonic_distance < 50 && ultrasonic_distance > 10)
        {
            user_present = 1;
        }
        else
        {
            user_present = 0;
            sit_time = 0;
        }
        
        // 读取压力传感器
        pressure_value = hx711_read();
        
        // 读取温湿度
        dht11_read_data(&temperature, &humidity);
        
        // 更新OLED显示
        char buffer[20];
        sprintf(buffer, "Sit:%lum", sit_time/60);
        oled_show_string(0, 2, buffer);
        
        sprintf(buffer, "Temp:%uC", temperature);
        oled_show_string(0, 4, buffer);
        
        sprintf(buffer, "Humi:%u%%", humidity);
        oled_show_string(0, 6, buffer);
        
        // 久坐提醒
        if(sit_time >= 3600) // 1小时
        {
            // RGB灯红色闪烁
            ws2812_set_color(255, 0, 0);
            delay_ms(500);
            ws2812_set_color(0, 0, 0);
            delay_ms(500);
            
            // 语音提醒
            syn6288_speak("Please stand up and move around");
            
            sit_time = 0; // 重置计时
        }
        
        delay_ms(1000);
    }
}

项目核心代码

#include "stm32f10x.h"
#include "ultrasonic.h"
#include "pressure.h"
#include "dht11.h"
#include "oled.h"
#include "ws2812.h"
#include "syn6288.h"

// 系统状态定义
typedef enum {
    USER_ABSENT = 0,
    USER_PRESENT,
    WARNING_ACTIVE
} SystemState;

// 全局变量
volatile uint32_t sit_time = 0;        // 久坐时间(秒)
volatile uint32_t warning_time = 3600; // 提醒时间阈值(1小时)
volatile SystemState system_state = USER_ABSENT;
volatile uint32_t system_tick = 0;

// 系统时钟初始化
void SysTick_Init(void) {
    SysTick->CTRL = 0;
    SysTick->LOAD = 9000 - 1;  // 1ms中断
    SysTick->VAL = 0;
    SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk |
                   SysTick_CTRL_ENABLE_Msk;
}

// GPIO初始化
void GPIO_Init(void) {
    // 使能GPIO时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN;
    
    // 初始化LED指示灯
    GPIOA->CRL &= 0xFF0FFFFF;
    GPIOA->CRL |= 0x00300000;  // PA5推挽输出
}

// 系统时钟中断服务函数
void SysTick_Handler(void) {
    system_tick++;
    
    // 每秒更新一次
    if(system_tick % 1000 == 0) {
        if(system_state == USER_PRESENT) {
            sit_time++;
        }
    }
}

// 用户状态检测
SystemState CheckUserStatus(void) {
    float distance = Ultrasonic_GetDistance();
    uint32_t pressure = Pressure_GetValue();
    
    // 判断用户是否在位
    if(distance < 50.0 && pressure > 100) {  // 距离<50cm且压力>100
        return USER_PRESENT;
    } else {
        return USER_ABSENT;
    }
}

// 显示健康信息
void DisplayHealthInfo(void) {
    DHT11_Data dht_data;
    DHT11_Read(&dht_data);
    
    OLED_Clear();
    OLED_ShowString(0, 0, "Sit Time:");
    OLED_ShowNum(72, 0, sit_time/60, 2);  // 显示分钟
    OLED_ShowString(96, 0, "min");
    
    OLED_ShowString(0, 2, "Temp:");
    OLED_ShowNum(48, 2, dht_data.temperature, 2);
    OLED_ShowString(72, 2, "C");
    
    OLED_ShowString(0, 4, "Humidity:");
    OLED_ShowNum(72, 4, dht_data.humidity, 2);
    OLED_ShowString(96, 4, "%");
    
    // 显示状态
    switch(system_state) {
        case USER_ABSENT:
            OLED_ShowString(0, 6, "Status: Absent");
            break;
        case USER_PRESENT:
            OLED_ShowString(0, 6, "Status: Working");
            break;
        case WARNING_ACTIVE:
            OLED_ShowString(0, 6, "Status: Warning!");
            break;
    }
}

// 久坐提醒
void SittingWarning(void) {
    if(system_state == WARNING_ACTIVE) {
        // RGB灯带红色闪烁
        WS2812_SetColor(255, 0, 0);
        delay_ms(500);
        WS2812_SetColor(0, 0, 0);
        delay_ms(500);
        
        // 语音提醒
        SYN6288_Speech("Please stand up and move around");
    }
}

// 系统状态管理
void SystemStateManager(void) {
    SystemState new_state = CheckUserStatus();
    
    switch(system_state) {
        case USER_ABSENT:
            if(new_state == USER_PRESENT) {
                system_state = USER_PRESENT;
                sit_time = 0;  // 重置计时
                WS2812_SetColor(0, 255, 0);  // 绿色表示正常
            }
            break;
            
        case USER_PRESENT:
            if(new_state == USER_ABSENT) {
                system_state = USER_ABSENT;
                WS2812_SetColor(0, 0, 0);  // 关闭灯带
            } else if(sit_time >= warning_time) {
                system_state = WARNING_ACTIVE;
            }
            break;
            
        case WARNING_ACTIVE:
            if(new_state == USER_ABSENT) {
                system_state = USER_ABSENT;
                WS2812_SetColor(0, 0, 0);
            } else if(sit_time < warning_time) {
                system_state = USER_PRESENT;
                WS2812_SetColor(0, 255, 0);
            }
            break;
    }
}

int main(void) {
    // 系统初始化
    SysTick_Init();
    GPIO_Init();
    Ultrasonic_Init();
    Pressure_Init();
    DHT11_Init();
    OLED_Init();
    WS2812_Init();
    SYN6288_Init();
    
    // 初始状态
    GPIOA->BSRR = GPIO_BSRR_BS5;  // 点亮指示灯
    system_state = USER_ABSENT;
    
    while(1) {
        // 系统状态管理
        SystemStateManager();
        
        // 显示健康信息(每秒更新)
        if(system_tick % 1000 == 0) {
            DisplayHealthInfo();
        }
        
        // 久坐提醒处理
        if(system_state == WARNING_ACTIVE) {
            SittingWarning();
        }
        
        // 系统指示灯闪烁(0.5Hz)
        if(system_tick % 1000 == 0) {
            GPIOA->ODR ^= GPIO_ODR_ODR5;
        }
        
        // 防止程序跑飞
        __WFI();
    }
}

// 简单的延时函数
void delay_ms(uint32_t ms) {
    uint32_t start_tick = system_tick;
    while((system_tick - start_tick) < ms);
}

总结

综上所述,本系统基于STM32F103C8T6主控芯片,设计了一款智能防久坐与健康办公解决方案。该系统通过超声波模块实时监测用户与桌面的距离,结合压力传感器判断用户坐姿状态,有效检测用户是否在位及久坐行为。当用户持续久坐超过预设时间时,系统会触发灯光和语音提醒,帮助用户养成健康习惯,同时OLED显示屏动态展示在座时长、环境温湿度等关键健康数据,提升办公环境的舒适性与安全性。

硬件方面,系统集成了HC-SR04超声波模块、HX711压力传感器和DHT11温湿度传感器,确保数据采集的准确性和实时性。显示与提醒部分采用0.96英寸OLED显示屏、WS2812 RGB灯带和SYN6288语音模块,实现了直观的信息展示和友好的交互提醒。整体设计结构紧凑、功能完善,能够有效促进用户健康办公,减少久坐带来的潜在风险,体现了智能技术在日常生活应用中的实用价值。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。