【香橙派系列教程】(四)基于ARM-Linux架构的语音控制刷抖音项目

【四】基于ARM-Linux架构的语音控制刷抖音项目

1.语音模块配置

整体逻辑是:

  1. 语音模块负责接收用户说话的信息,通过串口发送给H616
  2. H616写好业务逻辑的处理,当接收不同信号时来处理不同的业务
  3. 通过USB接口连接手机,利用adb指令来控制安卓手机

安卓的底层是Linux,所以也可以接收一些Linux指令

智能公元智能公元/AI产品零代码平台 (smartpi.cn)

进入官方平台,配置词条和识别后的串口输出指令。

1.创建产品

这里用到的语音模块型号为SU-03T

2.引脚配置

3.词条定义

4.添加控制

5.发布版本

其他的选项可以自行探索

6.烧录固件

首先连接好串口(记得交叉接线),插到电脑上面下载固件

下载需要冷启动:先把模块断电,然后点下载,下载进度变黄,之后再给模块上电

TXGPIO_B7
RXGPIO_B6

1.下载SDK固件包(里面自带烧录工具)

2.找到烧录工具

烧录器

固件位置与烧录器一个位置

开始烧录

烧录完固件之后,可以插到电脑上面配合串口助手看一下发送的信息

2.编程实现语音和开发板通信

首先将语音与开发板通过串口进行连接。

编译我们上一篇写的串口代码:

多文件编译方法: “ * ”为通配符,统一编译所有以uartT开头的文件

运行:

因为输出是乱码,所以需要我们修改一下发送的函数。

uartTool.c

//加入这段话
char myserialGetchar (const int fd)
{
  char x ;

  if (read (fd, &x, 1) != 1)
    return -1 ;

  return x ;
}

uartTool.h

char myserialGetchar (const int fd);

uartTest.c

添加串口读取一个字符的接口

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include "uartTool.h"
int fd;
void* readSerial()
{
    char cmd;
    while(1){
        cmd = myserialGetchar(fd);
        switch(cmd){
            case 'N':
                printf("next\n");
                break;
            case 'P':
                printf("pre\n");
                break;
            case 'Z':
                printf("zan\n");
                break;
            case 'Q':
                printf("qu\n");
                break;
        }
    }
}
int main(int argc, char **argv)
{
    char deviceName[32] = {'\0'};
    pthread_t readt;
    if(argc < 2){
        printf("uage:%s /dev/ttyS?\n",argv[0]);
        return -1;
    }
    strcpy(deviceName, argv[1]);
    if( (fd = myserialOpen(deviceName, 115200)) == -1){
        printf("open %s error\n",deviceName);
        return -1;
    }
    pthread_create(&readt, NULL, readSerial,NULL);
    while(1){sleep(10);}
}

3.手机接入Linux热拔插

1.dmesg命令

Linux dmesg(英文全称:display message):命令用于显示开机信息。

用法:dmesg

说明:查看所有开机日志信息

  • kernel 会将开机信息存储在 ring buffer 中。您若是开机时来不及查看信息,可利用 dmesg 来查看。
  • 开机信息亦保存在 /var/log 目录中,名称为 dmesg 的文件里。

1、查看命令版本

(base) [root@s186 ~]# dmesg -V
dmesg,来自 util-linux 2.23.2

2.过滤想查看信息

建议使用-i参数过滤时忽略大小写
(base) [root@s186 ~]# dmesg |grep -i cpu

2.adb调试

第一步:连接

用Type-c连接手机和orangepi zero2

输入指令查看usb设备:dmesg

此时能看到usb设备号和名称,这时只是单纯的识别了这个usb设备,但没有什么办法调试这个手机。

第二步:调试

如何调试?使用adb指令

//查看adb是否安装
adb version
//默认是没有安装adb的,安装指令:
sudo apt-get -y install adb

//调试
adb devices
//进入shell指令
adb shell

踩坑问题

**第一个坑:**OK了,还有一个点我们需要注意的是要打开手机的开发者选项 -> USB调试功能,不然就会出现以下情况

即使我们已经连接成功了,dmesg也能监测到,但是还是看不到任何信息。

我们打开手机USB调试功能之后,再次运行:

手机会弹出来usb调试确认界面,需要手动点击确认(有时候弹不出来,拔插多试试)

到此adb 和Android连接成功,此时adb可以调试Android,通过shell指令控制手机。

