基于MAX7800羽毛板语音控制ESP8266小车

news2024/12/25 12:31:41

1. 项目介绍

 

基于MAX7800羽毛板语音控制ESP8266小车
采用现成的KWS20关键词,['up', 'down', 'left', 'right', 'stop', 'go', 'yes', 'no', 'on', 'off', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'zero'],进行语音关键字识别远程控制小车。

 2. 项目设计思路

搭建环境《——》学习基本例程《——》熟悉基本编译下载调试功能《——》重点解析参考目标案例《——》各个模块功能调试《——》整体联调维护相关功能《——》演示总结

 系统设计图

我们开始主线任务和副线任务吧

3. 主线任务

主线任务围绕语音关键字识别远程控制三部分展开!🥳🥳🥳

3.1 远程遥控ESP8266小车——主线1

一步一个脚印,MQTT的ESP遥控小车从原理到实现,涉及硬件电路,程序设计,然后也探讨了个人见解,希望把两个归中传感器数值传递过去,减少实验步骤,提高速成感和成就感!🌼🌻🎏🛹🏃‍♂️

见网址:基于然也物联MQTT的ESP遥控小车

见项目进度主线1

  • 发射机
    请添加图片描述
  • 接收机

在这里插入图片描述

  • 最后效果

请添加图片描述

3.2 MAX7800实现KWS20 demo演示——主线2

Keyword Spotting Demo 软件演示了如何使用MAX78000 EVKIT 识别大量关键字。
KWS20 演示软件使用第二版 Google 语音命令数据集此演示使用了完整数据集中的以下 20 个关键字子集:

[‘up’, ‘down’, ‘left’, ‘right’, ‘stop’, ‘go’, ‘yes’, ‘no’, ‘on’, ‘off’, ‘one’, ‘two’, ‘three’, ‘four’, ‘five’, ‘six’, ‘seven’, ‘eight’, ‘nine’, ‘zero’]
其余关键字和无法识别的词属于“Unknown”类别,理解语音识别原理和相关神经网络代码调用。

见网址:【MAX7800实现KWS20 demo演示】_2345VOR的博客-CSDN博客_ai8x 训练

见项目进度主线2

在这里插入图片描述

3.3 ESP8266-NodeMCU软硬串口通讯——主线3

本次采用ESP8266node MCU开发板,利用自身软硬件串口通讯,采用关键字符串实现开灯功能🛹🛹🛹

见网址:ESP8266-NodeMCU软硬串口通讯

见项目进度主线3

在这里插入图片描述

3.4 MAX7800与ESP8266mcu串口通讯点灯——主线4

前期搭好MAX7800 的eclipse和ESP82666的Arduino开发环境,现在开始慢慢实现这两者的通讯,目前MAX7800 羽毛板可以发送字符串,但是ESP8266无法连续接收,因此采用简单的单个字符的串口通讯实现点灯功能。

见网址: MAX7800与ESP8266mcu串口通讯点灯

见项目进度主线4

在这里插入图片描述

3.5 MAX7800与ESP8266mcu通讯关键字控制——主线5

前期搭好MAX7800 的eclipse和ESP82666的Arduino开发环境,现在开始慢慢实现这两者的通讯,目前MAX7800 羽毛板可以发送字符串,但是ESP8266无法连续接收,因此采用简单的单个字符的串口通讯实现点灯功能,现在可以与esp8266实现KWS20关键字识别控制串口输出字符操作数。

见网址:MAX7800与ESP8266mcu通讯关键字控制

见项目进度副线1

在这里插入图片描述

4. 副线任务

副线任务围绕MAX7800基础案例开发,熟悉基本语法、相关外设驱动部分展开!🥳🥳🥳

4.1 搭建window下配置Maxim SDK环境——副线1

下面介绍如何在Windows下搭建Maxim SDK开发环境,我们就可以点灯,hello world啦!

见网址:【window下配置Maxim SDK环境】_2345VOR的博客-CSDN博客_maxim sdk

见项目进度副线1

在这里插入图片描述

4.2 MAX78000基础案例演示——副线2

挑选ADC、GPIO、UART三个幸运的例程进行学习演示,总结项目编译下载调试开发功能,熟悉语言规范。

见网址:【MAX78000基础案例演示】_2345VOR的博客-CSDN博客

见项目进度副线2

在这里插入图片描述

5. 具体实验

改善小车硬件结构,使羽毛板嵌入进去,设计控制逻辑程序,完成语音识别、串口驱动、关键字符解码、MQTT发送接收、设备驱动执行,程序控制流程图如下

5.1 前期构思

下面是语音关键字控制小车状态定义

5.1.1 语音匹配

['up', 'down']小车左右手部舵机状态

['left', 'right']小车左右转方向控制

['stop', 'go']小车状态控制

['yes', 'no']小车前进后退方向控制

['on', 'off']车灯控制状态

['one', 'two', 'three', 'zero']速度大小控制

['four', 'five', 'six', 'seven', 'eight', 'nine', 'unknow']无效关键字,保持小车原有状态

以上一共有15个字符MAX7800负责识别,然后发送到esp8266接收对应15个操作码。下图这是我通过MAX7800与esp8266通讯找到的,从225到339的15个操作码

