如何利用HaaS100打造一台蓝牙音箱

1、概述

HaaS100主芯片是一块高性能SoC,其内置了蓝牙4.2双模芯片,支持经典蓝牙和BLE低功耗蓝牙。那能不能用HaaS100打造一台蓝牙音箱呢?

答案是肯定的。本文就将介绍如何使用HaaS100来动手打造一台蓝牙音箱。

 

2、HaaS100蓝牙音箱方案

HaaS100开发板内置了内置了蓝牙4.2双模芯片,手机可以通过蓝牙与HaaS100建立蓝牙连接。只要在HaaS100上实现蓝牙中A2DP Profile(这是一个专门用蓝牙来传输音频的Profile,苹果手机和Android手机都默认支持这个功能),就可以接收手机传过来的蓝牙音频数据,然后在外接一个喇叭,就能将音乐播放出来啦。

如下图所示。

如何利用HaaS100打造一台蓝牙音箱_第1张图片

3、 如何打造

3.1 软件准备

3.1.1 蓝牙协议栈

HaaS100的软件包里面包含了双模蓝牙协议栈,位于如下路径:

components/wireless/bluetooth/bt_stack

用户可以使用这个蓝牙协议栈来操作蓝牙模块,打造自己的蓝牙音箱。

要在自己的应用中使用蓝牙模块,需要如下几步

  • 在自己应用的aos.mk加入bthost组件

 

  • 在GLOBAL_DEFINES里面加入AOS_COMP_BTHOST定义

 

  • 如果需要蓝牙音频播放,需要增加a2sa和uvoice组件

   

之后,即可以在应用中调用协议栈的接口来开启蓝牙音频。协议栈的接口基本位于

host/bluedroid/api,接口类似yoc_XXX。

 

与蓝牙音频相关的接口包括如下:

  • 蓝牙初始化/使能------位于api/yoc_bt_main.c
  • 蓝牙扫描/连接-------位于api/yoc_gap_bt_api.c
  • 蓝牙音频播放功能------位于api/yoc_a2dp_api.c
  • 蓝牙音频控制功能------位于api/yoc_avrc_api.c

通过调用这些接口组合,即可让我们的HaaS开发板有了蓝牙音频能力。但蓝牙协议栈复杂,接口众多,需要调用大量的API才能实现蓝牙音频播放。

有没有简单的方法打造一台蓝牙音箱呢?请继续往下看。

 

3.1.2 简单模式

为了方便开发者试用,我们已经为开发者准备了一个蓝牙音箱的demo,位于如下路径

application/example/classicBT_demo

用户执行如下指令进行编译

aos make classicBT_demo@haas100 -c config
aos make

编译后生成的固件烧录进开发板。

 

3.1.3 代码解读

经典蓝牙初始化

经典蓝牙初始化,包括如下几个步骤,

  • bluedroid协议栈初始化&启用

使用蓝牙协议栈时,需要先做如下调用。

参考代码如下:

    err = yoc_bluedroid_init();
    if (err != BT_OK) {
        EXAMPLE_TRACE_ERROR("yoc_bluedroid_init err= %d", err);
        return;
    }

    err = yoc_bt_gap_register_callback(example_classicBT_gap_cb);
    if (err){
        EXAMPLE_TRACE_ERROR("gap register error, error code = %x", err);
        return;
    }

    err = yoc_bluedroid_enable();
    if (err != BT_OK) {
        EXAMPLE_TRACE_ERROR("yoc_bluedroid_enable err= %d", err);
        return;
    }
  • 蓝牙名称设置

用于设置蓝牙名称,长度不超过255字节,读者可自行设置。

参考代码如下:

    /* device name */
#define EXAMPLE_CLASSICBT_DEV_NAME   "HaaS BT"
    char *device_name = EXAMPLE_CLASSICBT_DEV_NAME;
    yoc_bt_dev_set_device_name(device_name);
  • 蓝牙连接性设置

设置为可发现可连接模式,否则无法在手机上搜索并连接设备,读者可以根据应用场景来设置可连接性与可发现性,比如需要在某个按键操作下才可以进入此状态。

参考代码如下

    /* scan mode set */
    {
        yoc_bt_connection_mode_t conn;
        yoc_bt_discovery_mode_t  disc;

        conn = YOC_BT_CONNECTABLE;
        disc = YOC_BT_GENERAL_DISCOVERABLE;

        err = yoc_bt_gap_set_scan_mode(conn, disc);
        if (err != BT_OK) {
            EXAMPLE_TRACE_ERROR("scan mode set err= %d", err);
        }
    }

 

  • A2DP初始化

A2DP服务是即蓝牙音乐服务,使用此服务时需要在协议栈中初始化

    yoc_a2d_register_callback(example_classicBT_a2dp_cb);
    yoc_a2d_sink_register_data_callback(example_classicBT_a2dp_data_cb);
    yoc_a2d_sink_init();

 

  • 回调函数处理

蓝牙协议栈是基于事件回调的,应用层可以根据应用需求处理GAP的回调和A2DP的回调,参考用例中,回调基本用于状态记录以及打印,读者可以根据应用场景增加LED灯,然后根据返回状态闪烁不同的灯。

