Счётчик Гейгера и Народный мониторинг

Иногда хочется знать не только температуру или влажность на улице, но и измерять уровень радиации. Для этого можно использовать счётчик Гейгера. В этой статье я опубликовал код для отправки данных на Народный мониторинг.


Для этого одним из пользователей Narodmon был куплен кит для сборки счётчика Гейгера и отдельно трубка СБМ-20. Ссылка на магазин: Geiger Counter Radiation Detector DIY Kit Arduino Compatible ver. 3.00 w/o GM Tube. Фото с того же сайта:
И мной уже была написана прошивка к Arduino для работы с данным устройством. На самом деле работает всё довольно просто. Трубка периодически пробивается при пролёте ионизирующей частицы через объём газа. И тем чаще, чем выше уровень излучения. Схема воспринимает эти разряды как импульсы, которые отправляются на ардуину. В коде происходит подсчёт количества импульсов за определённое время, высчитывается количество импульсов за минуту. И полученное число умножается на константу, зависящую от типа трубки (для СБМ-20 = 0,57). В результате получаем уровень излучения в мкР/ч.
Внимание!
Трубка в счётчике Гейгера питается высоким напряжением (> 300 В). Будьте осторожны!

Если найдутся тестеры, то объединю этот код с кодом метеостанции.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
// Скетч для Arduino для отправки данных о радиационном фоне на Народный мониторинг
// Версия 1.0 (15.02.2016)
//
// Автор: Гладышев Дмитрий (2016)
//
// Часть кода взята здесь:
// http://www.rhelectronics.net/store/radiation-detector-geiger-counter-diy-kit-second-edition.html
//
 
/*
The standard unit of radiation dosing in an area is the micro-Sievert/hour (uSv/hr).
For this tube, multiply its CPM by 0.0057 to get the equivalent uSv/hr radiation level.
*/
 
#include <SPI.h>
#include <Ethernet.h>
 
bool Debug = false; //режим отладки
 
//********************************************************************************************
byte mac[] = { 0xDE, 0xAD, 0xBE, 0x00, 0x00, 0x00 }; //MAC-адрес Arduino
#define GEIGER_PIN       2      // пин для подключения счётчика Гейгера
#define GEIGER_INT       0      // прерывание для счётчика Гейгера
#define postingInterval  600000 // интервал между отправками данных в миллисекундах (10 минут)
#define LOG_PERIOD 15000        //Logging period in milliseconds, recommended value 15000-60000.
//********************************************************************************************
#define MAX_PERIOD 60000    //Maximum logging period
IPAddress server(94,19,113,221); // IP сервера народного мониторинга
char macbuf[13];
 
EthernetClient client;
 
unsigned long lastConnectionTime = 0;           // время последней передачи данных
boolean lastConnected = false;                  // состояние подключения
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
char replyBuffer[160];                          // буфер для отправки
 
volatile unsigned long counts;             //variable for GM Tube events
unsigned long cpm;                 //variable for CPM
unsigned long mkrh;
unsigned int multiplier;             //variable for calculation CPM in this sketch
unsigned long previousMillis;      //variable for time measurement
 
void tube_impulse(){               //procedure for capturing events from Geiger Kit
  counts++;
}
 
void setup() {
 
  if (Debug)
  {
    Serial.begin(9600);
  }
 
  // Пробуем подключиться по Ethernet до тех пор пока это не удастся
  do 
  {
    delay(1000);
  } while (Ethernet.begin(mac) == 0);
 
  lastConnectionTime = millis()-postingInterval+15000; //первое соединение через 15 секунд после запуска
 
  counts = 0;
  cpm = 0;
  multiplier = MAX_PERIOD / LOG_PERIOD;      //calculating multiplier, depend on your log period
 
  pinMode(GEIGER_PIN, INPUT);                // set pin INT0 input for capturing GM Tube events
  digitalWrite(GEIGER_PIN, HIGH);            // turn on internal pullup resistors, solder C-INT on the PCB
 
}
 
