Arduino Nano 手持盖革计数器:DIY 核辐射检测仪
零部件与材料
- Arduino Nano R3 × 1
- 成品盖革计数器套件(含 GM 管、高压电路) × 1
- 0.96" OLED 彩色显示屏 96×64 (SSD1331) × 1
- Micro USB 充电板(18650 电池) × 1
- 3.7V 4000mAh 18650 锂电池(带保护板) × 1
- 三极管 BC547 × 1
- 蜂鸣器 12mm × 1
- 电阻 1kΩ × 1
所需工具
- 3D 打印机
软件与设计工具
- Autodesk Fusion 360(外壳建模)
- Arduino IDE
- CURA(切片软件)
- ClickCharts(流程图)
- EasyEDA(电路设计)
- Fritzing(原理图绘制)
项目简介
项目源于购买一款 Banggood 成品盖革计数器套件。

目标:将套件装入 3D 打印手持外壳,做成完整的便携辐射检测仪。最终效果如下:

步骤 1:系统设计

配备 0.96 英寸彩色 OLED,显示 CPM(每分钟计数,电离事件检测率)和换算后的剂量当量 μSv/h(换算系数 151,适用于该 GM 管类型,参考 Wikipedia)。
显示的 CPM 并非直接计数 1 分钟,而是测量每秒计数 (CPS),存入覆盖过去 10 秒的数组,总和乘 6 得 CPM。过去 1 秒的计数以红色柱状图实时显示,便于高计数率或快速扫描辐射源时观察。
供电:18650 锂电池 + Micro USB 充电板。Arduino Nano USB 口保留供固件升级。额外蜂鸣器并联在套件蜂鸣器上增强音量。
所有电子元件内置于 3D 打印外壳:

OLED 单独安装在顶部盒体:

完全组装态:

步骤 2:盖革计数器组装
主要材料来源:
- Arduino Nano: 官方店
- 盖革套件: Banggood
- OLED: Banggood
- 充电板: Banggood
- 18650 电池: Banggood
- BC547、蜂鸣器、1kΩ 电阻各 1
电子原理图
套件原理图:

完整系统原理图:

5V 来自充电板上的 18650 电池,OLED 取 3.3V。面包板测试搭建图:

机械与电气组装
所有机电部件组装照片见项目附件。手持机无外露线缆。外壳预留 Micro USB 充电口和 Arduino Nano 固件升级口。
步骤 3:软件设计

OLED 显示视图:

完整 Arduino 代码
/********* Pierre Pennings (Dec 2019) 开发制作 *********
手持盖革计数器:成品套件 + Arduino Nano + 96×64 OLED 彩屏
10 秒滑动窗口计算平均 CPM,换算 μSv/h (系数 151)
OLED 显示实时 CPS 红色柱状图
18650 电池供电,开机显示电量
GPL3+ 许可证
*********/
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1331.h>
#include <SPI.h>
// OLED 接线
#define sclk 13 // SCL (蓝)
#define mosi 11 // SDA (白)
#define cs 10 // CS (灰)
#define rst 9 // RES (绿)
#define dc 8 // DC (黄)
#define LOGtime 1000 // 采样周期 1 秒
#define Minute 60000 // 1 分钟周期
#define show endWrite
#define clear() fillScreen(0)
// 颜色定义
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
Adafruit_SSD1331 display = Adafruit_SSD1331(cs, dc, rst);
int Counts = 0;
unsigned long previousMillis = 0;
int AVGCPM = 0;
int TenSecCPM = 0;
int units = 0, tens = 0, hundreds = 0, thousands = 0;
float Sievert = 0;
int COUNTS[10];
int t = 0;
void setup() {
Serial.begin(115200);
display.begin();
display.fillScreen(BLACK);
float Battery = analogRead(A3);
float BattPerc = 100 * (Battery / 770);
display.setCursor(4,4);
display.setTextSize(2);
display.setTextColor(MAGENTA);
display.println("Battery");
display.setCursor(4,24);
display.print(int(BattPerc)); display.print("."); display.print(int((10*BattPerc)-(10*int(BattPerc)))); display.print(" %");
delay(3000);
display.fillScreen(BLACK);
for (int x = 0; x < 10; x++) COUNTS[x] = 0;
attachInterrupt(0, IMPULSE, FALLING); // D2/INT0 外部中断
display.drawRect(0,0,96,64,WHITE);
display.setCursor(4,4);
display.setTextColor(RED);
display.setTextSize(2);
display.print("CPM");
display.setCursor(50,4);
display.setTextSize(1);
display.print("10 sec");
display.setCursor(50,12);
display.print("window");
display.setCursor(4,38);
display.setTextSize(1);
display.setTextColor(GREEN);
display.print("uSv/hr");
display.drawRect(0,48,96,16,YELLOW);
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > LOGtime) {
previousMillis = currentMillis;
COUNTS[t] = Counts;
TenSecCPM = 0;
for (int y = 0; y < 10; y++) TenSecCPM += COUNTS[y];
AVGCPM = 6 * TenSecCPM;
t++; if (t > 9) t = 0;
display.fillRect(4,20,90,17,BLACK);
display.setCursor(4,20);
display.setTextColor(RED);
display.setTextSize(2);
display.println(AVGCPM);
display.fillRect(45,38,50,10,BLACK);
display.setCursor(45,38);
display.setTextColor(GREEN);
display.setTextSize(1);
Sievert = AVGCPM / 151.0;
units = int(Sievert);
tens = int((10*Sievert) - (10*units));
hundreds = int((100*Sievert) - (100*units) - (10*tens));
thousands = int((1000*Sievert) - (1000*units) - (100*tens) - (10*hundreds));
display.print(units); display.print("."); display.print(tens); display.print(hundreds); display.println(thousands);
display.fillRect(1,49,94,14,BLACK);
display.fillRect(1,49,Counts,14,RED);
Counts = 0;
}
}
void IMPULSE() {
Counts++;
}
核心是外部中断服务程序 IMPULSE():GM 管触发使 INT 引脚拉低,连接 Arduino Nano D2 (INT0),attachInterrupt(0, IMPULSE, FALLING) 触发中断,Counts++。每秒更新显示:滑动窗口累加过去 10 秒计数 ×6 得 CPM,除以 151 得 μSv/h,实时 CPS 以红条显示。完整代码约 150 行,注释详尽。
代码文件
Geiger_Counter.ino 已含上方完整代码。
3D 打印文件
- OLED 显示屏外壳:
display_geiger_rev04_v2_bsLHSDvTUU.3mf - 主机外壳(上下盖):
geiger_counter_housing_top__bottom_rev04_v1_cvCIwkO13j.obj/ STL 文件
原理图
电子系统连接图见项目附件。
制造工艺
- 复古 Numitron 管时钟:Arduino Nano 驱动,低温可靠省电
- Arduino Nano 与 MPU-6050 构建实时陀螺仪游戏
- Arduino 数字骰子:LCD 显示随机点数的电子骰子
- DIY Arduino USB 游戏手柄 — 自制高性能游戏手柄
- 智能存钱罐:Arduino Nano 控制硬币识别器实现余额显示
- 自制 16×8 LED 矩阵俄罗斯方块游戏机:Arduino Nano + 74HC595 驱动
- Arduino + HC-05 蓝牙控制 LED:MIT App Inventor 手机 App 开发全攻略
- Arduino Nano + 摇杆控制双步进电机:Visuino 图形化教程
- 使用 Arduino、高压升压模块和 20x4 LCD 自制盖革-米勒计数器
- Pixel Chaser:Arduino Nano 单键 NeoPixel 追逐小游戏
- 自制高精度测距轮:Arduino Nano + 旋转编码器 + 1602 LCD
- 基于 Arduino、Yaler 与 IFTTT 构建 Web 化 IoT 仪表盘