Pagina 1 di 1

Geiger Counter for Arduino and Raspberry Pi to radmon.org

Messaggio da leggereInviato: 23/01/2019, 19:41
da root
Immagine
Immagine
Immagine
Immagine

NOTE: the geiger tube J305β is UV light and alfa ray sensitive, to avoid false readings you need to completely cover it with some black electrical tape,
eventually put a thin layer of copper sheet to protect it from EMI.

This device is compatible with many tubes working from 350V to 1000V

tube chosen: J305β Geiger Tube

Specifications:
Manufacturer: North Optic
Radiation Detection: β, γ
Length: 111mm
Diameter: 11mm
Recommended Voltage: 350V
Plateau Voltage: 360-440V
Sensitivy γ ( 60 Co): 65cps/(µR/s)
Sensitivy γ (equivalent Sievert): 108cpm / (µSv/h)
Max cpm: 30000
cps/mR/h: 18
cpm/m/h: 1080
cpm/µSv/h: 123.147092360319
Factor: 0.00812037037037

suggested H.T. tube supply circuit from manifacturer:
[img ]http://49v.com/asterisk/software/raspberry/J305HT.jpg[/img]

Tutorial and product page:

https://www.cooking-hacks.com/documenta ... i-tutorial

This device does not use serial communication to read measurement data!

----------------------------------------------------------------------------------------------------------------------

My Arduino code to measure uSv/h, send it to stdout and to activate LCD display and bargraph

Prerequisites: arduPi library for Raspberry

measure.c
Codice: Seleziona tutto
/*
 *  ------Geiger Tube board (Arduino Code) Example--------
 *
 *  Explanation: This example shows how to get the signal from the Geiger Tube
 *  in Arduino, we use one of the Arduino interrupt pins (PIN2).
 *  We count the time (ms) between two pulses of the Geiger tube.
 *
 *  Copyright (C) 2011 Libelium Comunicaciones Distribuidas S.L.
 *  http://www.libelium.com
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  Version:      0.3
 *  Design:      Marcos Yarza, David Gascon
 *  Implementation:   Marcos Yarza
 *
 *  Version     0.4
 *              20140420 by circulosmeos for RPi compatibility
 *              circulosmeos.wordpress.com
 *
 *  modified by P.M. Lovisolo Italy - http://forum.49v.com
 */

// include the arduPi library code:
#include "arduPi.h"

// include the LCD library code:
#include "LiquidCrystal.h"

// Threshold values for the led bar
#define TH1 75
#define TH2 150
#define TH3 250
#define TH4 400
#define TH5 600

// define geiger tube Conversion factor (cpm * conversion factor  = μSv/h)

// for J305By geiger tube
//#define CONV_FACTOR 0.00812

// for SBM-20 geiger tube (1/361)
#define CONV_FACTOR 0.00277

// Variables
int ledArray [] = {10,11,12,13,9};
int geiger_input = 2;
long count = 0;
long countPerMinute = 0;
long timePrevious = 0;
long timePreviousMeassure = 0;
long countPrevious = 0;
float radiationValue = 0.0;

void ledVar(int value);
void countPulse();

void setup(LiquidCrystal *lcd){
  pinMode(geiger_input, INPUT);
  digitalWrite(geiger_input,HIGH);
  for (int i=0;i<5;i++){
    pinMode(ledArray[i],OUTPUT);
  }

  // test led array ON
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
  pinMode(11, OUTPUT);
  digitalWrite(11, HIGH);
  pinMode(12, OUTPUT);
  digitalWrite(12, HIGH);
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
  pinMode(14, OUTPUT);
  digitalWrite(14, HIGH);
  pinMode(15, OUTPUT);
  digitalWrite(15, HIGH);
  pinMode(9, OUTPUT);
  digitalWrite(9, HIGH);

  //set up the LCD\'s number of columns and rows:
  lcd->begin(16, 2);
  lcd->clear();
  lcd->setCursor(0, 0);
  lcd->print("Radiation Sensor");
  lcd->setCursor(0,1);
  lcd->print("Board - 2019 -");
  delay(3000);

  lcd->clear();
  lcd->setCursor(0, 0);
  lcd->print("Counts*minute");
  lcd->setCursor(0,1);
  lcd->print("microSv*hour");
  delay(3000);
  //for (int i=0;i<5;i++){
  //  delay(200);
  //  lcd->scrollDisplayLeft();
  //}
  //delay(500);

  lcd->clear();
  lcd->setCursor(0, 0);
  lcd->print("- www.49v.com -");
  lcd->setCursor(0,1);
  lcd->print(" P.M. Lovisolo ");
  delay(3000);

  //led array off
  pinMode(10, OUTPUT);
  digitalWrite(10, LOW);
  pinMode(11, OUTPUT);
  digitalWrite(11, LOW);
  pinMode(12, OUTPUT);
  digitalWrite(12, LOW);
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  pinMode(14, OUTPUT);
  digitalWrite(14, LOW);
  pinMode(15, OUTPUT);
  digitalWrite(15, LOW);
  pinMode(9, OUTPUT);
  digitalWrite(9, LOW);

  lcd->clear();
  lcd->setCursor(0, 0);
  lcd->print("CPM=");
  lcd->setCursor(4,0);
  lcd->print(6*count);
  lcd->setCursor(8,0);
  lcd->print("counts");
  lcd->setCursor(0,1);
  lcd->print(radiationValue);
  lcd->setCursor(7,1);
  lcd->print(" uSv/h");

  attachInterrupt(2,countPulse,FALLING);

}

