- 2025-03-12
-
回复了主题帖:
2024 DigiKey大赛参与奖】开箱帖
秦天qintian0303 发表于 2025-3-11 17:29
其他板卡已经失去了对你的吸引力
主要是他家东东太贵了。
- 2025-03-11
-
发表了主题帖:
2024 DigiKey大赛参与奖】开箱帖
有幸参加2024 DigiKey“感知万物,乐享生活”创意大赛,非常开心地获得了参与奖。作为一个业余爱好者,为了以后更好地玩单片机,乘此机会购买了3个stlink,这样这样就可以在办公室、家里各放一个,方便使用。另外不得不说,得捷现在从购买到收货,越来越快啦!
- 2025-03-06
-
回复了主题帖:
手残党亲测!把激光雷达大卸八块后,我发现了这些惊天秘密...
激光雷达是个好东东,5米内又快又准。黑色的不怕的,只是反光率差点,能检测到的。害怕的是透明的玻璃,会导致检测失效。
- 2025-03-04
-
回复了主题帖:
拆解国产640分辨率的车用热成像镜头
这东西,那叫一个贵啊!
- 2025-03-03
-
加入了学习《得捷电子专区》,观看 红外温度检测及火灾报警器
- 2025-02-26
-
回复了主题帖:
免费申请:米尔-STM32MP257开发板,至少写5篇高质量报告可留板卡
nmg 发表于 2025-2-26 09:33
指的哪方面啊?
当然是任务啦!板子功能太强大,对自己技术没信心。
- 2025-02-25
-
回复了主题帖:
新年花灯节的灯光秀起来了——这么多花灯,你最pick哪一盏?
貌似漏了这篇
[新年点灯】呼吸灯——优雅永不过时 https://bbs.eeworld.com.cn/thread-1307358-1-1.html
-
回复了主题帖:
免费申请:米尔-STM32MP257开发板,至少写5篇高质量报告可留板卡
太难了!怕怕!
- 2025-02-24
-
回复了主题帖:
[新年点灯】呼吸灯——优雅永不过时
okhxyyo 发表于 2025-2-24 15:08
我一直在等它变成小黄鸭。。。
话说这只小鸭子该不会是你征用了家里小宝贝的玩具吧???
-
回复了主题帖:
>>征集 | 晒电机控制痛点与难题,一起寻求最优解!
作为一个喜欢玩平衡车的业余玩家,遇到电机的痛点有:
1、使用PWM调速时,低速没力气。死区大,难控制。
2、电磁干扰,导致主控重启。
3、编码器控制精度和价格的矛盾。
-
发表了主题帖:
[新年点灯】呼吸灯——优雅永不过时
本帖最后由 aramy 于 2025-2-24 14:29 编辑
在当今这个快节奏的时代,科技与生活的融合愈发紧密,而有一种独特的设计,以其柔和的光影和灵动的节奏,悄然成为现代生活美学中不可或缺的一部分——呼吸灯。它不仅是一种照明工具,更是一种情感的表达,一种氛围的营造,一种科技与艺术的完美结合。今天,让我们一同走进呼吸灯的世界,探索它背后的故事,感受它如何以优雅的姿态,点亮生活的每一个角落,成为永不过时的经典。
硬件:主控基于STM32G031G8U6制作好了的最小板子。加上镂空PCB焊接WS2812。
软件:使用STM32CUBEMX来初始化外设,主频使用64M
为了优雅,呼吸灯使用正弦曲线。使用串口控制颜色。
#include "ws2812.h"
#include "tim.h"
//低电平偏移,复位
#define WS2812_RST_NUM 300
//数据位
#define WS2812_SET (53) //1
#define WS2812_RSET (26) //0
//定义发送缓冲区
/*
300:低电平占位
(3*8):每个灯珠有3种颜色,每种颜色8位
*/
uint16_t WS2812_GRB_BUF[WS2812_RST_NUM+WS2812_MAX_NUM*(3*8)]={0};
//设置某一位的颜色
/*
uint16_t num:第多少个灯珠
uint8_t rv:红颜色亮度
uint8_t gv:绿颜色亮度
uint8_t bv:蓝颜色亮度
*/
void ws2812_set(uint16_t num,uint8_t rv,uint8_t gv,uint8_t bv){
uint32_t indexx=WS2812_RST_NUM+(num*(3*8));
for (uint8_t i = 0;i < 8;i++)
{
//填充数组
WS2812_GRB_BUF[indexx+i] = (gv << i) & (0x80)?WS2812_SET:WS2812_RSET;
WS2812_GRB_BUF[indexx+i + 8] = (rv << i) & (0x80)?WS2812_SET:WS2812_RSET;
WS2812_GRB_BUF[indexx+i + 16] = (bv << i) & (0x80)?WS2812_SET:WS2812_RSET;
}
}
//关闭所有
void ws2812_set_all_off(void){
for(uint16_t i=0;i<WS2812_MAX_NUM;i++){
ws2812_set(i,0,0,0);
}
}
//开启所有
void ws2812_set_all_on(void){
for(uint16_t i=0;i<WS2812_MAX_NUM;i++){
ws2812_set(i,255,255,255);
}
}
//初始化
void ws2812_init(void){
//设置关闭所有灯
ws2812_set_all_off();
HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)WS2812_GRB_BUF,sizeof(WS2812_GRB_BUF)/sizeof(uint16_t));
}
//--------------------灯动作------------------
void effect(char cl)
{
printf("Effect=%d\r\n",cl%6);
for(int i=0;i<WS2812_MAX_NUM;i++){
HAL_Delay(50);
switch(cl%7){
case 0:
ws2812_set(i,122,122,122);
break;
case 1:
ws2812_set(i,122,0,0);
break;
case 2:
ws2812_set(i,0,122,0);
break;
case 3:
ws2812_set(i,0,0,122);
break;
case 4:
ws2812_set(i,122,0,122);
break;
case 5:
ws2812_set(i,122,122,0);
break;
case 6:
ws2812_set(i,0,122,122);
break;
}
}
HAL_Delay(150);
ws2812_set_all_off();
}
void effect2(void){
int n=10;
while(n--){
for(int i=0;i<WS2812_MAX_NUM;i++){
for(int j=0;j<WS2812_MAX_NUM;j++){
ws2812_set(j,11,11,11);
}
ws2812_set(i,10,10,0);
ws2812_set(i+1,30,30,0);
ws2812_set(i+2,50,50,0);
ws2812_set(i+3,100,0,0);
i+=4;
HAL_Delay(100);
}
}
}
void effect3(void){
int n=10;
uint8_t halv=WS2812_MAX_NUM/2/2;
//开灯
for(uint8_t i=0;i<halv;i++){
ws2812_set(halv+i,n*15,n+i*2,i*5);
ws2812_set(halv-i,n*15,n+i*2,i*5);
ws2812_set(halv*3+i,n*15,n+i*2,i*5);
ws2812_set(halv*3-i,n*15,n+i*2,i*5);
HAL_Delay(1000);
}
//顶部点亮时闪烁
ws2812_set(0,255,255,255);
ws2812_set(halv*2,255,255,255);
HAL_Delay(300);
ws2812_set(0,0,0,0);
ws2812_set(halv*2,0,0,0);
HAL_Delay(300);
ws2812_set(0,255,255,255);
ws2812_set(halv*2,255,255,255);
//延时效果
HAL_Delay(2000);
//关灯
ws2812_set(0,0,0,0);
ws2812_set(halv*2,0,0,0);
for(uint8_t i=halv;i>0;i--){
ws2812_set(halv+i,0,0,0);
ws2812_set(halv-i,0,0,0);
ws2812_set(halv*3+i,0,0,0);
ws2812_set(halv*3-i,0,0,0);
HAL_Delay(1000);
}
}
static float min(float a, float b, float c)
{
float m;
m = a < b ? a : b;
return (m < c ? m : c);
}
static float max(float a, float b, float c)
{
float m;
m = a > b ? a : b;
return (m > c ? m : c);
}
void rgb2hsv(uint8_t r, uint8_t g, uint8_t b, float *h, float *s, float *v)
{
float red, green ,blue;
float cmax, cmin, delta;
red = (float)r / 255;
green = (float)g / 255;
blue = (float)b / 255;
cmax = max(red, green, blue);
cmin = min(red, green, blue);
delta = cmax - cmin;
/* H */
if(delta == 0)
{
*h = 0;
}
else
{
if(cmax == red)
{
if(green >= blue)
{
*h = 60 * ((green - blue) / delta);
}
else
{
*h = 60 * ((green - blue) / delta) + 360;
}
}
else if(cmax == green)
{
*h = 60 * ((blue - red) / delta + 2);
}
else if(cmax == blue)
{
*h = 60 * ((red - green) / delta + 4);
}
}
/* S */
if(cmax == 0)
{
*s = 0;
}
else
{
*s = delta / cmax;
}
/* V */
*v = cmax;
}
void hsv2rgb(float h, float s, float v, uint8_t *r, uint8_t *g, uint8_t *b)
{
int hi = ((int)h / 60) % 6;
float f = h * 1.0 / 60 - hi;
float p = v * (1 - s);
float q = v * (1 - f * s);
float t = v * (1- (1 - f) * s);
switch (hi){
case 0:
*r = 255 * v;
*g = 255 * t;
*b = 255 * p;
break;
case 1:
*r = 255 * q;
*g = 255 * v;
*b = 255 * p;
break;
case 2:
*r = 255 * p;
*g = 255 * v;
*b = 255 * t;
break;
case 3:
*r = 255 * p;
*g = 255 * q;
*b = 255 * v;
break;
case 4:
*r = 255 * t;
*g = 255 * p;
*b = 255 * v;
break;
case 5:
*r = 255 * v;
*g = 255 * p;
*b = 255 * q;
break;
}
}
//呼吸灯
void breath(uint16_t r,uint16_t g,uint16_t b)
{
float h,s,v;
uint8_t c_r, c_g, c_b;
/* 呼吸灯曲线表 */
const uint16_t index_wave[] = {255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,254,254,254,
254,254,254,254,254,254,253,253,253,253,253,253,253,253,253,252,252,252,252,252,252,252,251,251,251,251,
251,250,250,250,250,250,249,249,249,249,248,248,248,247,247,247,246,246,246,245,245,244,244,243,243,242,
242,241,241,240,240,239,238,238,237,236,236,235,234,233,232,231,231,230,229,228,226,225,224,223,222,220,
219,218,216,215,213,211,210,208,206,204,202,200,198,196,194,191,189,186,184,181,178,175,172,169,166,162,
159,155,151,147,143,139,134,130,125,120,115,110,104,98,92,86,80,73,66,59,51,43,35,27,18,9,1,1,9,18,27,35,
43,51,59,66,73,80,86,92,98,104,110,115,120,125,130,134,139,143,147,151,155,159,162,166,169,172,175,178,
181,184,186,189,191,194,196,198,200,202,204,206,208,210,211,213,215,216,218,219,220,222,223,224,225,226,
228,229,230,231,231,232,233,234,235,236,236,237,238,238,239,240,240,241,241,242,242,243,243,244,244,245,
245,246,246,246,247,247,247,248,248,248,249,249,249,249,250,250,250,250,250,251,251,251,251,251,252,252,
252,252,252,252,252,253,253,253,253,253,253,253,253,253,254,254,254,254,254,254,254,254,254,254,254,254,
254,254,255,255,255,255,255,255,255,255,255,255,255};
//传入的为RGB 颜色,将其转换为hsv
rgb2hsv(r, g, b, &h,&s, &v);
//保持HS不变,v变量亮度表
//printf("HSV %.2f, %.2f %.2f\r\n",h,s,v);
for(uint16_t n=0;n<=300;n++){
hsv2rgb(h,s,index_wave[n],&c_r,&c_g,&c_b);
//printf("%d RGB %d, %d %d \r\n",index_wave[n],c_r, c_g, c_b);
for(uint16_t i=0;i<WS2812_MAX_NUM;i++){
ws2812_set(i,c_r,c_g,c_b);
}
HAL_Delay(10);
}
}
[localvideo]5b8a9f67cb04dfbfb7bac51f76ee9dc8[/localvideo]
- 2025-02-22
-
回复了主题帖:
《Hello算法》走迷宫——深度优先、广度优先搜索
nmg 发表于 2025-2-21 22:00
喜欢电子版本,还是纸质版本?
电子版,代码练习可以CV
- 2025-02-21
-
发表了主题帖:
《Hello算法》走迷宫——深度优先、广度优先搜索
《Hello算法》有在线版学习的页面,看起来挺方便的。
曾经在视频中看见过迷宫小车走迷宫的,一直幻想着自己能有一辆小车,去写跑迷宫的算法,可惜至今任然未能实现。
走迷宫算法可以转换成图的数据结构去处理:
在这个图中寻找到一条能贯通指定两个节点的路径,就是迷宫的解。
遍历图寻找解有广度优先搜索(BFS)、深度优先搜索(DFS)。
广度优先搜索是一种逐层扩展的搜索算法。它从起点开始,逐层向外扩展,直到找到终点。BFS能够找到从起点到终点的最短路径。如同给迷宫灌水,水无差别地流淌,逐层灌下去。
实现步骤
初始化队列,将起点加入队列并标记为已访问。
从队列中取出一个节点,探索其所有未访问的节点相邻,并将这些节点加入队列。
重复上述步骤,直到队列为空或找到终点。
优点和缺点
优点:
能够找到最短路径。
实现相对简单。
缺点:
空间复杂度较高,因为需要存储大量节点。
深度优先搜索是一种用于遍历或搜索树或图的算法。它从起点开始,沿着一条路径尽可能深地探索,直到无法继续为止,然后回溯到上一个未完全探索的节点,继续搜索未访问的分支。类似于“永远沿着左边(右边)走,总能找到出路”的迷宫解法。
实现步骤
从起点开始,标记起点为已访问。
沿着一个方向(如上、下、左、右)递归地探索下一个节点。
如果遇到障碍物或已访问的节点,则回溯到上一个节点。
如果到达终点,则找到一条路径。
如果所有路径都探索完毕仍未找到终点,则无解。
优点和缺点
优点:
实现简单,代码易于编写。
空间复杂度相对较低。
可快速找到一条可行路径。
缺点:
找到的路径不一定是最短路径。
如果迷宫中有大量死胡同DFS,可能会陷入较深的路径,导致时间复杂度较高。
如果我有一辆迷宫小车,我会采用深度优先的算法,这样记忆的路径会偏少,能够尽快地走出迷宫。
- 2025-02-17
-
回复了主题帖:
机器人开发话题征集:写啥你来定!
觉着分两块吧!一个与人交互提供反馈,如各类聊天机器人,DeepSeek模型。这块发展的飞快。
一个是具体的执行机构,如各种关节机构,运动机构。这块发展感觉还是很滞后。
总体感觉很快就会有飞跃式的发展了!
- 2025-02-15
-
回复了主题帖:
《Hello算法》哈希表的认识
Jacktang 发表于 2025-2-15 10:15
看起来这个MD5的哈希算法还是好好学学哈
哈哈!算法挺复杂的,从来没能看明白过。直接用现成的就好!
- 2025-02-14
-
发表了主题帖:
《Hello算法》哈希表的认识
本帖最后由 aramy 于 2025-2-14 15:50 编辑
简单认识哈希表:
哈希表(Hash Table),是一种非常高效的数据结构,它通过哈希函数将键(key)映射到表中的一个位置来访问记录,从而实现快速的数据插入、查找和删除操作。
书中介绍了哈希表的一些算法,作为一种算法的介绍是比较简单的,哈希表在日常工作中接触的最多的大概就是MD5算法了吧。
回顾一下哈希表算法的目标:
日常中常见的MD5算法,就是一个哈希算法的实现。
单向性:MD5算法,将结果映射到16字节的散列。使得结果散列与待测字符串之间毫无关联,现在网上所谓的MD5破解,也只能是通过查表方式进行对碰,简单的字符串还能实现,复杂的就很困难。
抗碰撞性:这个找到一条旧闻,在2004年山东大学王小云教授成功破解MD5,能够找到不同的字符串,对应相同的MD5码!但是直到今天,MD5码依然广泛使用,证明了期抗碰撞性的顽强。
雪崩效应:记得以前学习古典密码时,遇到的移位算法的破解方法就是通过统计学计算不同字母的出现频率。然后制作移位字典,反向破解。MD5的哈希算法,在这里就实现的很优秀,只要源字符串有一丁点变化,结果就千差万别,而且无法统计出特定的规律。
- 2025-02-08
-
回复了主题帖:
这个春节最火爆的AI大模型deepseek,你玩了吗?
观望中,貌似钓鱼的APP已经出来了。
- 2025-02-04
-
发表了主题帖:
《Hello算法》增删改查——数组与链表
对数据的基础处理方法有增、删、改、查。四种基本操作。链表和数组都能支持这些基本操作。
1、查与改
数组是一种线性数据结构,数组元素被存储在连续的内存空间中,那么对于数组而言,可以直接定位到数组中的任意一个元素,所以复杂度为O(1)。定位到具体元素后即可做修改操作。
链表也是一种线性数据结构,其中的每个元素都是一个节点对象,各个节点通过“引用”相连接。引用记录了下一个节点的内存地址,通过它可以从当前节点访问到下一个节点。与数组不同,链表无法直接定位到任意一个元素,只能从头节点出发,逐个节点地遍历,直至找到目标节点。复杂度为O(n)。同样定位到具体元素,即可做修改操作。
2、增与删
数组应为元素是被存储在连续的内存空间里,并且内存空间在初始化时就被指定了。所以增加和删除元素变得很麻烦。增加元素时,需要重新申请一整块内存空间,新内存空间尺寸为当前内存空间加一;然后将当前内存空间中的元素与增加的元素,逐一地搬运到新的内存空间中去(这里存在申请新内存失败的风险)。删除元素时可以不用新申请内存空间,但是指定位置元素删除后,其后方所有的元素,都需要向前移动位置,形成新的数组。数组的增与删,内存操作都非常频繁,复杂度为O(n)。
链表在增与删上则方便很多,新增元素时:第一步将新增元素的下一节点指针指向需要插入位置的下一节点地址;第二步将需要插入位置的节点的下一元素指针,指向新增元素即可。
删除元素:第一步将指向待删除元素的指针,修该为待删除元素指向的下一节点地址;第二步释放待删除元素。链表的增和删,复杂度O(1)。
最后 关于数组与链表的总结,书上总结的非常到位:
数组和链表是两种基本的数据结构,分别代表数据在计算机内存中的两种存储方式:连续空间存储和分散空间存储。两者的特点呈现出互补的特性。
数组支持随机访问、占用内存较少;但插入和删除元素效率低,且初始化后长度不可变。
链表通过更改引用(指针)实现高效的节点插入与删除,且可以灵活调整长度;但节点访问效率低、占用内存较多。常见的链表类型包括单向链表、环形链表、双向链表。
列表是一种支持增删查改的元素有序集合,通常基于动态数组实现。它保留了数组的优势,同时可以灵活调整长度。
列表的出现大幅提高了数组的实用性,但可能导致部分内存空间浪费。
程序运行时,数据主要存储在内存中。数组可提供更高的内存空间效率,而链表则在内存使用上更加灵活。
缓存通过缓存行、预取机制以及空间局部性和时间局部性等数据加载机制,为 CPU 提供快速数据访问,显著提升程序的执行效率。
由于数组具有更高的缓存命中率,因此它通常比链表更高效。在选择数据结构时,应根据具体需求和场景做出恰当选择。
- 2025-01-31
-
回复了主题帖:
【Luckfox Pico Max评测】TMF8821驱动移植与测试
大佬!牛逼!
- 2025-01-22
-
回复了主题帖:
《Hello算法》开卷有益——迭代和递归算法
eew_Ya3s2d 发表于 2025-1-22 14:49
表达是挺简便的,但是计算的时候是不是会反复调用函数,是不是调用的数据越大,迭代的次数越大,消耗的时间 ...
迭代不会。迭代不会反复调用自身,如果有子函数,每次调用结束后就释放了资源。但是递归会,递归会重复调用自身,每次调用,都要将当前状态入栈,所以空间消耗比较大。