Chaosgoo | ESP32, IoT & Hardware DIY Blog - 嵌入式开发与硬件实战笔记

嵌入式开发与硬件实战笔记

ESP-IDF 硬核插件:用 embed_txtfiles 优雅地在固件里“塞”文件

0x00 背景

最近在翻看 GSC (Google Search Console) 的搜索关键词时,发现 esp-idf embed-txtfiles 这个词的出现频率高得惊人。看来大家在搞 ESP32 开发的时候,都被“如何在固件里优雅地放一个文件”这个问题困扰过。

在此之前,我为了实现一些功能(比如之前的那个桌面像素小屏幕),曾傻乎乎地把图片全转成了巨大的 C 数组(.h 文件)。结果可想而知:代码文件膨胀到几万行,IDE 索引卡死,每次微调一个像素都要重新编译半天,简直是灾难

不管是 HTTPS 的根证书、前端 HTML 页面,还是简单的配置文件,如果全都写成巨大的 const char[] 硬编码到代码里,那工程维护简直是自我折磨。今天就拿着我那块斥 9.9 元巨资买回来的 ESP32-C3 演示一下如何用 ESP-IDF 里的这个黑科技优雅地填坑

embed_textfiles

阅读更多
屏幕不够,算法来凑(二):ESP32 单色屏上的 Ditherpunk 实战

屏幕不够,算法来凑(二):ESP32 单色屏上的 Ditherpunk 实战

0x00 序

上一篇文章中,我们在浏览器中通过 JavaScript 模拟了各种抖动算法的视觉效果。虽然原理通透了,但真正的挑战在于硬件端:如何在资源受限的嵌入式设备上复现这些效果?

本文将记录我基于 ESP32-S3 和一块 1.54 寸 ST7305 单色屏的实战过程,探讨如何在单片机上实现从基础的阈值法到复杂的误差扩散等多种图像处理算法。

阅读更多
屏幕不够,算法来凑(一):Ditherpunk 抖动算法原理与 JS 实时演示

屏幕不够,算法来凑(一):Ditherpunk 抖动算法原理与 JS 实时演示

背景

在嵌入式开发领域,我们经常会遇到色彩位数极低的显示设备:

  • 经典的 SSD1306 (0.96寸 OLED),仅支持黑白两色。
  • 电子墨水屏 (E-Ink),通常只有黑白,且刷新率极低。

如果直接将 24 位真彩图片进行量化处理,其结果往往如同烧焦的木炭,细节丢失殆尽。但若引入 抖动算法(Dithering),这些 1-Bit 屏幕便能模拟出细腻的灰度感。

此前我曾尝试用 Rust 实现过一个版本,但作为博客演示,使用 JavaScript 与 Canvas 在浏览器中直接进行仿真最为直观。本文将介绍几种主流抖动算法的原理及其 JS 实现。


阅读更多

告别AT指令:ESP32通过PPPoS驱动4G模块上网

前言

在之前的文章中,我们都是利用ESP32自带的WiFi进行网络连接。但在户外或者没有WiFi覆盖的角落,想要让设备联网,就得请出“4G模块”了。

air780eg_modem

通常大家驱动4G模块(比如SIM800, Air724, EC20等)最原始的方法是用UART发送AT指令。
比如 AT+HTTPINITAT+HTTPPARA… 这种方式不仅繁琐,而且解析返回字符串简直是噩梦,写出来的代码全是状态机,一旦模块吐点乱码,程序直接暴毙。手动解析AT指令简直是坏文明!

为了优雅地使用4G模块,我决定使用 PPPoS(Point-to-Point Protocol over Serial)。
简单来说,就是把串口“伪装”成一个网卡。这样底层的TCP/IP协议栈(LwIP)就能直接接管网络,我们写上层代码时,完全不用关心是在用WiFi还是4G,直接调标准的Socket接口就完事了。

So Fragrant

阅读更多

使用Bindgen为ELK生成Rust绑定

介绍

bindgen 是一个能自动为 C(或 C++)库生成 Rust 绑定的辅助库和命令行工具。

elk 是一个迷你的JS引擎.
能够实现类似于这样的效果

main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
##include <stdio.h>
##include "elk.h"

// C function that adds two numbers. Will be called from JS
jsval_t sum(struct js *js, jsval_t *args, int nargs) {
if (nargs != 2) return js_err(js, "2 args expected");
double a = js_getnum(args[0]); // Fetch 1st arg
double b = js_getnum(args[1]); // Fetch 2nd arg
return js_mknum(a + b);
}

