基于STM32的智能防久坐与健康办公系统
项目开发背景
随着现代办公环境的普及和信息技术的快速发展,越来越多的人群需要长时间在办公桌前工作,导致久坐成为日常生活中的普遍现象。研究表明,持续久坐不仅会引发颈椎和腰椎疾病,还可能增加肥胖、心血管问题及代谢综合征的风险,严重影响工作效率与个人健康。
传统的健康提醒方式往往依赖于简单的定时器或手动设置,缺乏智能化和实时性,用户容易因工作专注而忽略提醒,无法有效改善坐姿习惯。此外,单一传感器监测的局限性难以全面反映用户的在位状态和坐姿变化,亟需一种集成多传感器与智能提醒的综合解决方案。
为此,本项目基于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语音模块,实现了直观的信息展示和友好的交互提醒。整体设计结构紧凑、功能完善,能够有效促进用户健康办公,减少久坐带来的潜在风险,体现了智能技术在日常生活应用中的实用价值。
- 点赞
- 收藏
- 关注作者
评论(0)