在这里插入图片描述

关键字    up    down   left  right   stop   go   yes  no    on    off    one   two   three  zeroothers
字符    CI   DFN  GO   RPX  SY    TV   U   h   ac   fnld   2   3  4go5
操作数    225  226    227  228   229   230  231   232   233   234  236  237   238    235  239


关键代码展示

/* Set of detected words */
const char keywords[NUM_OUTPUTS][10] = { "UP",    "DOWN", "LEFT",   "RIGHT", "STOP",  "GO",
                                         "YES",   "NO",   "ON",     "OFF",   "ONE",   "TWO",
                                         "THREE", "FOUR", "FIVE",   "SIX",   "SEVEN", "EIGHT",
                                         "NINE",  "ZERO", "Unknown" };
const uint8_t TestTxData[BUFF1_SIZE]="CDGRSTUhaf234555555g5";

 5.1.2 操作码匹配

  • 横坐标依次是小车关键状态

小车左右转方向,小车油门大小(有方向),左边舵机手,右边舵机手,车灯

  • 纵坐标依次是语音关键字

['up', 'down', 'left', 'right', 'stop', 'go', 'yes', 'no', 'on', 'off', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'zero']

下图显示小车关键状态语音关键字一一对应关系!!!

关键代码展示

int A[4]={400,1850,3400,4200},B[6]={600,1850,3700,4200,3400,4090},C[4]={90,120,180,200},D[4]={90,60,0,200},E[4]={0,1,5,10};
int action[2][5] = {
  { A[3], B[3], C[3], D[3], E[3] },
  { A[1], B[1], C[1], D[1], E[0]}
};
int mylist[15][5] = {
  { A[3], B[3], C[2], D[2], E[3] },//up
  { A[3], B[3], C[0], D[0], E[3] },//down
  { A[0], B[3], C[1], D[2], E[3] },//left
  { A[2], B[3], C[2], D[1], E[3] },//right
  { A[1], B[1], C[1], D[1], E[0] },//stop
  { A[3], B[2], C[3], D[3], E[1] },//go
  { A[3], B[1], C[3], D[3], E[3] },//yes
  { A[3], B[0], C[3], D[3], E[3] },//no
  { A[3], B[3], C[3], D[3], E[1] },//on
  { A[3], B[3], C[3], D[3], E[0] },//off
  { A[3], B[1], C[3], D[3], E[3] },//zero
  { A[3], B[4], C[3], D[3], E[3] },//1
  { A[3], B[2], C[3], D[3], E[3] },//2
  { A[3], B[5], C[3], D[3], E[3] },//3
  { A[3], B[3], C[3], D[3], E[3] }//unknow
};

5.2 硬件结构

此部分搭建系统的原理图和实物连接

原理图源码见:嘉立创EDA(标准版) - 免费、易用、强大的在线电路设计软件

5.2.1 原理图

  • 发射机

 物料说明:

MAX7800:主控,语音识别20个关键单词,发送特定字符到esp8266,并SD卡记录,显示屏显示(没有设计TFT显示屏接线)

在这里插入图片描述

ESP8266T:中转器,接收MAX7800特定字符,匹配对应操作码关联小车状态参数,采用然也物联网平台使用MQTT远程传输小车状态参数指令

在这里插入图片描述

LED1:显示器,通过PWM驱动显示传输时的小车速度,采用亮暗程度表达

  • 接收机

 物料说明:

ESP8266:主控,采用然也物联网平台使用MQTT远程接收小车状态参数指令,下发操作码关联小车状态参数,驱动电机舵机LED

在这里插入图片描述

L293D:拓展驱动板,采用ESP12E 电机拓展板与 NodeMCU ESP8266 Amica 板兼容,扩展板直接放在微控制器上。电机的电源连接到 VM/GND 接线盒,电路板的电源连接到 VIN/GND 接线盒。如果电机的电源与 NodeMCU 的电源相同(<10V 最大值),则可以使用桥连接 VIN 和 VM 引脚。电机连接到接线端子 A+、A-、B+、B-。

在这里插入图片描述

电机R:采用TT马达减速电机,连接右边坦克链条履带结构

电机L:采用TT马达减速电机,连接左边坦克链条履带结构

舵机R:采用常见的90舵机作为右手臂

 

舵机L:采用常见的90舵机作为右手臂

 LED2:作为车灯,电机运行时亮,可单独关键词“on,off”控制

 电源:采用2S航模电池作为接收机的能量供应

5.2.2 实物连接

  • 发射机

在这里插入图片描述

  • 接收机

后视图

前视图

 

侧视图

 

 5.3 软件设计

项目工程在gitcode托管,目前有两版,第一版可以简单测试串口,发行版可以正常控制

5.3.1 接收机

  • max7800程序部分main.c,详细见工程
//字符数组定义
const char keywords[NUM_OUTPUTS][10] = { "UP",    "DOWN", "LEFT",   "RIGHT", "STOP",  "GO",
                                         "YES",   "NO",   "ON",     "OFF",   "ONE",   "TWO",
                                         "THREE", "FOUR", "FIVE",   "SIX",   "SEVEN", "EIGHT",
                                         "NINE",  "ZERO", "Unknown" };