void loop(LiquidCrystal *lcd){
  if (millis()-timePreviousMeassure > 60000){
    detachInterrupt(2);
    countPerMinute = 1*count;
    //countPerMinute = count/10;
    radiationValue = countPerMinute * CONV_FACTOR;
    timePreviousMeassure = millis();
    //Serial.print("cpm = ");
    //Serial.print(countPerMinute,DEC);
    //Serial.print(" - ");
    //Serial.print("uSv/h = ");
    //Serial.println(radiationValue,4);
    lcd->clear();
    lcd->setCursor(0, 0);
    lcd->print("CPM=");
    lcd->setCursor(4,0);
    lcd->print(countPerMinute);
    lcd->setCursor(8,0);
    lcd->print("counts");
    lcd->setCursor(0,1);
    lcd->print(radiationValue,4);
    lcd->print((int)radiationValue);
    lcd->setCursor(7,1);
    lcd->print(" uSv/h");

    //fprintf(stderr,"CPM ");
    //fprintf(stderr,"%d\n",countPerMinute);
    fprintf(stderr,"%f",radiationValue);
    fprintf(stderr," uSv/h\n");

    //led var setting
    if(countPerMinute <= TH1) ledVar(0);
    if((countPerMinute <= TH2)&&(countPerMinute>TH1)) ledVar(1);
    if((countPerMinute <= TH3)&&(countPerMinute>TH2)) ledVar(2);
    if((countPerMinute <= TH4)&&(countPerMinute>TH3)) ledVar(3);
    if((countPerMinute <= TH5)&&(countPerMinute>TH4)) ledVar(4);
    if(countPerMinute>TH5) ledVar(5);

    count = 0;

    attachInterrupt(2,countPulse,FALLING);

    delay (60000);

  }

}

void countPulse(){
  //detachInterrupt(2);
  count++;
  //while(digitalRead(2)==0){
  //}
  //attachInterrupt(2,countPulse,FALLING);
}

void ledVar(int value){
  if (value > 0){
    for(int i=0;i<=value;i++){
      digitalWrite(ledArray[i],HIGH);
    }
    for(int i=5;i>value;i--){
      digitalWrite(ledArray[i],LOW);
    }
  }
  else {
    for(int i=5;i>=0;i--){
      digitalWrite(ledArray[i],LOW);
    }
  }
}


int main (){

    // initialize the library with the numbers of the interface pins
    // AFTER WirePi has been initialized (!)
    LiquidCrystal lcd(3,4,5,6,7,8);

    setup(&lcd);

    while(1){
        loop(&lcd);
    }
    return (0);
}

Note:
modified for the SBM-20 tube, if you want to use the J305B tube, you need to comment-out the SBM-20 CONV_FACTOR section and remove comment in the J305 section this way:

Codice: Seleziona tutto
// for J305By geiger tube
#define CONV_FACTOR 0.00812
// for SBM-20 geiger tube (1/361)
//#define CONV_FACTOR 0.00277


compile the code for Raspberry:

Codice: Seleziona tutto
g++ -lrt -lpthread measure.c LiquidCrystal.cpp Print.cpp arduPi.cpp -o measure


setting permission to file:

Codice: Seleziona tutto
chmod 755 measure


to launch file from Raspberry console (test):

Codice: Seleziona tutto
sudo ./measure


My Raspberry scripts (all Bash):

prerequisites:
Codice: Seleziona tutto
sudo apt-get install bc


