专栏名称: 安信可科技
全球领先的联网模组、智能家居等物联网硬件方案提供商。
目录
相关文章推荐
笛扬新闻  ·  柯桥这所学校太牛了,拿下全省冠军! ·  12 小时前  
话匣子  ·  马拉多纳死亡案,真相大白 ·  12 小时前  
海棠观察  ·  这些路段将进行交通管制! ·  昨天  
长春晚报  ·  明日,关闭 ·  2 天前  
51好读  ›  专栏  ›  安信可科技

用M61系列模块做一个手机蓝牙自拍杆?

安信可科技  · 公众号  ·  · 2024-10-21 12:00

正文


以下作品由安信可社区用户

lazy 制作




闲话



开始其实想做蓝牙键盘的,后来顺便把自拍杆功能也实现了。

虽然市面上有很多这样的产品,但是作为 DIY 爱好者的快乐不就是折腾吗。折腾使我快乐。

比如,刚到手的 AiPi-KVM 被我用 12V 点亮的故事

【我和小安派】故(shi)事(gu)AiPi-KVM 短暂的一生后续

后来买了一堆零件,还想着用烙铁焊上结果焊盘都干掉了。



HID简介


The Human Interface Device (HID) ,即人机交互设备。定义了蓝牙在人机接口设备中的协议、特征和使用规程。典型的应用包括蓝牙鼠标、蓝牙键盘、蓝牙游戏手柄等。该协议改编自 USB HID Protocol。


手机蓝牙的 HID 是指人机接口设备。


HID 是蓝牙技术中的一种协议,用于描述设备与人之间的交互接口。下面是详细的解释:

HID 基本含义 :HID 是英文“Human Interface Devices”的缩写,中文可以翻译为“人机接口设备”。在蓝牙技术中,HID 被广泛应用在各种设备之间,尤其是手机与外设之间。比如,我们常常用手机的蓝牙连接鼠标、键盘等外部设备,这时就会用到 HID 协议。

工作原理 :当手机通过蓝牙与另一个设备建立连接时,如果另一设备支持 HID 协议,那么手机就可以识别并与之通信。这种通信允许用户通过这些外设设备进行更直观、便捷的操作。比如,使用蓝牙连接的键盘输入文字,或者使用鼠标移动屏幕上的光标。

手机中的应用场景 :在日常生活中,手机蓝牙的 HID 功能经常被用于连接各种外部设备,如耳机、音箱、游戏手柄等。这使得手机的功能得到了扩展,提高了用户的使用体验。通过 HID 协议,这些设备可以与手机快速建立连接,并进行数据传输和控制。


总的来说,手机蓝牙的 HID 是指人机接口设备协议,它使得手机能够识别并与各种外部设备进行通信,提高了用户的使用体验和便捷性。


详细学习参考可以下资料:

【USB 系列】自定义 USB HID 设备 bzhou830

【小安派试玩】基于 HID 协议的 USB 键盘测试 iiv

(二十)零基础开发小安派-Eyes-S1【番外篇】——BLE 基础通讯

用 btstack 开发一个简单的蓝牙自拍杆

【低功耗蓝牙】⑤ HID 协议

USB HID 报告描述符教程 - 知乎




HID 自拍原理


其实想要实现蓝牙自拍功能其实比较简单,目前市面上的手机大多都可以通过按“音量-”按键进行拍照。知道了这个实现起来就比较简单了。只要我们能够模拟点击“音量-”按键就可以实现遥控拍照功能。

既然知道了拍照原理下一步我们就要开始想办法通过 HID 实现这个功能。


前置条件


自拍杆 HID 报告描述【使用的话把# 替换换成 //】



# Report ID 1: Advanced buttons 0x05, 0x0C,       # Usage Page (Consumer) 0x09, 0x01,       # Usage (Consumer Control) 0xA1, 0x01,       # Collection (Application) 0x85, 0x01,       #     Report Id (1) 0x15, 0x00,       #     Logical minimum (0) 0x25, 0x01,       #     Logical maximum (1) 0x75, 0x01,       #     Report Size (1) 0x95, 0x01,       #     Report Count (1) 0x09, 0xCD,       #     Usage (Play/Pause) 0x81, 0x06,       #     Input (Data,Value,Relative,Bit Field) 0x0A, 0x83, 0x01, #     Usage (AL Consumer Control Configuration) 0x81, 0x06,       #     Input (Data,Value,Relative,Bit Field) 0x09, 0xB5,       #     Usage (Scan Next Track) 0x81, 0x06,       #     Input (Data,Value,Relative,Bit Field) 0x09, 0xB6,       #     Usage (Scan Previous Track) 0x81, 0x06,       #     Input (Data,Value,Relative,Bit Field) 0x09, 0xEA,       #     Usage (Volume Down) 0x81, 0x06,       #     Input (Data,Value,Relative,Bit Field) 0x09, 0xE9,       #     Usage (Volume Up) 0x81, 0x06,       #     Input (Data,Value,Relative,Bit Field) 0x0A, 0x25, 0x02, #     Usage (AC Forward) 0x81, 0x06,       #     Input (Data,Value,Relative,Bit Field) 0x0A, 0x24, 0x02, #     Usage (AC Back) 0x81, 0x06,       #     Input (Data,Value,Relative,Bit Field) 0xC0              # End Collection 作者:我是鹏老师 https://www.bilibili.com/read/cv15067064/ 出处:bilibili