**第二个坑:**当我输入adb shell时,也会报错

这是我出现的一种情况1:

手机:选择USB用于传输文件,可以进入adb调试,但是到达shell指令这块会出问题

这个的解决办法在第三个坑介绍

还有另外一种情况2:

手机:选择USB用于仅充电,直接卡在访问设备这里,进入不了adb调试

没有访问权限,也就是没有生成文件柄,应用层无法操作接入的硬件设备:

此时,需要配置文件,以支持USB设备的热拔插,支持UDEV的机制

linux下一切皆文件:
udev机制:说白了就是为插入或者拔掉的设备,添加文件柄删除文件柄。

  1. 在/etc/udev/rules.d文件夹下创建规则文件
cd /etc/udev/rules.d/
sudo vim oppo-android.rules
  1. 在文件中添加内容
//1.USB子系统       2.环境变量:USB设备                  3.权限
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0666"

**第三个坑:**当我使用adb指令的时候,始终报错这个

这是因为adb工具是安装在orangepi上面的,进入手机的shell指令肯定是找不到的,我们需要退回orangepi的命令行,就可以正常使用adb shell指令了。


3.总结

a. 把手机接入开发板
b. 安装adb工具,在终端输入adb安装指令: sudo apt-get install adb
c. dmeg能查看到手机接入的信息,但是输入adb devices会出现提醒
    dinsufficient permissions for device: user in plugdev group; are your udev
    rules wrong?
d. 配置文件,以支持USB设备的热拔插,支持UDEV的机制
    在/etc/udev/rules.d 文件夹下创建规则文件
    cd /etc/udev/rules.d/
    sudo vim 51-android.rules
    在文件中添加内容 SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0666"
e. 在手机开发者选项中,打开USB调试,重新拔插手机
f. 手机弹出调试提醒,点确认手机调试模式

4. 用shell指令来操作手机屏幕,模拟手动滑屏幕

目前我们语音控制刷抖音,只需要这四个指令即可。

adb shell input swipe 540 1300 540 500 100 //向下滑动 540是水平的,1300是竖直方向,下是500,100是100毫秒内完成
adb shell input swipe 540 500 540 1300 100 //向上滑动
adb shell "seq 2 | while read i;do input tap 350 1050 & input tap 350 1050 & sleep 0.2;done;" //点赞
adb shell input keyevent 26 //锁屏

这里多介绍一些常用的shell指令(吃不饱的同学可以加餐哈!哈哈哈哈)

1.adb相关命令

  1. 关闭adb服务:adb kill-server

  2. 开启adb服务:adb start-server

  3. 查看当前连接的手机设备:adb devices

  4. 多设设备操作,< -s 虚拟设备名称 >

  5. 重启设备:adb reboot 指定虚拟设备: adb -s 设备名称 reboot

  6. 查看日志: adb logcat 清除日志: adb logcat -c

  7. 进入linux shell下 adb shell 其中常用的linux命令 cd cat 等等 输入su可以获取超级管理员名称了 要确定是否有哪些命令 进入 system/bin目录 就知道了

  8. 代理链接:adb connect [ip:post]

  9. 获取MAC地址:adb shell cat /sys/class/net/wlan0/address

  10. 安装应用:adb install <name.apk>

  11. 卸载安装包:adb uninstall <name.apk>

  12. 保存缓存文件重新安装:adb install -r <name.apk>

  13. 断开连接:adb disconnect <设备名>

  14. 文件复制到移动设备 ,后面跟设备目录:adb push filename /sdcard/

  15. 模拟位置点击(x,y):adb shell input tap

  16. 模拟滑动( x,yx1,y1 ),还可传入滑动缓冲:adb shell input swipe

  17. 获取当前页面的UI层 次,保存为xml文件:uiautomator dump dump: creates an XML dump of current UI hierarchy

18.模式实现输入:adb shell input text <输入任意内容>

2.adb模拟按键对照表

keycode含义
3HOME 键
4返回键
5打开拨号应用
6挂断电话
24增加音量
25降低音量
26电源键
27拍照(需要在相机应用里)
64打开浏览器
82菜单键
85播放/暂停
86停止播放
87播放下一首
88播放上一首
122移动光标到行首或列表顶部
123移动光标到行末或列表底部
126恢复播放
127暂停播放
164静音
176打开系统设置
187切换应用
207打开联系人
208打开日历
209打开音乐
210打开计算器
220降低屏幕亮度
221提高屏幕亮度
223系统休眠
224点亮屏幕
231打开语音助手
276如果没有 wakelock 则让系统休眠