如下代码A2DP状态回调,其中event =YOC_A2D_CONNECTION_STATE_EVT代表,A2DP连接事件,可据根据p_param中的参数获取是连接还是断开。

static void  example_classicBT_a2dp_cb(uint16_t event, void *p_param)
{
    yoc_a2d_cb_param_t *a2d = NULL;

    EXAMPLE_TRACE_DEBUG("%s evt %d", __func__, event);
    switch (event) {
    case YOC_A2D_CONNECTION_STATE_EVT:
        {
            uint8_t *bda;

            a2d = (yoc_a2d_cb_param_t *)(p_param);
            bda = a2d->conn_stat.remote_bda;
            EXAMPLE_TRACE_DEBUG("A2DP connection state: %d, [%02x:%02x:%02x:%02x:%02x:%02x]",
                 a2d->conn_stat.state, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
            if (a2d->conn_stat.state == YOC_A2D_CONNECTION_STATE_DISCONNECTED) {
                if (a2d->conn_stat.disc_rsn == YOC_A2D_DISC_RSN_NORMAL) {
                    example_classicBT_a2dp_state_cb(EXAMPLE_CLASSICBT_A2DP_DISCONNECTED, bda);
                } else {
                    example_classicBT_a2dp_state_cb(EXAMPLE_CLASSICBT_A2DP_LINK_LOSS, bda);
                }
            } else if (a2d->conn_stat.state == YOC_A2D_CONNECTION_STATE_CONNECTED) {
                example_classicBT_a2dp_state_cb(EXAMPLE_CLASSICBT_A2DP_CONNECTED, bda);
            } else if (a2d->conn_stat.state == YOC_A2D_CONNECTION_STATE_CONNECTING) {
                example_classicBT_a2dp_state_cb(EXAMPLE_CLASSICBT_A2DP_CONNECTING, bda);
            }
            break;
        }

 

3.2 硬件准备

软件编译烧录后,是不是就可以播放了呢?硬件还有注意点:

首先,需要接上蓝牙天线,不接容易引发卡顿,连接不畅等问题,接线方式如下图所示

另外,HaaS100上缺乏喇叭,声音无法输出,我们需要找一个,这类喇叭可以在淘宝等网站较为容易的找到,建议找功率在2W左右。

然后我们根据HaaS的接线图,找到排针接口的26PIN和28PIN,如下图

如何利用HaaS100打造一台蓝牙音箱_第2张图片

这2根引脚是音频功放的输出,可以直接接到喇叭的输入,如下图

这样硬件准备工作就做好了。

 

3.3 播放实测

程序启动后,蓝牙初始化成功并等待用户手机连接。

手机打开系统蓝牙设置界面,搜索周边蓝牙设备,可看到“HaaS BT”的蓝牙设备,如下图所示。

如何利用HaaS100打造一台蓝牙音箱_第3张图片

点击连接,弹出配对提示框,点击配对后蓝牙连接成功。

如何利用HaaS100打造一台蓝牙音箱_第4张图片

打开手机的音乐播放器,播放音乐,即可听到音乐在HaaS100的开发板上播放了。

 

4、蓝牙音频简介

这一章节,我们介绍一下蓝牙的音频协议A2DP。

蓝牙音频协议A2DP是蓝牙的高质量音频传输协议,有约20年历史的协议标准了,使用广泛,各类无线耳机,音箱,车载都使用了A2DP协议。到苹果airpods热卖后,蓝牙音频更是一片火热。

事实上,蓝牙诞生20多年,协议标准从1.0到5.2,A2DP协议并没有太多的技术升级,A2DP的整体架构如下

如何利用HaaS100打造一台蓝牙音箱_第5张图片

A2DP定义了Source和Sink2个角色,其中Source是音频的传输端,一般就是手机,电脑;Sink是音频的接收端,一般就是各类耳机和音箱了。

A2DP协议是一个上层协议,其利用AVDTP作为传输通道,利用SDP作为服务发现通道。而作为A2DP业务承载的AVDTP传输通道又分为Signalling信令通道和Stream音频流通道。信令通道传输控制与播放参数协商命令,而音频流通道则用于音频数据的传输。

A2DP音频原本是作为蓝牙的高质量音频协议存在的,但早期蓝牙标准组织为了保证传输带宽的平稳,同时也为了降低耳机的解码难度,选择了SBC作为音频编解码传输的主要标准。SBC带宽占用较大而音质效果一般,达不到高质量标准,虽然A2DP也支持一些可选的编解码器比如MP3,TRACK3等,但支持度都比较差,效果也有限,之后不少厂商提出了私有的新编解码器来提升音质,比如高通的APTX,索尼的LDAC等,并将编码器集成进了android新版本中。目前很多android手机均支持这些编码器,只要耳机音箱支持,即可开启这些编码器来提升音质。

目前HaaS仅支持SBC作为编解码器,后续可以根据业务需求实现诸如LDAC等高品质音频。

 

5、开发者技术支持

如需更多技术支持,可加入钉钉开发者群,或者关注微信公众号

更多技术与解决方案介绍,请访问阿里云AIoT首页https://iot.aliyun.com/

你可能感兴趣的:(HaaS解决方案,HaaS,物联网,蓝牙,iot,嵌入式)