const uint8_t TestTxData[BUFF1_SIZE]="CDGRSTUhaf234555555g5";



//置信度大于90采用串口2发送
/* output char*/
                if(probability>90){
					*firstName = TestTxData[out_class];
					writemsg( firstName, 1);//发送串口2字符指令
					printf("\n count : %d: %d: %s\n", count++,count%62,firstName);
					/*   */
                }
  • esp8266T程序
// #include <WiFi.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// #define joyX 34
// #define joyY 35
// int Ym, Fx, R, L;
// 设置wifi接入信息(遥控器要连接的wifi)
// const char* ssid = "J09 502";
// const char* password = "qwertyuiop111";
// const char* ssid = "vor";
// const char* password = "vor980501";
const char* ssid = "XY-031026";
const char* password = "12345678";
String topicString = "minivorCar214923790t7";  //输入自己的特定主题名,能保证别人不和你重复就行

const char* mqttServer = "test.ranye-iot.net";
// const char* mqttServer = "8.142.157.58";
// 如以上MQTT服务器无法正常连接,请前往以下页面寻找解决方案
// http://www.taichi-maker.com/public-mqtt-broker/

WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

/**mixly**/
#include <SoftwareSerial.h>
#define timer1 300
volatile int item;
volatile byte item1;
volatile int item2;
volatile byte item3;
volatile int operators;
String strings;
int A[4]={400,1850,3400,4200},B[6]={600,1850,3700,4200,3400,4090},C[4]={90,120,180,200},D[4]={90,60,0,200},E[4]={0,1,5,10};
int action[2][5] = {
  { A[3], B[3], C[3], D[3], E[3] },
  { A[1], B[1], C[1], D[1], E[0]}
};
int mylist[15][5] = {
  { A[3], B[3], C[2], D[2], E[3] },//up
  { A[3], B[3], C[0], D[0], E[3] },//down
  { A[0], B[3], C[1], D[2], E[3] },//left
  { A[2], B[3], C[2], D[1], E[3] },//right
  { A[1], B[1], C[1], D[1], E[0] },//stop
  { A[3], B[2], C[3], D[3], E[1] },//go
  { A[3], B[1], C[3], D[3], E[3] },//yes
  { A[3], B[0], C[3], D[3], E[3] },//no
  { A[3], B[3], C[3], D[3], E[1] },//on
  { A[3], B[3], C[3], D[3], E[0] },//off
  { A[3], B[1], C[3], D[3], E[3] },//zero
  { A[3], B[4], C[3], D[3], E[3] },//1
  { A[3], B[2], C[3], D[3], E[3] },//2
  { A[3], B[5], C[3], D[3], E[3] },//3
  { A[3], B[3], C[3], D[3], E[3] }//unknow
};
SoftwareSerial mySerial(0, 5);
/******/

void setup() {
  /**mixly**/
  item = 0;
  item1 = ' ';
  item2 = 0;
  item3 = ' ';
  operators = 4;//stop
  strings = "hello";
  Serial.begin(115200);
  mySerial.begin(115200);
  pinMode(4, OUTPUT);
  //v1: 串口读取
  //v2: 串口周期性点灯
  //v3: 添加语音串口通讯点灯
  //v4: 添加二维数组语音控制
  digitalWrite(4, LOW);
  Serial.println(strings);
  mySerial.println(strings);
  /******/
  // pinMode(joyX, INPUT);
  // pinMode(joyY, INPUT);
  WiFi.mode(WIFI_STA);                     //设置ESP8266工作模式为无线终端模式
  connectWifi();                           // 连接WiFi
  mqttClient.setServer(mqttServer, 1883);  // 设置MQTT服务器和端口号
  connectMQTTServer();                     // 连接MQTT服务器
}
int count = 0;
void loop() {
  if (mqttClient.connected()) {  // 如果开发板成功连接服务器
    pubMQTTmsg();
    //count = 0;
    mqttClient.loop();    // 保持客户端心跳
  } else {                // 如果开发板未能成功连接服务器
    connectMQTTServer();  // 则尝试连接服务器
  }
  delay(10);
}

void connectMQTTServer() {
  // 根据ESP32的MAC地址生成客户端ID(避免与其它ESP32的客户端ID重名)
  String clientId = "esp8266-" + WiFi.macAddress();
  // 连接MQTT服务器
  if (mqttClient.connect(clientId.c_str())) {
    Serial.println("MQTT Server Connected.");
    Serial.println("Server Address: ");
    Serial.println(mqttServer);
    Serial.println("ClientId:");
    Serial.println(clientId);
  } else {
    Serial.print("MQTT Server Connect Failed. Client State:");
    Serial.println(mqttClient.state());
    delay(3000);
  }
}

