安価な中華ガイガーカウンターをIoT化(放射線測定マップの作成 Ⅰ)

# 3種類のガイガーカウンター

いくつか買ってみました。


![IMG_20231021_101846.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/1181f46d-c8f0-2659-dc37-941c7aef7c94.jpeg)

型番はBR-9C、BR-9B BR-6

![IMG_20231021_113212.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/4c3d71ac-5cf0-54e9-9e14-afb4715c644c.jpeg)

- BR-6  白いもの
  - ガイガーカウンター機能 
  - 電池2本
  - Taobao で 169元 で入手
- BR-9B  灰色
  - ガイガーカウンター機能 
  - 電池3本
  - Taobao で 198元 で入手
- BR-9C  黄色
  - ガイガーカウンター機能 と 電磁界測定機能
  - 電池3本
  - Taobao で 298元 で入手
   
中身です。

![IMG_20231021_100624.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/4f412b98-4d68-d2bd-0c51-26ac6be3707e.jpeg)

BR-6 は大きいので大きなガイガー管を使っているのかと思いましたが
![IMG_20231021_100711.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/2b28c273-f6b7-8735-e05a-c48f5c6a3165.jpeg)

同じものを使っているぽい?

![IMG_20231021_101915.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/4e898f9c-789f-37a6-17bc-c51a78587f44.jpeg)

# ターゲット

今回は、BR-9B を使って IoT化することにしてみました。


![IMG_20231019_232918.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/58b6e242-5dec-ff3b-5874-b943a630b718.jpeg)

# 内部構成


回路図に起してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/cb89492d-b01f-e5b6-1a8d-7e3b75af26db.png)

ここの「Radiation Detect」から信号を取り出します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/f08a25b4-9b6a-6dc0-2749-75aaf37f09f9.png)

検出パルスは100μSでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/ae01411b-ae20-064e-0eeb-9ea5bbc5d59e.png)

以下のように作戦をたてます

- このパルスをマイコンで取得する
- マイコンは内部で使用するものではなく、別個にマイコンを追加する
- 既存のスイッチ操作、画面表示の変更は行わない
- IoTのために マイコンとしてESP32を使用する




# IoT化しよう

用意するもの

- BR-9B
- ジャンパーケーブル
- ESP32DevkitV1
![IMG_20231021_110036.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/584ec884-828c-6a9e-da1d-f513bc086546.jpeg)



まず、ESP32DevKitV1 の ENスイッチを基板ごと削り取ります。
![IMG_20231021_105140.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/aa7d2f01-1e2b-e836-f92d-6fb97fd75b97.jpeg)

注意、プルアップ抵抗は温存しておく必要があります。
![IMG_20231021_105201.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/bd8cb61c-7b4d-e477-32bc-daa18fa2e938.jpeg)

裏側のピンも片側一列除去しておきます。写真では8ピン残してますが、後でブザーと干渉したのでもっと取ったほうがいいかも。

![IMG_20231021_105227.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/90aaaa9a-885a-3c60-5a16-e9b212dcf2d1.jpeg)

筐体に穴を開けて
![IMG_20231021_105245.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/162a218c-434f-348e-bc8d-33272d1589ec.jpeg)

内部に固定します。今回はホットボンドを使って固定しました。
![IMG_20231021_110416.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/75baab44-d603-bf0e-0894-ff5e13595138.jpeg)

写真のようにジャンパーを配線します。

![IMG_20231021_111906.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/64b9879c-fa4d-3bde-f0f0-a97dacdf1e3d.jpeg)

赤の線は R22 に。これで元々のUSBコネクタ給電と並列になります。
![IMG_20231021_111650.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/3e7a5a61-510c-9b00-0b8e-e7cfcc189377.jpeg)
黄色の線は R4,T3,T2がつながっているいずれかへ。
![IMG_20231021_111658.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/b594e76c-0983-d602-eaf2-8f9603395859.jpeg)
ジャンパーをVIN,GND、GPIOにつなぎます。GPIO は今回GPIO27に接続しました。
![IMG_20231021_111720.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/8ae96ad4-97a4-cc22-9ee9-885504fbd76a.jpeg)


閉じます。ガイガー管に配線が接触しないように注意して。
![IMG_20231021_111932.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/892772b5-f540-6e24-f788-8b8246f038dc.jpeg)

動作したところ

![IMG_20231019_232918.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/58b6e242-5dec-ff3b-5874-b943a630b718.jpeg)


# ソフトウェア

## 動作テスト