调用实例说明:

命令: adb shell input keyevent <keycode>
  1. 示例,点击电源键:adb shell input keyevent 26  #执行效果相当于按电源键。
  2. 示例,输入"你好啊中国":adb shell input text "你好啊中国"  #执行效果相当于用户输入"你好啊中国"。
  3. 示例,模拟点击任何位置:adb shell input tap x y (x和y表示点击的坐标)

5.整合

接线图

语音模块

TXGPIO_B7
RXGPIO_B6

B6->8 B7->10

手机USB接口插到开发板上面。

代码

对于代码中system函数的使用,在进程一篇中有过讲解:进程

uartTest.c

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pthread.h>
#include "uartTool.h"
int fd;
void* readSerial()
{
    char cmd;
    while(1){
        cmd = myserialGetchar(fd);
        switch(cmd){
            case 'N':
                printf("next\n");
                system("adb shell input swipe 540 1300 540 500 100");
                break;
            case 'P':
                printf("pre\n");
                system("adb shell input swipe 540 500 540 1300 100");
                break;
            case 'Z':
                printf("zan\n");
                system("adb shell \"seq 2 | while read i;do input tap 350 1050 &input tap 350 1050 & sleep 0.2;done;\"");
                break;
            case 'Q':
                printf("qu\n");
                system("adb shell input keyevent 26");
                break;
        }
    }
}
int main(int argc, char **argv)
{
    char deviceName[32] = {'\0'};
    pthread_t readt;
    if(argc < 2){
        printf("uage:%s /dev/ttyS?\n",argv[0]);
        return -1;
    }
    strcpy(deviceName, argv[1]);
    if( (fd = myserialOpen(deviceName, 115200)) == -1){
        printf("open %s error\n",deviceName);
        return -1;
    }
    pthread_create(&readt, NULL, readSerial,NULL);
    while(1){sleep(10);}
}

uartTool.c

//uartTool.c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "wiringSerial.h"
int myserialOpen (const char *device, const int baud)
{
    struct termios options ;
    speed_t myBaud ;
    int status, fd ;
    switch (baud){
        case 9600: myBaud = B9600 ; break ;
        case 115200: myBaud = B115200 ; break ;
    }
    if ((fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1)
        return -1 ;
    fcntl (fd, F_SETFL, O_RDWR) ;
    // Get and modify current options:
    tcgetattr (fd, &options) ;
    cfmakeraw (&options) ;
    cfsetispeed (&options, myBaud) ;
    cfsetospeed (&options, myBaud) ;
    options.c_cflag |= (CLOCAL | CREAD) ;
    options.c_cflag &= ~PARENB ;
    options.c_cflag &= ~CSTOPB ;
    options.c_cflag &= ~CSIZE ;
    options.c_cflag |= CS8 ;
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ;
    options.c_oflag &= ~OPOST ;
    options.c_cc [VMIN] = 0 ;
    options.c_cc [VTIME] = 100 ; // Ten seconds (100 deciseconds)
    tcsetattr (fd, TCSANOW, &options) ;
    ioctl (fd, TIOCMGET, &status);
    status |= TIOCM_DTR ;
    status |= TIOCM_RTS ;
    ioctl (fd, TIOCMSET, &status);
    usleep (10000) ; // 10mS
    return fd ;
}
void serialSendstring (const int fd, const char *s)
{
    int ret;
    ret = write (fd, s, strlen (s));
    if (ret < 0)
        printf("Serial Puts Error\n");
}
int serialGetstring (const int fd, char *buffer)
{
    int n_read;
    n_read = read(fd, buffer,32);
    return n_read;
}
//加入这段话
char myserialGetchar (const int fd)
{
  char x ;

  if (read (fd, &x, 1) != 1)
    return -1 ;

  return x ;
}

uartTool.h

//**uartTool.h**
int myserialOpen (const char *device, const int baud);
void serialSendstring (const int fd, const char *s);
int serialGetstring (const int fd, char *buffer);
char myserialGetchar (const int fd);

编译gcc uartTest.c uartTool.c -pthread

运行./a.out /dev/ttyS5

  • 17
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘猫.exe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值