void pubMQTTmsg() {
  static int value;  // 客户端发布信息用数字

  char publishTopic[topicString.length() + 1];  // 这么做是为确保不同用户进行MQTT信息发布时,ESP8266客户端名称各不相同,
  strcpy(publishTopic, topicString.c_str());

  // Ym = analogRead(joyY);  //读取油门信息
  // Fx = analogRead(joyX);  //读取方向信息
  // // 建立发布信息。信息内容以Hello World为起始,后面添加发布次数。
  // String messageString = "A" + String(Ym) + "B" + String(Fx) + "C" + String(R) + "D" + String(L) + "E";
/**mixly**/
  procedure2();
  procedure();
  procedure4(operators);
  if (item > 234 && item < 239) {
    // procedure3();
    // delay(100);
    item = (map(item - 235, 0, 3, 0, 255));
    analogWrite(4, item);
  }
  if (item == 229) {
    digitalWrite(4, LOW);
  }
  String messageString = strings;
/**mixly**/
  char publishMsg[messageString.length() + 1];
  strcpy(publishMsg, messageString.c_str());
  // 实现ESP32向主题发布信息
  if (mqttClient.publish(publishTopic, publishMsg)) {
    //Serial.println("Publish Topic:");Serial.println(publishTopic);
    //Serial.println("Publish message:");
    Serial.println(publishMsg);
  } else {
    Serial.println("Message Publish Failed.");
  }
  delay(timer1);
}
void connectWifi() {
  WiFi.begin(ssid, password);
  //等待WiFi连接,成功连接后输出成功信息
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi Connected!");
  Serial.println("");
}

void procedure() {
  if (item3 != item1) {
    Serial.print("item:  ");
    Serial.println(item);
    Serial.print("item1:  ");
    Serial.println(item1);
    item3 = item1;
  }
}

void procedure2() {
  if (Serial.available() > 0) {
    item1 = Serial.read();
  }
  if (mySerial.available() > 0) {
    item1 = mySerial.read();
    item = String(item1).toInt();
    operators = item - 225;
  }
  if (item == 0) {
    item = item2;
  }
  item2 = item;
}

void procedure3() {
  Serial.println("ok");
  mySerial.println("ok");
}

void procedure4(int x) {
  for (int i = 0; i <= 4; i = i + (1)) {
    if (mylist[x][i] < action[0][i]) {
      action[1][i] = mylist[x][i];
    }
  }
  strings = String("A") + String(3700-action[1][0]) + String("B") + String(action[1][1]) + String("C") + String(action[1][2]) + String("D") + String(action[1][3]) + String("E") + String(action[1][4]) + String("F");
  // strings0 = String("A") + String(A[1]) + String("B") + String(B[1]) + String("C") + String(C[1]) + String("D") + String(D[1]) + String("E") + String(E[0]) + String("F");

  // Serial.print("massage:  ");
  // Serial.println(strings);
}

5.3.2 发射机

  • esp8266R程序
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Ticker.h>
#include <espnow.h>
#include <Servo.h>  // 调用Servo库
Servo servo_R;      // 定义Servo对象来控制
Servo servo_L;      // 定义Servo对象来控制
Ticker ticker;
/*
 		Board pin | NodeMCU GPIO | 	Arduino IDE
 					A- 										1 												5 or D1
 					A+ 										3 												0 or D3
 					B- 										2 												4 or D2
 					B+ 										4 												2 or D4
*/
#define IN_1 D1
#define IN_2 D3
#define IN_3 D2
#define IN_4 D4
#define LED D7
// #define servopinr D5
// #define servopinl D6

//↑↑↑以上4个IO口可以输出PWM波,实现全比例控制速度


// 设置wifi接入信息(根据小车要连接的WiFi信息进行修改)
// const char* ssid = "J09 502";
// const char* password = "qwertyuiop111";
// const char* ssid = "vor";
// const char* password = "vor980501";
const char* ssid = "XY-031026";
const char* password = "12345678";
String topicString = "minivorCar214923790t7";  //与esp32代码中的该部分相同
int YmMedian = 1816;                          //油门中位值
int FxMedian = 1811;                          //方向中位值


const char* mqttServer = "test.ranye-iot.net";
// 如以上MQTT服务器无法正常连接,请前往以下页面寻找解决方案
// http://www.taichi-maker.com/public-mqtt-broker/

int Ym, Fx, LeCar;
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

void setup() {
  pinMode(IN_1, OUTPUT);
  pinMode(IN_2, OUTPUT);
  pinMode(IN_3, OUTPUT);
  pinMode(IN_4, OUTPUT);
  pinMode(LED, OUTPUT);
  // pinMode(servopinr, OUTPUT);  //设定舵机接口为输出接口
  // pinMode(servopinl, OUTPUT);  //设定舵机接口为输出接口
  while (esp_now_init() != 0) {
    Serial.println("Error initializing ESP-NOW");
  }
  
  servo_R.attach(D5,500,2500);                       // 控制线连接数字D5
  servo_L.attach(D6,500,2500);                       // 控制线连接数字D6
  goStop();
  Serial.begin(115200);                     // 启动串口通讯(波特率为9600,波特率可以理解为串口传输数据的速度)
  WiFi.mode(WIFI_STA);                      //设置ESP8266工作模式为无线终端模式(8266像手机一样连接到wifi的模式)
  connectWifi();                            // 连接WiFi
  mqttClient.setServer(mqttServer, 1883);   // 设置MQTT服务器和端口号
  mqttClient.setCallback(receiveCallback);  // 设置MQTT订阅回调函数
  connectMQTTserver();                      // 连接MQTT服务器
  ticker.attach(0.3, touch);
}

void loop() {
  if (mqttClient.connected()) {  // 如果开发板成功连接服务器
    mqttClient.loop();           // 处理信息以及心跳
  } else {                       // 如果开发板未能成功连接服务器
    goStop();
    connectMQTTserver();  // 则尝试连接服务器
  }
}


// 连接MQTT服务器并订阅信息
void connectMQTTserver() {
  // 根据ESP8266的MAC地址生成客户端ID(避免与其它ESP8266的客户端ID重名)
  String clientId = "esp8266-" + WiFi.macAddress();

  // 连接MQTT服务器
  if (mqttClient.connect(clientId.c_str())) {
    Serial.println("MQTT Server Connected.");
    Serial.println("Server Address:");
    Serial.println(mqttServer);
    Serial.println("ClientId: ");
    Serial.println(clientId);
    subscribeTopic();  // 订阅指定主题
  } else {
    Serial.print("MQTT Server Connect Failed. Client State:");
    Serial.println(mqttClient.state());
    delay(5000);
  }
}


// 收到信息后的回调函数
// char Ym0[5], Fx0[5];  //储存接受到的油门和方向数据
// int Alocation, Blocation, Clocation, Ym1, Fx1;
char Ym0[5], Fx0[5], R0[5], L0[5], M0[5];                                                    //储存接受到的油门和方向数据
int Alocation, Blocation, Clocation, Dlocation, Elocation, Flocation, Ym1=1850, Fx1=1850, R1=90, L1=90, M1=0;  //定义解析标记位
// 收到信息后的回调函数
//A1827B1835C180D180E0F
void receiveCallback(char* topic, byte* payload, unsigned int length) {
  if ((char)payload[0] == 'A')  //检测esp8266是否联网
  {
    LeCar = 1;
  } else {
    LeCar = 0;
  }

  int j = 0, k = 0, l = 0, n = 0, o = 0;
  for (int i = 1; i < 6; i++) {
    if ((char)payload[i] != 'B') {
      Ym0[j] = (char)payload[i];
      j += 1;
    } else {
      Blocation = i;
      break;
    }
  }
  for (int i = Blocation + 1; i < 11; i++) {
    if ((char)payload[i] != 'C') {
      Fx0[k] = (char)payload[i];
      k += 1;
    } else {
      Clocation = i;
      break;
    }
  }
  for (int i = Clocation + 1; i < 15; i++) {
    if ((char)payload[i] != 'D') {
      R0[l] = (char)payload[i];
      l += 1;
    } else {
      Dlocation = i;
      break;
    }
  }
  for (int i = Dlocation + 1; i < 19; i++) {
    if ((char)payload[i] != 'E') {
      L0[n] = (char)payload[i];
      n += 1;
    } else {
      Elocation = i;
      break;
    }
  }
  for (int i = Elocation + 1; i < length; i++) {
    if ((char)payload[i] != 'E') {
      M0[o] = (char)payload[i];
      o += 1;
    } else {
      Flocation = i;
      break;
    }
  }
  // Ym1 = String(Ym0).toInt();
  // Fx1 = String(Fx0).toInt();
  Fx1 = String(Ym0).toInt();
  Ym1 = String(Fx0).toInt();
  R1 = String(R0).toInt();
  L1 = String(L0).toInt();
  M1 = String(M0).toInt();
  //Ym1 = map(Ym1,YmMedian+50, 4095, 0, 255);
  //  Serial.print("Ym=");
  //  Serial.print(Ym1);
  //  Serial.print(",FX=");
  //  Serial.println(Fx0);

  for (int i = 0; i < 5; i++) {
    Ym0[i] = '\0';
    Fx0[i] = '\0';
    R0[i] = '\0';
    L0[i] = '\0';
    M0[i] = '\0';
  }
}

// 订阅指定主题
void subscribeTopic() {
  char subTopic[topicString.length() + 1];
  strcpy(subTopic, topicString.c_str());
  if (mqttClient.subscribe(subTopic)) {
    Serial.println("Subscrib Topic:");
    Serial.println(subTopic);
  } else {
    Serial.print("Subscribe Fail...");
  }
}

void connectWifi() {
  WiFi.begin(ssid, password);
  //等待WiFi连接,成功连接后输出成功信息
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi Connected!");
  Serial.println("");
}
int Speedy1, Speedy2, Speedx1, Speedx2, direction;
void touch() {
  //    Serial.print(Ym1);
  //     Serial.print(",");
  //     int a=YmMedian+50;
  //     Serial.println(a);
  if (Ym1 > YmMedian + 50) {
    Ym = map(Ym1, YmMedian + 50, 4095, 0, 255);
    Speedy1 = Ym;
    direction = 0;
    //   Serial.print("Speedy1:");
    //   Serial.println(Speedy1);
    Speedy2 = 0;
  } else if (Ym1 < YmMedian - 50) {
    Ym = 255 - map(Ym1, 0, YmMedian - 50, 0, 255);
    Speedy1 = 0;
    direction = 1;
    Speedy2 = Ym;
    //    Serial.print("Speedy2:");
    //    Serial.println(Speedy2);
  } else if (Fx1 > FxMedian + 50) {
    Fx = map(Fx1, FxMedian + 50, 4095, 0, 255);
    Speedx1 = Fx;
    //   Serial.print("Speedx1:");
    //   Serial.println(Speedx1);
    Speedx2 = 0;
  } else if (Fx1 < FxMedian - 50) {
    Fx = 255 - map(Fx1, 0, FxMedian - 50, 0, 255);
    Speedx1 = 0;
    Speedx2 = Fx;
    //    Serial.print("Speedx2:");
    //    Serial.println(Speedx2);
  } else if (YmMedian - 50 < Ym1 < YmMedian + 50 && FxMedian - 50 < Fx1 < FxMedian + 50) {
    Speedy1 = 0;
    Speedy2 = 0;
    Speedx1 = 0;
    Speedx2 = 0;
    Ym = 0;
    Fx = 0;
  }
  if (LeCar == 1)
    GoCar();
  else
    goStop();
}


