- 2024-12-04
-
回复了主题帖:
【Follow me第二季第4期】任务2:PDM麦克风的学习
lijinlei 发表于 2024-12-4 12:32
大佬,你的串口数据是用什么工具采集的啊?
我是菜鸟,我看论坛的各位都是大佬,我一会传上去
-
发表了主题帖:
【Follow me第二季第4期】任务2:PDM麦克风的学习
本帖最后由 zsy-s 于 2024-12-4 17:23 编辑
# 硬件
麦克风使用的型号:MP34DT06JTR
手册
lr引脚的定义
# 知识点学习
高保真音频:44khz
数字音频信号PDM代表脉冲密度调制(Pulse Density Modulation)。以非常高的频率采集音频信号,也被称为:Oversampled 1-bit Audio。PDM是一种调制形式,用于表示数字域中的模拟信号。
采样时许:
sck是采样频率,在每个上升沿或者下降沿采集一位音频数据。
对于右声道来说,上升沿启动右声道数据,最多tren时间后,右声道数据有效,下降沿后延迟trdis时间后,数据可以变化,这样保证了下降沿采集音频数据时,数据能保证有效。
## 数据的使用
PDM信号无法直接驱动DA进行声音播放,PDM信号要变为声音信号还需要进行下采样,经过一次低通滤波和抽样,然后成为PCM信号。
pdm是快速对音频进行调制的一种协议,通过密度来表示音频的模拟信号的幅度。密集的1标志正幅度,密集的0标识负幅度,平均交替的01标识 0幅度。如下如所示。
# 代码
包含官方的pdm头文件。
#include
配置pdm 并启动pdm数据采集。
```c
static const int frequency = 16000;
static const char channels = 1;
PDM.onReceive(onPDMdata);
if (!PDM.begin(channels, frequency)) {
Serial.println("Failed to start PDM!");
while (1);
}
```
回调读取数据并设置可读数据长度。
```c
void onPDMdata() {
// Query the number of available bytes
int bytesAvailable = PDM.available();
// Read into the sample buffer
PDM.read(sampleBuffer, bytesAvailable);
// 16-bit, 2 bytes per sample
samplesRead = bytesAvailable / 2;
}
```
打印采集到pdm数据
```c
if (samplesRead) {
for (int i = 0; i < samplesRead; i++) {
if(channels == 2) {
Serial.print("L:");
Serial.print(sampleBuffer);
Serial.print(" R:");
i++;
}
Serial.println(sampleBuffer);
}
samplesRead = 0;
}
```
# 效果
# 结论
pdm转换声音的逻辑,不太熟悉,学习到了,在更新一下
串口工具
- 2024-12-02
-
回复了主题帖:
有奖直播 | 报名STM32全球线上峰会,了解重磅新品!
- 2024-11-29
-
发表了主题帖:
【Follow me第二季第4期】任务2: IMU传感器
本帖最后由 zsy-s 于 2024-11-29 14:54 编辑
# 介绍
LSM6DSOXTR是一款高性能的6轴惯性测量单元(IMU),由STMicroelectronics(意法半导体)制造。集成了3轴数字加速度计和3轴数字陀螺仪,采用系统级封装技术,具有出色的性能和低功耗特性。提供SPI、I²C和MIPI I3C串行接口,支持主处理器数据同步。是一款功能强大、性能卓越的6轴IMU。
封装度深得好处,显而易见,开发毫无费力,手册都不用看得。
# 代码
imu模块有依赖库可使用。
在包管理器上,搜索LSM6DSOX。
添加 #include <Arduino_LSM6DSOX.h> 应用就可以愉快开发了。
如下是依赖库得接口说明
初始化imu模块
if(IMU.begin() == 0){
Serial.println("IMU.begin fail \n\r ");
}
读取 加速计和陀螺仪数据。
float x,y,z;
float gx, gy, gz;
// the loop function runs over and over again forever
void loop() {
digitalWrite(LEDB, HIGH); // turn the LED on (HIGH is the voltage level)
digitalWrite(LEDR, LOW); // turn the LED off by making the voltage LOW
digitalWrite(LEDG, LOW); // turn the LED off by making the voltage LOW
delay(200); // wait for a second
digitalWrite(LEDB, LOW); // turn the LED off by making the voltage LOW
digitalWrite(LEDR, HIGH); // turn the LED off by making the voltage LOW
digitalWrite(LEDG, LOW); // turn the LED off by making the voltage LOW
delay(200);
digitalWrite(LEDB, LOW); // turn the LED off by making the voltage LOW
digitalWrite(LEDR, LOW); // turn the LED off by making the voltage LOW
digitalWrite(LEDG, HIGH); // turn the LED off by making the voltage LOW
delay(200); // wait for a second
Serial.println("RP2040 hello \n\r ");
if (IMU.accelerationAvailable()) {
IMU.readAcceleration(x,y,z);
Serial.print("Acceleration:");
Serial.print(x);
Serial.print('\t');
Serial.print(y);
Serial.print('\t');
Serial.println(z);
}
if (IMU.gyroscopeAvailable()) {
IMU.readGyroscope(gx, gy, gz);
Serial.print("Gyroscope:");
Serial.print(gx);
Serial.print('\t');
Serial.print(gy);
Serial.print('\t');
Serial.println(gz);
}
if (IMU.temperatureAvailable())
{
int temperature_deg = 0;
IMU.readTemperature(temperature_deg);
Serial.print("LSM6DSOX Temperature = ");
Serial.print(temperature_deg);
Serial.println(" °C");
}
效果如下,温度挺准,准确得多算了十度。
# 知识学习
从手册查看芯片坐标轴,如下
从上端看,x是航向,y是偏角,z是俯仰。
静止不动得情况,有一个恒定得地心引力,1g,作用到芯片上。
加速度值就能看出来,平放时候,z轴加速度 为1,反过来放 -1.
90度侧放,y轴的值分别 1 -1.
90度竖放,x轴值分别 1 -1.
陀螺仪的数值分别来自于航向/翻滚/俯仰方向的角速度变化值,可以分别尝试绕航向角转,翻滚角转,俯仰角转,能明显看出来对应的数值变化。
# 疑难问题
无
# 结论
只有一个赞,arduino的库写的正好。之前看过c写的imu代码,一大片的初始化代码,很复杂,看很久也迷糊。
还是用轮子写,写的开心
- 2024-11-27
-
发表了主题帖:
【Follow me第二季第4期】点亮led/串口输出
本帖最后由 zsy-s 于 2024-11-27 19:10 编辑
# 编译环境
arduino封装了好多好多东西。
为了编译,下了手册,模块手册,2040的csdk手册。结果全都用不上。
开启arduino ide。开发板管理器搜索 nano boards(包含rp2040支持),点击安装包。不用翻墙,网速很快,一会安装完成。
rgb led接到WiFi模块上,rp2040通过与wifi模块通信,间接实现了点灯,故还需要一个wifi库支持。
项目-》 导入库-》管理库,搜索 wifinina,点击安装,开发环境搭建完毕。
# 点亮led
配置引脚
pinMode(LEDB, OUTPUT);
pinMode(LEDR, OUTPUT);
pinMode(LEDG, OUTPUT);
200ms周期点亮各个颜色的灯
void loop() {
digitalWrite(LEDB, HIGH); // turn the LED on (HIGH is the voltage level)
digitalWrite(LEDR, LOW); // turn the LED off by making the voltage LOW
digitalWrite(LEDG, LOW); // turn the LED off by making the voltage LOW
delay(200); // wait for a second
digitalWrite(LEDB, LOW); // turn the LED off by making the voltage LOW
digitalWrite(LEDR, HIGH); // turn the LED off by making the voltage LOW
digitalWrite(LEDG, LOW); // turn the LED off by making the voltage LOW
delay(200);
digitalWrite(LEDB, LOW); // turn the LED off by making the voltage LOW
digitalWrite(LEDR, LOW); // turn the LED off by making the voltage LOW
digitalWrite(LEDG, HIGH); // turn the LED off by making the voltage LOW
delay(200); // wait for a second
Serial.println("RP2040 hello \n\r ");
}
[localvideo]5c43a0fcd5bcb034ef5f01f92119f415[/localvideo]
通过串口输出日志,效果如下:
# 问题解决
不安装wifi库会出现找不到 fatal error: WiFiNINA.h: No such file or directory
安装wifimnina库,问题消失
# 总结
烧录过程,arduino封装了进入下载+下载固件流程。点亮led的过程,一行代码下去,aeduino提供的接口做了很多活,封的有点多且深。
封装的太好,好处就简单省心,但是但凡烧不了,就得抓瞎。
- 2024-11-26
-
发表了日志:
【读书】《RISC-V 体系结构编程与实践(第2版)》-- 结构学习
-
发表了主题帖:
【读书】《RISC-V 体系结构编程与实践(第2版)》-- 结构学习
收到书一直没拆封阅读,今天加班大概学习一下书的结构设计。
对于一个系统架构的书籍,第一章介绍了risc-v的知识和来龙去脉,对于初学者十分友好。可以快速对risc-v有一个立体的理解。
linux上,具有五大子系统:分别是进程调度系统、虚拟文件系统(VFS)、内存管理单元(MMU)、网络单元、进程间通信(IPC)。
面向linux吃饭的同学,这五大块就是我们的饭碗,还是可以继续吃好多年,东西很多很复杂。
其中,内存管理一直都是很重要的一个模块,本书使用了大半的篇幅介绍了内存管理的各个枝叶:
如 tlb,缓存管理,内存屏障,内存分布,mmu的功能等子模块的知识。也是一个出现问题,极度考验内功的模块。很喜欢书中对内存子系统拆解。
中断系统对于从事硬件相关开发的同学来说,是一个重中之重的模块,涉及到中断嵌套,中断的调用机制等知识。
脱离与系统之外的编译器链接器等知识点,开源的和闭源的工具有很多,学习起来也很复杂,本书开了三章来讲编译相关的知识,其中汇编部分最近一直在研究,会仔细研究学习学习。
第三章介绍了一些基础指令集,距离我有点远,会快速读一遍。
第二章的实验平台的搭建,可以帮助同学快速脱离硬件学习risc-v,简单快捷。
第四章对于调式程序来说,是一个很重要的章节,能够从上到下的分析遇到的各类程序运行异常问题。
第18 19 20 21章,读起来有点难,需要多读几遍,试试学习一下
-
发表了主题帖:
【Follow me第二季第4期】板子介绍
本帖最后由 zsy-s 于 2024-11-27 17:43 编辑
# 前言
活动地址备忘地址:https://www.eeworld.com.cn/huodong/digikey_follow_me_2024_04/
# 展示
小可爱展示图片
开箱的包装
nano板子前景
nano板子后背景
# 资料
原理图
# led
板载设计led有三个,一个指示spiclk的灯;一个5v转3.3v灯指示;一个rgb灯,接到了wifi模组上。
# flash
一块128Mbit的norflash (AT25SF128A-MHB-T)。使用四线spi。
# 麦克
一个MEMS音频传感器全向立体声数字麦克风,信号MP34DT06JTR。
# 陀螺仪
陀螺仪型号:LSM6DSOX
# 解密芯片
ATECC608A-MAHDA-T
# 通信
一个wifi 模块:NINA-W102-00B
- 2024-11-20
-
回复了主题帖:
读书入围名单:《RISC-V 体系结构编程与实践(第2版)》
个人信息无误,确认可以完成阅读计划和打卡任务
- 2024-11-19
-
回复了主题帖:
【Follow me第二季第3期】ek-ra6m5 板子认识
秦天qintian0303 发表于 2024-11-18 15:07
PMOD接口好像很多都带,不过这玩意怎么区分正反啊
我不知道,没用过这玩意,一直都是菜鸟的笨办法,直接拉线
- 2024-11-18
-
加入了学习《FollowMe 第二季:3 - EK_RA6M5 开发板入门》,观看 EK-RA6M5 开发板入门
- 2024-11-16
-
发表了主题帖:
【Follow me第二季第3期】ek-ra6m5 led 和按钮的接口使用
本帖最后由 zsy-s 于 2024-11-29 23:16 编辑
# 备忘
活动地址:https://www.eeworld.com.cn/huodong/digikey_follow_me_2024_03/
# 日志输出
由于使用usb接口模拟串口代码量太大,所以使用rtt输出日志比较方便。
本次使用了例程:gpt_ek_ra6m5_ep
查看项目文件可知,启动包含SEGGER_RTT,官方已经添加进去对rtt的支持,可支持使用
例程已经封装了rtt的接口,实际不能输出。
打开编译成果,打开.map文件,找到.bss._SEGGER_RTT,复制结果到 J-Link RTT Viewer里的地址,就能输出日志了。
难受的很,每次编译,rtt的地址都变化,每次都查询,累得很。
# api 介绍
R_ICU_ExternalIrqOpen() 用于打开一个外部中断模块实例。
R_ICU_ExternalIrqEnable() 用于使能外部中断,使能后即可触发产生外部中断。
控制引脚
```c
R_BSP_PinAccessEnable(); //开启PFS registers
R_BSP_PinWrite(pin1, BSP_IO_LEVEL_HIGH); //写高电平
R_BSP_PinWrite(pin2, BSP_IO_LEVEL_LOW); //写低电平
R_BSP_PinAccessDisable(); //禁止PFS registers
```
# 代码
查看按钮和led引脚
有两个按钮,三个led灯。
配置引脚
```c
static const uint16_t g_bsp_prv_leds[] =
{
(uint16_t) BSP_IO_PORT_00_PIN_06, ///< LED1
(uint16_t) BSP_IO_PORT_00_PIN_07, ///< LED2
(uint16_t) BSP_IO_PORT_00_PIN_08, ///< LED3
};
const bsp_leds_t g_bsp_leds =
{
.led_count = (uint16_t) ((sizeof(g_bsp_prv_leds) / sizeof(g_bsp_prv_leds[0]))),
.p_leds = &g_bsp_prv_leds[0]
};
```
最方便简单的方法通过官方提供的工具配置引脚
如下
项目中已配置按键引脚为输入,开启中断服务函数,三个led为输出。
链接文件,写的好复杂
启动入口函数: Reset_Handler
system.c 文件中声明函数:void R_BSP_WarmStart(bsp_warm_start_event_t event) __attribute__((weak));
标记为weak。在我们的主文件 hal_entry.c文件中,重新定义了函数R_BSP_WarmStart。
程序启动过程中,启动文件会调用 函数 R_BSP_WarmStart。
配置引脚中断,需要把此引脚的inpu配置取消掉,此处按照下图模式改掉。
如下图所示,增加一个中断
写代码,开启我们配置的中断。
# 烧录固件
编译程序,生成hex格式的固件。
打开flash lite 工具,如下图。
选中设备,找到生成的hex固件,点击 ‘programe device’,烧录下固件,如下图。
使用另一个按钮,开启中断,并控制另外一个led绿灯,效果如下
[localvideo]820e1ce69d7a5ee48f0337d9de4f56e0[/localvideo]
#疑难问题
如果中断的配置,没有找到属性窗口,可以如下,调出来
# 代码
-
发表了主题帖:
【Follow me第二季第3期】ek-ra6m5 编译环境
本帖最后由 zsy-s 于 2024-11-16 11:57 编辑
# 纲要
工具链是包括编译器, 连接器和解释器组成的综合开发环境, 交叉编译工具链只要由binutils, gcc和glibc三个部分组成。免费提供方主要有三家:第一是GNU , 第二是Codesourcery, 第三是Linora。收费版提供方有ARM原厂提供的armcc, IAR提供的编译器。
# 配置
安装e2 studio工具,会自动安装编译工具链,使用的时候可能会出现找不到编译工具链,可以使用手动加载安装的工具链。
## 配置fsp支持包
下发exe安装文件
安装路径选择 s2 studio路径
# 调试程序
插入j10 debug调试口,可以进行下载程序并调试。
j11 串口,可以用于查看程序的日志。
- 2024-11-13
-
发表了主题帖:
【Follow me第二季第3期】ek-ra6m5 板子认识
本帖最后由 zsy-s 于 2024-11-15 14:55 编辑
# 硬件介绍
结构设计图如下,能够看到接口类型。
实物指示图如下,对照板子更清楚明了。
设计图
板子上有两颗flash,原理图上16和17页是两个flash,不过是同一张原理图,可能设计师复制完没有继续修改。
64 MB flash手册
具有五个led,其中三个用户灯,led1 led2 led3,用来完成作业一。
有三个按钮,其中s3为reset按钮
s1 s2 可以用于输入事件。
具有两个usb高速接口,可以做device,也可以做host。
两个flash,一个是四位Macronix 256 Mb (32 MB) serial flash Quad-SPI memory (MX25L25645G).另一个是八位 Macronix 512 Mb (64 MB) Octal serial flash memory (MX25LM51245GM).
有两个电流得测试点,用于测试usb得电流和mcu得电流。
### 调试
板子提供了三种调试方式:板上调试,调试板上mcu,调试外部mcu
板上调试,使用j10的usb接口,通过s124 mcu 调试ra6m5芯片。
调试板上mcu,可以通过引脚20针j20或者10针j13,使用外部调试器调试板上ra6m5芯片。
调试外部mcu,使用板上s124调试外部任何ra系列芯片。
跳针接法如下:
# 备注
板子得跳针有两种: trace-cut jumpers 和solder-bridge jumpers
trace-cut jumpers 是引脚连接得。solder-bridge jumpers是默认不连接的。
-
回复了主题帖:
【Follow me第二季第3期】ek-ra6m5 开箱
https://www.eeworld.com.cn/huodong/digikey_follow_me_2024_03/
- 2024-11-12
-
回复了主题帖:
汇编 命令tst cmp bne beq 理解
13620203064 发表于 2024-11-12 16:54
这是什么CPU的指令?arm,x86,mips的?
arm,我少写了个重要得信息
-
发表了主题帖:
汇编 命令tst cmp bne beq 理解
tst cmp是两个比较指令,结果会更新到cpsr 寄存器里
tst 是一个位与指令
cmp是一个减法指令
计算结果,会改变 cpsr寄存器的 nzcv 状态位上。
bne 获取cpsr寄存器 z位,决定是否跳转指令后的地址。
个人理解上,可以这么理解:
1,r0中数据与02 与计算,状态结果保存到cpsr
2, 计算结果与0 比较,若不相等,则跳转bne后的地址执行,否则继续执行
如下:
TST r0,#02
BNE sleep
LDR r1,#0
- 2024-11-11
-
发表了主题帖:
【Follow me第二季第3期】ek-ra6m5 开箱
本帖最后由 zsy-s 于 2024-11-11 21:39 编辑
# 一节
没想到 板卡会这么大,各类线配的挺全的。
板卡设计的很漂亮,
设计的细节很多,看得出来板卡设计开发是能上的都上了。
以下是板卡的开箱图
** 外包装 **
** 配料表 **
** 板卡背面 **
# 二节
下一步搭环境,点一个led
-
加入了学习《直播回放: FollowMe 3 与得捷一起解锁开发板的超能力》,观看 FollowMe 3 与得捷一起解锁开发板的超能力
- 2024-11-08
-
发表了主题帖:
【2024 DigiKey创意大赛】+ 体感控制小游戏的实现
本帖最后由 zsy-s 于 2024-11-26 11:00 编辑
# 前言
本设计只要是实现了通过传感器,实现对被控物的移动,实现体感小游戏的小设计。
时间紧迫,原先设计的许多细节不实现了,最先最简单的被控物移动。
本项目基于官方例程 usb_keyboard 修改。
使用了两个模块:ESP32-S3-LCD-EV-Board和 ICM-20948
# 结构设计
## ESP32-S3-LCD-EV-Board
ESP32-S3-LCD-EV-Board搭载了ESP32-S3-WROOM-1模组,该模组内置ESP32-S3系列芯片,配备了一块GC9503CV LCD触摸屏,支持480x480分辨率,显示效果清晰。同时,它采用了FT5x06触摸屏驱动,确保触摸操作的准确性和响应速度。这样的配置使得用户可以通过触摸方式与开发板进行交互,ESP32-S3-LCD-EV-Board以其强大的核心性能、清晰的显示效果、准确的触摸操作、丰富的扩展接口以及详细的文档和例程等优点,成为了一款备受关注的屏幕交互开发板。它适用于物联网应用、AIoT领域的多种应用场景以及智能家居控制等领域,是开发者和工程师们进行项目开发的得力助手。
## ICM-20948
ICM-20948是一款备受好评的高性能九轴运动传感器,集成了3轴陀螺仪、3轴加速度计、3轴磁力计以及数字运动处理器(DMP),使得这款传感器能够同时监测设备的旋转、加速度以及磁场信息,非常适合用于姿态检测、运动跟踪等应用场景。支持I2C和SPI通信接口,这两种接口都是常用的微控制器通信协议,使得传感器与微控制器的连接更加便捷。ICM-20948的低功耗和高精度特性使其成为物联网应用中的理想选择。例如,在智能家居系统中,可以利用该传感器监测门窗的开关状态、人体的运动状态等。是一款性能卓越、功能强大的九轴运动传感器。其低功耗、高精度、封装小巧以及完善的驱动支持等特点,使得它在物联网应用、可穿戴设备、无人机与机器人等领域具有广泛的应用前景。对于需要精确运动检测的开发者来说,ICM-20948无疑是一个值得考虑的选择。
# 代码讲解
功能简单,从大佬 alanlan86 借了一些代码,计算出来航向角的值。
得到传感器的方向角
```c
void
icm_read_task(void *args)
{
esp_err_t ret = icm20948_configure(ACCE_FS_2G, GYRO_FS_1000DPS);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "ICM configuration failure");
vTaskDelete(NULL);
}
ESP_LOGI(TAG, "ICM20948 configuration successfull!");
icm20948_acce_value_t acce;
icm20948_gyro_value_t gyro;
icm20948_temp_value_t ttmp;
icm20948_Drec_t *ffff ;
while(1) {
ret = icm20948_get_acce(icm20948, &acce);
if (ret == ESP_OK){
//ESP_LOGI(TAG, "ax: %lf ay: %lf az: %lf", acce.acce_x, acce.acce_y, acce.acce_z);
}
ret = icm20948_get_gyro(icm20948, &gyro);
if (ret == ESP_OK){
//ESP_LOGI(TAG, "gx: %lf gy: %lf gz: %lf", gyro.gyro_x, gyro.gyro_y, gyro.gyro_z);
}
icm20948_get_Temp(icm20948, &ttmp);
if (ret == ESP_OK){
//ESP_LOGI(TAG, "temp: %lf",ttmp.temp);
}
ffff = getxAngle(acce.acce_x_r,acce.acce_y_r,acce.acce_z_r,gyro.gyro_y);
// ESP_LOGI(TAG, "getxAngle: %d : %d",ffff->xxx,ffff->yyy);
while(((ffff->xxx != 1) && (ffff->xxx != 0)) && ((ffff->yyy != 1) && (ffff->yyy != 0))){
ffff->xxx = ffff->xxx/2;
ffff->yyy = ffff->yyy/2;
}
xxCnt = ffff->xxx;
yyCnt = ffff->yyy;
ESP_LOGI(TAG, "------getxAngle: %d : %d",xxCnt,yyCnt);
vTaskDelay(10 / portTICK_PERIOD_MS);
}
vTaskDelete(NULL);
}
```
移动被控物的代码,通过传感器得到移动方向
```c
void MoveMan()
{
ESP_LOGI(TAG, "--------xxCnt[%d]------yyCnt[%d]----------",xxCnt,yyCnt);
lv_coord_t xx = lv_obj_get_x(objMan);
lv_coord_t yy = lv_obj_get_y(objMan);
if((xxCnt == 0) && (yyCnt == 0)) return;
//lv_style_set_translate_y(&styleMan, -20); //Translation
if(xxCnt < 0){
//xx += -1;
xx = xx