做个桌面像素小屏幕吧

给自己做个桌面像素小屏幕吧

展示一下自己制作迷你版本的像素显示屏的过程

背景

之前疫情期间(2020-02~2020-03)做过一个大号的像素屏幕作为生日礼物送人了,当时使用的芯片是ESP32,开发语言是micropython。
那个初号机的性能表现不是很好,所以计划做一个使用C/C++的版本,能够更高帧率运行。

如果只是纯粹的重写固件,那么和大多数人做的AWatrix就没多大区别了,所以决定做一个迷你版本的像素显示屏出来。

很多地方是参考了AWatrix的代码,因为AWatrix除了必须连接服务器才可以使用以外,真的是非常优秀的一个固件。
AWatrix使用到的一些库很具有参考价值,比FastLED_NexPixel如它把LED点阵当作一块”屏幕”来使用,可以很方便的绘制出一些基础图形。
开发工具为PlantformIO,也是一个很方便的工具了,VSCode装上插件就好了。

开始整活

0x01 绘制电路板

万能的某宝上能够找到的内置WS2812的LED贴片灯最小的就是2020LED,长宽各为2mm,比常规AWatrix使用的5050或者3535小很多。
奈何没有现成品,就只能自己画一个电路板了,好在电路非常简单,就是一个接一个,然后绕成S型就好啦。

这次选择的PCB绘制软件为Eagle PCB,因为免费小巧。(但是我打算以后用KiCad画电路图了,因为开源强大)
磨磨唧唧的画完了电路图。

然后提交Gerber文件到厂家,等待3天后就收到了成品。

0x02 焊接LED贴片灯

这一步没什么好说的,我用的是锡膏,熔点在182度,于是先涂抹在板子上,然后风枪对着就是一阵吹。

大概花费了半天时间才焊完所有的贴片灯,因为实在是太麻烦了啊,不小心就碰掉了一个,然后发生一系列连锁反应。

0x03 获取代码,修改参数

代码位于Github
下载以后,使用PlantformIO导入工程。

  • 修改位于gmatrix_config.h中的B站ID和城市以及天气的Key
1
2
3
#define SUNING_TIME_URL "http://quan.suning.com/getSysTime.do"
#define BILIBILI_SUBSCRIPTION_URL "http://api.bilibili.com/x/relation/stat?vmid=哔哩哔哩UID"
#define WEATHER_URL "http://api.openweathermap.org/data/2.5/weather?q=城市的拼音&appid=天气api"
  • 修改位于Gmartix.cpp中的WiFi名称和密码。
    1
    2
    3
    4
    // WiFi名称
    const char *ssid = "CloseWrt_9.6G_D96AS5";
    // WiFi密码
    const char *pwd = "have5seeds";
    然后直接使用PlantformIO的编译或者下载到板子

0x04 烧录固件

使用PlantformIO可以直接下载到板子上,也可也Build以后使用其他烧录工具烧录。
我使用的烧录软件是NodeMCU Firmware Programmer

插上板子选择对应的端口号,然后点击Flash就可以进行烧录了。

0x05 接线&组装

材料清单

序号 名称 数量 备注
1 WeMos D1 mini 1
2 LED板 1 自制
3 htu01d 1 温湿度传感器
4 导线 ?
5 3D打印外壳 1
6 亚克力光栅 1
7 A4纸 1
8 深色半透亚克力 1
9 后盖 1 可以采用任意材料自制

接线

WeMos D1 mini引脚名称 htu01d
5V VCC
GND GND
D3 SDA
D1 SCL
WeMos D1 mini引脚名称 LED屏幕
不接 正面从上至下第2个孔
GND 正面从上至下第2个孔
5V 正面从上至下第3个孔
D2 正面从上至下第4个孔
WeMos D1 mini引脚名称 散热风扇
5V 红线
GND 黑线

光栅制作使用的是定制亚克力,而外壳使用的3D打印,按照下图的顺序组装,需要注意的是光栅与深色半透亚克力之间需要加一层A4纸进行柔光。

0x06成品展示

参考资料:
AWatrix

materialpalette

HomeKit ESP32 Control Light III

快把你家的灯接入HomeKit吧其三(整合篇)

我的回合,抽卡。发动魔法卡–融合!

第一篇文章中介绍了如何控制LED的亮灭,而第二篇文章中介绍了如何控制舵机旋转到指定的角度,那么现在让它们融合起来了吧!

融合前的检测

在LED的Demo中,每次开灯关灯操作都会调用**led_write(bool status)**函数,所以我们只需要根据传进来的status值,旋转舵机到对应的角度即可。