有了它我们就可以模拟手机按键了。


具体实现

这里蓝牙部分主要参考官方的教程里面的蓝牙功能

【完全开源】智能桌面助手——AiPi-DSL_Dashboard
https://bbs.ai-thinker.com/forum.php?mod=viewthread&tid=42026&fromuid=16612

资料获取

AiPi-DSL_Dashboard 资料包地址: https://docs.ai-thinker.com/dsl
AiPi-DSL_Dashboard 资料包地址(Github): https://github.com/Ai-Thinker-Open/AiPi-Open-Kits/tree/master/AiPi-DSL_Dashboard



项目目录结构


-BLE_HID 负责蓝牙

-main 程序主入口

-wifi MQTT 接入准备


程序


main


int main(void){  ……   // 保留蓝牙相关任务   xTaskCreate(ble_hid_task, (char*)"ble_hid_task", 1024, NULL, 10, NULL);   vTaskStartScheduler();  ……}


ble_hid_dev.c 蓝牙任务管理


/** * @brief HID 任务 * * @param arg*/void ble_hid_task(void* arg){    // 主要是通知【lvgl】UI更新蓝牙状态的由于没有屏幕暂时注释以下两行代码    // ble_queue = xQueueCreate(1, 512);    // xTaskCreate(queue_receive_ble_task, "queue_ble_task", 1024, arg, 7, NULL);    vTaskDelay(200/portTICK_RATE_MS);    hid_key_num_t kb_num;    btblecontroller_em_config();    ble_init();    bas_init();    dis_init(0x01, 0x07AF, 0x707, 0x2A50);    hog_kb_init();    ble_kb_start();    ble_hid_queue = xQueueCreate(1, 4);    while (1) {        xQueueReceive(ble_hid_queue, &kb_num, portMAX_DELAY);        ble_hid_dev_send(kb_num);    }}



ble_hid_dev.h 文件中添加


typedef  enum {    HID_KEY_NUMBLE_NONE = 0,    HID_KEY_NUMBLE_SELFIE_STICK,// 自拍杆    ……}


kb.h 文件中添加

typedef enum {    KEY_NUMBLE_SELFIE_STICK = 0X10, // 拍照    ……}
int send_selfie_stick_value(struct bt_conn* conn, uint8_t* keyboard_cmd); // 拍照指令



修改 kb.c

增加

static uint8_t report_selfie_stick_map[] ={    // Report ID 1: Advanced buttons    0x05, 0x0C,       // Usage Page (Consumer)    0x09, 0x01,       // Usage (Consumer Control)    0xA1, 0x01,       // Collection (Application)    0x85, 0x01,       //     Report Id (1)    0x15, 0x00,       //     Logical minimum (0)    0x25, 0x01,       //     Logical maximum (1)    0x75, 0x01,       //     Report Size (1)    0x95, 0x01,       //     Report Count (1)    0x09, 0xCD,       //     Usage (Play/Pause)    0x81, 0x06,       //     Input (Data,Value,Relative,Bit Field)    0x0A, 0x83, 0x01, //     Usage (AL Consumer Control Configuration)    0x81, 0x06,       //     Input (Data,Value,Relative,Bit Field)    0x09, 0xB5,       //     Usage (Scan Next Track)    0x81, 0x06,       //     Input (Data,Value,Relative,Bit Field)    0x09, 0xB6,       //     Usage (Scan Previous Track)    0x81, 0x06,       //     Input (Data,Value,Relative,Bit Field)    0x09, 0xEA,       //     Usage (Volume Down)    0x81, 0x06,       //     Input (Data,Value,Relative,Bit Field)    0x09, 0xE9,       //     Usage (Volume Up)    0x81, 0x06,       //     Input (Data,Value,Relative,Bit Field)    0x0A, 0x25, 0x02, //     Usage (AC Forward)    0x81, 0x06,       //     Input (Data,Value,Relative,Bit Field)    0x0A, 0x24, 0x02, //     Usage (AC Back)    0x81, 0x06,       //     Input (Data,Value,Relative,Bit Field)    0xC0              // End Collection    //通用按键    // 0x05, 0x0C,        // Usage Page (Consumer)    // 0x09, 0x01,        // Usage (Consumer Control)    // 0xA1, 0x01,        // Collection (Application)    // 0x85, 0x03,        //   Report ID (3)    // 0x15, 0x00,        //   Logical Minimum (0)






请到「今天看啥」查看全文