ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

开源8通道脑电采集设备:ADS1299+ESP32完整方案

2026/9/21 2:11:36 拓冰建站 浏览量
开源8通道脑电采集设备:ADS1299+ESP32完整方案 做脑电采集这事搁几年前基本是大学实验室或者医疗设备公司的专利一台正经的8通道脑电放大器动辄几万块个人玩家想碰根本摸不着门路。我去年开始研究脑机接口相关内容越看越觉得市面上的方案要么贵得离谱要么封闭得让人抓狂后来盯上了TI的ADS1299和ESP32这对组合断断续续折腾了几个月做出了一个名叫YuEEG的开源8通道脑电采集设备不敢说多成熟但整个链路从模拟前端到无线传输再到上位机显示都跑通了。这篇就把我的完整设计思路、硬件细节、固件坑点和实测数据全部整理出来给想入坑脑电采集的朋友一份能直接照着做的参考。YuEEG本质上就是一块高精度生物电采集板ADS1299负责把电极上微伏级别的脑电信号放大、滤波并转换成24位数字信号ESP32负责控制采集时序、读取数据并通过WiFi或蓝牙把数据甩给电脑或手机。整套设备成本控制在300元以内支持8通道同步采样采样率可配置从250SPS到16kSPS直接覆盖脑电、心电、肌电等常用生物电信号的采集需求。适合哪些人呢想做脑机接口方向课程设计的在校生、研究情绪识别或睡眠分期的算法工程师、以及纯粹对生物电好奇的嵌入式硬件爱好者。就算你之前完全没接触过模拟电路只要用过Arduino、会基础的电路焊接照着这篇也能把设备跑起来。1. 项目整体设计与思路解析1.1 这套设备到底能做什么先回答一个最直接的问题为什么要自己做一台脑电采集设备而不是直接去买现成的OpenBCI或者商用脑电仪OpenBCI的Cyton板子确实做得不错8通道价格大概在两千块左右而且同样基于ADS1299软件生态也成熟。但问题在于它是个封闭硬件扩展性受限你没法按自己的需求改模拟前端也没法随意定制无线协议。商用脑电仪更不用说了动辄几万起步数据格式封闭算法验证全靠厂商SDK想自由地做点研究基本没门。YuEEG的逻辑很简单把最核心的模拟前端和数字控制部分全部开源让每个开发者都能低成本拿到一台基础性能不输商用设备的脑电采集仪。真正做起来之后它能干的事其实远超脑电这一项。因为ADS1299本身就是个多用途生物电ADC芯片8个通道可以自由配置成单端输入或差分输入配合不同电极和滤波设置心电、肌电、眼电都能采。这意味着你做完脑电还能顺手做个心率监测或者肌肉疲劳检测项目。我实际测试下来这套设备在250SPS采样率、24倍增益的配置下输入参考噪声能压到1μVpp以内这个指标已经能满足大部分脑电研究的需求了。配合ESP32的WiFi传输延迟大概在10到20毫秒左右做实时SSVEP视觉诱发电位实验也够用。1.2 为什么偏偏选ADS1299加ESP32很多人看到ADS1299的第一反应是这芯片好是好但不好焊啊而且网上资料少。这确实是实情但也正因如此才值得花时间做出一套完整的开源方案来。ADS1299是一颗8通道、24位分辨率、内置可编程增益放大器PGA的Δ-Σ型ADC专门为生物电测量设计。它有几个其他ADC芯片很难替代的优势输入参考噪声极低在增益24倍、250SPS采样率下典型值约1μVpp。脑电信号本身只有10到100μV信噪比要求极高普通ADC根本达不到这个量级。8通道真正同步采样每个通道都有独立的Δ-Σ调制器和数字滤波器不是用多路复用器轮询切换的这对多通道脑电分析至关重要因为各导联之间的相位关系必须精确。内置偏置驱动和右腿驱动电路这两个功能在实际生物电测量中非常实用。偏置驱动用来把人体共模电压拉到一个适合ADC输入的范围右腿驱动则能大幅抑制50Hz工频干扰。用分立元件搭这套电路非常麻烦ADS1299直接集成了。内置测试信号和导联脱落检测调试阶段特别方便不用外接信号源就能验证整个采集链路是否正常。至于主控选ESP32核心原因是它把无线通信问题一次性解决了。ADS1299出来的是SPI接口的数字信号理论上接任何单片机都行但如果你用STM32后续还得外挂ESP8266或者蓝牙模块才能把数据传到电脑上链路长、功耗高、故障点多。ESP32板载WiFi和蓝牙双核240MHz主频SPI接口最高能跑到80MHz处理ADS1299的数据流绰绰有余。更关键的是成本ESP32模组在批量采购时单价能压到15块以内整个控制核心的成本比单独买一个MCU加一个WiFi模块还便宜。这里多说一句ESP32的蓝牙和WiFi能不能同时用的问题。能但底层是时分复用的因为两者共享同一个射频前端。实测下来ESP32同时开着WiFi和BLE两种连接都能保持但BLE的数据吞吐率会明显下降。在我们这个场景里WiFi负责传输完整的8通道原始数据BLE只用来做控制指令下发和小数据量的状态查询完全没有冲突。2. 硬件方案与关键电路设计2.1 ADS1299模拟前端的电路细节ADS1299虽然集成了大量模拟功能但它终究不是个即插即用的模块外围电路的设计直接决定最终信号质量。输入保护电路是第一个坑。人体皮肤和电极之间会积累静电尤其是干燥环境下一碰电极就可能放出几千伏的静电直接打坏ADC输入引脚。我最初一版板子省掉了保护电路结果烧了两片ADS1299一片将近100块教训深刻。后来老老实实在每个输入通道上加了串联电阻加ESD保护二极管串联电阻取值10kΩESD管用的BAT54S双二极管把正负输入都钳位到电源轨之间。这个保护电阻也会和输入电容构成RC低通滤波器截止频率算下来大概是1.6kHz左右对脑电信号频段0.5到100Hz没有任何影响。交流耦合还是直流耦合也是需要做决策的点。脑电信号是微伏级别但电极和皮肤接触会产生一个几十到几百毫伏的直流偏置电压如果这个直流分量进到后级放大电路会把动态范围直接吃掉。ADS1299内置的PGA支持最高24倍增益在这么高的增益下几百毫伏的直流偏置就能让输出饱和。所以我在每路输入和ADS1299的AIN引脚之间串了一个100nF的电容和芯片内部的可编程输入阻抗共同构成高通滤波器把直流分量隔掉截止频率大概在0.5Hz左右确保脑电的低频信号能通过但直流偏置被阻断。偏置驱动电路接法是这样的所有通道的偏置驱动输出通过一个100kΩ电阻汇总然后接到一个跟随器输出接到右腿驱动电极。这样每个通道的共模电压会被主动拉低实测对50Hz工频干扰能有20dB以上的抑制效果。2.2 电源系统怎么设计ADS1299对电源质量的要求非常高模拟电源的纹波直接耦合到信号里面。我的方案是电源部分完全模拟数字分离3.7V锂电池升压到5V然后用LDO分别转出2.5V和-2.5V给ADS1299的AVDD和AVSS再用另一颗LDO转出3.3V给ESP32和数字电路。这里有个很关键的经验ESP32的3.3V电源一定要和ADS1299的模拟电源完全分开中间用磁珠连接。不然ESP32的WiFi射频发射时电流波动大会在电源上产生尖峰干扰直接体现在脑电波形上表现为周期性的高频毛刺。我第一版PCB没做电源隔离WiFi一开波形就乱排查了两天最后发现是电源串扰。负压产生用的是一颗电荷泵负压芯片输出-2.5V。需要注意的是电荷泵的开关频率会产生开关噪声我实测大概在几百kHz到1MHz不等这个频段和脑电信号差得很远后续加个LC滤波就能压到影响范围以下。参考电压这里我直接用了ADS1299的内部参考4.5V输出对应到±2.5V电源下满量程范围刚刚好。如果你的应用对精度要求更高可以改用外部参考芯片但DIY场景内部参考已经完全够用省掉一颗基准芯片的成本和面积。2.3 ESP32主控与接口分配ESP32上我用的模组是ESP32-WROOM-32E接口分配是这样的SPI通信走HSPIVSPI留给未来扩展SCLK接GPIO18MISO接GPIO19MOSI接GPIO23CS接GPIO5数据就绪中断DRDY引脚是ADS1299拉低表示数据准备好了接ESP32的GPIO34配置成下降沿中断偏置驱动控制信号接GPIO33复位引脚RESET接GPIO32有个接线细节要注意ADS1299的DRDY引脚是开漏输出需要外部上拉电阻到3.3V我用的10kΩ上拉。如果不加上拉SPI通信会偶发性失步表现为数据错位或通道错乱。另外SPI的时钟极性和相位设置必须匹配ADS1299的要求从datasheet上可以确认是SPI模式1CPOL0, CPHA1。这个设错了读出来的数据全是乱码。第一次调试时我就是因为这个浪费了一整天。2.4 电极接口与佩戴方式YuEEG的电极接口用的标准2.0mm扣式接口可以兼容市面上常见的Ag/AgCl湿电极。湿电极需要搭配导电膏使用优点是信号质量好接触阻抗低适合实验环境。如果是做日常监测场景可以后期换成干电极但干电极的接触阻抗高信号噪声会明显变大需要算法层面做更多处理。电极位置参考国际标准的10-20系统YuEEG的8个通道我默认配置为Fp1、Fp2、F3、F4、C3、C4、P3、P4这8个位置。参考电极放在左耳垂A1右耳垂A2接偏置驱动。实测这个配置做α波检测和SSVEP实验效果不错。3. 固件开发环境与软件架构3.1 开发环境选择YuEEG的固件用Arduino框架写的这可能是全文最实用的一条建议如果你只想把设备跑起来做数据采集没必要上ESP-IDF。很多搞嵌入式的朋友对Arduino框架有偏见觉得它太玩具。但实际对比下来ESP32上的Arduino框架底层依然是官方的ESP-IDF只是封装了一层便于调用的API性能和直接写IDF相差无几。而且Arduino生态里有现成的WiFi、蓝牙、WebSocket库写起来效率极高。ADS1299是需要频繁操作寄存器的高实时性设备Arduino的digitalWrite和SPI库在ESP32上底层直接映射到寄存器操作性能完全不是问题。如果你偏好更专业的环境用PlatformIOVSCode也是不错的选择。PlatformIO本质上还是调用了Arduino框架但项目管理、依赖管理比Arduino IDE规范很多推荐代码量上来以后切换到PlatformIO。3.2 ADS1299的寄存器配置全流程ADS1299上电后默认处于单次转换模式要正常工作需要经过一个严格的初始化流程。我把代码里的核心步骤拆解一下这部分是最容易踩坑的地方。复位和等待稳定是第一步。RESET引脚拉低至少4个时钟周期再拉高然后等待芯片内部参考电压稳定我个人习惯等500ms给足了余量。停止连续转换模式发送SDATAC命令。这一步非常重要芯片上电后默认不是连续转换模式但配置寄存器前必须确保处于停止转换状态否则写入的寄存器值不可靠。配置CONFIG1寄存器设置采样率。这个寄存器的低5位决定了采样率250SPS对应的值是0x96500SPS是0x951kSPS是0x94。采样率越高数据量越大ESP32的WiFi传输压力也越大所以默认用250SPS兼顾信号质量和传输稳定性。配置CONFIG3寄存器设置为连续转换模式同时打开内部参考打开偏置驱动放大器。CONFIG3的位设置里最关键的是第5位要置1选择连续转换模式第3位置1使能内部参考第2位和第1位使能偏置驱动。配置每个通道的CHnSET寄存器。每个通道寄存器是8位高3位配置PGA增益中间3位配置输入短接或外部输入。脑电应用增益设置成24倍对应二进制110。如果做心电增益降到6倍或12倍足够因为心电信号比脑电大一个量级。配置完成后发送RDATAC命令进入连续转换模式此时DRDY引脚会周期性地拉低表示新数据准备好ESP32在下降沿中断里通过SPI读取28字节数据即可。3.3 数据读取与无线传输实现ADS1299连续模式下每个数据帧是28字节前4字节是状态字后面24字节是8个通道各3字节的24位ADC数据。通道数据的三个字节需要手动拼成一个32位无符号整数再根据符号位转换成有符号数除以增益和参考电压才能换算成实际电压值。SPI读取用ESP32的SPI库一个关键优化是不要在每次读取时都重新初始化SPI设置这样会有几百微秒的额外开销可能导致数据丢失。正确做法是初始化一次SPI事务然后在中断处理函数里直接连续读取28字节。无线传输我默认用了WiFi加TCP协议。ESP32创建TCP服务器电脑端用Python脚本socket连接数据以二进制流的形式持续发送。每帧28字节前面加上一个两字节的帧头标记比如0xAA55上位机按帧头同步数据。实测250SPS下8通道原始数据流的带宽需求大约是28字节×250Hz 7KB/sWiFi带宽余量非常充足。电脑端的上位机用Python写的pySerial版本用于有线的调试socket版本用于WiFi连接绘图用matplotlib。代码里做了环形缓冲边收数边画实时波形帧率大概能到10FPS以上调试够用。如果需要更流畅的显示后期可以换PyQtGraph性能比matplotlib高一两个数量级。蓝牙传输我没作为默认方案原因是BLE的吞吐率限制比较紧张250SPS、8通道、28字节每帧的原始数据加上协议开销已经接近BLE 4.2的极限了。但用BLE做控制通道是极好的选择手机App发送开始采集、停止采集等指令同时接收设备回传的状态信息。4. 信号实测与质量评估4.1 基础电气性能测试硬件组装完成后第一步不是直接往脑袋上戴电极而是做电气性能验证。我这里给出了完整的测试流程照着一步步来可以快速定位问题测试信号验证是最基本的检测。给ADS1299输入一个10Hz、100μV的正弦波信号用信号发生器输出同时把增益设成24倍250SPS采样率。用Python上位机记录数据后做FFT看频谱图的基波幅度和失真情况。我实测这个配置下基波幅度误差在2%以内谐波失真小于0.05%说明ADC的线性度完全OK。值得注意的是测试信号源的输出阻抗要尽量低而且信号线要屏蔽否则引入的噪声会掩盖真实的芯片性能。输入短接噪声测试是衡量系统底噪的黄金标准。把所有通道的输入短接到模拟地然后记录几秒钟的数据计算峰峰值噪声。我实测增益24倍、250SPS下的短接噪声8个通道的峰峰值在1.2到2μV之间平均约1.5μVppRMS噪声约0.3μV。这个指标和商用脑电设备处于同一水平说明板子的模拟前端设计是合格的。如果在做这个测试时发现噪声超过5μVpp优先检查电源部分。按经验八成是模拟地和数字地没处理好或者LDO选型不当。还有一个很容易忽略的点ADS1299底部的裸露焊盘必须焊接良好并连接到模拟地否则散热不良会导致芯片温度升高热噪声显著增加我第一版手工焊接时疏忽了这点噪声从1.5μV直接飙到8μV。共模抑制比测试是另一个关键指标。把两个输入的信号线短接共同接到信号发生器的输出端让信号发生器输出一个相对于单片地线的大幅共模信号测量ADC输出端的残余信号比值就是CMRR。ADS1299数据手册上标称CMRR为-110dB但实际效果很大程度取决于前端电路的对称性所以PCB布局时输入走线必须保持等长、等距、平行走线尽量靠近这个细节决定了你能否真正发挥出芯片的性能。4.2 人体脑电实测基础测试通过后就可以开始人体实验了。第一个推荐做的实验是闭眼α波检测。α波是大脑枕区在清醒放松、闭眼状态下出现的8到13Hz节律性电活动幅度通常在20到100μV是验证脑电设备有没有真正采集到脑电信号的最直观证据。实验方法受试者坐好闭眼放松5分钟电极按10-20系统放置在O1和O2位置参考电极在左耳垂偏置驱动在右耳垂。采样率250SPS增益24倍带通滤波范围0.5Hz到40Hz。数据采集30秒后在Python里做FFT频谱分析。预期结果频谱图上应该在10Hz附近出现明显的峰值如果你是安静的闭眼状态但还没完全睡着这个峰基本都会出现。我第一次测的时候那个α峰非常干净峰值频率在10.3Hz左右幅度约为25μV那一刻有点激动毕竟一整块板子的价值在波形上清清楚楚地体现出来了。睁眼后α波会被抑制这是脑电研究里公认的经典现象。我还做了一个睁眼和闭眼交替的连续记录波形上明显能看出α波的周期性出现和消失说明设备的时域分辨率和灵敏度都足够捕捉这类经典脑电节律。第二个推荐的实验是SSVEP稳态视觉诱发电位。屏幕上一个固定频率比如10Hz闪烁的方块人盯着看枕区视觉皮层会产生同频率的诱发电位。在频谱图上能看到10Hz基波和20Hz谐波的明显峰值。这个实验特别适合验证多通道同步采集能力因为不同通道之间诱发电位的相位延迟可以精确测量。我把8个通道全部用上同时记录O1、O2、P3、P4等多个位置各通道都能清晰看到10Hz的峰而且通道间的相位关系稳定验证了8通道同步采样的精度。5. 常见问题与排查心得折腾这个项目下来踩过的坑可以写满一页纸我挑最重要的几个问题整理出来做成速查表照着排查能省下大量时间。现象可能原因排查方法SPI读取全是0xFF或0x00SPI模式不对、接线错误检查SPI模式必须为1检查MISO/MOSI是否接反数据读取出来通道顺序错乱DRDY中断时序问题确保每个DRDY下降沿只读一次用逻辑分析仪抓时序WiFi开启后波形出现高频毛刺电源被WiFi射频干扰模拟电和数字电之间加磁珠检查LDO输出电容工频50Hz干扰严重电极接触不良、屏蔽缺失涂抹导电膏、检查参考电极、使用屏蔽线所有通道输出满量程输入直流偏置过大检查交流耦合电容是否焊好电极是否湿润蓝牙连上后WiFi吞吐率骤降双协议时分复用用WiFi传数据时禁用BLE或降低BLE的通信频率通信类问题里最高频的是SPI数据错位。症状是读出的数据每帧都差一个字节或者通道顺序不对但波形看起来又隐约有点信号的样子。这类问题直接拿逻辑分析仪抓SPI总线最直接看DRDY和SCLK的时序关系。有一次我折腾了一晚上最后发现是接线时MISO和MOSI接反了。硬件调试真的不能光靠眼睛示波器或逻辑分析仪是刚需。信号质量类问题中工频干扰最难缠。50Hz工频干扰几乎无处不在灯具、插座、仪器设备都会辐射出来。人体本身就是一个大天线EEG测量本质上是踩在干扰信号上面测微弱生物信号。解决办法是电极皮肤接触阻抗要压到10kΩ以下湿电极配合导电膏很容易实现参考电极要接好偏置驱动的增益调整到合适位置采集设备使用电池供电彻底隔绝电源地回路最后再用软件做50Hz陷波滤波。还有一个特别容易忽略的坑ADS1299的寄存器写入不生效。这主要是因为没有发送SDATAC命令就尝试配置寄存器。ADS1299在连续转换模式下是不接受寄存器配置的必须先在SDATAC模式下完成所有寄存器配置再发送RDATAC进入连续模式。如果配置过程中间被打断可能出现寄存器值写进去但行为不变的情况解决办法简单粗暴重新初始化流程保证每一步的时序严格正确。关于ESP32的开发环境坑说真心话Arduino框架在ESP32上虽然好用但入口有坑。ESP32的Arduino核心在首次安装时需要从GitHub下载编译工具链国内网络环境经常失败而且失败后Arduino IDE也不报明确错误只会在编译时告诉你找不到xtensa编译器。解决办法是先把ESP32开发板支持包手动下载好的压缩包放到Arduino的staging目录里或者在PlatformIO里指定board指向已安装的开发板框架。我第一次搭环境卡了三个小时最后就是靠手动离线安装解决的。电源设计的问题到最后才暴露。最开始为了省事直接用ESP32开发板的3.3V给ADS1299供电结果发现数据噪声始终压不下去。后来换了低噪声LDO单独供电噪声立刻降了一个数量级。这里有个通用结论像ADS1299这种高性能模拟芯片电源质量怎么强调都不过分一个几十块的LDO能解决几天的排错时间这笔投入非常划算。电池续航方面实测下来整套设备待机电流约50mAWiFi全速传输时约120mA左右用1000mAh锂电池可以连续工作约8小时满足一天实验的需求。如果想进一步增强续航可以让ESP32在无数据时进入深度睡眠但代价是恢复时间变长实时性变差我目前没有这样做。6. 扩展方向与我的个人体会YuEEG做到现在这版已经满足了我最初的需求一台低成本、全开源的8通道脑电采集平台可以自由验证算法也可以持续做硬件改进。但它的上限远不止于此这里聊几个我觉得有价值的扩展方向。无线电极帽是很自然的一个延伸。现在的8通道设备需要自己用线连接每个电极位置线多了以后很乱而且线缆本身就是巨大的工频干扰天线。如果能用柔性电路板做一顶集成电极的帽子信号线尽量短配合屏蔽层信号质量还能再上一个台阶。多板级联扩展通道数ADS1299支持菊花链模式理论上可以多块板子级联扩展到16通道甚至32通道。比如做高密度脑电研究或者做头皮分布图对脑电地形图显示感兴趣的这个方向值得深入研究。ESP32的SPI速率足够快菊花链级联时只需要额外多读一串数据对CPU的压力不大。与现有开源社区生态结合方面YuEEG的数据格式和OpenBCI的格式兼容这样可以直接用OpenBCI GUI做显示省去重写上位机的功夫。机器学习方面Python生态里的MNE库是脑电信号处理的事实标准读入CSV或OpenBCI格式数据后可以无缝对接LSTM、CNN这类深度学习模型做情绪分类、运动想象识别等任务。还有个很现实的扩展方向是做睡眠监测。脑电是睡眠分期金标准之一配合眼电和肌电信号能区分REM和NREM阶段。YuEEG的8通道规模刚好可以同时采集脑电、眼电、肌电、心电四个维度一台设备实现完整的睡眠监测闭环。我之前试过用这套设备连续记录一晚的脑电信号配合简单的自动分期算法准确率能达到70%以上当然这是后话算法的细节等以后有空再单独写一篇。最后说说我的真实感受。做这个项目最大的收获不是那块波形漂亮的板子而是把教科书里的知识和真实硬件之间的鸿沟填平了。ADS1299的数据手册写得再清楚都不如亲手焊一块板子、看一次DRDY时序、处理一次工频干扰来得深刻。硬件调试中很多问题看着神秘其实背后就是一个简单的工程细节但你不亲自踩一遍永远不会记住。如果你也想尝试自己的脑电采集设备我的建议是别急着追求高大上的硬件设计先把基础链路跑通用最常规的电路和方案验证采集和传输流程再逐步优化信号质量。YuEEG整套设计文件、固件源码和上位机代码都在开源仓库里照着做一遍你学到的会比看十篇文章多得多。也欢迎在评论区分享你做完之后的实测数据咱们一起让这个方案越来越完善。