- 2025-06-30
-
发表了主题帖:
【Follow me第三季第1期】任务汇总
本帖最后由 eew_uscYT9 于 2025-6-30 23:56 编辑
【Follow me第三季第1期】 任务一,搭建开发环境、串口输出 https://bbs.eeworld.com.cn/thread-1319161-1-1.html
【Follow me第三季第1期】 任务二 LED控制 https://bbs.eeworld.com.cn/thread-1319162-1-1.html
【 Follow me第三季第1期】+ 任务三:运动传感器数据读取 https://bbs.eeworld.com.cn/thread-1319175-1-1.html
【Follow me第三季第1期】任务五-光线强度检测 https://bbs.eeworld.com.cn/thread-1319176-1-1.html
课时管理 - 课程管理 - EEWORLD大学堂
- 2025-06-29
-
加入了学习《DK FollowMe: STM32F429I-DISC1及任务讲解》,观看 STM32F429I-DISC1及任务讲解
-
发表了主题帖:
【 Follow me第三季第1期】+ 任务三:运动传感器数据读取
本帖最后由 eew_uscYT9 于 2025-6-29 16:47 编辑
任务要求:运动传感器数据读取——读取运动传感器的数据,并通过串口数据;
借鉴了Oliver_c大佬的帖子,Follow me第三季第1期】+ 任务三:运动传感器数据读取 https://bbs.eeworld.com.cn/thread-1317081-1-1.html
实现了对运动传感器数据的读取,并且通过串口输出到电脑上
实现步骤: 开启SPI5 ->读取I3G4250D的数据->通过串口1输出到电脑上
BSP_GYRO_Init(); 对运动传感器进行初始化
进行数据的获取
BSP_GYRO_GetXYZ(xyz);
printf("data:%f,%f,%f\r\n",xyz[0],xyz[1],xyz[2]);
-
发表了主题帖:
【Follow me第三季第1期】 任务一,搭建开发环境、串口输出
本帖最后由 eew_uscYT9 于 2025-6-29 01:35 编辑
下面是我的开发环境
keil加上stm32cubemx,
安装过程就不再详细的描述了,
我是通过cubemx快速生成板子的工程代码,快速开发,下面是生成代码步骤
选择第一个,根据芯片开发,在搜索框内输入STM32F429ZIT6,找到开发板对应的芯片,点击
点击start,开始新建项目
勾上外部晶振和对应的sw烧录接口
勾上串口1,用串口1进行输出
系统时钟选择8mhz的外部晶振输入,主频为180mhz
接着选择工程对应的位置,然后点击右上角的generate coede就能生成对应的工程了
在工程里加入下面的代码就能用printf输出内容了
int fputc(int ch, FILE *f){
uint8_t temp[1] = {ch};
HAL_UART_Transmit(&huart1, temp, 1, 0xffff);
return ch;
}
串口1输出的结果
- 2025-06-21
-
发表了主题帖:
【Follow me第三季第1期】任务五-光线强度检测
本帖最后由 eew_uscYT9 于 2025-6-29 22:33 编辑
Grove-Light传感器集成了一个光电阻(依赖光强调整电阻)来检测光强。 当光强度增加时,光电阻的电阻降低。 板上的双OpAmp芯片LM358产生与光强度相对应的电压(即基于电阻值)。 输出信号为模拟值,亮度越亮,值越大。
该模块可用于构建光控开关,通过ADC读取对应的数据,实现在白天关闭灯,并在夜间开启灯。
cubenmx配置如下,打开ADC1,选择通道5
通过ADC1读取Grove-Light传感器的数据,对数据进行判断就能实现在光强的时候关灯,光弱的时候开灯
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1,100);
adcdata =HAL_ADC_GetValue(&hadc1);
voltage = adcdata*(3.3/4096);
if(voltage > 1.5)
{
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_14, GPIO_PIN_RESET);
}
else
{
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_14, GPIO_PIN_SET);
}
演示视频
[localvideo]db44e73662a8344c2e82a00987c07b29[/localvideo]
-
发表了主题帖:
【Follow me第三季第1期】 任务二 LED控制
本帖最后由 eew_uscYT9 于 2025-6-29 01:52 编辑
任务二(必做):LED控制——控制板载LED灯,并实现呼吸灯效果
通过查看板子的原理图,发现LED对应的引脚没有PWM功能,所以我用GPIO模拟PWM
利用定时器中断进行计数,根据计数值控制灯的亮灭时间,达到PWM的效果
void breatheLED(void) {
if(count >= 100) {
count = 0;
if(dir == 0) {
dir_count++;
} else if(dir == 1) {
dir_count--;
}
}
if(dir_count <= 0) {
dir = 0;
} else if(dir_count >= 100) {
dir = 1;
}
if(count < dir_count) {
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_14, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_14, GPIO_PIN_RESET);
}
}
效果如下
[localvideo]93b03f016de8ba6a3ac05009e920e6e9[/localvideo]
- 2025-01-08
-
回复了主题帖:
【Follow me第二季第4期】基于 Edge Impulse 的语音识别
lugl4313820 发表于 2024-12-30 22:25
咱们这个语音识别,是要联网?还是把算法下载到本地就可以识别了?
把算法下载到了单片机上
- 2024-12-30
-
回复了主题帖:
【Follow me第二季第4期】任务汇总
【Follow me第二季第4期】代码-嵌入式开发相关资料下载-EEWORLD下载中心
- 2024-12-29
-
上传了资料:
【Follow me第二季第4期】代码
-
加入了学习《任务提交》,观看 任务提交
-
加入了学习《fm4任务展示》,观看 fm4任务展示
-
回复了主题帖:
【Follow me第二季第4期】任务二 学习IMU基础知识,通过串口打印六轴原始数据
补充一下演示视频
[localvideo]9de5480931303ec0416d695adf902631[/localvideo]
-
加入了学习《Follow me第二季第4期 Arduino? Nano RP2040 Connect活动项目总结》,观看 Follow me第二季第4期项目总结
-
回复了主题帖:
【Follow me第二季第4期】任务汇总
【Follow me第二季第4期】基于 Edge Impulse 的语音识别 https://bbs.eeworld.com.cn/thread-1302947-1-1.html
-
发表了主题帖:
【Follow me第二季第4期】基于 Edge Impulse 的语音识别
本帖最后由 eew_uscYT9 于 2024-12-28 23:23 编辑
本项目教你如何做出自己的语音识别
本项目的大体流程 我的语音识别是识别开灯和关灯两个声音,听到对应的声音就对板子上的灯进行开和关
https://studio.edgeimpulse.com/ 先去这个网站注册好账号
然后创建一个新的项目
输入项目名字,其他保存不动
接着到了数据的采集,我通过对Edge Impulse的文档查阅,发现可以用Arduino Nano主板进行数据的采集,其他的数据采集方式有手机、Edge Impulse CLI(该方式比较复杂)
先下载Edge Impulse准备好的固件
然后把该固件下载到nano板子上
接着点左边的data acquisition
点击下面所指的图标就能进行数据的采集,数据分为训练数据集和测试数据集,一般是8、2开,
数据采集完之后点击creat impulse进行训练的设置,如下面所示,设置完之后点击save impulse
点击mfcc进行参数的设置,直接默认设置,然后保存参数
然后点击上方的generate features进行生成特征 ,根据feature explorer能够看出我的数据区分度还是挺高的
接着点击classifier 进行训练,参数都可以用默认设置
点击model testing进行模型测试 我的模型训练还是可以的 接下来进行模型的部署,我们现在arduino,然后进行build,把生成的文件下载下来,打开arduino ide进行添加
我的代码如下
/* Edge Impulse ingestion SDK
* Copyright (c) 2022 EdgeImpulse Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// If your target is limited in memory remove this macro to save 10K RAM
#define EIDSP_QUANTIZE_FILTERBANK 0
/*
** NOTE: If you run into TFLite arena allocation issue.
**
** This may be due to may dynamic memory fragmentation.
** Try defining "-DEI_CLASSIFIER_ALLOCATION_STATIC" in boards.local.txt (create
** if it doesn't exist) and copy this file to
** `<ARDUINO_CORE_INSTALL_PATH>/arduino/hardware/<mbed_core>/<core_version>/`.
**
** See
** (https://support.arduino.cc/hc/en-us/articles/360012076960-Where-are-the-installed-cores-located-)
** to find where Arduino installs cores on your machine.
**
** If the problem persists then there's not enough memory for this model and application.
*/
/* Includes ---------------------------------------------------------------- */
#include <rp2040_inferencing.h>
#include <PDM.h>
#include "WiFiNINA.h"
#define led1 LEDB
#define led2 LEDG
#define led3 LEDR
/** Audio buffers, pointers and selectors */
typedef struct {
int16_t *buffer;
uint8_t buf_ready;
uint32_t buf_count;
uint32_t n_samples;
} inference_t;
static inference_t inference;
static signed short sampleBuffer[2048];
static bool debug_nn = false; // Set this to true to see e.g. features generated from the raw signal
static volatile bool record_ready = false;
/**
* [url=home.php?mod=space&uid=159083]@brief[/url] Arduino setup function
*/
void setup()
{
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(led3, OUTPUT);
pinMode(led2, OUTPUT);
// comment out the below line to cancel the wait for USB connection (needed for native USB)
while (!Serial);
Serial.println("Edge Impulse Inferencing Demo");
// summary of inferencing settings (from model_metadata.h)
ei_printf("Inferencing settings:\n");
ei_printf("\tInterval: ");
ei_printf_float((float)EI_CLASSIFIER_INTERVAL_MS);
ei_printf(" ms.\n");
ei_printf("\tFrame size: %d\n", EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE);
ei_printf("\tSample length: %d ms.\n", EI_CLASSIFIER_RAW_SAMPLE_COUNT / 16);
ei_printf("\tNo. of classes: %d\n", sizeof(ei_classifier_inferencing_categories) / sizeof(ei_classifier_inferencing_categories[0]));
if (microphone_inference_start(EI_CLASSIFIER_RAW_SAMPLE_COUNT) == false) {
ei_printf("ERR: Could not allocate audio buffer (size %d), this could be due to the window length of your model\r\n", EI_CLASSIFIER_RAW_SAMPLE_COUNT);
return;
}
}
/**
* @brief Arduino main function. Runs the inferencing loop.
*/
void loop()
{
ei_printf("Starting inferencing in 2 seconds...\n");
delay(2000);
ei_printf("Recording...\n");
bool m = microphone_inference_record();
if (!m) {
ei_printf("ERR: Failed to record audio...\n");
return;
}
ei_printf("Recording done\n");
signal_t signal;
signal.total_length = EI_CLASSIFIER_RAW_SAMPLE_COUNT;
signal.get_data = µphone_audio_signal_get_data;
ei_impulse_result_t result = { 0 };
EI_IMPULSE_ERROR res = run_classifier_continuous(&signal, &result, debug_nn);
if (res != EI_IMPULSE_OK) {
ei_printf("ERR: Failed to run classifier (%d)\n", res);
return;
}
// print inference return code
ei_printf("run_classifier returned: %d\r\n", res);
print_inference_result(result);
//ei_printf(" %s: ", ei_classifier_inferencing_categories[i]);
}
/**
* @brief PDM buffer full callback
* Copy audio data to app buffers
*/
static void pdm_data_ready_inference_callback(void)
{
int bytesAvailable = PDM.available();
// read into the sample buffer
int bytesRead = PDM.read((char *)&sampleBuffer[0], bytesAvailable);
if ((inference.buf_ready == 0) && (record_ready == true)) {
for(int i = 0; i < bytesRead>>1; i++) {
inference.buffer[inference.buf_count++] = sampleBuffer[i];
if(inference.buf_count >= inference.n_samples) {
inference.buf_count = 0;
inference.buf_ready = 1;
break;
}
}
}
}
/**
* @brief Init inferencing struct and setup/start PDM
*
* @param[in] n_samples The n samples
*
* [url=home.php?mod=space&uid=784970]@return[/url] { description_of_the_return_value }
*/
static bool microphone_inference_start(uint32_t n_samples)
{
inference.buffer = (int16_t *)malloc(n_samples * sizeof(int16_t));
if(inference.buffer == NULL) {
return false;
}
inference.buf_count = 0;
inference.n_samples = n_samples;
inference.buf_ready = 0;
// configure the data receive callback
PDM.onReceive(pdm_data_ready_inference_callback);
PDM.setBufferSize(2048);
delay(250);
// initialize PDM with:
// - one channel (mono mode)
if (!PDM.begin(1, EI_CLASSIFIER_FREQUENCY)) {
ei_printf("ERR: Failed to start PDM!");
microphone_inference_end();
return false;
}
// optionally set the gain, defaults to 24
// Note: values >=52 not supported
//PDM.setGain(40);
return true;
}
/**
* @brief Wait on new data
*
* @return True when finished
*/
static bool microphone_inference_record(void)
{
bool ret = true;
record_ready = true;
while (inference.buf_ready == 0) {
delay(10);
}
inference.buf_ready = 0;
record_ready = false;
return ret;
}
/**
* Get raw audio signal data
*/
static int microphone_audio_signal_get_data(size_t offset, size_t length, float *out_ptr)
{
numpy::int16_to_float(&inference.buffer[offset], out_ptr, length);
return 0;
}
/**
* @brief Stop PDM and release buffers
*/
static void microphone_inference_end(void)
{
PDM.end();
ei_free(inference.buffer);
}
void print_inference_result(ei_impulse_result_t result) {
// Print how long it took to perform inference
ei_printf("Timing: DSP %d ms, inference %d ms, anomaly %d ms\r\n",
result.timing.dsp,
result.timing.classification,
result.timing.anomaly);
ei_printf("Predictions:\r\n");
for (uint16_t i = 0; i < EI_CLASSIFIER_LABEL_COUNT; i++) {
if(result.classification[i].value>0.7)
{
switch (i) {
case 0: digitalWrite(led3, LOW); break;
case 1: digitalWrite(led3, HIGH); break;
default: digitalWrite(led2, LOW);
}
}
ei_printf(" %s: ", ei_classifier_inferencing_categories[i]);
ei_printf("%.5f\r\n", result.classification[i].value);
}
// Print anomaly result (if it exists)
#if EI_CLASSIFIER_HAS_ANOMALY == 1
ei_printf("Anomaly prediction: %.3f\r\n", result.anomaly);
#endif
}
#if !defined(EI_CLASSIFIER_SENSOR) || EI_CLASSIFIER_SENSOR != EI_CLASSIFIER_SENSOR_MICROPHONE
#error "Invalid model for current sensor."
#endif
演示视频
[localvideo]d8177a49fca202d9ad2e38951857c1aa[/localvideo]
- 2024-12-28
-
回复了主题帖:
【Follow me第二季第4期】任务三 学调试PDM麦克风,通过串口打印收音数据和音频波形
本帖最后由 eew_uscYT9 于 2024-12-29 23:27 编辑
[localvideo]2d950ac4b69a1ed58dc86b1ceae90a16[/localvideo]
对应的视频展示
还有一个和pico2联动,通过打响指能控制nano板子和pico2板子的灯进行变化
[localvideo]2d51811098e155c28760aee1191550e6[/localvideo]
- 2024-12-26
-
加入了学习《【Follow me第二季第4期】ARDUINO NANO RP2040 CONNECT》,观看 Arduino NANO RP2040演示合集
-
回复了主题帖:
【Follow me第二季第4期】任务三 学调试PDM麦克风,通过串口打印收音数据和音频波形
Jacktang 发表于 2024-12-24 07:45
结果输出的曲线为什么是下降的
截的是做完之后的数据
- 2024-12-23
-
加入了学习《Arduino? Nano RP2040 Connect 任务视频》,观看 PDM 数据打印及音频波形
-
发表了主题帖:
【Follow me第二季第4期】任务汇总
本帖最后由 eew_uscYT9 于 2025-1-11 21:43 编辑
视频
【Follow me第二季第4期】-EEWORLD大学堂
必做任务一:搭建环境并开启第一步Blink三色LED / 串口打印Hello DigiKey & EEWorld!;
【Follow me第二季第4期】任务一Blink、串口打印 https://bbs.eeworld.com.cn/thread-1301039-1-1.html
必做任务二:学习IMU基础知识,调试IMU传感器,通过串口打印六轴原始数据;
【Follow me第二季第4期】任务二 学习IMU基础知识,通过串口打印六轴原始数据 https://bbs.eeworld.com.cn/thread-1301142-1-1.html
必做任务三:学习PDM麦克风技术知识,调试PDM麦克风,通过串口打印收音数据和音频波形。
通过打响指进行灯的控制,也控制pico2的灯的亮灭
具体流程如下
【Follow me第二季第4期】任务三 学调试PDM麦克风,通过串口打印收音数据和音频波形 https://bbs.eeworld.com.cn/thread-1301144-1-1.html
发挥任务:
【Follow me第二季第4期】基于 Edge Impulse 的语音识别 https://bbs.eeworld.com.cn/thread-1302947-1-1.html
心得体会
通过这次我学习到了IMU的使用、麦克风的使用、了解到了音频的波形,也学习到了怎么样进行机器学习,并且自己也部署了一个可以识别命令的进行开关灯的小demo
最后非常感谢EEWorld和得捷电子举办的活动,这次活动让我收获了许多知识,希望能多出一点有关ai方向,让我们了解前沿,与前沿接轨
代码
https://download.eeworld.com.cn/detail/eew_uscYT9/635471