This is the main script I programmed to start measuring uSv/h, to display data on the LCD and to save measurements in a csv temporary file.
The csv file is regenerated (empty) at each reboot since I don't want a huge file and also because I use MySQL to store all data.
If you are to much worried about writing data too frequently to the internal SD card, you can use a ramdisk or an external USB drive.

print_rad2csv.sh
Codice: Seleziona tutto
#!/bin/bash
measure 2>&1 | awk '{ print strftime("%s %Y-%m-%d %H:%M:%S"), $0; fflush(); }'  | sed -e 's/\s\+/,/g;w /var/www/rad/readings.csv'

note: the awk part add unixtime, date and time, the sed part substitutes "spaces" with "commas" and writes the csv file,
unixtime (optional) will be used as a primary key in Mysql to avoid importing duplicates.

add print_rad2csv.sh to "/etc/rc.local" file:

Codice: Seleziona tutto
#!/bin/sh -e
#
# rc.local
#
/bin/sh /root/print_rad2csv.sh
#
exit 0


results:

/var/www/rad/readings.csv
Codice: Seleziona tutto
1548232110,2019-01-23,09:28:30,0.056840,uSv/h
1548232170,2019-01-23,09:29:30,0.073080,uSv/h
1548232290,2019-01-23,09:31:30,0.048720,uSv/h


radmon.sh
Codice: Seleziona tutto
#!/bin/bash

