前言:
收到安信可小安派BW21-CBV-Kit的板卡,前期搭建完环境后,一直在学习园长的教程。申请时并不了解这块开发板,觉着应该和ESP-CAM对标,应该是差不多的开发板,但是收到后,通过学习园长的教程,才发现这个小安派BW21功能出奇的强大啊!尤其在机器学习方面,性能强的不是一点半点了。园长的教程超棒,可以跟着探索机器学习的世界啦!
需求:
打雷啦!下雨啦!快关窗户啊!计划使用小安派BW21实现监控是否下雨,控制窗户开关的功能。当下雨时,就通过舵机,关闭窗户;雨过天晴,再打开窗户,拥抱的自然!
软硬件:BW21-CBV-Kit开发板,舵机。Arduino IDE。希望能早日在platformIO上支持这块开发板,Arduino IDE真心不好用。
实现:
整个项目基于AudioClassification例程改造。AudioClassification例程是一个声音区分的例程,能检测 521 种不同的音频。本项目中,仅仅需要识别雨声,所以将与下雨相关的声音挑出来,进行保留,其余的声音类别不做识别(保留了噪声类型)。

开关窗的动作使用舵机实现。BW21-CBV-Kit开发板中舵机驱动库为 AmebaServo.h
,使用上和Arduino中的舵机库使用相同。就是这个管脚对应有点奇怪,这里使用了8号GPIO,对应的是丝印为IOF15的管脚。使用两个变量,isRaining用来标识是否下雨,采用在时间周期内识别到2次以上的特定声音类别,即判断为下雨了,此时驱动舵机关闭窗户。当时间周期内没有识别到指定的声音类型,则驱动舵机打开窗户。测试过程中时间周期设置为60秒,实际使用中应该设置更长的时间,如15分钟或半小时。
/*
Example guide:
https://www.amebaiot.com/en/amebapro2-arduino-neuralnework-face-audio-classification/
*/
// #include "WiFi.h"
#include "StreamIO.h"
#include "NNAudioClassification.h"
#include "AudioClassList.h"
#include <AmebaServo.h>
AmebaServo myservo; //添加一个舵机控制
long raintime = 0;
short isRaining = 0;
// NN audio classification requires 16KHz
AudioSetting configA(16000, 1, USE_AUDIO_AMIC); // Sample rate, Channel count, Mic type
Audio audio;
NNAudioClassification audioNN;
StreamIO audioStreamerNN(1, 1); // 1 Input Audio -> 1 Output Audio Classification
void setup() {
// Configure audio peripheral for audio data format
audio.configAudio(configA);
audio.begin();
audioNN.configAudio(configA);
audioNN.setResultCallback(ACPostProcess);
audioNN.modelSelect(AUDIO_CLASSIFICATION, NA_MODEL, NA_MODEL, NA_MODEL, DEFAULT_YAMNET);
audioNN.begin();
myservo.attach(8); //舵机 设置为IOF15管脚
myservo.write(0); //默认开窗
// Configure StreamIO object to stream data from audio to audio classification
audioStreamerNN.registerInput(audio);
audioStreamerNN.registerOutput(audioNN);
if (audioStreamerNN.begin() != 0) {
Serial.println("StreamIO link start failed");
}
}
void loop() {
if (isRaining > 2) {
// 下雨了,要关窗
Serial.println("下雨了,需要关窗");
isRaining=0;
myservo.write(90); //关窗
}
if (millis() - raintime > 1000 * 60) {
Serial.println("雨停了,需要关窗");
isRaining = 0; //长时间没检测到下雨,就重置状态
myservo.write(0); //关窗
}
}
// User callback function
void ACPostProcess(std::vector<AudioClassificationResult> results) {
// printf("No of Audio Detected = %d\r\n", audioNN.getResultCount());
if (audioNN.getResultCount() > 0) {
for (int i = 0; i < audioNN.getResultCount(); i++) {
AudioClassificationResult audio_item = results[i];
int class_id = (int)audio_item.classID();
if (audioNames[class_id].filter) {
int prob = audio_item.score();
// 过滤一下,将可信度设置为75%
if (prob > 75) {
printf("%d class %d, score: %d, audio name: %s\r\n", i, class_id, prob, audioNames[class_id].audioName);
if (class_id == 282 || class_id == 283 || class_id == 284 || class_id == 285 || class_id == 286 || class_id == 287) {
// 发现下雨了,关闭窗户
// printf("下雨了,需要关窗");
isRaining = isRaining > 10 ? 10 : isRaining + 1;
raintime = millis();
// myservo.write(180);
}
}
}
}
}
}
展示:
开机后,舵机处于关闭窗户状态。

听到下雨声,关闭窗户。


视频:
【根据雨声自动开关窗】 https://www.bilibili.com/video/BV1TwXjYwEAh/?share_source=copy_web&vd_source=5c0d591d24b24b586d120335adf6a093