- 2025-02-21
-
回复了主题帖:
射频芯片知识
华为没有入选吗?我感觉华为应该在这方面比较突出的!
-
发表了主题帖:
【泰坦触觉 TITAN Core开发套件】Primitves概述
在开发套件的操作中,使用说明如下:
Primitives Overview
Primitives are basic haptic effects used to create unique sensations by controlling parameters like
intensity, duration, and waveform properties. They serve as building blocks for composing complex
haptic experiences. Below are the 4 types of basic primitives: pulse, tick, vibrate, pause.
基元概述
基元是通过控制强度、持续时间和波形属性等参数来创建独特触感的基本效果。它们作为构建复杂触觉体验的基石。
以下是四种基本基元:脉冲(pulse)、滴答(tick)、振动(vibrate)、暂停(pause)。
脉冲(Pulse):产生一个短暂而强烈的震动,常用于模拟点击或敲击的感觉。
滴答(Tick):一种轻柔且快速的震动,通常用来表示轻微的触碰或确认。
振动(Vibrate):持续性的震动效果,适用于长时间的反馈或提醒。
暂停(Pause):没有震动,用于在不同的震动效果之间插入间隔,增强节奏感和区分度。
Pulse
Description: A single, soft impulse used for pulses, bumps, wobbles, and motion forces.
基元类型:脉冲(Pulse)
描述:
脉冲是一种单一的、柔和的冲击效果,常用于模拟脉动、碰撞、晃动和运动力量等触感。它通过短促而集中的震动来传递特定的感觉
PULSE(1, 10, 0.8); //强度 = 1.0, 持续时间 = 10ms, 平滑度 = 0.8
PULSE(0.5, 20); //强度 = 0.5, 持续时间 = 20ms, 平滑度 = 0.5 [default]
Tick Description:
A single, sharp impulse used for clicks, textures, taps, and impacts.
滴答(Tick)
描述:
滴答是一种单一的、尖锐的冲击效果,常用于模拟点击、纹理、轻拍和撞击等触感。它通过短促而清晰的震动来传递特定的感觉,适用于以下场景:
点击:模拟按钮或开关的操作。
纹理:模拟不同表面的触感,如粗糙或光滑。
轻拍:模拟轻微的敲击或触摸。
撞击:模拟物体之间的短暂碰撞。
代码示例:
TICK(1, 10, 0.8); //intensity = 1.0, duration = 10ms, sharpness = 0.8
TICK(0.5, 20); //intensity = 0.5, duration = 20ms, sharpness = 1
Vibrate
Description: A continuous vibration with customizable frequency, intensity, sharpness, and
waveform fullness. Used for alerts, textures, and other sustained effects.
振动(Vibrate)
描述:
振动是一种连续的震动效果,其频率、强度、尖锐度和波形饱满度均可自定义。它适用于警报、纹理模拟和其他持续性效果。
频率:控制震动的快慢,从缓慢的脉动到快速的颤动。
强度:决定震动的力度,从轻微的提示到强烈的反馈。
尖锐度:调整震动的感觉,从柔和到尖锐。
波形饱满度:改变震动的波形特性,如正弦波、方波等,以影响触感的具体表现。
通过这些可调参数,振动效果可以广泛应用于以下场景:
警报:提供持续的震动提醒,如来电或通知。
纹理模拟:模拟不同材质的表面触感,增强虚拟现实或游戏中的沉浸感。
代码:
VIBRATE(100, 1, 1000, 1); //frequency = 100hz, intensity = 1.0, duration =
1000ms, sharpness = 1
VIBRATE(250, 0.5, 250, 0.8); //frequency = 250hz, intensity = 0.5, duration =
250ms, sharpness = 0.8
暂停(Pause)
描述:
暂停是在指定的持续时间内停止所有触觉输出。这用于在不同的触觉效果之间插入间隔,以增强节奏感和区分度。
代码:
PAUSE(1000) ; // duration = 1000ms
以上为马达的四种基本工作单元,即:脉冲(pulse)、滴答(tick)、振动(vibrate)、暂停(pause)。
pulse、tick有3个输入参数(intensity、Duration、sharpness),在说明书中讲述了他的工作输入参数,以及默认值。
Vibrate(振动)有4个输入参数(Frequency 、Intensity、Duration、Sharpness)Vibrate的Duration的时间相比pulse、Tick的200ms要长,为10000ms。即最长一次可以振动10S钟。
最后给出了一个综合的示例:
#include "Esp32PicoMini.h"
#include "VectorHaptics.h"
#include <VHBasePrimitives.h>
#include <VHEffectReceiver.h>
// Defining the VectorHaptics and VHBasePrimitives objects to access the haptic
channel and base primitives.
VectorHaptics<Esp32PicoMini> vh;
VHBasePrimitives bp;
VHEffectReceiver effRec;
void setup()
{
VHChannel chnl(1, 25);
chnl.setPrimitives(PULSE|TICK|VIBRATE);
vh.setChannel(&chnl); // Adding the channel to the board.
effRec.InitSerial();
vh.log(ERR_LOG|WAR_LOG|INF_LOG);
vh.Init({&bp,&effRec}); // Initializing the VHBasePrimitives object.
xTaskCreate(LoopDriver,"LoopDriver",8000,NULL,configMAX_PRIORITIES,NULL);
}
void loop()
{
vh.EffectDriver();
}
void LoopDriver(void *param)
{
while (true)
{
// Playing basic primitives in a loop.
vh.play(VIBRATE(100, 1, 500, 1));
vh.play(PAUSE(500));
vh.play(PULSE(1, 10));
vh.play(PAUSE(1000));
vh.play(TICK(1, 10));
vh.play(PAUSE(5000));
vh.play(VIBRATE(200, 1, 1000, 1));
vh.play(PAUSE(2000));
delay(10);
}
}
- 2025-02-20
-
回复了主题帖:
【泰坦触觉 TITAN Core开发套件】让马达“振起来”
okhxyyo 发表于 2025-2-20 11:49
TITAN收到反馈并积极听取意见,已经更新文档,把小伙伴提的这个点给写进去啦!!
...
感谢管管大大的关心,努力学习中,希望能学有所成!
-
回复了主题帖:
[国产芯AGM新品AG32VH407]2.部署AG32 MCU开发环境
python已经升级到了13了呀,环境创建非常详细,感谢分享!
- 2025-02-19
-
回复了主题帖:
关于一个成绩分类的C语言实现的两种方式
se7ens 发表于 2025-2-18 18:00
if语句逻辑看起来很清晰,可能比较容易看懂
但是if有个缺点就是结构需要从头写到尾,不能乱了,但是switch就不需要分次序,可以先7,再8,在后期调试会好很多,在很多有预测的CPU中,命中比较快。
-
回复了主题帖:
AG32VH407RCT6简介以及AG芯片环境搭建
宸肆0628 发表于 2025-2-19 19:33
我研究一下怎么修改帖子,实在不行我再发新帖
辛苦了,改好了,给你点赞,评分,加油!
-
回复了主题帖:
AG32VH407RCT6简介以及AG芯片环境搭建
这个教程挺好的,能不能在这里配点文字+图片。然后楼主的录屏是不是太小了一点,看不清楚呀。
-
回复了主题帖:
[树莓派Pico 2 RP2350开发板] 搭建编译环境
看来楼主的功底非常不错呀,请问这个板子,有多少种开发方式呢?
-
回复了主题帖:
【先楫HPM5361】00_开箱及环境搭建(RT-Thread studio篇)
不用造轮子,那是真方便,我想问一下,他这个板子自带下载调试器吗?
- 2025-02-18
-
发表了主题帖:
【泰坦触觉 TITAN Core开发套件】让马达“振起来”
本帖最后由 lugl4313820 于 2025-2-18 21:01 编辑
前面一直卡在开发环境的问题了,昨天在大佬的指点下,终于适配好了环境,能成功的编译下载了。
【泰坦触觉 TITAN Core开发套件】解编译报错
这一篇主要学习官方示例的一些基础功能:
1、驱动文件的引用:
#include "Esp32PicoMini.h" // Esp32PicoMini.h is the hardware abstraction layer (HAL) to connect with ESP32 Pico Mini board.
#include "VectorHaptics.h" // VectorHaptics.h is the main header file that connects sublibraries included in the Vector Haptics Library.
#include <VHBasePrimitives.h> // VHBasePrimitives.h is fundamental building blocks for creating haptic effects (using primitives like Vibration, Pulse, Pause)
#include <VHChannels.h> // VHChannels.h allows developers to create multiple channels to play haptic effects.
在以上四个驱动文件中,是我们从官网下载,并保存在C:\Users\liujianhua\Documents\Arduino\libraries这个路径下面的VHCore目录下面的驱动。为官方对特有的马达驱动封装好的库。
但是我通过Everthing搜索,这几个文件,在好几个包里都不,不知道他会定位到哪个具体的文件里:
2、引入头文件后,开始实例化对象
VectorHaptics<Esp32PicoMini> vh;
VHBasePrimitives bp;
通过注释的翻译,大致内容为:声明VectorHaptics和VHBasePrimitics对象以访问触觉通道和基本原语
“VHBasePrimitives.h”是用于创建触觉效果的基本构建模块,其中包含诸如振动(Vibration)、脉冲(Pulse)、暂停(Pause)等基本元素。这个文件在创建触觉效果的过程中起着基础且关键的作用,是实现各种不同触觉反馈的重要组成部分。它提供了特定的功能和工具,让开发者能够利用其中的基本元素来构建丰富多样的触觉体验。
理解大致的意思是 一个是从哪个IO输出,另一个是输出什么们的方式,如果振动、脉冲、暂停。
3、接下来,初始化通道
// 使用通道号、GPIO引脚和通道标签创建VH通道。通道标签用于标识通道。
VHChannel chnl1(1, 25,{"Left channel", "Channel 1", "Left", "Finger"},15);
VHChannel chnl2(2, 26,{"Right channel", "Channel 2", "Right", "Finger"},15);
VHChannel chnl3(3, 27, 33,{"Motor channel", "Channel 3", "Motor", "Finger"},32); // Dual motor channel so the third parameter is the second GPIO pin
VHChannels chnlList({&chnl1,&chnl2,&chnl3}); // Adding all channels to a channel list
初始通道在他的注释中有这样的解释:
* #include <VHChannels.h>
* // Creating mono channel with channel number, gpio pin, channel tags
* VHChannel chnl1(1, 25,{"Left channel", "Channel 1", "Left", "Finger"},15);
* // Creating mono channel with channel number, gpio pin, channel tags
* VHChannel chnl2(2, 26,{"Right channel", "Channel 2", "Right", "Finger"},15);
* // Creating dual channel with channel number, gpio pin1,gpio pin1, channel tags
* VHChannel chnl3(3, 27, 33,{"Motor channel", "Channel 3", "Motor", "Finger"},32);
* // Adding all channels to a channel list
* VHChannels channels({&chnl1,&chnl2,&chnl3});
在上面的注释中有三种方式来进行注册,一个是channel number +gpio pin + channel tags,其中tags是一个标签列,我认真的学习了好久的时间,没有怎么明白。
同样channel2-3也是这种模式,但是第3种,似乎是用两个IO同时输出的。需要找原理图来看看,是不是如此,他是不是两个PWM进行互补的驱动。
在最后,使用chnlist把两个通道绑到一起。
4、在setup函数中,初始化
void setup()
{
// Initializing the VectorHaptics object with the channel list and the base primitives object.
vh.Init({&chnlList,&bp});
}
5、测试代码
void loop()
{
// Playing effects using channel number VIBATE 振动
vh.play({TICK(1, 10), PAUSE(2000), TICK(1, 10), PAUSE(2000), VIBRATE(100, 1, 1000, 1, 1), PAUSE(2000)}, 1);
vh.play({PAUSE(2000)});
// Playing effects using channel tags
vh.play({TICK(1, 10), PAUSE(2000), TICK(1, 10), PAUSE(2000), VIBRATE(100, 1, 1000, 1, 1), PAUSE(2000)}, "Left;&;Finger");
vh.play({PAUSE(2000)});
vh.play({TICK(1, 10), PAUSE(2000), TICK(1, 10), PAUSE(2000), VIBRATE(100, 1, 1000, 1, 1), PAUSE(2000)}, "Right;Finger");
}
编译与下载后,两个电机就开始脉冲、振动交替进行。
【小结】
其实我已经不怎么用Ardnuino来写东西了,这次重新回炉,有好些东西还是不熟练,还得继续努力才行。
-
发表了主题帖:
《Hello算法》分享队列基于数组的实现
在上一节,我使用链表来实现了队列。下面介绍如下何用数组来实现。
在数组中删除首元素的时间复杂度为 O(n),这会导致出队操作效率较低。然而,我们可以采用以下巧妙方法来避免这个问题。
我们可以使用一个变量 front 指向队首元素的索引,并维护一个变量 size 用于记录队列长度。定义 rear = front + size ,这个公式计算出的 rear 指向队尾元素之后的下一个位置。
基于此设计,数组中包含元素的有效区间为 [front, rear - 1],各种操作的实现方法如图 5-6 所示。
入队操作:将输入元素赋值给 rear 索引处,并将 size 增加 1 。
出队操作:只需将 front 增加 1 ,并将 size 减少 1 。
可以看到,入队和出队操作都只需进行一次操作,时间复杂度均为 O(1);
你可能会发现一个问题:在不断进行入队和出队的过程中,front 和 rear 都在向右移动,当它们到达数组尾部时就无法继续移动了。为了解决此问题,我们可以将数组视为首尾相接的“环形数组”。
对于环形数组,我们需要让 front 或 rear 在越过数组尾部时,直接回到数组头部继续遍历。这种周期性规律可以通过“取余操作”来实现,代码如下所示:
根据书中的代码,我结合自己的理解编写了实现代码如下:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int *nums; // 存储队列元素的数组
int front; // 队首指针,指向队首元素
int queSize; // 尾指针,指向队尾元素的下一个位置
int queCapacity; // 队列容量
} ArrayQueue;
/* 构构建函数 */
ArrayQueue *newArrayQueue(int capacity) {
ArrayQueue *queue = (ArrayQueue *)malloc(sizeof(ArrayQueue)); // 分配空间
if(queue == NULL)
{
printf("malloc failed!\n");
return NULL;
}
//初始化数组
queue->queCapacity = capacity;
queue->nums = (int *)malloc(sizeof(int) * queue->queCapacity);
if(queue->nums == NULL)
{
printf("malloc failed!\n");
return NULL;
}
queue->front = queue->queSize = 0;
return queue;
}
/* 释放队列 */
void delArrayQueue(ArrayQueue *queue) {
if(queue == NULL)
return;
free(queue->nums);
free(queue);
}
/* 获取队列的容量 */
int getArrayQueueSize(ArrayQueue *queue) {
if(queue == NULL)
return -1;
return queue->queCapacity;
}
/* 获取队列的长度 */
int size(ArrayQueue *queue)
{
if(queue == NULL)
return -1;
return queue->queSize;
}
/* 判断队列是否为空 */
int isEmpty(ArrayQueue *queue)
{
if(queue == NULL)
return -1;
return queue->queSize == 0;
}
/* 访问k队首元素 */
int peek(ArrayQueue *queue, int *val)
{
if(queue == NULL)
return -1;
if(queue->queSize == 0)
return -2;
*val = queue->nums[queue->front];
return 0;
}
/* 入队 */
int enqueue(ArrayQueue *queue, int val)
{
if(queue == NULL)
return -1;
if(queue->queSize == queue->queCapacity)
{
printf("队列已满\r\n");
return -2;
}
int rear = (queue->front + queue->queSize) % queue->queCapacity;
queue->nums[rear] = val;
queue->queSize++;
return 0;
}
/* 出队 */
int pop(ArrayQueue *queue, int *val)
{
if(queue == NULL)
return -1;
if(queue->queSize == 0)
{
printf("队列已空\r\n");
return -2;
}
*val = queue->nums[queue->front];
queue->front = (queue->front + 1) % queue->queCapacity;
queue->queSize--;
return 0;
}
/* 打印队列 */
void printArrayQueue(ArrayQueue *queue)
{
if(queue == NULL)
return;
for(int i = 0; i < queue->queSize; i++)
{
printf("%d ", queue->nums[(queue->front + i) % queue->queCapacity]);
}
printf("\r\n");
}
int main()
{
int val;
ArrayQueue *queue = newArrayQueue(5);
printf("队列长度:%d\r\n", size(queue));
printf("队列是否为空:%d\r\n", isEmpty(queue));
printf("队列容量:%d\r\n", getArrayQueueSize(queue));
printf("队列入队:%d\r\n", enqueue(queue, 1));
printArrayQueue(queue);
printf("队列入队:%d\r\n", enqueue(queue, 2));
printf("队列入队:%d\r\n", enqueue(queue, 3));
printf("队列入队:%d\r\n", enqueue(queue, 4));
printf("队列入队:%d\r\n", enqueue(queue, 5));
printf("队列入队:%d\r\n", enqueue(queue, 6));
printArrayQueue(queue);
printf("队列长度:%d\r\n", size(queue));
pop(queue, &val);
printf("队列出队:%d\r\n", val);
pop(queue, &val);
printf("队列出队:%d\r\n", val);
pop(queue, &val);
printf("队列出队:%d\r\n", val);
pop(queue, &val);
printf("队列出队:%d\r\n", val);
pop(queue, &val);
printf("队列出队:%d\r\n", val);
pop(queue, &val);
printf("队列长度:%d\r\n", size(queue));
printf("队列是否为空:%d\r\n", isEmpty(queue));
delArrayQueue(queue);
}
实现效果:
liujianhuadeiMac:pro_node liujianhua$ gcc Array_queue.c
liujianhuadeiMac:pro_node liujianhua$ ./a.out
队列长度:0
队列是否为空:1
队列容量:5
队列入队:0
1
队列入队:0
队列入队:0
队列入队:0
队列入队:0
队列已满
队列入队:-2
1 2 3 4 5
队列长度:5
队列出队:1
队列出队:2
队列出队:3
队列出队:4
队列出队:5
队列已空
队列长度:0
队列是否为空:1
通过上面的测试,我理解了基于数组实现队列的方法,队列在单片机的串口接收中最为常用。以后偿试使用队列接收来处理数据。
-
回复了主题帖:
[国产芯AGM新品AG32VH407]1.熟悉AG32芯片特性、开发板功能、调试工具
送了一个下载器,厂家还不错呀,单这个下载器,好几百吧。
-
回复了主题帖:
[兆易GD32H759I-EVAL]4.熟悉CAN总线通讯,通过CAN工具与PC端进行通讯测试
他这个CAN通信不用跳线吧,这块开发板,跳线多,看着有点头疼。
- 2025-02-17
-
发表了主题帖:
【泰坦触觉 TITAN Core开发套件】解编译报错
【泰坦触觉 TITAN Core开发套件】Arduino编译固件报错 - DIY/开源硬件专区 - 电子工程世界-论坛
这篇帖子中,我偿试编译示例,但是总是不成功,经@HonestQiao大佬的提醒,一定需要2.1.18与2.0.17才能编译成功:
在我卸载掉3.1.1,再去安装2.0.17时,无论是开梯子还是等,都没有安装成功,然后在安装时,报错相应的文件下载不成功。
报错信息如下:
Error: 2 UNKNOWN: Get "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2-patch5/riscv32-esp-elf-gcc8_4_0-esp-2021r2-patch5-win64.zip":
于是,我偿试用迅雷来下载,结果下载速度非常快:
然后我把这三个压缩包放到目录中,再执行安装,终于安装成。
C:\Users\liujianhua\AppData\Local\Arduino15\staging\packages
编译示例也成功了:
【经验教训】
1、原因是Arduino版本不对,对应的库函数不对。
2、建议官方及时在说明文档中强调一定要这两个版本来适配。要不真是浪费时间。
3、最好建把对应的压缩包打包,以便用户快速安装环境!
-
回复了主题帖:
【泰坦触觉 TITAN Core开发套件】Arduino编译固件报错
我又仔细的核对的用户快入门手册,然后编译还是提示找不到库
C:/Users/liujianhua/AppData/Local/Arduino15/packages/esp32/tools/esp-x32/2405/bin/../lib/gcc/xtensa-esp-elf/13.2.0/../../../../xtensa-esp-elf/bin/ld.exe: c:\Users\liujianhua\Documents\Arduino\libraries\VHBoard\src\esp32\libVHBoard.a(Esp32PicoMini.cpp.o):(.literal._ZN13Esp32PicoMini8initPinsEh+0x10): undefined reference to `ledcAttachPin'
C:/Users/liujianhua/AppData/Local/Arduino15/packages/esp32/tools/esp-x32/2405/bin/../lib/gcc/xtensa-esp-elf/13.2.0/../../../../xtensa-esp-elf/bin/ld.exe: c:\Users\liujianhua\Documents\Arduino\libraries\VHBoard\src\esp32\libVHBoard.a(Esp32PicoMini.cpp.o): in function `Esp32PicoMini::initPins(unsigned char)':
C:\Users\joshi\Documents\Arduino\libraries\VHBoard\src/Esp32PicoMini.cpp:121:(.text._ZN13Esp32PicoMini8initPinsEh+0x37): undefined reference to `ledcAttachPin'
把所有的库都下载到了目录中了:
-
回复了主题帖:
【泰坦触觉 TITAN Core开发套件】Arduino编译固件报错
是不是水土不伏呀。
-
回复了主题帖:
【泰坦触觉 TITAN Core开发套件】Arduino编译固件报错
我又重新下载了固件包,编译,他还是提示有我这里没有环境!
-
回复了主题帖:
【工程师秘籍】基于HK32C030的高效智能排风扇解决方案揭秘!
可以偿试一下,做一些开源的方案,这样有些厂家可以直接拿过来,跟据自己的需要,少量改动就可以使用。
-
回复了主题帖:
【工程师秘籍】基于HK32C030的高效智能排风扇解决方案揭秘!
国内厂商,现在都在给出一些基于自家的芯片解决方案,这都一些新的突破点吧。
-
回复了主题帖:
[兆易GD32H759I-EVAL]3.熟悉I2C、SPI操作EEPROM和SPI FLASH,移植FlashDB数据库
大佬,这个spi是QSPI接口的FLASH芯片吗?看了GD的命名和一些方式,国内的好些厂商的风格都差不多,象灵动好象也是开机打印一下频率等一些基础信息。