# L305By tube conversion factor from uSv/h to CPM (CPM = uSv/h * conv)
conv=123.14709
# read last value from csv file generated by my instrument
line="$(/usr/bin/tail -n 1 /var/www/rad/readings.csv | cut --complement -c  1-31 | cut --complement -c  9-14 | sed -e 's/,/ /g')"
# calculations to get CPM from uSv/h
#echo $line
line2="$(echo "$line*$conv" | bc)"
#echo $line2
line3="$(echo $line2 | awk '{print int($1+0.5)}')"
#echo  $line3
# send data to radmon.org
user="pilovis"
password="mypwd"
exec=`wget -O /dev/null "http://radmon.org/radmon.php?function=submit&user=$user&password=$password&value=$line3&unit=CPM"


send to radmon.org the last CPM reading every minute:

crontab -e
Codice: Seleziona tutto
*/1 * * * * /bin/sh /root/radmon.sh


Extra:
Import data into MySQL database:

import_csv2sql.sh
Codice: Seleziona tutto
#!/bin/bash
/usr/bin/mysql -upilovis -pmypwd --local_infile=1 data -e "LOAD DATA LOCAL INFILE '/var/www/rad/readings.csv' INTO TABLE letture_radiazioni FIELDS TERMINATED BY ',' enclosed by '\


MySQL db structure
Codice: Seleziona tutto
CREATE TABLE `letture_radiazioni` (
  `unix_time` bigint(20) NOT NULL,
  `date` date DEFAULT NULL,
  `time` time DEFAULT NULL,
  `value` decimal(10,6) DEFAULT NULL,
  `unit` text,
  PRIMARY KEY (`unix_time`),
  UNIQUE KEY `unix_time` (`unix_time`)


I'm planning to move from one reading for 6000 ms (one minute) to one reading for 30000 ms (30 minutes), to get more consistent data.

Re: Geiger Counter for Arduino and Raspberry Pi to radmon.or

Messaggio da leggereInviato: 23/01/2019, 21:16
da root
A very simple web page in HTML to show your data and graphs from radmon.org

Codice: Seleziona tutto
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<title>
</title>
<head>
<meta http-equiv="refresh" content="30" >
</head>
<body>
<font size="2">
<div align="center">
<p>
<i>this page auto refreshes every 30 seconds</i>
<p>
</font>
<font size="4">
<hr>
<b>- Current readings:</b>
<p>
<img src="http://www.radmon.org/radmon.php?function=cpmreading&user=pilovis"/> (Counts per minute)
<p>
<hr>
<p>
<center>
<form action="http://www.radmon.org/radmon.php?user=pilovis&function=graphtoday&refresh=true" method="post">
<input type="submit" value="Update graphs">
</form>
<br>
<img src="https://radmon.org/UserGraphs/pilovis/graphlasthour.png" alt="" />
<br>
<img src="https://radmon.org/UserGraphs/pilovis/graphtoday.png" />
<p>
<hr>
</center>
</font>
</body>
</html>


note: change "pilovis" with your username.

Re: Geiger Counter for Arduino and Raspberry Pi to radmon.or

Messaggio da leggereInviato: 23/01/2019, 21:42
da root
Next step will be to connect a GPS and a 3G USB dongles to this device, than put it in my car and start sending data/position 24 hours a day to a central database.

Geiger tube SBM-20 (russian)

Messaggio da leggereInviato: 24/01/2019, 8:18
da root
I also tested the SBM-20 tube on this device.

Conversion factor for SBM-20 tube.

Russian SBM-20
60Co 1/150 = 0.00664
226Ra 1/198 = 0.00504

Please note that conversion factor varies depending on the tube sensitivity at different isotopes, Cobalt60 and Radium226

Nevertheless, based on my testing compared to the local university lab readings, and based on what Libellum (the company that manufacture the kit) declares here:
http://www.libelium.com/wireless_sensor ... _counters/
the most appropriate value for SBM-20 tube whit this circuit seems to be 0.00277

Re: Geiger Counter for Arduino and Raspberry Pi to radmon.or

Messaggio da leggereInviato: 24/01/2019, 21:30
da root
If you want to use the SBM-20 geiger tube instead of the junky J305By default tube, you need to do a little modification on the radiation board:
the C2 capacitor of 1 uF (see image below) should be increased at about 2 uF to higher the H.T. from 370V to 400V to better supply the SBM-20 tube.
Actually the SBM-20 works even at 370V, but obviously 400V is better.

It's enough to solder in parallel to the existing C2 cap another electrolytic cap of 1 uF, be careful with the polarity, on SMD capacitor the line is the + (positive), in the ciclindrical standard capacitor the line is the - (negative).

Immagine

In case you would need 500V for another kind of tube, the capacitor should be increased up to 10 uF.

Re: Geiger Counter for Arduino and Raspberry Pi to radmon.or

Messaggio da leggereInviato: 28/01/2019, 4:23
da root
Sometime it may happen that the "measure" process involved in the CPM measurements could die, in that case you will notice "0" CPM readings for long time.
To avoid that I wrote the following two scripts that continuously check if the "measure" process is running and if not they can restart it.

geiger-check.sh
Codice: Seleziona tutto
#!/bin/bash

# Check if "measure" process is running, if not launch a script
# -x flag only match processes whose name (or command line if -f is
# specified) exactly match the pattern.
while [ 1 ]
do
if pgrep -x "measure" > /dev/null
then
    echo "Running" > /dev/null
else
    echo "Stopped" > /dev/null
    /bin/sh /root/restart-geiger.sh
fi
/bin/sleep 30
done


restart-geiger.sh
Codice: Seleziona tutto
#!/bin/bash
#
# kill measure process if running.
/bin/kill $(ps aux | grep 'printout-html.sh' | /usr/bin/awk '{print $2}')
/bin/sleep 1
# restart CPM reading processes
/bin/sh /root/print_rad2csv.sh &

Re: Geiger Counter for Arduino and Raspberry Pi to radmon.or

Messaggio da leggereInviato: 30/01/2019, 16:26
da root
Just to improve the system and get notification every time the CPM reading goes above a certain limit.

I choosed to get notification by XMPP since I have my own personal XMPP server, but you can easily change the code and get notification by SMS or/and by email.

To install a simple XMMP client on Raspberry do the following:

Codice: Seleziona tutto
sudo apt-get install sendxmpp


then create config file for sendxmpp:

Codice: Seleziona tutto
echo "me@myjabberserver.com mypassword" >> ~/.sendxmpprc

note: change "me@myjabberserver.com" and "mypassword" with yours credentials

Bash code modified (see above):
Codice: Seleziona tutto
#!/bin/bash
# send data to radmon.org and send notification for alarm state
#
# SBM-20 tube conversion factor from uSv/h to CPM
conv=361
# read last value from csv file generated by the instrument
line="$(/usr/bin/tail -n 1 /tmp/readings.csv | cut --complement -c  1-31 | cut --complement -c  9-14 | sed -e 's/,/ /g')"
# calculations to get CPM from uSv/h
#echo $line
line2="$(echo "$line*$conv" | bc)"
#echo $line2
line3="$(echo $line2 | awk '{print int($1+0.5)}')"
#echo  $line3
# send data to radmon.org
user="my_radmon_username"
password="mypasswd"
exec=`wget -O /dev/null "http://radmon.org/radmon.php?function=submit&user=$user&password=$password&value=$line3&unit=CPM"`
/bin/sleep 5
##### alarm section #####
# notify alarm by XMPP if CPM > 75
alarm=75
if [ $line3 -gt $alarm ];
then
echo "Alarm CPM > "$line3 | sendxmpp -s hello me@myjabberserver.com
else
    echo "everything is normal" > /dev/null 2>&1;
fi;