void GoCar() {
  analogWrite(IN_1, Speedy1 + Speedx1 + Speedy2);
  digitalWrite(IN_2, direction);
  analogWrite(IN_3, Speedy1 + Speedx2 + Speedy2);
  digitalWrite(IN_4, direction);
  Serial.println("IN_1: " + String(Speedy1 + Speedx1 + Speedy2) + "IN_3: " + String(Speedy1 + Speedx2 + Speedy2));
  Serial.println("A" + String(Ym1) + "B" + String(Fx1) + "C" + String(R1) + "D" + String(L1) + "E"+ String(M1) + "F");
  servo_R.write(R1);             	// 舵机角度写入
  servo_L.write(L1);             	// 舵机角度写入
  digitalWrite(LED,M1);
}



void goStop() {
  digitalWrite(IN_1, LOW);
  digitalWrite(IN_2, LOW);
  digitalWrite(IN_3, LOW);
  digitalWrite(IN_4, LOW);
  digitalWrite(LED, LOW);
  servo_R.write(90);             	// 舵机角度写入
  servo_L.write(90);             	// 舵机角度写入
  // delay(100);
}

6.  实验效果

首先是搭建接收机和发射机硬件结构,然后下载程序,检查设备接线,测试15组关键字功能

max7800串口打印效果

21:05:31.663 -> ***** Init *****
21:05:31.664 -> pChunkBuff: 128
21:05:31.665 -> pPreambleCircBuffer: 3840
21:05:31.668 -> pAI85Buffer: 16384
21:05:31.737 -> Error opening SD card: FR_NOT_READY
21:05:31.741 -> *** !!!SD ERROR (mounting) !!! ***
21:05:31.744 -> 
21:05:31.744 -> *** I2S & Mic Init ***
21:05:33.741 -> 
21:05:33.741 -> *** READY ***
21:05:42.895 -> 136448 Word starts from index: 132480, avg:499 > 350 
21:05:43.371 -> 144000: Word ends, Appends 4992 zeros 
21:05:43.375 -> 144000: Starts CNN: 1
21:05:43.376 -> 
21:05:43.378 -> 144000: Completes CNN: 1
21:05:43.381 -> CNN Time: 1843 us
21:05:43.382 -> Min: -128,   Max: 127 
21:05:43.384 -> ----------------------------------------- 
21:05:43.388 -> Detected word: ON (96.5%)
21:05:43.391 ->  count : 0: 1: a
21:05:43.392 -> 
21:05:43.392 -> ----------------------------------------- 
21:05:43.454 -> Error opening SD card: FR_NOT_READY
21:05:43.455 -> *** !!!SD ERROR!!! ***
21:05:43.457 -> 
21:05:43.457 -> 
21:05:43.457 -> *** READY ***
21:05:47.081 -> 201984 Word starts from index: 198016, avg:407 > 350 
21:05:47.502 -> 208640: Word ends, Appends 5888 zeros 
21:05:47.507 -> 208640: Starts CNN: 2
21:05:47.511 -> 208640: Completes CNN: 2
21:05:47.513 -> CNN Time: 1843 us
21:05:47.518 -> Min: -115,   Max: 110 
21:05:47.518 -> ----------------------------------------- 
21:05:47.520 -> Detected word: OFF (100.0%)
21:05:47.523 ->  count : 1: 2: f
21:05:47.524 -> 
21:05:47.524 -> ----------------------------------------- 
21:05:47.583 -> Error opening SD card: FR_NOT_READY
21:05:47.586 -> *** !!!SD ERROR!!! ***
21:05:47.588 -> 
21:05:47.589 -> 
21:05:47.589 -> *** READY ***

 

esp8266T串口打印效果

21:05:02.727 -> rll��|�l�|�$�#|����r�c�"�p�N�lNn���bp��ls$rlp�N��$��#n�|���b��nn�$��l �Nn�{lor���o{r� p�o�r������bN��o�c��no��d �Nn�lor���Nrl`r��or$`����l$`��N�dhello
21:05:03.814 -> .....
21:05:08.553 -> WiFi Connected!
21:05:08.553 -> 
21:05:08.740 -> MQTT Server Connected.
21:05:08.740 -> Server Address: 
21:05:08.740 -> test.ranye-iot.net
21:05:08.740 -> ClientId:
21:05:08.740 -> esp8266-C8:2B:96:08:73:AD
21:05:08.740 -> A1850B1850C120D60E0F
21:05:09.051 -> A1850B1850C120D60E0F
21:05:09.361 -> A1850B1850C120D60E0F

 