void loop()
{
  //Если вдруг нам случайно приходят откуда-то какие-то данные,
  //то просто читаем их и игнорируем, чтобы очистить буфер
  if (client.available())
  {
    client.read();
  }
 
  if (!client.connected() && lastConnected)
  {
    if (Debug)
    {
      Serial.println();
      Serial.println("disconnecting.");
    }
    client.stop();
  }
 
  //если не подключены и прошло определённое время, то делаем замер,
  //переподключаемся и отправляем данные
  if (!client.connected() && (millis() - lastConnectionTime > postingInterval)) 
  {
    //формирование HTTP-запроса
    memset(replyBuffer, 0, sizeof(replyBuffer));
    strcpy(replyBuffer,"ID=");
 
    memset(macbuf, 0, sizeof(macbuf));
    //Конвертируем MAC-адрес
    for (int k=0; k<6; k++)
    {
      int b1=mac[k]/16;
      int b2=mac[k]%16;
      char c1[2],c2[2];
 
      if (b1>9) c1[0]=(char)(b1-10)+'A';
      else c1[0] = (char)(b1) + '0';
      if (b2>9) c2[0]=(char)(b2-10)+'A';
      else c2[0] = (char)(b2) + '0';
 
      c1[1]='\0';
      c2[1]='\0';
 
      strcat(macbuf,c1);
      strcat(macbuf,c2);
    }
    strcat(replyBuffer, macbuf);
 
    unsigned long currentMillis = millis();
 
    counts = 0;
    attachInterrupt(GEIGER_INT, tube_impulse, FALLING);  //define external interrupts
    while (millis()-currentMillis < LOG_PERIOD)
    {
    }
    detachInterrupt(GEIGER_INT);
    cpm = counts * multiplier;
    mkrh = round((float)cpm*0.57); // CPM --> мкР/ч
 
    char temp[8];
    itoa(mkrh, temp);
    strcat(replyBuffer, "&");
    strcat(replyBuffer, "R1=");
    strcat(replyBuffer, temp);
 
    strcat(replyBuffer,'\0');
 
    if (Debug)
    {
      Serial.println(replyBuffer);
      Serial.print("Content-Length: ");
      Serial.println(len(replyBuffer));
    }
 
    //отправляем запрос
    httpRequest();
  }
  //храним последнее состояние подключения
  lastConnected = client.connected();
}
 
//Функция отправки данных
void httpRequest() 
{
  if (client.connect(server, 80))
  {
    if (Debug)
    {
      Serial.println("connecting...");
    }
    // отправляем HTTP POST запрос:
    client.println("POST http://narodmon.ru/post.php HTTP/1.0");
    client.println("Host: narodmon.ru");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.print("Content-Length: ");
    client.println(len(replyBuffer));
    client.println();
    client.println(replyBuffer);
    client.println();
 
    lastConnectionTime = millis();
  } 
  else
  {
    if (Debug)
    {
      Serial.println("connection failed");
      Serial.println("disconnecting.");
    }
    client.stop();
  }
}
 
//Функция определения длины строки
int len(char *buf)
{
  int i=0; 
  do
  {
    i++;
  } while (buf[i]!='\0');
  return i;
}
 
//Функция переворота строки
void reverse(char s[])
{
  int i, j;
  char c;
 
  for (i = 0, j = strlen(s)-1; i<j; i++, j--) 
  {
    c = s[i];
    s[i] = s[j];
    s[j] = c;
  }
}
 
//Функция конвертирования числа в символьный массив
void itoa(int n, char s[])
{
  int i, sign;
 
  if ((sign = n) < 0)       /* записываем знак */
    n = -n;                 /* делаем n положительным числом */
  i = 0;
  do {                      /* генерируем цифры в обратном порядке */
    s[i++] = n % 10 + '0';  /* берем следующую цифру */
  } while ((n /= 10) > 0);  /* удаляем */
  if (sign < 0)
    s[i++] = '-';
  s[i] = '\0';
  reverse(s);
}
В строках 21-25:
mac — MAC-адрес Arduino. Это ваш уникальный идентификатор на сайте народного мониторинга. Поэтому для защиты от совпадений рекомендую использовать MAC-адрес вашего компьютера/роутера/телефона с изменённым последним байтом (чтобы не было коллизии внутри локальной сети).
GEIGER_PIN — пин подключения счётчика. Не изменяйте, если не знаете что делаете.
GEIGER_INT — номер прерывания. Не изменяйте, если не знаете что делаете.
postingInterval — интервал отправки данных в миллисекундах.
LOG_PERIOD — время замера в миллисекундах. Максимум 60000 мс.
Файлы
Скачать скетч (6.73 KB)

Работа проверялась с Arduino IDE v1.0.5-r2.

Предупреждение!
Автор не несёт ответственности за возможную порчу оборудования. Всё, что вы делаете — вы делаете на свой страх и риск!

Похожие записи:

7 Комментарии “Счётчик Гейгера и Народный мониторинг

  1. классно
    обязательно попробую.

    А можно еще количество осадков определять?
    Есть китайские осадкомеры, которые по 433 передают данные с улицы на домашний модуль.
    Вот бы его к Ардуино прикрутить и на Народный мониторинг передавать….

    Температура, давление и влажность — все уже реализовано много раз.
    А осадки — нет!

  2. Здравствуйте! Спасибо за интересный проект! А нет ли возможности сделать хорошие фото этой платы счётчика? Хочется повторить.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *