Buat Penghitung Geiger Tangan dengan Arduino Nano
Komponen dan Perlengkapan
- Arduino Nano R3 — 1 unit
- Kit Penghitung Geiger Siap Pakai — 1 unit
- Layar OLED warna 0.96" 96 * 64 — 1 unit
- Papan charger micro USB — 1 unit
- Baterai Li-ion Rechargeable 18650 3.7v 4000mAh Terlindungi — 1 unit
- Transistor BC547 — 1 unit
- BUZZER -12MM — 1 unit
- Resistor 1k ohm — 1 unit
Alat dan Mesin yang Diperlukan
Aplikasi dan Layanan Online
- Autodesk Fusion 360
- Arduino IDE
- CURA
- ClickCharts
- EasyEDA
- Fritzing
Tentang Proyek Ini
Proyek ini dimulai setelah saya membeli kit penghitung Geiger siap pakai dari Banggood.
Idealnya adalah untuk meletakkan kit ini dalam perabot 3D-printed sehingga set penghitung Geiger lengkap yang berfungsi dapat ditangan. Hasil akhir ditunjukkan di bawah ini:
Langkah 1: Desain Sistem
Desain penghitung Geiger tangan ditunjukkan dalam diagram di bawah ini:
Penghitung Geiger dilengkapi dengan layar OLED warna 0,96 inci, yang memberitahukan pengguna tentang CPM yang diukur (ukuran laju deteksi peristiwa ionisasi per menit) serta (dihitung) setara dosis dalam µSv/hr menggunakan faktor sederhana 151 yang dapat ditemukan dalam literatur untuk jenis tabung Geiger-Müller (GM) yang digunakan.
Lihat juga Wikipedia: https://en.wikipedia.org/wiki/Counts_per_minute
Sebenarnya CPM yang ditampilkan adalah hasil perhitungan hitungan untuk satu menit, dengan mengukur hitungan per detik (CPS) dan menyimpan pengukuran ini dalam array yang mencakup periode sepuluh detik terakhir. Total jumlah hitungan selama periode 10 detik terakhir dikalikan 6 untuk mendapatkan nilai CPM.
Jumlah hitungan selama detik terakhir digunakan untuk menampilkan jumlah pengukuran saat ini melalui diagram batang pada layar OLED. Ini berguna dalam kasus laju hitungan tinggi, atau ketika terjadi perubahan cepat laju hitungan ketika penghitung tangan digerakkan di atas sumber radiasi.
Penghitung Geiger didayai oleh baterai Li-ion tipe 18650, yang dapat diisi daya melalui plug micro-USB. Port USB Arduino Nano juga dapat diakses untuk perubahan perangkat lunak. Buzer tambahan terhubung ke papan penghitung Geiger untuk meningkatkan suara ionisasi dalam tabung GM.
Semua elektronika untuk penghitung Geiger dibangun dalam perabot 3D-printed:
Layar OLED ditempatkan dalam kotak terpisah di atas penghitung Geiger:
Versi yang sepenuhnya dirakit:
Langkah 2: Membuat Rangkaian Penghitung Geiger
Berikut adalah bahan yang digunakan:
- Arduino NANO 1
- Kit Penghitung Geiger 1
- Layar OLED warna 0.96" 96 * 64 1
- Papan Charger Micro USB Baterai 18650 1
- Baterai Li-ion Rechargeable 18650 3.7v 4000mAh Terlindungi 1
- Transistor BC547 1
- BUZZER -12MM 1
- Resistor 1k Ohm 1
Desain Elektronik
Desain elektronik dari kit penghitung Geiger ditunjukkan dalam diagram rangkaian berikut:
Diagram rangkaian dari setup lengkap Penghitung Geiger adalah sebagai berikut:
Daya 5V disediakan dari baterai Li-Ion rechargeable yang ditempatkan di Papan Charger Micro USB. Tegangan 3,3 V untuk layar OLED diambil dari papan ini.
Setup papan roti yang digunakan untuk pengujian dan pembangunan perangkat lunak dengan ARDUINO IDE, ditunjukkan dalam gambar berikut:
Pemasangan Mekanik dan Elektrik
Pemasangan semua bagian mekanik dan elektronik ditunjukkan dalam gambar di bawah ini:
Perhatikan bahwa penghitung Geiger tangan tidak memiliki koneksi kabel.
Untuk pengisian daya baterai Li-ion 3,7V ada pembuka terpisah dalam perabot untuk (sementara) menghubungkan plug micro USB.
Koneksi mini USB tambahan tersedia untuk pembaruan perangkat lunak Arduino Nano.
Langkah 3: Desain Perangkat Lunak
Diagram alur berikut menunjukkan desain perangkat lunak umum dari Penghitung Geiger:
Tampilan pada layar OLED 0,96", adalah:
Sketsa Arduino lengkap tercantum di bawah ini:
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1331.h>
#include <SPI.h>
//Koneksi untuk layar OLED
#define sclk 13 //SCL (kabel biru)
#define mosi 11 //SDA (kabel putih)
#define cs 10 //CS (kabel abu-abu)
#define rst 9 //RES (kabel hijau)
#define dc 8 //DC (kabel kuning)
#define LOGtime 1000 //Waktu Logging dalam milidetik (1 detik)
#define Minute 60000 //periode 1 menit untuk menghitung nilai CPM
#define show endWrite
#define clear() fillScreen(0)
// Definisi Warna
#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; //variabel yang berisi jumlah peristiwa Tabung GM dalam LOGtime
unsigned long previousMillis= 0; //variabel untuk menyimpan waktu sebelumnya
int AVGCPM = 0; //variabel yang berisi rata-rata floating jumlah hitungan selama periode jendela bergerak tetap
int TenSecCPM = 0;
int units = 0;
int tens = 0;
int hundreds = 0;
int thousands = 0;
float Sievert = 0;
int COUNTS[10]; // array untuk menyimpan jumlah impuls yang diukur dalam 10 periode berturut-turut 1 detik
int t = 0;
////////////////////kode setup yang diikutinya, akan berjalan sekali setelah "Power On" atau setelah RESET///////////////////
void setup() {
Serial.begin(115200);
display.begin();
display.fillScreen(BLACK);
floatBattery = analogRead(A3); //(kabel oranye)
floatBattPerc = 100 * (Battery/770);
//Serial.print("battery value = "); Serial.println (Battery); Serial.print("battery percentage = "); Serial.println (BattPerc);
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++) { //masukkan semua data ke Array COUNTS ke 0 (Posisi Array berjalan dari 0 hingga 10;
COUNTS[x] = 0; //10 posisi yang mencakup periode 10 detik
}
attachInterrupt(0, IMPULSE, FALLING); //definisikan interrupt eksternal pada pin D2/INT0 untuk memulai rutinitas interrupt IMPULSE (kabel hijau)
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);
}////////////////////////kode loop yang diikutinya, akan berjalan berulang-ulang sampai "Power Off" atau RESET/////////
void loop()
{
unsignedlong currentMillis= millis();
if(currentMillis - previousMillis >LOGtime)
{
previousMillis = currentMillis;
COUNTS[t] = Counts;
for (int y = 0; y < 10 ; y++) { //tambahkan semua data di Array COUNTS bersama-sama
TenSecCPM = TenSecCPM + COUNTS[y]; //dan hitung rata-rata CPM bergulang selama periode 10 detik
}
AVGCPM = 6* TenSecCPM;
TenSecCPM = 0;
t++ ;
if (t > 9) { t = 0 ;}
//Serial.print ("COUNTS "); Serial.print(t);Serial.print (" = ");Serial.println (COUNTS[t]);
display.fillRect(4,20,90,17,BLACK); // hapus bidang nilai CPM pada layar
display.setCursor(4,20);
display.setTextColor(RED);
display.setTextSize(2);
display.println(AVGCPM);
//Serial.print ("AVGCPM = "); Serial.print(AVGCPM); //Serial.print (" CPM = "); Serial.println(CPM);
display.fillRect(45,38,50,10,BLACK); // hapus bidang nilai uSv/Hr pada layar
display.setCursor(45,38);
display.setTextColor(GREEN);
display.setTextSize(1);
Sievert = (AVGCPM /151.0) ; //Serial.print (" Sievert = ");Serial.println (Sievert);
units = int (Sievert); //Serial.print ("units = "); Serial.println(units);
tens = int ((10*Sievert) - (10*units)); //Serial.print ("tens = "); Serial.println(tens);
hundreds = int ((100*Sievert) - (100*units) - (10* tens)); //Serial.print ("hundreds = "); Serial.println(hundreds);
thousands = int ((1000*Sievert) - (1000*units) - (100*tens) - (10*hundreds)); //Serial.print ("thousands ="); Serial.println (thousands);
display.print (units); display.print("."); display.print (tens); display.print (hundreds);display.println (thousands);
display.fillRect(1,49,94,14,BLACK); // hapus bidang indikator CPM pada layar
display.fillRect(1,49,Counts,14,RED); //isi bidang indikator CPM pada layar
Counts = 0;
}
}//////////////////END ofLOOP////////////////////////////////////
/////////////////////////////////Berikutnya adalah Fungsi untuk menghitung jumlah impuls dari kit Penghitung Geiger
void IMPULSE()
{
Counts++;
}
Bagian terpenting dari sketsa adalah fungsi interrupt yang dipanggil ketika impuls pada tabung GM dari Penghitung Geiger diukur yang memicu output INT dari Penghitung Geiger (dengan membuatnya LOW untuk waktu singkat). Sinyal INT terhubung ke pin D2 (pin interrupt eksternal INT0 dari Arduino Nano):
attachInterrupt(0, IMPULSE, FALLING);
Sinyal INT akan memulai rutinitas interrupt IMPULSE () untuk menambah Counts sebesar 1:
void IMPULSE() {Counts++ ; }
Setelah lewatnya 1000 milidetik:
- integer Counts dikembalikan ke 0
- array COUNTS [ ] diisi dengan jumlah hitungan yang diukur selama 1000 milidetik terakhir
- total jumlah hitungan selama 10 detik terakhir dihitung dengan menambahkan semua angka dari array COUNTS [ ] dan dikalikan 6 untuk menampilkan nilai CPM pada layar.
- setara dosis yang diekspresikan dalam µSv/hr dihitung dengan pembagian nilai CPM dengan 151 (nilai yang ditemukan dalam literatur).
- Pada layar OLED warna, sebuah bar merah ditampilkan berdasarkan nilai Counts dalam detik terakhir, sehingga sebenarnya menampilkan nilai CPS (Counts Per Second)
Sketsa ARDUINO lengkap untuk Penghitung Geiger terdiri dari sekitar 150 baris kode. Daftar lengkap disertakan sebagai bagian dari tutorial ini, kode ARDUINO (lihat bab 9) disediakan dengan banyak komentar.
Kode
Geiger_Counter.inoArduino
Sketsa ARDUINO untuk Penghitung Geiger yang berjalan pada Arduino Nano:
/********* Proyek ini telah dikembangkan dan diproduksi oleh Pierre Pennings (Desember 2019), Proyek ini tentang membuat Penghitung Geiger Tangan menggunakan kit Penghitung Geiger siap pakai, dalam detektor radiasi tangan yang dicetak 3D. Kit terhubung ke Arduino Nano yang menghitung jumlah impuls dari tabung Geiger/Muller selama periode 10 detik dan kemudian menampilkan rata-rata CPM (Counts Per Minute) pada layar OLED warna 96*64. Nilai CPM yang diukur juga ditampilkan sebagai mikro Sievert per Jam (dengan faktor konversi sederhana 151) Layar OLED juga menampilkan jumlah impuls yang diukur saat ini (per detik) dan menampilkan pengukuran sebagai bar merah yang bergerak pada layar. Perabot yang dicetak 3D juga berisi baterai 18650-Ion Lithium (dapat diisi ulang) yang menyediakan daya 5V untuk Arduino Nano serta kit Penghitung Geiger dan 3,3V untuk layar OLED. Saklar power-on dan beeper eksternal melengkapi detektor. Saat menyala, tingkat pengisian baterai 18650 ditampilkan pada layar warna. Kode ini dilisensikan di bawah lisensi GPL3+. *********/ #include <Adafruit_GFX.h> #include <Adafruit_SSD1331.h> #include <SPI.h> //Koneksi untuk layar OLED #define sclk 13 //SCL (kabel biru) #define mosi 11 //SDA (kabel putih) #define cs 10 //CS (kabel abu-abu) #define rst 9 //RES (kabel hijau) #define dc 8 //DC (kabel kuning) #define LOGtime 1000 //Waktu Logging dalam milidetik (1 detik) #define Minute 60000 //periode 1 menit untuk menghitung nilai CPM #define show endWrite #define clear() fillScreen(0) // Definisi Warna #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; //variabel yang berisi jumlah peristiwa Tabung GM dalam LOGtime unsigned long previousMillis = 0; //variabel untuk menyimpan waktu sebelumnya int AVGCPM = 0; //variabel yang berisi rata-rata floating jumlah hitungan selama periode jendela bergerak tetap int TenSecCPM = 0; int units = 0; int tens = 0; int hundreds = 0; int thousands = 0; float Sievert = 0; int COUNTS[10]; // array untuk menyimpan jumlah impuls yang diukur dalam 10 periode berturut-turut 1 detik int t = 0; //////////////////kode setup yang diikutinya, akan berjalan sekali setelah "Power On" atau setelah RESET/////////////////// void setup() { Serial.begin(115200); display.begin(); display.fillScreen(BLACK); float Battery = analogRead(A3); //(kabel oranye) float BattPerc = 100 * (Battery/770); //Serial.print ("battery value = "); Serial.println (Battery); Serial.print ("battery percentage = "); Serial.println (BattPerc); 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++) { //masukkan semua data ke Array COUNTS ke 0 (Posisi Array berjalan dari 0 hingga 10; COUNTS[x] = 0; //10 posisi yang mencakup periode 10 detik } attachInterrupt(0, IMPULSE, FALLING); //definisikan interrupt eksternal pada pin D2/INT0 untuk memulai rutinitas interrupt IMPULSE (kabel hijau) 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); } ////////////////////////kode loop yang diikutinya, akan berjalan berulang-ulang sampai "Power Off" atau RESET///////// void loop() { unsigned long currentMillis = millis(); if(currentMillis - previousMillis > LOGtime) { previousMillis = currentMillis; COUNTS[t] = Counts; for (int y = 0; y < 10 ; y++) { //tambahkan semua data di Array COUNTS bersama-sama TenSecCPM = TenSecCPM + COUNTS[y]; //dan hitung rata-rata CPM bergulang selama periode 10 detik } AVGCPM = 6* TenSecCPM; TenSecCPM = 0; t++ ; if (t > 9) { t = 0 ;} //Serial.print ("COUNTS "); Serial.print(t); Serial.print (" = ");Serial.println (COUNTS[t]); display.fillRect(4,20,90,17,BLACK); // hapus bidang nilai CPM pada layar display.setCursor(4,20); display.setTextColor(RED); display.setTextSize(2); display.println(AVGCPM); //Serial.print ("AVGCPM = "); Serial.print (AVGCPM); //Serial.print (" CPM = "); Serial.println (CPM); display.fillRect(45,38,50,10,BLACK); // hapus bidang nilai uSv/Hr pada layar display.setCursor(45,38); display.setTextColor(GREEN); display.setTextSize(1); Sievert = (AVGCPM /151.0) ; //Serial.print (" Sievert = "); Serial.println (Sievert); units = int (Sievert); //Serial.print ("units = "); Serial.println (units); tens = int ((10*Sievert) - (10*units)); //Serial.print ("tens = "); Serial.println (tens); hundreds = int ((100*Sievert) - (100*units) - (10* tens)); //Serial.print ("hundreds = "); Serial.println (hundreds); thousands = int ((1000*Sievert) - (1000*units) - (100*tens) - (10*hundreds)); //Serial.print ("thousands = "); Serial.println (thousands); display.print (units); display.print("."); display.print (tens); display.print (hundreds); display.println (thousands); display.fillRect(1,49,94,14,BLACK); // hapus bidang indikator CPM pada layar display.fillRect(1,49,Counts,14,RED); // isi bidang indikator CPM pada layar Counts = 0; } } //////////////////END of LOOP//////////////////////////////////// /////////////////////////////////Berikutnya adalah Fungsi untuk menghitung jumlah impuls dari kit Penghitung Geiger void IMPULSE() { Counts++; }
Bagian dan Kotak Pelindung Kustom
Perabot yang dicetak 3D untuk layar OLED 0,96”
display_geiger_rev04_v2_bsLHSDvTUU.3mfhousing yang dibuat dengan Fusion 360, terdiri dari bagian atas dan bawah:
geiger_counter_housing_top__bottom_rev04_v1_cvCIwkO13j.objFile stl 3D
Skematik
Diagram ini menunjukkan pengaturan elektronik: