从零打造直流电机 PID 驱动系统(三):iOS 蓝牙控制 APP 开发(新手友好版)
前言
大家好!在上一篇《从零打造可落地的直流电机 PID 驱动系统(二):增加蓝牙远程控制功能》中,我们成功为电机系统添加了 HC-05 经典蓝牙模块,实现了无线远程控制。但很多 iOS 用户反馈:普通开发者无法直接用 iOS 原生框架连接 HC-05 经典蓝牙(需要苹果 MFi 认证,门槛极高)。
因此本文将基于BLE 蓝牙低功耗模块(如 HM-10/HC-08,兼容原系统硬件接口),从零教大家开发一款 iOS 原生控制 APP,实现电机启停、速度调节、PID 参数在线修改和实时转速显示功能。全程使用 SwiftUI(苹果最新 UI 框架,代码量少、易上手),所有代码都加了详细注释,零基础也能跟着做。
一、开发前准备(新手必看)
1.1 硬件准备
- 已完成的直流电机 PID 驱动系统(上一篇的成品)
- BLE 蓝牙模块(推荐HM-10 BLE 4.0,直接替换原 HC-05,引脚完全兼容)
- iOS 设备(iPhone 5s 及以上,系统版本 iOS 13.0+)
- 数据线(用于连接电脑和 iPhone 调试)
1.2 软件准备
- Xcode 15.0+(苹果官方开发工具,Mac App Store 免费下载)
- LightBlue(App Store 免费下载,蓝牙调试神器,用于测试 BLE 模块)
- 基础 Swift 语法知识(只需了解变量、函数、类的基本概念即可)
1.3 关键前提说明(⚠️ 非常重要)
iOS 的CoreBluetooth原生框架仅支持 BLE 蓝牙低功耗设备,不支持 HC-05 等经典蓝牙设备的普通开发。经典蓝牙开发需要申请苹果 MFi 认证,个人开发者几乎无法通过。因此必须将原 HC-05 替换为 BLE 模块,本文所有内容均基于 BLE 模块实现。
二、iOS 蓝牙开发基础(5 分钟入门)
2.1 CoreBluetooth 核心概念
BLE 通信采用中心 - 外设架构:
- 中心设备(Central):我们的 iPhone,主动扫描和连接外设
- 外设(Peripheral):电机系统上的 HM-10 模块,被动等待连接
- 服务(Service):外设提供的功能集合,每个服务有唯一的 UUID
- 特征值(Characteristic):服务下的具体数据通道,用于读写数据,每个特征值也有唯一的 UUID
2.2 蓝牙连接完整流程
三、新建 Xcode 项目与基础配置
3.1 创建 SwiftUI 项目
- 打开 Xcode,选择 "Create a new Xcode project"
- 选择 "iOS" → "App",点击 "Next"
- 填写项目名称(如
MotorControl),界面选择 "SwiftUI",语言选择 "Swift",点击 "Next" - 选择保存路径,点击 "Create"
3.2 申请蓝牙权限
- 打开项目中的
Info.plist文件 - 右键选择 "Add Row",添加以下两个权限:
Privacy - Bluetooth Always Usage Description:值填写 "需要蓝牙连接电机控制系统"Privacy - Bluetooth Peripheral Usage Description:值填写 "需要蓝牙连接电机控制系统"
验证来源:苹果官方蓝牙权限配置指南
四、蓝牙管理类实现(核心代码)
新建一个 Swift 文件,命名为BluetoothManager.swift,这是整个 APP 的蓝牙核心,负责所有蓝牙操作。
import Foundation import CoreBluetooth // 蓝牙管理类,遵循中心设备代理协议 class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate, ObservableObject { // 中心设备管理器 private var centralManager: CBCentralManager! // 当前连接的外设 @Published var connectedPeripheral: CBPeripheral? // 扫描到的外设列表 @Published var discoveredPeripherals: [CBPeripheral] = [] // 蓝牙状态 @Published var bluetoothState: CBManagerState = .unknown // 用于读写数据的特征值 private var writeCharacteristic: CBCharacteristic? private var readCharacteristic: CBCharacteristic? // 电机系统的BLE服务和特征值UUID(HM-10默认值) private let serviceUUID = CBUUID(string: "FFE0") private let characteristicUUID = CBUUID(string: "FFE1") override init() { super.init() // 初始化中心设备管理器 centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.main) } // MARK: - 中心设备状态更新 func centralManagerDidUpdateState(_ central: CBCentralManager) { bluetoothState = central.state if central.state == .poweredOn { print("蓝牙已开启,开始扫描设备") scanForPeripherals() } else { print("蓝牙未开启或不可用") stopScan() discoveredPeripherals.removeAll() } } // MARK: - 扫描外设 func scanForPeripherals() { guard centralManager.state == .poweredOn else { return } // 扫描指定服务的外设(过滤无关设备) centralManager.scanForPeripherals(withServices: [serviceUUID], options: nil) } func stopScan() { centralManager.stopScan() } // 发现外设时调用 func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: N