int main(void) {
char mem[200];
struct js *js = js_create(mem, sizeof(mem)); // Create JS instance
js_set(js, js_glob(js), "sum", js_mkfun(sum))); // Import sum()
jsval_t result = js_eval(js, "sum(3, 4);", ~0); // Call sum
printf("result: %s\n", js_str(js, result)); // result: 7
return 0;
}

如果这个执行内容来自于服务器下发,那就可以很方便地动态下发程序然后执行特定的任务.

阅读更多

CH592F利用SPI+DMA驱动WS2812灯珠

前言

在上一篇《从零开始:用CH592F制作CS2生命值胸章》的文章中,我展示了如何利用CH592F这颗蓝牙芯片制作一个和游戏联动的生命值指示器.

而本文将介绍生命值计数器的一个技术细节:如何使用CH592F驱动WS2812.
虽然WS2812的时序要求比较严格,通常可以使用GPIO翻转配合精准延时来实现,但那样会占用大量的CPU资源,导致蓝牙协议栈或其他中断任务受阻.
为了实现“零”CPU占用的炫酷灯效,我决定利用CH592F的SPI外设配合DMA来模拟WS2812的时序.
WS2812Timing

阅读更多

为 AdSense 铺路:我如何修复 'GSC 重复网页' 与 Canonical 致命错误(Hexo, 301, robots 详解)

背景

之前发布的MCompass项目文章站从Cloudflare后台分析来看, 流量可观.
但是考虑到因为版权问题无法售卖装置变现,所以决定采取流量变现的方式. 国内的广告联盟需要备案, 而本站使用Cloudflare解析到境外的Pages服务器, 这对于备案来说不是很合规, 最后决定接入AdSense, 结果没想到申请多次都收到以”需要采取行动:您的 AdSense 申请“为标题,内容是”感谢您关注 Google AdSense。经审核,您的申请需要稍作调整,才能获得批准。您完成调整后,我们的专家会审核您的网站是否符合我们的计划政策。“的邮件.

最终决定对本站进行一次彻底的SEO优化.

阅读更多

Claude Code初体验

背景

之前买的Jetpack Compose教程的群群主最近一直在称赞Codex,Claude Code之类的有多么强大, 激发了我对这种CLI式的AI兴趣.是时候研究一下了.
claude

初步了解

在哔哩哔哩上简单搜索到几个介绍视频, 尤其是看到了Codex的那个演示, 一个人下发多个任务,然后每个任务后面都有一个AI在不同分支为他自动修改代码,调试代码直到完成任务,更是迫不及待的体验一下这种一个人就是一个团队的力量.

阅读更多

踩坑与收获:2025独立开发者Google Play上架实战复盘

背景与初衷

入行安卓开发已有一段时间。学生时期曾注册并使用过
Google Play 开发者账号,在当时的审核环境下完成过
多款应用的发布与实践。

随着平台政策和合规要求的持续调整,
该历史账号已主动终止使用,相关应用亦已停止维护。
该阶段的经历主要作为个人技术成长过程的一部分予以记录。
play_store_old_account_screenshot

阅读更多

UNO R4 Wi-Fi 接入 Home Assistant

项目介绍

本项目是Funpack第五期板卡三的任务1实现.
任务目标是让UNO R4 Wi-Fi通过网络连接到智能云端, 并模拟成一个可以控制的灯, 通过远程控制调整自带的LED矩阵点亮范围.

实现思路

将UNO R4作为灯装置接入IOT平台, 随后在IOT平台上下发命令来操作UNO R4, 调整这个”灯”的亮度.
这里我选择的是可以部署在内网环境下的Home Assistant.

UNO R4通过MQTT服务器与Home Assistant进行通信. MQTT服务器选择EMQX开源版.

结构图

阅读更多

Friday Ink 今天是周五吗

今天是周五吗

2025年11月29日更新:根据读者的反馈和长达一年的实测,我补充了关于 SSD1607 与 SSD1681 屏幕驱动的功耗对比细节,以及 Rust 固件开发的更多背景。

预览图 - Fusion 360 建模

前言

这是一个拖了很久的项目, 有很多废案. 隔一段时间想起来有这回事情,于是缝缝补补, 推倒很多次.

阅读更多