Flipper Zero 盖革计数器实战指南:flipper_geiger 硬件接线、fbt 构建与源码解析
Flipper Zero 盖革计数器实战指南flipper_geiger 硬件接线、fbt 构建与源码解析【免费下载链接】FlipperPlayground (and dump) of stuff I make or modify for the Flipper Zero项目地址: https://gitcode.com/GitHub_Trending/fl/Flipper本文基于当前仓库中归档的 flipper_geiger 官方应用源码完整讲解如何在 Flipper Zero 上搭建一台便携式辐射测量仪从探测板选型与 GPIO 接线、fbt编译部署到界面操作、无盖革管的自测模式再到逐行拆解其事件驱动源码实现。读完本文你将能够在自己的 Flipper Zero 上编译运行该应用并理解 cps/cpm 计数、自动缩放图表背后的实现原理。应用定位一块探测板 一个 Flipper Zeroflipper_geiger应用名为Geiger counter是一个运行在 Flipper Zero 上的盖革计数器Geiger counter应用用于测量环境中的电离辐射强度。它的本质是一个频率计数器盖革-米勒管每探测到一次电离事件如 α、β、γ 粒子或射线就输出一个脉冲应用统计单位时间内的脉冲数并换算为辐射读数。需要特别强调的一点是运行该应用必须外接一块盖革计数器探测板仅靠 Flipper Zero 本体无法完成辐射探测。原文档给出的板子为常见的铝电解式盖革探测模块其探测管如 J305 类盖革-米勒管需要数百伏高压偏置由探测板上自带的升压电路提供Flipper Zero 只需负责供电与信号采集。该应用在仓库中的归档位置为 flipper_geiger 目录包含三个核心文件文件作用README.md官方使用说明接线、构建、使用场景application.famfbt 应用清单文件声明应用元信息flipper_geiger.c应用唯一源码文件单文件实现硬件接线5V 供电与 A7 信号采集接线是整个部署过程中最容易出错的一环原文档对此给出了明确的约束供电探测板使用 Flipper Zero 的5V 电源引脚供电GPIO 排针上的 5V 脚与 GND 一同引出。信号输出注意不能使用探测板上标记为 Arduino 的输出引脚——Arduino 输出的逻辑电平偏低无法被 Flipper Zero 的 GPIO 可靠识别。应改用探测板的jack 输出端口3.5mm 插孔或同轴输出口该端口直接输出高压侧脉冲信号。接入引脚将 jack 输出端连接到 Flipper Zero 的A7 GPIO引脚gpio_ext_pa7同时连接好 GND 共地。以下为官方提供的接线示意图来自 img/schematic.jpg图中可以清楚看到三条关键连线红色线对应 5V 电源、绿色线对应 GND、黑色线由 Flipper Zero 的 A7 引脚接入探测板的信号输出端。信号线并非接到 Arduino 输出脚而是接到探测板面向外部设备的脉冲输出端口。从源码可以印证 A7 引脚的硬件角色——flipper_geiger.c 中应用将gpio_ext_pa7配置为下降沿中断输入并注册了中断回调furi_hal_gpio_init(gpio_ext_pa7, GpioModeInterruptFall, GpioPullUp, GpioSpeedVeryHigh); // ... furi_hal_gpio_add_int_callback(gpio_ext_pa7, gpiocallback, event_queue);GpioModeInterruptFallGpioPullUp的组合意味着无脉冲时 A7 被内部上拉保持高电平探测板每输出一个负脉冲高→低跳变就触发一次中断对应一次计数。这正是每次电离事件 一个脉冲 一次中断计数的硬件链路。构建与部署fbt 编译与 .fap 安装原文档提供了两条部署路径源码编译或直接拷贝预编译产物。路径一fbt 源码编译前提是本机已安装 Flipper Zero 官方固件的fbt 构建工具链即包含fbt命令、applications_user目录的开发环境。步骤为将仓库中的flipper_geiger 目录整体复制到固件工程的applications_user目录下连接 Flipper ZeroUSB执行./fbt launch_app APPSRCapplications_user/flipper_geigerlaunch_app会完成编译、烧录并自动在设备上启动该应用无需手动操作。路径二直接拷贝 .fap如果不想或无法在本地编译可以直接将编译好的flipper_geiger.fap文件拷贝到 Flipper Zero 的 SD 卡存放外部应用的目录通常为apps对应分类目录中即可运行。应用清单application.fam 解析fbt之所以能识别、编译并分类该应用靠的是同目录下的 application.fam其内容完整如下App( appidflipper_geiger, nameGeiger counter, apptypeFlipperAppType.EXTERNAL, entry_pointflipper_geiger_app, cdefines[APP_GEIGER], requires[ gui, ], stack_size1 * 1024, fap_icongeiger.png, fap_categoryGPIO_Extra, )几个字段的工程含义值得展开说明apptypeFlipperAppType.EXTERNAL应用被编译为独立 .fap 外部应用不内置于固件方便独立分发与升级entry_pointflipper_geiger_app指定程序入口函数对应源码中的int32_t flipper_geiger_app()requires[gui]声明依赖 Furi 的 GUI 子系统fbt 据此链接gui、input、notification等模块stack_size1 * 1024为应用分配 1 KiB 栈空间说明该应用内存占用极小属于轻量级 GPIO 工具类应用fap_categoryGPIO_Extra决定 .fap 在设备应用菜单中的归类为 GPIO 扩展应用通常位于apps/GPIO_Extra分类下fap_icongeiger.png指定应用图标资源。启动与界面操作编译并启动后在 Flipper Zero 应用菜单的 GPIO 扩展分类中可以找到 Geiger counter 应用见 img/flipper1.png与 POCSAG Pager、Weather Station、Dice 等同属外部应用列表应用主界面顶部实时显示cps - cpm两组读数下方为脉冲柱状图见 img/flipper6.png界面操作非常简洁只有两个按键按 OK 键短按清空当前图表与计数重新开始测量适合切换测量对象或测量地点按 Back 键退出应用。无需盖革管的测试模式A4 → A7 跳线这是原文档提供的一个非常实用的自检技巧在没有盖革探测管的情况下可以用一根杜邦线把 Flipper Zero 的 A4 GPIO 直接连接到 A7 GPIO从而验证应用与固件链路是否正常。原理在于A4 引脚被应用用作 PWM 信号发生器。应用启动时即通过furi_hal_pwm_start在 A4LPTIM2 定时器通道上输出 PWM 信号见 flipper_geiger.cfuri_hal_pwm_start(FuriHalPwmOutputIdLptim2PA4, 5, 20);并且源码中的每秒定时器回调clock_tick会不断用随机数更新 PWM 频率见 flipper_geiger.cstatic void clock_tick(void* ctx) { furi_assert(ctx); uint32_t randomNumber furi_hal_random_get(); randomNumber 0xFFF; if (randomNumber 0) randomNumber 1; furi_hal_pwm_start(FuriHalPwmOutputIdLptim2PA4, randomNumber, 50); // ...发送 ClockEventTypeTick 事件到队列 }A4 上的 PWM 信号频率每隔一秒随机变化一次占空比 50%当它经跳线灌入 A7 的下降沿中断输入时就会产生与真实盖革脉冲类似的计数信号。此时观察界面柱状图应持续跳动、cps/cpm 不断变化且读数随频率随机变化而波动——若能看到这些现象说明 GPIO 中断、事件循环、计数统计与绘图渲染整条链路工作正常问题大概率出在真实探测板的接线或供电上。这一点在原文档的使用场景图A4 接 A7 的测试截图中也有直观展示。使用场景与读数解读原文档给出了四类典型测量场景全部通过真实运行截图佐证环境本底辐射Ambient radioactivity将设备放置在普通环境中测量日常背景辐射水平读数通常较低且平稳铅容器内的铀矿石将铀矿石样本封入铅容器后测量——铅屏蔽会吸收大部分射线读数显著下降贴近探测管的铀矿石将铀矿石样本直接接触盖革管测量读数会明显升高反映矿石的强放射源特性连续测量多场景在同一个图表中连续经历上述场景此时图表纵轴刻度会自动缩放即使数值跨数量级变化也能完整呈现。cps / cpm 的含义界面顶部的两组读数定义如下cpsCounts Per Second每秒计数最近 1 秒内探测到的脉冲总数反映瞬时辐射强度波动较大cpmCounts Per Minute每分钟计数辐射测量最常用的单位。本应用采用最近 60 秒滑动窗口的近似算法即把最近 60 个秒级计数累加近似得到每分钟计数。从源码看cpm 的计算在每秒 tick 处理逻辑中完成见 flipper_geiger.clfsrMutex-cpm lfsrMutex-line[0]; uint32_t max lfsrMutex-line[0]; for (int i1;iSCREEN_SIZE_X/2;i) { if (i 60) lfsrMutex-cpm lfsrMutex-line[i]; if (lfsrMutex-line[i] max) max lfsrMutex-line[i]; }其中line[]是一个 64 项的环形滚动数组line[0]是最近一秒的计数line[59]往前推 59 秒——累加i 60的项即得到最近 60 秒脉冲总数作为 cpm 的近似值应用刚启动不足 60 秒时cpm 会随窗口逐步填满而逐渐趋于真实值。源码实现深度解析flipper_geiger采用典型的 Flipper Zero 事件驱动架构中断回调 消息队列 主事件循环 互斥锁保护共享状态。整个应用只有一个源码文件 flipper_geiger.c非常值得作为 GPIO 中断类应用的入门范本。1. 事件模型与共享数据结构源码用枚举定义了三类事件flipper_geiger.ctypedef enum { EventTypeInput, // 按键输入 ClockEventTypeTick, // 每秒定时器 EventGPIO, // A7 下降沿中断 } EventType;共享状态mutexStruct集中存放所有会被多线程访问的数据flipper_geiger.ctypedef struct { uint32_t cps, cpm; // 每秒/每分钟计数 uint32_t line[SCREEN_SIZE_X/2]; // 滚动柱状数据64 个采样点 float coef; // 纵轴缩放系数 } mutexStruct;该结构体被封装进ValueMutex绘图回调与主循环之间通过互斥锁同步访问避免中断/定时器上下文与渲染上下文的数据竞争。2. GPIO 中断计数链路gpiocallback是中断回调flipper_geiger.c它不做任何数据处理只是向消息队列投递一个EventGPIO事件static void gpiocallback(void* ctx) { FuriMessageQueue* queue ctx; EventApp event {.type EventGPIO}; furi_message_queue_put(queue, event, 0); }主循环收到EventGPIO后仅仅执行counterflipper_geiger.c。这种中断里只做最简操作计数交给主循环的设计正是 2023-01-15 版本更新日志中所说的大量事件也能无问题处理的优化思路中断回调保持极短耗时避免在中断上下文做重活导致事件丢失。3. 每秒 tick滚动数组与自动缩放应用启动一个 1000ms 周期的FuriTimer每秒触发一次ClockEventTypeTick主循环中对应的处理逻辑flipper_geiger.c完成三件事滚动移位将line[]数组整体后移一位把最新秒级计数counter写入line[0]同时将cps更新为counter并清零计数器计算 cpm累加最近 60 个采样点自动缩放找出当前窗口内的最大值max计算缩放系数if (max 0) lfsrMutex-coef ((float)(SCREEN_SIZE_Y-15))/((float)max); else lfsrMutex-coef 1;SCREEN_SIZE_Y - 15表示图表绘制区高度——屏幕高 64 像素顶部预留 15 像素给文字区。缩放系数随辐射强度自动调整这解释了原文档中多场景连续测量时图表刻度自动调整的行为。4. 渲染与清空绘图回调draw_callbackflipper_geiger.c在互斥锁保护下快照共享状态然后以snprintf格式化顶部文字%ld cps - %ld cpm用FontPrimary字体居中绘制在 (64, 10)以每 2 像素一根竖线的密度绘制 64 根柱状竖线SCREEN_SIZE_X/2 64柱高由line[i] * coef决定。OK 短按清空的处理位于输入事件分支flipper_geiger.c将counter、cps、cpm全部清零line[]逐项置 0并触发一次界面刷新。5. 退出与资源清理按 Back 键退出主循环后源码按顺序执行完整清理flipper_geiger.c禁用并移除 A7 中断回调、停止 A4 PWM、释放消息队列、销毁互斥锁、移除并释放 ViewPort、释放定时器、关闭 GUI 记录。规范的内外设清理保证了应用反复进出不会泄漏资源或污染 GPIO 状态。版本演进与注意事项原文档记录了应用的变更历史从中可以看到项目的演进脉络日期变更内容2023-01-08初始版本发布2023-01-09补充接线示意图并修复代码2023-01-15代码修复与大量优化现在可无问题处理大量事件最后汇总本应用的几条关键注意事项必须外接盖革探测板才能获得真实读数裸机运行只能靠 A4→A7 跳线自测探测板由 Flipper Zero 的5V引脚供电注意共地信号线接探测板的 jack 输出端口而非 Arduino 输出脚后者电压不足以驱动 Flipper Zero 的 GPIO 中断信号接入A7引脚且源码将其配置为下降沿中断 内部上拉务必保持信号极性匹配若使用官方固件构建将 flipper_geiger 目录 复制到applications_user后执行./fbt launch_app APPSRCapplications_user/flipper_geiger即可一键编译运行仓库内该目录属于source-OLDER归档区参考实现时以当前固件 SDK 的 API 版本为准做适配。【免费下载链接】FlipperPlayground (and dump) of stuff I make or modify for the Flipper Zero项目地址: https://gitcode.com/GitHub_Trending/fl/Flipper创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考