まずは、単純なところから。
```
int count;
void setup() {
  Serial.begin(115200);
  pinMode(27, INPUT);

}

void loop() {
   int check=digitalRead(27);
   if ( 0 == check ) {
     count=count+1;
     Serial.println(count);
     delayMicroseconds(200);
   }
}
```
シリアルモニターで確認

```
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:8896
load:0x40080400,len:5816
entry 0x400806ac
1
2
3
4
5
6
7

```
うまく取れているようです。
なお、検出時のウェイトで 200μ秒にしていますが、100μ秒だとダブルカウントすることがあったので実験的に調整した値です。

## WiFi に接続
「ESP32 の WiFi 設定をアクセスポイント＋ Web サーバで行う」
https://qiita.com/nanbuwks/items/171d830c92617702ad7e

を使って、以下のようにしてみました。
```


#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <SPIFFS.h>
#include <FS.h>

const int WiFiSetPin = 16; // GPIO16  push with boot : AP mode on
const char* settings = "/wifi_settings.txt";
// AP mode WiFi Setting
const char* defaultWifiMode = "APMode";
const char* defaultSsid = "ORION";
const char* defaultEssKey = "11111111";
String wifiMode;
String ssid;
String essKey;
String channel;
char *sensorModeStr;
int WiFiSet = 0;  // 0 ... normal operation / 1 ... WiFi Setting Mode
int count;

WebServer server(80);

void handleRoot(){
  char temp[500];
  snprintf ( temp, 500,
"<html>\
<head>\
<title>Geiger Demo</title>\
<style>\
body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }\
</style>\
</head>\
<body>\
<h1> %d </h1>\
<br> :geiger count\
<hr> \
<a href=\"\/wifiInput\">wifi settings</a> \
</body>\
</html>",count);
  server.send ( 200, "text/html", temp );
}

void wifiInput() {
  String html = "";
  html += "<h1>WiFi Settings</h1>";
  html += "<form method='post' action='/wifiSet'>";
  html += "  <br>";
  html += "  <input type='text' name='essid' >ESSID<br>";
  html += "  <input type='text' name='key' >KEY(pass)<br>";
  html += "  <br>";
  html += "  <input type='submit'><br>";
  html += "</form>";
  server.send(200, "text/html", html);
}

void wifiSet() {
  String wifiMode = "clientMode";
  String setSsid = server.arg("essid");
  String setKey = server.arg("key");
  String setChannel = server.arg("0");

  File f = SPIFFS.open(settings, "w");
  f.println(wifiMode);
  f.println(setSsid);
  f.println(setKey);
  f.println(channel);
  f.close();

  String html = "";
  html += "<h1>WiFi Settings</h1>";
  html += "ESSID:" + setSsid + "<br>";
  html += "key(pass):" + setKey + "<br>";
  html += "<hr>";
  html += "<h1>Please Reset!</h1>";

  server.send(200, "text/html", html);
}

void handleNotFound(){
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  server.send(404, "text/plain", message);
}

void setup(void){

  pinMode(27, INPUT);
    
  Serial.begin(115200);
  Serial.println("");
  Serial.println("ESXAR Program Start");
  delay(1000);
  pinMode ( WiFiSetPin, INPUT_PULLUP );
  WiFiSet=digitalRead(WiFiSetPin);
//   init filesystem
  bool res = SPIFFS.begin(true); // FORMAT_SPIFFS_IF_FAILED
  if (!res) {
      Serial.println("SPIFFS.begin fail");
  }
  // check port
  int i;
  delay(1000);
  // settings read
  if ((1 ==digitalRead(WiFiSetPin)) && (1 ==WiFiSet)){
    WiFiSet=1; // boot on default  
  } else {
    WiFiSet=0;
  }
  // set file read
  File fp = SPIFFS.open(settings, "r");
  if (!fp) {
      Serial.println("open error");
  }
  wifiMode = fp.readStringUntil('\n'); // always "clientMode"
  ssid = fp.readStringUntil('\n');
  essKey = fp.readStringUntil('\n');
  channel = fp.readStringUntil('\n');  // no use
  Serial.print("wifiMode:");
  Serial.println(wifiMode);
  Serial.print("ssid:");
  Serial.println(ssid);
  Serial.print("essKey:");
  Serial.println(essKey);
  fp.close();
  wifiMode.trim();
  ssid.trim();
  essKey.trim();
  channel.trim();
  if ( 0 == wifiMode.compareTo("clientMode") ){
  } else if ( 0 == wifiMode.compareTo("APMode") ) {
  } else {
       Serial.print("SPIFFS data seems clash. Default load...");
       wifiMode=defaultWifiMode;
       ssid=defaultSsid;
       essKey=defaultEssKey;
       File f = SPIFFS.open(settings, "w");
       f.println(wifiMode);
       f.println(ssid);
       f.println(essKey);
       f.close();
  }
  if ( 0 == WiFiSet ) { 
    Serial.println("WiFiMode is ON");
    //----------WiFi access point---------
    Serial.println();
    Serial.print("Configuring access point...");
  /* You can remove the password parameter if you want the AP to be open. */
    if ( 0 == wifiMode.compareTo("APMode") ){
      WiFi.softAP(ssid.c_str(), essKey.c_str());
      IPAddress myIP = WiFi.softAPIP();
      Serial.print("AP IP address: ");
      Serial.println(myIP);
    }
    //----- WiFi client --------------
    if ( 0 == wifiMode.compareTo("clientMode") ){
      WiFi.begin(ssid.c_str(), essKey.c_str());
      Serial.println("");
    // Wait for connection
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println("");
      Serial.print("Connected to ");
      Serial.println(ssid);
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());
    }
  }
  if (1 == WiFiSet) { 
    Serial.println("WiFiMode default boot");
    //----------WiFi access point---------
    Serial.println();
    Serial.print("Configuring access point...");
  /* You can remove the password parameter if you want the AP to be open. */
    WiFi.softAP(defaultSsid, defaultEssKey);
    IPAddress myIP = WiFi.softAPIP();
    Serial.print("AP IP address: ");
    Serial.println(myIP);
  }
  server.on("/",     handleRoot);
  server.on("/wifiInput",  wifiInput);
  server.on("/wifiSet", wifiSet);
  server.onNotFound(handleNotFound);
  server.begin();
  Serial.println("HTTP server started");  
}




void loop() {
   int check=digitalRead(27);
   if ( 0 == check ) {
     count=count+1;
     Serial.println(count);
     delayMicroseconds(200);
   }
   // Handle incoming connections 
   server.handleClient();
}

```
これを起動すると、シリアルモニターからは以下のように出てきます。

```

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:8896
load:0x40080400,len:5816
entry 0x400806ac

ESXAR Program Start
wifiMode:APMode

ssid:ORION

essKey:11111111

WiFiMode is ON

Configuring access point...AP IP address: 192.168.4.1
HTTP server started
1
2
3
4
5
6
7
dhcps: send_offer>>udp_sendto result 0
8
9
10
```
PCやスマホから SSID ORION ESSKEY 11111111 でアクセスし、192.168.4.1にアクセスすると以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/98a2abc0-e10a-0f5f-0e3e-da5ee0a462db.png)
「wifi settings」を押すと以下の画面になるので 設置環境の WiFi 設定を入力し、登録します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/1e6d2b6d-aa69-3089-5c62-4b2c2373e474.png)

電源を抜いて、再度プラグインすると以下のように表示されてWiFi が登録され、IP アドレスが 192.168.0.
103 であることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/71b99e07-aad2-37b0-12be-2cd25ebca57d.png)

192.168.0.103 にアクセスすると以下のようにカウントが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/eaf50c79-b398-1947-ae65-09a5bce59c9f.png)


## ここから先

サーバにデータを保管したりするのは上記のプログラムを元にがんばってみよう！

# 問題点

- リセットがうまくいかないことがある。EN端子のコンデンサ除去が原因?
- 今回の改造では、ESP32 の動作はUSB電源時のみ
  - 電池動作 でも ESP32 を動かすのがいい?
  - 電池動作時は WiFi を切ってデータロガー的な動作をするとか。
- いちいち起動操作をしないといけない
  - スイッチ操作を ESP32 から介入する?
- BR-9シリーズは中国語表示
  - BR-6だと英語表示なのでこれを使った方がいい?
  - オリジナルのマイコンのファームウェアを書き換えることは?
  - STC8A8K64D4
- 筐体の工作
  - ESP32 の書き換えが必要でない場合は穴あけは必要ない
- WiFi の設定
  - 再設定はGPIO操作でスイッチ
  - いいやりかたがないかな?
  - DHCPクライアント時のIPアドレスを知るには?
    - mDNS を導入したい 








# 専用基板化の検討

- ESP32DEVKITV1 を使ってさほど苦労なくできるので必要性を感じない
- オリジナルの基板を完全置き換えするぐらいでないとメリットはない
- LCDコントローラがドライバ対応しているならワンチャン?

.
.
.

もしかしたら専用基板化して中身をESP32に変えたら、ここらへんぽい位置づけの汎用電子工作に使えるなにかになるかな?

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/095713a9-7063-be48-e849-fe47b42b32d7.png)