先让我们从mcpwm_servo_control_example.c中提取出需要的方法, 内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// 引入的头文件

#include "driver/mcpwm.h"
#include "soc/mcpwm_periph.h"
#include "esp_attr.h"

// 舵机参数的宏定义
#define SERVO_MIN_PULSEWIDTH 500 // 最小脉冲时间ms
#define SERVO_MAX_PULSEWIDTH 2500 // 最大脉冲时间ms
#define SERVO_MAX_DEGREE 180 // 舵机最大可旋转角度

// 初始化2号端口为PWM
static void mcpwm_example_gpio_initialize(void)
{
printf("initializing mcpwm servo control gpio......\n");
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, 18); //Set GPIO 2 as PWM0A, to which servo is connected
}

// 该方法输入目标角度,输出对应高电平脉冲宽度单位us
static uint32_t servo_per_degree_init(uint32_t degree_of_rotation)
{
uint32_t cal_pulsewidth = 0;
cal_pulsewidth = (SERVO_MIN_PULSEWIDTH + (((SERVO_MAX_PULSEWIDTH - SERVO_MIN_PULSEWIDTH) * (degree_of_rotation)) / (SERVO_MAX_DEGREE)));
return cal_pulsewidth;
}

// 开灯函数
void turn_on(void *arg)
{
uint32_t angle;
//1. mcpwm gpio 初始化
mcpwm_example_gpio_initialize();
//2. 初始化 mcpwm 配置
printf("Configuring Initial Parameters of mcpwm......\n");
mcpwm_config_t pwm_config;
pwm_config.frequency = 50; // 舵机信号频率为50Hz,每个周期时长20ms
pwm_config.cmpr_a = 0; //duty cycle of PWMxA = 0
pwm_config.cmpr_b = 0; //duty cycle of PWMxb = 0
pwm_config.counter_mode = MCPWM_UP_COUNTER;
pwm_config.duty_mode = MCPWM_DUTY_MODE_0;
mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config); //应用上面配置到 PWM0A & PWM0B
// 旋转角度
printf("Angle of rotation: %d\n", 0);
// 计算60度对应的脉冲宽度
angle = servo_per_degree_init(60);
printf("pulse width: %dus\n", angle);
mcpwm_set_duty_in_us(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A, angle);
vTaskDelay(10); //Add delay, since it takes time for servo to rotate, generally 100ms/60degree rotation at 5V
vTaskDelete(NULL);
}

// 关灯函数
void turn_off(void *arg)
{
uint32_t angle;
//1. mcpwm gpio 初始化
mcpwm_example_gpio_initialize();
//2. 初始化 mcpwm 配置
printf("Configuring Initial Parameters of mcpwm......\n");
mcpwm_config_t pwm_config;
pwm_config.frequency = 50; //frequency = 50Hz, i.e. for every servo motor time period should be 20ms
pwm_config.cmpr_a = 0; //duty cycle of PWMxA = 0
pwm_config.cmpr_b = 0; //duty cycle of PWMxb = 0
pwm_config.counter_mode = MCPWM_UP_COUNTER;
pwm_config.duty_mode = MCPWM_DUTY_MODE_0;
mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config); //ConfigurePWM0A & PWM0B with above settings
printf("Angle of rotation: %d\n", 0);
// 计算120度对应的脉冲宽度
angle = servo_per_degree_init(120);
printf("pulse width: %dus\n", angle);
mcpwm_set_duty_in_us(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A, angle);
vTaskDelay(10); //Add delay, since it takes time for servo to rotate,generally 100ms/60degree rotation at 5V
vTaskDelete(NULL);
}

// 最后修改led_write函数为
void led_write(bool on)
{
if (on)
{
// 接收到开灯命令,执行开灯任务
xTaskCreate(turn_on, "turn_on", 4096, NULL, 5, NULL);
}
else
{
// 接收到关灯命令,执行关灯任务
xTaskCreate(turn_off, "turn_off", 4096, NULL, 5, NULL);
}
}

完整的文件位于
HomeKitServoLight.c

来瞅一瞅效果吧。

现在舵机就听我们的指令了哦!

再配合上一个简陋的结构,就可以控制开关了。
servo_on_light

别担心,最终的成品可不会这样寒酸。
本系列还没有结束,还有第四部分的结构设计,尽请期待吧!

下期预告:快把你家的灯接入HomeKit吧其四(结构设计篇)

参考资料:
ESP-IDF 编程指南

Espressif IoT Development Framework

© 2025 Do U Find IT? All Rights Reserved.
Theme by hiero