芯片方案选型对比
** Nordic nRF52系列 vs TI CC2640系列 vs Dialog DA14580系列 **
nRF52832/nRF52840
- 优势:
超低功耗(2.4GHz下接收电流5.4mA,发射电流5.3mA@0dBm),支持BLE 5.0,内置DSP指令加速振动信号处理。
丰富外设(12位ADC、PWM输出驱动马达),Flash容量512KB/1MB,适合复杂逻辑。 - 劣势:成本略高。
TI CC2640R2F
- 优势:
专为传感器设计(待机电流1μA),集成可编程传感器控制器。 - 劣势:BLE 4.2协议栈,内存受限(128KB Flash)。
Dialog DA14580
- 优势:
最低功耗(峰值电流4.9mA),成本最低。 - 劣势:资源有限(128KB ROM,无内置DSP),需外置Flash。
推荐方案:
选用nRF52840,因其平衡功耗与性能,支持BLE长距离模式(Coded PHY),内置硬件加速适合实时信号处理。
传感器端代码实现(C语言)
硬件初始化
#include "nrfx_saadc.h"
#include "nrfx_timer.h"
#include "nrf_pwm.h"
void hardware_init() {
// ADC配置(振动传感器输入)
nrfx_saadc_config_t adc_config = NRFX_SAADC_DEFAULT_CONFIG;
nrfx_saadc_init(&adc_config, saadc_handler);
nrf_saadc_channel_config_t channel_cfg =
NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);
nrfx_saadc_channel_init(0, &channel_cfg);
// PWM配置(振动马达输出)
nrf_pwm_config_t pwm_cfg = {
.output_pins = {NRF_GPIO_PIN_MAP(0, 12), NRF_PWM_PIN_NOT_CONNECTED},
.irq_priority = 4,
.base_clock = NRF_PWM_CLK_1MHz,
.count_mode = NRF_PWM_MODE_UP,
.top_value = 1000,
.load_mode = NRF_PWM_LOAD_COMMON,
.step_mode = NRF_PWM_STEP_AUTO
};
nrf_pwm_init(NRF_PWM0, &pwm_cfg);
}
振动信号采集
#define SAMPLE_RATE 100 // Hz
static nrfx_timer_t timer = NRFX_TIMER_INSTANCE(1);
void vibration_sampling_start() {
nrfx_timer_config_t timer_cfg = {
.frequency = NRF_TIMER_FREQ_1MHz,
.mode = NRF_TIMER_MODE_TIMER,
.bit_width = NRF_TIMER_BIT_WIDTH_32
};
nrfx_timer_init(&timer, &timer_cfg, timer_handler);
nrfx_timer_extended_compare(&timer, NRF_TIMER_CC_CHANNEL0,
(1000000/SAMPLE_RATE), NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
nrfx_timer_enable(&timer);
}
void saadc_handler(nrfx_saadc_evt_t const *p_event) {
if (p_event->type == NRFX_SAADC_EVT_DONE) {
int16_t raw_value = p_event->data.done.p_buffer[0];
ble_send_vibration_data(raw_value); // BLE发送数据
}
}
BLE数据传输
#include "ble_nus.h"
static ble_nus_t m_nus; // BLE Nordic UART Service
void ble_init() {
ble_nus_init_t nus_init = {0};
nus_init.data_handler = nus_data_handler;
ble_nus_init(&m_nus, &nus_init);
}
void ble_send_vibration_data(int16_t data) {
uint8_t buffer[2];
buffer[0] = (data >> 8) & 0xFF;
buffer[1] = data & 0xFF;
ble_nus_data_send(&m_nus, buffer, 2, NULL);
}
void nus_data_handler(ble_nus_evt_t *p_evt) {
if (p_evt->type == BLE_NUS_EVT_RX_DATA) {
// 接收远程振动数据并驱动马达
int16_t remote_data = (p_evt->params.rx_data.p_data[0] << 8) | p_evt->params.rx_data.p_data[1];
nrf_pwm_sequence_t seq = {
.values.p_common = &remote_data,
.length = 1
};
nrf_pwm_simple_playback(NRF_PWM0, &seq, 1, NRF_PWM_FLAG_LOOP);
}
}
手机APP端实现(Android Kotlin)
BLE数据接收与MQTT上传
class BleManager(context: Context) {
private val mqttClient = MqttClient(context, "tcp://mqtt.server.com:1883")
private val nusCallback = object : BleManagerGattCallback() {
override fun onCharacteristicChanged(device: BluetoothDevice, data: ByteArray) {
val vibrationData = ByteBuffer.wrap(data).short
mqttClient.publish("user/${device.address}/vibration", data)
}
}
fun connectToDevice(device: BluetoothDevice) {
connect(device).useAutoConnect(false).with(nusCallback).enqueue()
}
}
MQTT数据接收与振动反馈
class MqttClient(context: Context, brokerUrl: String) : MqttAndroidClient(context, brokerUrl, "clientId") {
init {
setCallback(object : MqttCallback {
override fun messageArrived(topic: String, message: MqttMessage) {
if (topic.contains("/vibration")) {
val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vibrator.vibrate(VibrationEffect.createOneShot(message.payload.toShort().toLong(), 255))
}
}
})
}
}
服务器端实现(Python)
MQTT消息路由
import paho.mqtt.client as mqtt
import json
def on_connect(client, userdata, flags, rc):
client.subscribe("user/+/vibration")
def on_message(client, userdata, msg):
topic_parts = msg.topic.split('/')
sender_id = topic_parts[1]
receiver_id = get_pair_user(sender_id) # 从数据库查询配对用户
client.publish(f"user/{receiver_id}/vibration", msg.payload)
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("localhost", 1883)
client.loop_forever()
用户配对数据库(SQLite)
import sqlite3
def init_db():
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS users
(id TEXT PRIMARY KEY, name TEXT, paired_with TEXT)''')
conn.commit()
def get_pair_user(user_id):
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
cursor.execute("SELECT paired_with FROM users WHERE id=?", (user_id,))
return cursor.fetchone()[0]
信号链时序说明
-
A点传感器
- ADC采样频率100Hz,通过BLE通知手机APP(nRF52840广播间隔可配置为30ms)。
- 手机APP收到数据后通过MQTT QoS1级别发布到服务器。
-
服务器路由
- 根据用户配对表将数据转发给B用户订阅的主题。
-
B点设备
- 手机APP通过BLE连接将振动数据写入nRF52840的PWM模块,驱动马达。
功耗优化:
- nRF52840使用事件驱动架构,ADC和BLE仅在数据就绪时唤醒。
- 采用BLE连接参数协商(例如connInterval=100ms,slaveLatency=4)。
30

被折叠的 条评论
为什么被折叠?



