智能自行车状态监测与防盗系统
项目开发背景
随着城市化进程的加速和环保意识的提升,自行车作为一种绿色、便捷的出行工具,在全球范围内受到广泛欢迎。然而,自行车盗窃问题日益严重,给用户带来财产损失和不便,传统机械锁具的防护能力有限,难以应对复杂的盗窃手段。此外,用户对骑行数据记录和实时状态监控的需求也在增长,这促使了智能自行车系统的开发。
在现有市场中,自行车防盗和状态监测方案多依赖于简单的物理锁具或独立的电子设备,缺乏集成化和智能化。这些方案无法实时感知车辆异常移动、追踪位置或提供全面的骑行数据分析,导致用户无法及时响应盗窃事件或优化骑行体验。因此,亟需一种融合多传感器和通信技术的综合解决方案。
本项目基于现代物联网和嵌入式系统技术,旨在设计一款智能自行车状态监测与防盗系统。通过集成霍尔传感器、MPU6050姿态传感器和GPS模块,系统能够实时计算速度与里程、监测车身姿态并记录骑行轨迹。同时,利用Wi-Fi/蓝牙模块和电磁锁实现远程警报和锁定功能,有效提升防盗能力,并通过手机APP和本地显示屏提供直观的数据交互。
该系统的开发不仅响应了用户对自行车安全和便捷管理的需求,还推动了智能交通设备的发展。通过结合低成本硬件和高效算法,项目有望降低自行车盗窃率,增强骑行体验,并为智慧城市出行生态的构建提供支持。
设计实现的功能
(1)通过霍尔传感器计算车轮转速,进而得到实时速度与里程。
(2)通过MPU6050监测车身姿态,当判定为异常移动(被盗)时,锁定电子锁并向车主手机发送警报。
(3)通过GPS模块记录骑行轨迹,并可通过手机APP查看。
(4)所有数据可在本地OLED屏幕上显示。
项目硬件模块组成
(1) 主控芯片:STM32F103C8T6单片机。
(2) 传感与定位:A3144霍尔传感器、MPU6050姿态传感器、GPS模块。
(3) 通信与报警:ESP8266 Wi-Fi/蓝牙模块(或4G模块)、有源蜂鸣器。
(4) 执行机构:继电器控制的电磁锁。
设计意义
该智能自行车状态监测与防盗系统的设计意义在于提升自行车的安全性和使用便利性。通过集成霍尔传感器和MPU6050姿态传感器,系统能够实时监测车轮转速和车身姿态,有效识别异常移动情况,从而及时锁定电子锁并发送警报,大大降低自行车被盗的风险,保护用户的财产安全。
系统通过GPS模块记录骑行轨迹,并结合手机APP查看功能,使用户能够回顾和分析骑行路线,这不仅有助于日常通勤或休闲骑行的规划,还能为健身活动提供数据支持,增强骑行的趣味性和实用性。
本地OLED屏幕显示所有关键数据,如速度和里程,使用户无需依赖外部设备即可快速获取信息,提高了系统的易用性和响应速度,同时减少了对外部网络的依赖,确保在无网络环境下仍能正常运作。
整体设计整合了现代传感、通信和控制技术,体现了物联网在智能交通领域的应用潜力,为自行车智能化提供了可行方案,推动传统交通工具向更安全、高效的方向发展。
设计思路
本系统以STM32F103C8T6单片机作为核心控制器,负责协调各个硬件模块的工作,实现自行车状态监测与防盗功能。系统通过集成传感器、通信模块和执行机构,构建一个完整的智能监测网络。
在速度与里程计算方面,使用A3144霍尔传感器检测车轮旋转,通过计算单位时间内脉冲次数来推导车轮转速,进而结合车轮周长计算出实时速度和累计里程。STM32主控芯片处理这些数据,确保计算准确性和实时性。
对于防盗功能,MPU6050姿态传感器持续监测车身姿态变化,当检测到异常移动(如非正常倾斜或震动)时,STM32会判断为被盗状态,并触发继电器控制的电磁锁进行锁定,同时通过ESP8266 Wi-Fi/蓝牙模块向车主手机发送警报信息,配合有源蜂鸣器发出声音警示。
GPS模块用于记录骑行轨迹,实时获取位置数据并存储在系统中,车主可通过手机APP查看历史轨迹。通信模块负责将GPS数据上传到云端或直接传输到手机,确保轨迹信息的可访问性和持久性。
所有监测数据,包括速度、里程、姿态状态和位置信息,都会在本地OLED屏幕上实时显示,方便用户直观查看自行车当前状态。STM32主控统一管理数据采集、处理和显示流程,确保系统稳定运行。
整个设计注重实际应用,硬件模块之间通过STM32进行高效协同,传感器数据采集、通信传输和执行控制各环节紧密衔接,形成一个可靠的状态监测与防盗系统。
框架图
+-------------------+ +-------------------+
| 霍尔传感器 |------>| |
| (A3144) | | |
+-------------------+ | |
| 主控芯片 |
+-------------------+ | (STM32F103C8T6) |
| MPU6050 |------>| |
| 姿态传感器 | | |
+-------------------+ | |
| |
+-------------------+ | |
| GPS模块 |------>| |
| | +-------------------+
+-------------------+ |
|
v
+-------------------+ +-------------------+
| OLED显示屏 |<------| |
| | | 通信模块 |
+-------------------+ | (ESP8266) |
| |
+-------------------+ | |
| 蜂鸣器 |<------| |
| (报警) | +-------------------+
+-------------------+ |
|
v
+-------------------+ +-------------------+
| 电磁锁 |<------| 继电器 |
| (通过继电器控制) | | |
+-------------------+ +-------------------+
|
v
+-------------------+
| 手机APP |
| (查看数据/警报) |
+-------------------+
系统总体设计
智能自行车状态监测与防盗系统以STM32F103C8T6单片机作为核心控制器,负责协调和处理各个模块的数据与指令。系统通过集成多种传感器实现状态监测,其中A3144霍尔传感器用于检测车轮转动,通过计算脉冲频率得到实时速度与累计里程;MPU6050姿态传感器持续监测车身倾斜和移动状态,当检测到异常振动或位移时,系统判定为潜在盗窃行为,立即触发防盗机制。
在防盗功能中,系统通过继电器控制电磁锁进行锁定,防止自行车被移动,同时利用ESP8266 Wi-Fi/蓝牙模块或4G模块将警报信息发送至车主手机,确保及时通知。此外,GPS模块实时记录骑行轨迹,数据通过通信模块上传至云端,车主可通过手机APP查看历史路径和当前位置。
所有采集的数据,包括速度、里程、姿态信息和GPS位置,均可在本地OLED屏幕上实时显示,方便用户直观查看自行车状态。系统设计注重实际应用,各模块协同工作,实现了高效的监测、防盗和数据分析功能。
系统功能总结
| 功能 | 关键硬件模块 | 功能描述 |
|---|---|---|
| 实时速度与里程计算 | A3144霍尔传感器、STM32F103C8T6 | 通过霍尔传感器检测车轮转速,由主控芯片计算并输出实时速度与总里程。 |
| 车身姿态监测与防盗警报 | MPU6050、继电器控制电磁锁、ESP8266、有源蜂鸣器 | 监测车身姿态,当判定异常移动(如被盗)时,锁定电磁锁,并通过通信模块向手机发送警报,蜂鸣器发声提醒。 |
| 骑行轨迹记录与查看 | GPS模块、ESP8266 | 使用GPS模块记录骑行路径,数据通过通信模块传输,用户可通过手机APP查看历史轨迹。 |
| 数据本地显示 | OLED屏幕(假设)、STM32F103C8T6 | 所有监测数据(如速度、里程、姿态状态)在本地OLED屏幕上实时显示。 |
设计的各个功能模块描述
霍尔传感器模块用于监测自行车车轮的转速,通过A3144霍尔传感器检测车轮上安装的磁铁信号,主控芯片STM32F103C8T6处理这些脉冲信号,计算车轮转动频率,从而得出实时速度和累计里程数据。
姿态监测与防盗模块利用MPU6050传感器检测车身的倾斜和加速度变化,当系统判断为异常移动时,主控芯片STM32F103C8T6会控制继电器驱动的电磁锁进行锁定,防止车辆被盗,同时通过ESP8266 Wi-Fi模块向车主手机发送警报通知,并触发有源蜂鸣器发出声音警示。
GPS轨迹记录模块通过GPS模块获取自行车的实时位置信息,主控芯片STM32F103C8T6存储和处理这些数据,形成骑行轨迹记录,用户可以通过手机APP经由ESP8266模块查看历史路线和当前位置。
数据显示模块将所有采集的数据,包括速度、里程、位置和系统状态,实时显示在本地连接的OLED屏幕上,为用户提供直观的信息反馈。
上位机代码设计
#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <chrono>
#include <mutex>
#include <map>
#include <iomanip>
#include <sstream>
#include <winsock2.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")
// 数据结构定义
struct BikeStatus {
double speed; // 实时速度 km/h
double distance; // 累计里程 km
double roll; // 横滚角
double pitch; // 俯仰角
double latitude; // 纬度
double longitude; // 经度
bool isLocked; // 电子锁状态
bool alertTriggered; // 报警触发状态
std::string timestamp; // 时间戳
};
class BikeMonitor {
private:
SOCKET clientSocket;
std::mutex dataMutex;
BikeStatus currentStatus;
bool isConnected;
bool running;
std::thread receiveThread;
std::vector<std::pair<double, double>> gpsTrajectory; // GPS轨迹记录
public:
BikeMonitor() : clientSocket(INVALID_SOCKET), isConnected(false), running(false) {
initializeStatus();
}
~BikeMonitor() {
disconnect();
}
// 初始化状态数据
void initializeStatus() {
currentStatus.speed = 0.0;
currentStatus.distance = 0.0;
currentStatus.roll = 0.0;
currentStatus.pitch = 0.0;
currentStatus.latitude = 0.0;
currentStatus.longitude = 0.0;
currentStatus.isLocked = false;
currentStatus.alertTriggered = false;
currentStatus.timestamp = getCurrentTime();
}
// 连接到下位机
bool connectToDevice(const std::string& ip, int port) {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cerr << "WSAStartup failed!" << std::endl;
return false;
}
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == INVALID_SOCKET) {
std::cerr << "Socket creation failed!" << std::endl;
return false;
}
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(port);
serverAddr.sin_addr.s_addr = inet_addr(ip.c_str());
if (connect(clientSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
std::cerr << "Connection failed!" << std::endl;
closesocket(clientSocket);
return false;
}
isConnected = true;
running = true;
// 启动数据接收线程
receiveThread = std::thread(&BikeMonitor::receiveData, this);
std::cout << "Connected to bike device successfully!" << std::endl;
return true;
}
// 断开连接
void disconnect() {
running = false;
isConnected = false;
if (receiveThread.joinable()) {
receiveThread.join();
}
if (clientSocket != INVALID_SOCKET) {
closesocket(clientSocket);
clientSocket = INVALID_SOCKET;
}
WSACleanup();
std::cout << "Disconnected from bike device." << std::endl;
}
// 发送控制命令
bool sendCommand(const std::string& command) {
if (!isConnected) {
std::cerr << "Not connected to device!" << std::endl;
return false;
}
std::string fullCommand = command + "\n";
if (send(clientSocket, fullCommand.c_str(), fullCommand.length(), 0) == SOCKET_ERROR) {
std::cerr << "Send command failed!" << std::endl;
return false;
}
std::cout << "Command sent: " << command << std::endl;
return true;
}
// 锁定电子锁
bool lockBike() {
return sendCommand("LOCK");
}
// 解锁电子锁
bool unlockBike() {
return sendCommand("UNLOCK");
}
// 获取当前状态
BikeStatus getCurrentStatus() {
std::lock_guard<std::mutex> lock(dataMutex);
return currentStatus;
}
// 获取GPS轨迹
std::vector<std::pair<double, double>> getGPSTrajectory() {
std::lock_guard<std::mutex> lock(dataMutex);
return gpsTrajectory;
}
// 显示状态信息
void displayStatus() {
std::lock_guard<std::mutex> lock(dataMutex);
std::cout << "\n=== 智能自行车状态监测 ===" << std::endl;
std::cout << "时间: " << currentStatus.timestamp << std::endl;
std::cout << "速度: " << std::fixed << std::setprecision(1) << currentStatus.speed << " km/h" << std::endl;
std::cout << "里程: " << std::fixed << std::setprecision(2) << currentStatus.distance << " km" << std::endl;
std::cout << "姿态 - 横滚: " << std::fixed << std::setprecision(2) << currentStatus.roll
<< "°, 俯仰: " << currentStatus.pitch << "°" << std::endl;
std::cout << "GPS位置: " << std::fixed << std::setprecision(6) << currentStatus.latitude
<< ", " << currentStatus.longitude << std::endl;
std::cout << "电子锁: " << (currentStatus.isLocked ? "锁定" : "解锁") << std::endl;
std::cout << "报警状态: " << (currentStatus.alertTriggered ? "触发" : "正常") << std::endl;
std::cout << "轨迹点数: " << gpsTrajectory.size() << std::endl;
if (currentStatus.alertTriggered) {
std::cout << "!!! 警报: 检测到异常移动 !!!" << std::endl;
}
}
private:
// 数据接收线程
void receiveData() {
char buffer[1024];
int bytesReceived;
while (running && isConnected) {
bytesReceived = recv(clientSocket, buffer, sizeof(buffer) - 1, 0);
if (bytesReceived > 0) {
buffer[bytesReceived] = '\0';
processReceivedData(std::string(buffer));
} else if (bytesReceived == 0) {
std::cout << "Connection closed by device." << std::endl;
break;
} else {
std::cerr << "Receive data error!" << std::endl;
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
// 处理接收到的数据
void processReceivedData(const std::string& data) {
std::lock_guard<std::mutex> lock(dataMutex);
std::istringstream iss(data);
std::string line;
while (std::getline(iss, line)) {
if (line.empty()) continue;
// 解析数据格式: TYPE:VALUE1,VALUE2,...
size_t colonPos = line.find(':');
if (colonPos == std::string::npos) continue;
std::string dataType = line.substr(0, colonPos);
std::string valuesStr = line.substr(colonPos + 1);
std::istringstream valuesStream(valuesStr);
std::string value;
std::vector<std::string> valueList;
while (std::getline(valuesStream, value, ',')) {
valueList.push_back(value);
}
if (dataType == "SPEED" && valueList.size() >= 2) {
currentStatus.speed = std::stod(valueList[0]);
currentStatus.distance = std::stod(valueList[1]);
}
else if (dataType == "ATTITUDE" && valueList.size() >= 2) {
currentStatus.roll = std::stod(valueList[0]);
currentStatus.pitch = std::stod(valueList[1]);
// 姿态异常检测
if (std::abs(currentStatus.roll) > 45 || std::abs(currentStatus.pitch) > 45) {
currentStatus.alertTriggered = true;
triggerAlarm();
}
}
else if (dataType == "GPS" && valueList.size() >= 2) {
currentStatus.latitude = std::stod(valueList[0]);
currentStatus.longitude = std::stod(valueList[1]);
// 记录GPS轨迹
gpsTrajectory.push_back(std::make_pair(
currentStatus.latitude, currentStatus.longitude));
}
else if (dataType == "LOCK") {
currentStatus.isLocked = true;
}
else if (dataType == "UNLOCK") {
currentStatus.isLocked = false;
}
else if (dataType == "ALERT") {
currentStatus.alertTriggered = true;
triggerAlarm();
}
currentStatus.timestamp = getCurrentTime();
}
}
// 触发警报
void triggerAlarm() {
std::cout << "\n!!! 自行车防盗警报触发 !!!" << std::endl;
std::cout << "检测到异常移动,请立即检查自行车状态!" << std::endl;
std::cout << "位置: " << currentStatus.latitude << ", " << currentStatus.longitude << std::endl;
// 在实际应用中,这里可以发送短信、邮件或推送通知
sendCommand("LOCK"); // 自动锁定
}
// 获取当前时间字符串
std::string getCurrentTime() {
auto now = std::chrono::system_clock::now();
auto time_t = std::chrono::system_clock::to_time_t(now);
std::tm tm;
localtime_s(&tm, &time_t);
std::ostringstream oss;
oss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");
return oss.str();
}
};
// 主应用程序类
class BikeMonitorApp {
private:
BikeMonitor monitor;
bool appRunning;
public:
BikeMonitorApp() : appRunning(false) {}
void run() {
appRunning = true;
std::cout << "=== 智能自行车状态监测与防盗系统 ===" << std::endl;
// 连接到设备
if (!connectToDevice()) {
std::cerr << "Failed to connect to device. Exiting..." << std::endl;
return;
}
// 主循环
mainLoop();
}
void stop() {
appRunning = false;
monitor.disconnect();
}
private:
bool connectToDevice() {
std::string ip;
int port;
std::cout << "请输入设备IP地址 (默认: 192.168.1.100): ";
std::getline(std::cin, ip);
if (ip.empty()) ip = "192.168.1.100";
std::cout << "请输入端口号 (默认: 8080): ";
std::string portStr;
std::getline(std::cin, portStr);
port = portStr.empty() ? 8080 : std::stoi(portStr);
return monitor.connectToDevice(ip, port);
}
void mainLoop() {
while (appRunning) {
displayMenu();
handleUserInput();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
void displayMenu() {
std::cout << "\n=== 主菜单 ===" << std::endl;
std::cout << "1. 显示当前状态" << std::endl;
std::cout << "2. 锁定自行车" << std::endl;
std::cout << "3. 解锁自行车" << std::endl;
std::cout << "4. 查看GPS轨迹" << std::endl;
std::cout << "5. 清除警报" << std::endl;
std::cout << "0. 退出程序" << std::endl;
std::cout << "请选择操作: ";
}
void handleUserInput() {
int choice;
std::cin >> choice;
std::cin.ignore(); // 清除输入缓冲区
switch (choice) {
case 1:
monitor.displayStatus();
break;
case 2:
if (monitor.lockBike()) {
std::cout << "自行车已锁定" << std::endl;
}
break;
case 3:
if (monitor.unlockBike()) {
std::cout << "自行车已解锁" << std::endl;
}
break;
case 4:
displayGPSTrajectory();
break;
case 5:
// 在实际实现中,需要发送清除警报命令
std::cout << "警报已清除" << std::endl;
break;
case 0:
appRunning = false;
std::cout << "正在退出程序..." << std::endl;
break;
default:
std::cout << "无效选择,请重新输入!" << std::endl;
break;
}
}
void displayGPSTrajectory() {
auto trajectory = monitor.getGPSTrajectory();
std::cout << "\n=== GPS骑行轨迹 ===" << std::endl;
std::cout << "总轨迹点数: " << trajectory.size() << std::endl;
for (size_t i = 0; i < trajectory.size(); ++i) {
std::cout << "点 " << (i + 1) << ": "
<< std::fixed << std::setprecision(6)
<< trajectory[i].first << ", "
<< trajectory[i].second << std::endl;
}
}
};
// 主函数
int main() {
// 设置控制台输出编码为UTF-8,支持中文显示
SetConsoleOutputCP(65001);
BikeMonitorApp app;
try {
app.run();
} catch (const std::exception& e) {
std::cerr << "程序异常: " << e.what() << std::endl;
return -1;
}
std::cout << "程序正常退出" << std::endl;
return 0;
}
模块代码设计
#include "stm32f10x.h"
// 硬件引脚定义
#define HALL_SENSOR_PIN GPIO_Pin_0 // PA0 - 霍尔传感器
#define BUZZER_PIN GPIO_Pin_1 // PA1 - 蜂鸣器
#define RELAY_PIN GPIO_Pin_2 // PA2 - 继电器控制电磁锁
#define OLED_SCL_PIN GPIO_Pin_6 // PB6 - OLED SCL
#define OLED_SDA_PIN GPIO_Pin_7 // PB7 - OLED SDA
#define MPU6050_SCL_PIN GPIO_Pin_10 // PB10 - MPU6050 SCL
#define MPU6050_SDA_PIN GPIO_Pin_11 // PB11 - MPU6050 SDA
#define GPS_TX_PIN GPIO_Pin_2 // PA2 - GPS TX
#define GPS_RX_PIN GPIO_Pin_3 // PA3 - GPS RX
#define ESP8266_TX_PIN GPIO_Pin_9 // PA9 - ESP8266 TX
#define ESP8266_RX_PIN GPIO_Pin_10 // PA10 - ESP8266 RX
// MPU6050寄存器地址
#define MPU6050_ADDR 0xD0
#define PWR_MGMT_1 0x6B
#define ACCEL_XOUT_H 0x3B
#define GYRO_XOUT_H 0x43
// 全局变量
volatile uint32_t wheel_pulse_count = 0;
volatile uint32_t total_distance = 0; // 单位:米
volatile float current_speed = 0.0; // 单位:km/h
volatile uint8_t theft_alert_flag = 0;
// 车轮周长(米),根据实际车轮尺寸调整
#define WHEEL_CIRCUMFERENCE 2.0
// 延时函数
void delay_ms(uint32_t nCount) {
for(uint32_t i = 0; i < nCount * 1000; i++);
}
// GPIO初始化
void GPIO_Init_Config(void) {
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN;
// 霍尔传感器输入
GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0);
GPIOA->CRL |= GPIO_CRL_CNF0_1; // 浮空输入
// 蜂鸣器输出
GPIOA->CRL &= ~(GPIO_CRL_MODE1 | GPIO_CRL_CNF1);
GPIOA->CRL |= GPIO_CRL_MODE1_0; // 推挽输出,10MHz
// 继电器输出
GPIOA->CRL &= ~(GPIO_CRL_MODE2 | GPIO_CRL_CNF2);
GPIOA->CRL |= GPIO_CRL_MODE2_0; // 推挽输出,10MHz
// I2C引脚
GPIOB->CRL &= ~(GPIO_CRL_MODE6 | GPIO_CRL_CNF6);
GPIOB->CRL |= GPIO_CRL_MODE6_0 | GPIO_CRL_CNF6_1; // 复用开漏输出
GPIOB->CRL &= ~(GPIO_CRL_MODE7 | GPIO_CRL_CNF7);
GPIOB->CRL |= GPIO_CRL_MODE7_0 | GPIO_CRL_CNF7_1; // 复用开漏输出
}
// 外部中断初始化 - 霍尔传感器
void EXTI_Init_Config(void) {
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
// PA0连接到EXTI0
AFIO->EXTICR[0] &= ~AFIO_EXTICR1_EXTI0;
AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI0_PA;
// 上升沿触发
EXTI->RTSR |= EXTI_RTSR_TR0;
// 使能EXTI0中断
EXTI->IMR |= EXTI_IMR_MR0;
// 配置NVIC
NVIC_EnableIRQ(EXTI0_IRQn);
NVIC_SetPriority(EXTI0_IRQn, 0x00);
}
// I2C1初始化 - OLED显示
void I2C1_Init_Config(void) {
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
// 复位I2C1
I2C1->CR1 |= I2C_CR1_SWRST;
I2C1->CR1 &= ~I2C_CR1_SWRST;
// 配置时钟频率
I2C1->CR2 |= 36; // APB1时钟36MHz
I2C1->CCR = 180; // 100kHz标准模式
I2C1->TRISE = 37; // 最大上升时间
// 使能I2C1
I2C1->CR1 |= I2C_CR1_PE;
}
// I2C2初始化 - MPU6050
void I2C2_Init_Config(void) {
RCC->APB1ENR |= RCC_APB1ENR_I2C2EN;
// 复位I2C2
I2C2->CR1 |= I2C_CR1_SWRST;
I2C2->CR1 &= ~I2C_CR1_SWRST;
// 配置时钟频率
I2C2->CR2 |= 36; // APB1时钟36MHz
I2C2->CCR = 180; // 100kHz标准模式
I2C2->TRISE = 37; // 最大上升时间
// 使能I2C2
I2C2->CR1 |= I2C_CR1_PE;
}
// UART1初始化 - ESP8266通信
void UART1_Init_Config(void) {
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
// 配置波特率 115200
USART1->BRR = 36000000 / 115200;
// 使能发送和接收
USART1->CR1 |= USART_CR1_TE | USART_CR1_RE;
// 使能UART1
USART1->CR1 |= USART_CR1_UE;
}
// UART2初始化 - GPS模块
void UART2_Init_Config(void) {
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
// 配置波特率 9600
USART2->BRR = 36000000 / 9600;
// 使能发送和接收
USART2->CR1 |= USART_CR1_TE | USART_CR1_RE;
// 使能UART2
USART2->CR1 |= USART_CR1_UE;
}
// I2C起始信号
void I2C_Start(I2C_TypeDef* I2Cx) {
I2Cx->CR1 |= I2C_CR1_START;
while(!(I2Cx->SR1 & I2C_SR1_SB));
}
// I2C停止信号
void I2C_Stop(I2C_TypeDef* I2Cx) {
I2Cx->CR1 |= I2C_CR1_STOP;
while(I2Cx->SR2 & I2C_SR2_MSL);
}
// I2C发送地址
void I2C_SendAddress(I2C_TypeDef* I2Cx, uint8_t address) {
I2Cx->DR = address;
while(!(I2Cx->SR1 & I2C_SR1_ADDR));
(void)I2Cx->SR2; // 读取SR2清除ADDR标志
}
// I2C发送数据
void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t data) {
I2Cx->DR = data;
while(!(I2Cx->SR1 & I2C_SR1_TXE));
}
// I2C接收数据
uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx) {
while(!(I2Cx->SR1 & I2C_SR1_RXNE));
return I2Cx->DR;
}
// MPU6050初始化
void MPU6050_Init(void) {
// 唤醒MPU6050
I2C_Start(I2C2);
I2C_SendAddress(I2C2, MPU6050_ADDR);
I2C_SendData(I2C2, PWR_MGMT_1);
I2C_SendData(I2C2, 0x00); // 解除休眠
I2C_Stop(I2C2);
delay_ms(10);
}
// 读取MPU6050加速度数据
void MPU6050_ReadAccel(int16_t* accel_data) {
I2C_Start(I2C2);
I2C_SendAddress(I2C2, MPU6050_ADDR);
I2C_SendData(I2C2, ACCEL_XOUT_H);
I2C_Start(I2C2);
I2C_SendAddress(I2C2, MPU6050_ADDR | 0x01);
for(uint8_t i = 0; i < 6; i++) {
if(i == 5) {
I2C2->CR1 &= ~I2C_CR1_ACK; // 最后一个字节不发送ACK
}
((uint8_t*)accel_data)[i] = I2C_ReceiveData(I2C2);
}
I2C_Stop(I2C2);
}
// 蜂鸣器控制
void Buzzer_Control(uint8_t state) {
if(state) {
GPIOA->BSRR = BUZZER_PIN; // 置位
} else {
GPIOA->BRR = BUZZER_PIN; // 复位
}
}
// 电磁锁控制
void ElectromagneticLock_Control(uint8_t state) {
if(state) {
GPIOA->BSRR = RELAY_PIN; // 锁定
} else {
GPIOA->BRR = RELAY_PIN; // 解锁
}
}
// OLED显示初始化(简化版)
void OLED_Init(void) {
// OLED初始化序列
uint8_t init_cmd[] = {0xAE, 0x20, 0x10, 0xB0, 0xC8, 0x00, 0x10, 0x40, 0x81, 0xFF, 0xA1, 0xA6, 0xA8, 0x3F, 0xA4, 0xD3, 0x00, 0xD5, 0xF0, 0xD9, 0x22, 0xDA, 0x12, 0xDB, 0x20, 0x8D, 0x14, 0xAF};
for(uint8_t i = 0; i < sizeof(init_cmd); i++) {
I2C_Start(I2C1);
I2C_SendAddress(I2C1, 0x78); // OLED地址
I2C_SendData(I2C1, 0x00); // 命令模式
I2C_SendData(I2C1, init_cmd[i]);
I2C_Stop(I2C1);
}
}
// OLED显示字符串(简化版)
void OLED_ShowString(uint8_t x, uint8_t y, char* str) {
// 设置显示位置
I2C_Start(I2C1);
I2C_SendAddress(I2C1, 0x78);
I2C_SendData(I2C1, 0x00);
I2C_SendData(I2C1, 0xB0 + y);
I2C_SendData(I2C1, 0x00);
I2C_SendData(I2C1, 0x10 + (x & 0x0F));
I2C_SendData(I2C1, 0x00);
I2C_SendData(I2C1, 0x01 + ((x >> 4) & 0x0F));
I2C_Stop(I2C1);
// 发送字符数据
while(*str) {
I2C_Start(I2C1);
I2C_SendAddress(I2C1, 0x78);
I2C_SendData(I2C1, 0x40); // 数据模式
// 这里简化字符显示,实际需要字库
I2C_SendData(I2C1, *str++);
I2C_Stop(I2C1);
}
}
// 速度计算函数
void Calculate_Speed(void) {
static uint32_t last_pulse_count = 0;
static uint32_t last_time = 0;
uint32_t current_time = SysTick->VAL;
if(current_time < last_time) {
uint32_t pulse_diff = wheel_pulse_count - last_pulse_count;
uint32_t time_diff = last_time - current_time;
// 计算速度 (km/h)
current_speed = (pulse_diff * WHEEL_CIRCUMFERENCE * 3.6f) / (time_diff * 0.001f);
// 计算总里程
total_distance += pulse_diff * WHEEL_CIRCUMFERENCE;
last_pulse_count = wheel_pulse_count;
}
last_time = current_time;
}
// 防盗检测函数
void Theft_Detection(void) {
int16_t accel_data[3];
MPU6050_ReadAccel(accel_data);
// 计算加速度矢量大小
float accel_magnitude = sqrt(accel_data[0]*accel_data[0] +
accel_data[1]*accel_data[1] +
accel_data[2]*accel_data[2]);
// 如果检测到异常移动且自行车未在骑行状态
if(accel_magnitude > 2000 && current_speed < 1.0) {
theft_alert_flag = 1;
ElectromagneticLock_Control(1); // 锁定电磁锁
Buzzer_Control(1); // 触发蜂鸣器
// 通过ESP8266发送警报
USART1->DR = 'A'; // 发送警报信号
while(!(USART1->SR & USART_SR_TC));
}
}
// 系统初始化
void System_Init(void) {
// 系统时钟配置
RCC->CR |= RCC_CR_HSEON;
while(!(RCC->CR & RCC_CR_HSERDY));
RCC->CFGR |= RCC_CFGR_PLLMULL9;
RCC->CFGR |= RCC_CFGR_PLLSRC;
RCC->CR |= RCC_CR_PLLON;
while(!(RCC->CR & RCC_CR_PLLRDY));
RCC->CFGR |= RCC_CFGR_SW_PLL;
while(!(RCC->CFGR & RCC_CFGR_SWS_PLL));
// 各模块初始化
GPIO_Init_Config();
EXTI_Init_Config();
I2C1_Init_Config();
I2C2_Init_Config();
UART1_Init_Config();
UART2_Init_Config();
MPU6050_Init();
OLED_Init();
// 配置SysTick定时器
SysTick->LOAD = 9000 - 1; // 1ms中断
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
}
// 霍尔传感器中断服务函数
void EXTI0_IRQHandler(void) {
if(EXTI->PR & EXTI_PR_PR0) {
wheel_pulse_count++;
EXTI->PR = EXTI_PR_PR0; // 清除中断标志
}
}
// 主函数
int main(void) {
System_Init();
char display_buffer[20];
while(1) {
// 计算速度
Calculate_Speed();
// 防盗检测
Theft_Detection();
// OLED显示更新
sprintf(display_buffer, "Speed:%.1fkm/h", current_speed);
OLED_ShowString(0, 0, display_buffer);
sprintf(display_buffer, "Dist:%lum", total_distance);
OLED_ShowString(0, 2, display_buffer);
if(theft_alert_flag) {
OLED_ShowString(0, 4, "ALERT! THEFT!");
} else {
OLED_ShowString(0, 4, "Status:Normal");
}
delay_ms(500);
}
}
// UART1中断服务函数 - ESP8266数据接收
void USART1_IRQHandler(void) {
if(USART1->SR & USART_SR_RXNE) {
uint8_t data = USART1->DR;
// 处理来自手机APP的指令
if(data == 'U') { // 解锁指令
ElectromagneticLock_Control(0);
theft_alert_flag = 0;
Buzzer_Control(0);
}
}
}
// UART2中断服务函数 - GPS数据接收
void USART2_IRQHandler(void) {
if(USART2->SR & USART_SR_RXNE) {
uint8_t gps_data = USART2->DR;
// 解析GPS数据(NMEA协议)
// 这里简化处理,实际需要完整解析
}
}
项目核心代码
#include "stm32f10x.h"
#include "oled.h"
#include "mpu6050.h"
#include "gps.h"
#include "esp8266.h"
#include "hall_sensor.h"
#include "buzzer.h"
#include "lock.h"
// 全局变量定义
volatile uint32_t hall_count = 0;
volatile uint32_t total_distance = 0;
volatile uint8_t speed_kmh = 0;
volatile uint8_t theft_alarm = 0;
volatile uint8_t system_locked = 0;
// 函数声明
void System_Init(void);
void Timer2_Init(void);
void EXTI0_Init(void);
void USART1_Init(void);
void USART2_Init(void);
void I2C1_Init(void);
void GPIO_Init(void);
void Calculate_Speed_Distance(void);
void Check_Theft_Status(void);
void Update_Display(void);
void Send_Alarm_Message(void);
int main(void)
{
// 系统初始化
System_Init();
// 外设初始化
Timer2_Init();
EXTI0_Init();
USART1_Init(); // GPS
USART2_Init(); // ESP8266
I2C1_Init(); // MPU6050 & OLED
GPIO_Init();
// 模块初始化
OLED_Init();
MPU6050_Init();
GPS_Init();
ESP8266_Init();
Buzzer_Init();
Lock_Init();
// 显示欢迎界面
OLED_ShowString(0, 0, "Bike Monitor", 16);
OLED_ShowString(0, 2, "System Ready", 16);
Delay_ms(2000);
OLED_Clear();
while(1)
{
// 计算速度和里程
Calculate_Speed_Distance();
// 检测防盗状态
Check_Theft_Status();
// 更新显示
Update_Display();
// 如果检测到异常移动,发送警报
if(theft_alarm)
{
Send_Alarm_Message();
theft_alarm = 0;
}
Delay_ms(100);
}
}
// 系统初始化
void System_Init(void)
{
// 开启时钟
RCC->APB2ENR |= (1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<8)|(1<<14);
RCC->APB1ENR |= (1<<0)|(1<<17)|(1<<21);
// 设置系统时钟
SystemInit();
SystemCoreClockUpdate();
}
// 定时器2初始化 - 用于速度计算
void Timer2_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 999;
TIM_TimeBaseStructure.TIM_Prescaler = 7199;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM2, ENABLE);
NVIC_EnableIRQ(TIM2_IRQn);
}
// 外部中断初始化 - 霍尔传感器
void EXTI0_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
// USART1初始化 - GPS
void USART1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
// TX - PA9, RX - PA10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
// USART2初始化 - ESP8266
void USART2_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
// TX - PA2, RX - PA3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART2, &USART_InitStructure);
USART_Cmd(USART2, ENABLE);
}
// I2C1初始化 - MPU6050 & OLED
void I2C1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
// SCL - PB6, SDA - PB7
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x00;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 400000;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
}
// GPIO初始化
void GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 霍尔传感器输入 - PA0
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 蜂鸣器输出 - PA1
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 电磁锁控制 - PA4
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
// 计算速度和里程
void Calculate_Speed_Distance(void)
{
static uint32_t last_hall_count = 0;
uint32_t current_count = hall_count;
// 计算速度 (km/h)
// 假设车轮周长2米,每秒脉冲数 * 2 * 3.6 = km/h
speed_kmh = (current_count - last_hall_count) * 2 * 3.6;
// 计算总里程 (米)
total_distance = current_count * 2;
last_hall_count = current_count;
}
// 检测防盗状态
void Check_Theft_Status(void)
{
static uint8_t stable_count = 0;
MPU6050_Data mpu_data;
MPU6050_Read_Data(&mpu_data);
// 检测异常移动 - 角度变化过大
if(abs(mpu_data.Angle_X) > 30 || abs(mpu_data.Angle_Y) > 30)
{
stable_count++;
if(stable_count > 5) // 连续5次检测到异常
{
if(!system_locked)
{
theft_alarm = 1;
system_locked = 1;
Lock_Activate(); // 锁定电子锁
Buzzer_On(); // 开启蜂鸣器报警
}
}
}
else
{
stable_count = 0;
}
}
// 更新显示
void Update_Display(void)
{
char display_buf[20];
OLED_Clear();
// 显示速度
sprintf(display_buf, "Speed: %d km/h", speed_kmh);
OLED_ShowString(0, 0, display_buf, 16);
// 显示里程
sprintf(display_buf, "Dist: %ld m", total_distance);
OLED_ShowString(0, 2, display_buf, 16);
// 显示状态
if(system_locked)
{
OLED_ShowString(0, 4, "Status: LOCKED", 16);
}
else
{
OLED_ShowString(0, 4, "Status: NORMAL", 16);
}
// 显示GPS状态
if(GPS_Get_Fix_Status())
{
OLED_ShowString(0, 6, "GPS: Fixed", 16);
}
else
{
OLED_ShowString(0, 6, "GPS: Searching", 16);
}
}
// 发送警报消息
void Send_Alarm_Message(void)
{
char alarm_msg[100];
GPS_Data gps_data;
GPS_Get_Data(&gps_data);
sprintf(alarm_msg, "ALERT: Bike theft detected! Location: Lat:%f,Lon:%f",
gps_data.latitude, gps_data.longitude);
ESP8266_Send_Message(alarm_msg);
}
// 定时器2中断服务函数 - 每秒执行一次
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
// 每秒更新一次GPS数据
GPS_Update();
}
}
// 外部中断0服务函数 - 霍尔传感器计数
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{
hall_count++;
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
// USART1中断服务函数 - GPS数据接收
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
uint8_t data = USART_ReceiveData(USART1);
GPS_Receive_Byte(data);
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
// 延时函数
void Delay_ms(uint32_t nCount)
{
volatile uint32_t i, j;
for(i = 0; i < nCount; i++)
for(j = 0; j < 8000; j++);
}
总结
智能自行车状态监测与防盗系统通过集成多种传感器和通信模块,实现了对自行车状态的全面监控与高效防盗。该系统能够实时计算速度和里程,监测车身姿态变化,并在检测到异常移动时自动锁定电子锁并向用户发送警报,同时记录骑行轨迹供用户随时查看。
硬件部分以STM32F103C8T6单片机为核心,结合霍尔传感器、MPU6050姿态传感器和GPS模块进行数据采集与定位,并通过ESP8266等通信模块实现远程警报功能。所有数据可在本地OLED屏幕上直观显示,确保系统操作简便且响应迅速。
整体而言,这一系统将传感技术、通信控制与用户交互紧密结合,不仅提升了自行车的安全性,还为用户提供了便捷的状态跟踪体验,具有较高的实用性和可靠性。
- 点赞
- 收藏
- 关注作者
评论(0)