esp8266R串口打印效果

21:09:05.523 -> sdlܟ<�l�<�l�c|����r�#�c��gn�dog���c8��lrd;lx�o��d��#g�|�Ǐ#��ng�$��l �'o�dgs���ors�`p�'�s�ܜ���co�<�c��'o��d`�'o�dgs���or$`r��gsl`�����d`��g�d........
21:09:14.394 -> WiFi Connected!
21:09:14.394 -> 
21:09:14.797 -> MQTT Server Connected.
21:09:14.797 -> Server Address:
21:09:14.797 -> test.ranye-iot.net
21:09:14.797 -> ClientId: 
21:09:14.797 -> esp8266-48:55:19:16:40:C1
21:09:14.797 -> Subscrib Topic:
21:09:14.797 -> minivorCar214923790t7
21:09:18.079 -> IN_1: 0IN_3: 0
21:09:18.079 -> A1850B1850C120D60E0F
21:09:18.388 -> IN_1: 0IN_3: 0

 

演示视频:基于MAX7800羽毛板语音控制ESP8266小车_哔哩哔哩_bilibili

7. 总结

  • 这是我第二次参加嵌入式相关的网上比赛活动,第一次是RT-Thread的【基于RT-Thread+RA6M4的智能鱼缸系统设计之鱼我所欲也】活动,作品是022年暑假做的获得第六名,还是比较 开心!
  • 我相信我的付出,期待这一次的成绩!

虽然这次比赛初期我没有进行kws20 demo的训练试验,但是勇敢的我说是站在巨人的肩膀上,有点小遗憾我的时间和电脑都比较拉胯,下次争取做一些训练,跑一跑模型!🛹🛹🛹我们每天都一点点结合联动丰富生活,从而实现对外部世界进行充分的感知,尽最大努力认识这个有机与无机的环境,科学地合理地进行创作和发挥效益,然后为人类社会发展贡献一点微薄之力。🤣🤣🤣
🥳🥳🥳再次非常感谢大赛支持和胡同学,乔大哥等等🥳🥳🥳

参考文献

  • [window10下配置Maxim SDK]()
  • [数据手册]()
  • [MAX78000板卡项目汇总]()
  • [应用笔记]()
  • [MAX78000 关键字定位演示 v.3]()
  • [【window下配置Maxim SDK环境】]()
  • [【MAX78000基础案例演示】]()
  • [【MAX7800实现KWS20 demo演示】]()
  • [【MAX7800与ESP8266mcu串口通讯点灯】]()
     

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/144428.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JSP——EL表达式

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;JAVA开发者…

年度征文 | 回顾2022,展望2023 (清风与我)

个人简介&#xff1a; 名称内容个人主页清风与我学习方向主攻前端方向推荐学习vue&#xff0c;vue3&#xff0c;node.js&#xff0c;React&#xff0c;项目实战推荐学习用网站菜鸟教程&#xff0c;博客&#xff0c;哔哩哔哩 …学习用资源网vue&#xff0c;element&#xff0c;…

Apollo星火计划学习笔记——Apollo开放空间规划算法原理与实践

文章目录1. 开放空间规划算法总体介绍1.1 Task: OPEN_SPACE_ROI_DECIDER1.2 Task: OPEN_SPACE_TRAJECTORY_PROVIDER1.3 Task: OPEN_SPACE_TRAJECTORY_PARTITION1.4 Task: OPEN_SPACE_FALLBACK_DECIDER2. 基于混合A *的路径规划算法2.1 hybrid A*的简要思想2.2 RS曲线2.3 Apollo…

一文读懂方壳电池仓段差缺陷检测

摩根大通预计&#xff0c;2025年中国新能源汽车渗透率将达46.3%&#xff0c;彭博新能源财经最新发布的《新能源汽车市场长期展望》(EVO)报告显示&#xff0c;到2025年底&#xff0c;新能源汽车保有量将达到7700万辆&#xff0c;不难看出新能源行业依旧前景广阔。围绕“新能源”…

JDBC(Java Database connect)详解

一、相关概念 什么是JDBC JDBC&#xff08;Java Data Base Connectivity,java数据库连接&#xff09;是一种用于执行SQL语句的Java API&#xff0c;可以为多种关系数据库提供统一访问&#xff0c;它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准&#xff0c;据此可…

软件测试门槛低么?适合初学者么

随着软件工程活动的不断演化&#xff0c;软件测试工作已经成为了不可或缺的一部分&#xff0c;测试工作某种程度上是可以很大幅度提高软件的产品质量以及提升用户的使用满意度。因此&#xff0c;许多想要学习软件测试的朋友也许常常会有这样的困惑&#xff0c;软件测试门槛低吗…

JS数组对象——根据日期进行排序Date.parse(),按照时间进行升序或降序排序localeCompare()

JS数组对象——根据日期对象进行排序&#xff0c;按照时间进行升序或降序排序场景复现封装数组对象的排序方法根据日期和时间对象排序1、按照日期时间混合排序2、分别按照日期和时间进行排序场景复现 排序在项目中非常实用&#xff0c;出现频率极高&#xff0c;尤其是后台管理…

用javascript分类刷leetcode17.栈(图文视频讲解)

目录 Stack的特点&#xff1a;先进后出&#xff08;FILO&#xff09; 使用场景&#xff1a;十进制转2进制 函数调用堆栈 js里没有栈&#xff0c;但是可以用数组模拟 42/2 42%20 21/2 21%21 10/2 10%20 5/2 5%21 2/2 2%20 1/2 1%21 stack: [0,1,0,1,0,1] res: 1 0 1 …

VC#复习资料

一、选择题 2、“闪电”图标 3、using命名空间 命名空间的设计目的是提供一种让一组名称与其他名称分隔开的方式&#xff0c;using 关键字表明程序使用的是给定命名空间中的名称&#xff0c;使用 using 命名空间指令&#xff0c;这样在使用的时候就不用在前面加上命名空间名称…

golang学习

由于期末考试没时间学算法学了一波go放松一下 这可能是我学语言最认真的一次了&#xff08; 跟的是尚硅谷学完的 二倍速快进 折腾了一周左右 网络编程部分没看 因为不懂计网 不想学&#xff08; 虽然已经很老的课了 但是顺平老师雀氏讲的太细了也是听完了自己也没时间写笔记 …

QT5.14.2编译mysql-5.7.25 32位驱动办法

开发环境&#xff1a;Windows10QT5.14.2MySQL5.7.25 编译步骤&#xff1a; 1、下载安装mysql压缩包&#xff0c;下载地址为&#xff1a;https://cdn.mysql.com/archives/mysql-5.7/mysql-5.7.25-win32.zip 也可以打开MySQL :: Download MySQL Community Server (Archived Ve…

Electron主进程渲染进程间通信的四种方式

在electron中进程使用 ipcMain 和 ipcRenderer 模块&#xff0c;通过开发人员定义的“通道”传递消息来进行通信。新的版本中electron推荐使用上下文隔离渲染器进程进行通信&#xff0c;这种方式的好处是无需在渲染进程中直接使用ipcRenderer发送消息&#xff0c;这种在渲染进程…

JWT令牌入门

上篇文章我们写了如何登录&#xff0c;我们着重学习Token模式下的单点登录 一、访问令牌的类型 透明令牌&#xff0c;是客户端存储一段引用数字&#xff0c;然后到达服务器指向服务器中特定的令牌 类似于&#xff0c;cookie中存储了sessionId他们之间的关系 自包含令牌&#x…

猿代码超算实习生,五步助力拿到高薪offer

虽说行行出状元&#xff0c;但是一旦入错行&#xff0c;那就是一辈子的事。互联网的潮水已经退去&#xff0c;普通人再进入也只是勉强温饱。与其朝不保夕的被裁员&#xff0c;倒不如提前锁定未来30年的幸福。 20大以来&#xff0c;芯片国产化、超算&#xff08;先进计算&#…

docker的run,cmd,entrypoint分析和对比

写在前面 本文一起看下Dockerfile中经常用到的几个类似命令&#xff0c;RUN&#xff0c;CMD&#xff0c;ENTRYPOINT。 1&#xff1a;容器是怎么来的&#xff1f; 想要有容器我们就必须先创建镜像&#xff0c;而想要有镜像&#xff0c;我们则必须写一个用来描述想要创建的镜像…

Struts2基本架构

Struts2基本架构1、Struts2执行流程2、web.xml配置3、Action控制器3.1、核心控制器3.2、业务控制器4、Result配置5、struts.xml核心配置5.1、constant元素5.2、package元素5.3、配置文件加载顺序1、Struts2执行流程 如下例子&#xff1a; 执行流程如下&#xff1a; 浏览器将请…

Python Flask开发笔记

Python Flask开发笔记一、创建flask项目1.开发环境&#xff1a;2.安装Flask3.使用pycharm&#xff0c;创建flask项目二、flask介绍1.介绍初始flask主程序接口文件2.Flask() 类1.Flask参数解释0.sys.modules用于缓存程序导入模块名1.import_name 主程序模块名2.static_url_path …

IconJar - Mac 上的一款多功能图标素材管理工具

IconJar - Mac 上的一款多功能图标素材管理工具 IconJar 是一个多功能的图标管理工具&#xff0c;由世界各地的设计师和开发人员使用。在一个应用程序中搜索、组织、预览和检索图标&#xff0c;而不是创建大量的文件夹来存储你的收藏。这款应用针对黑暗模式进行了优化&#xff…

2022年自动化测试工具汇总——实用的功能测试工具篇

如今&#xff0c;UI自动化测试工具就和雨后春笋般&#xff0c;层出不穷。由于每种工具都有自己的重点和策略&#xff0c;所以总是让人无从下手。今天我们来对比现在使用比较广泛的几个UI自动化测试工具&#xff0c;来看看他们之间的优缺点。 首先&#xff0c;我们先简单介绍一下…

4.6.4、边界网关 BGP 的基本工作原理

1、力求寻找较好的路由 因特网采用分层次的路由选择协议 内部网关协议&#xff08;例如&#xff1a;路由信息协议 RIP 或开放最短路径优先 OSPF&#xff09; 它们都是设法使分组在一个自治系统内尽可能有效地从源网络传输到目的网络无需考虑自治系统外部其他方面的策略 外部…