Pages: [1]   Go Down
Author Topic: Geiger counter datalogger w/RTC for Chernobyl  (Read 1281 times)
0 Members and 1 Guest are viewing this topic.
Berkeley, CA
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm trying to develop a radiation data logger with an RTC for an upcoming trip to Chernobyl.  I'm hoping to use it in conjunction with a GPS datalogger to map radiation hotspots.

Equipment:
UNO
Adafruit Data Logger Shield http://www.ladyada.net/make/logshield/design.html
GM-10 geiger counter http://www.blackcatsystems.com/GM/products/GM10GeigerCounter.html

Using this code from an earlier post by Radioactive: http://arduino.cc/forum/index.php/topic,54367.0.html
I'm able to log CPM but I can't figure out how to get the csv to include a field of RTC time.

I'm really new at this and any help would be greatly appreciated!

Code:
Code:
// Geiger Counter example

/* Adapted by Tracy Albert from programing for a frequecy counter by,
 Martin Nawrath KHM LAB3
 Kunsthochschule f¸r Medien Kˆln
 Academy of Media Arts
 http://www.khm.de
 http://interface.khm.de/index.php/labor/experimente/
 */
#include <FreqCounter.h>
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"

#define LOG_INTERVAL  1000 // mills between entries
#define CS 10
#define MOSI 11
#define MISO 12
#define SCK 13
#define redLEDpin 2
#define greenLEDpin 3

RTC_DS1307 RTC; // define the Real Time Clock object

///////////////////////////////////////////////////
//
// VARAIABLES
//
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;

char name[] = "GEIGER.CSV";

unsigned long frq = 0;
unsigned long cnt = 0;


///////////////////////////////////////////////////
//
// FUNCTIONS
//

// store error strings in flash to save RAM
#define error(s) error_P(PSTR(s))

void error_P(const char *str)
{
  PgmPrint("error: ");
  SerialPrintln_P(str);
  if (card.errorCode()) {
    PgmPrint("SD error: ");
    Serial.print(card.errorCode(), HEX);
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
     // red LED indicates error
  digitalWrite(redLEDpin, HIGH);
  }
  while(1);  // effectively STOP the sketch
}


void writeToFile(char *fileName, char *str)
{
  if (file.open(root, fileName, O_CREAT | O_APPEND | O_WRITE))
  {
    file.write((uint8_t *)str, strlen(str));
    file.close();
  }
}



unsigned long getFrequency()
{
  unsigned long freq = 0;

  FreqCounter::f_comp=10;               // Cal Value / Calibrate with professional Freq Counter
  FreqCounter::start(1000L);           // 1 sec Gate Time  L to force long.
  while (FreqCounter::f_ready == 0)
  {
    freq = FreqCounter::f_freq;
  }
  return freq;
}


///////////////////////////////////////////////////
//
// SETUP
//
void setup(void)
{
  Serial.begin(9600);
  Serial.println("Geiger Counter 0.1");

  // SD card error 1,ff fix.
  pinMode(CS, OUTPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(SCK, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(redLEDpin, OUTPUT);
  pinMode(greenLEDpin, OUTPUT);
 
  // init all for SD access.
  if (!card.init(true)) error("card.init");
  if (!volume.init(card)) error("volume.init");
  if (!root.openRoot(volume)) error("openRoot");

  Serial.println("Setup ready");
}


///////////////////////////////////////////////////
//
// LOOP - FOREVER
//
void loop()
{
    DateTime now;

  // delay for the amount of time we want between readings
  delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));
 
  digitalWrite(greenLEDpin, HIGH);

  // GET MEASUREMENT
  frq = getFrequency();

  // DISPLAY IT ON SERIAL
  Serial.print(cnt++);
  Serial.print("  cpm: ");
  Serial.println(frq);
 
  // fetch the time
  now = RTC.now();
  Serial.print(", ");
  Serial.print(now.year(), DEC);
  Serial.print("/");
  Serial.print(now.month(), DEC);
  Serial.print("/");
  Serial.print(now.day(), DEC);
  Serial.print(" ");
  Serial.print(now.hour(), DEC);
  Serial.print(":");
  Serial.print(now.minute(), DEC);
  Serial.print(":");
  Serial.print(now.second(), DEC);
 
  // WRITE TO FILE
  char buffer[32];
  // all fields comma separated so Excel can make a graph
  sprintf(buffer, "%ld,  cpm,  %ld, Hz \r\n", cnt, frq, now);

  writeToFile(name, buffer);
}
Logged

Central MN, USA
Offline Offline
Tesla Member
***
Karma: 72
Posts: 7171
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Safety first friend! You will need a commercial counter with you.

Regarding your question. I don't know either how to do a Geiger counter or SD card write but these three lines are very awfully close to what you want to do:

Code:
  char buffer[32];
  // all fields comma separated so Excel can make a graph
  sprintf(buffer, "%ld,  cpm,  %ld, Hz \r\n", cnt, frq, now);


Currently the sprintf is just formatting cnt and frg. But there is no formatting for "now". Plus, now is not a basic data type, you should use now.minute for instance instead of now. So try the following to see if it works.

Code:
  char buffer[64];
  // all fields comma separated so Excel can make a graph
  sprintf(buffer, "%ld,  cpm,  %ld, Hz %d minute \r\n", cnt, frq, now.minute);


If it works, just try expanding the code to include all date stuff you need.
Logged


Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


For your safety you should seriously consider to take a commercial radiationMeter.

For the arduino sketch I would change the structure of your main loop (because of safety).

main changes:
- It continuesly displays the value on serial => see an accurate reading any time (display and SD card are now decoupled
- it uses the LEDS to indicate the exceeding of a THRESHOLD value  // to be defined.
- it logs at fixed intervals AND if safety thresholds are exceeded
- it creates a new logfile every day. This is more robust than using one file.

Hopes this helps,



Code:
unsigned long lastLogTime = 0;
unsigned long lastDisplayTime = 0;

void loop()
{
  // GET MEASUREMENTS
  unsigned long frq = getFrequency();
  DateTime now = RTC.now();

  if (frq < THRESHOLD_SAFE)   // use the LEDS for warning !!
  {
   digitalWrite(greenLEDpin, HIGH);
   digitalWrite(redLEDpin, LOW);
  }
  else if (frq < THRESHOLD_WARNING)
  {
   digitalWrite(greenLEDpin, HIGH);
   digitalWrite(redLEDpin, HIGH);
  }
  else // SERIOUS RISK !!
  {
   digitalWrite(greenLEDpin, LOW);
   digitalWrite(redLEDpin, HIGH);
   // add a buzzer here  for when you are sleeping???
  }

  // DISPLAY MEASUREMENTS ON SERIAL
  if (millis() - lastDisplayTime > DISPLAY_INTERVAL)   // set this to e.g. 250 millis = 4x second
  {
    Serial.print(now.hour(), DEC);
    Serial.print(":");
    Serial.print(now.minute(), DEC);
    Serial.print(":");
    Serial.print(now.second(), DEC);
    Serial.print("   ");
    Serial.print(cnt++, DEC);
    Serial.print("  cpm.");
    Serial.print(frq);
    Serial.println("  hz. ");
    lastDisplayTime = millis();
  }

  // LOG EVERY INTERVAL OR IF FRQ IS TOO HIGH !!
  if ((millis() - lastLogTime > LOG_INTERVAL) || (frq > THRESHOLD_SAFE))
  {
    // WRITE TO FILE
    // fields comma separated so Excel can make a graph - structure: DATE, TIME, CNT, FREQ
    char buffer[64];
    sprintf(buffer, "%d-%d-%d, %d:%d:%d, %ld, %ld\r\n", now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second(), cnt, frq );

    char logFileName[24];
    sprintf(logFileName, "%04d%02d%02d.csv", now.year(), now.month(), now.day());

    writeToFile(logFileName, buffer);
    lastTime = millis();
  }
}

Can you post the schematics of your device?

Rob

 
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Berkeley, CA
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ah thanks for the help, I ended up pretty much completely redoing the code.  I've got it working but the .txt files are coming out strange.  I think using a string would work but I can't figure out how to get those to work.

Pictures of the device here (with case I milled for it): http://www.flickr.com/photos/aceshigh450/5819196351/

Schematic for the device:
http://www.flickr.com/photos/aceshigh450/5912525613/

And the new code:
Code:
#include <FreqCounter.h>  //FREQ
#include <Wire.h>         //For RTC
#include "RTClib.h"        //For RTC
RTC_DS1307 RTC;            //For RTC
#include <SD.h>            //For log
const int chipSelect = 10;
File myFile;

void setup() {

//Start Serial
  Serial.begin(57600);                    // connect to the serial port
  Serial.println("Frequency Counter");
  
//Start RTC
  Wire.begin();              
  RTC.begin();
  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");}
  if (RTC.isrunning()){
    Serial.println("RTC is running");}
    
//Check SD
  Serial.print("Initializing SD card...");
  pinMode(10, OUTPUT);
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    digitalWrite(2, HIGH);   // set the LED on
    return;
  }
  Serial.println("card initialized.");

//Prep File
  //file open
  myFile = SD.open("test.txt", FILE_WRITE);
  //write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("timestamp,date,time, cps,");
    //note consistant data structure here
    //timestamp, date, time, cps<frq>
   // close the file:
    myFile.close();
    Serial.println("ready.");
  }
 }
 
 
 
long int cpm;
long int frq;



void loop() {
 
 ///FREQ Counter components
    FreqCounter::f_comp= 10;    // Set compensation to 12
//////////////////////IMPORTANT CHANGE INTERVAL FOR READINGS HERE///////////////  
    FreqCounter::start(1000);   // Start counting with gatetime of 1000ms
    while (FreqCounter::f_ready == 0)         // wait until counter ready

    frq=FreqCounter::f_freq;            // read result
    Serial.print("cps:");
    Serial.println(frq);                // print result
  
 ///RTC components
    DateTime now = RTC.now();

    Serial.print(now.year(), DEC);  
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.print(':');
    Serial.print("gmt");
    Serial.println();
    Serial.println();
 
 ///SAFETY
 // use the LEDS for warning !!
 //2CPS=117CPM=1.02µSv/hr=24.65µSv/dy=9000µSv/yr 9mSv/yr Airline safe dose
 
if (frq <= 11)  //11Cps=649cpm=5.70µSv/hr=136.98µSv/dy=50000µSv/yr 50mSv/yr Nuclear Worker Limit
  {
   digitalWrite(3, HIGH);
   digitalWrite(2, LOW);
  }
  else if (frq >11 && frq <= 22) //22Cps=1305cpm=11.415µSv/hr=273.96µSv/dy=100000µSv/yr 100000mSv/yr Threshold for detectable cancer risk
  {
   digitalWrite(3, HIGH);
   digitalWrite(2, HIGH);
  }
  else if (frq > 22) //
  {
   digitalWrite(3, LOW);
   digitalWrite(2, HIGH);
  }
///2=RED 3=GREEN
 
 /// Logging
 
//file open
  myFile = SD.open("test.txt", FILE_WRITE);
  
  //write to it:
  if (myFile) {
    Serial.print("logging...");
    //note consistant data structure here
    //timestamp, date, time, cps<frq>
    myFile.println(now.unixtime());
    myFile.println(',');
    myFile.println(now.year(), DEC);  
    myFile.println('/');
    myFile.println(now.month(), DEC);
    myFile.println('/');
    myFile.println(now.day(), DEC);
    myFile.println(',');
    myFile.println(now.hour(), DEC);
    myFile.println(':');
    myFile.println(now.minute(), DEC);
    myFile.println(':');
    myFile.println(now.second(), DEC);
    myFile.println(':');
    myFile.println("gmt");
    myFile.println(',');
    myFile.println(frq);
   // close the file:
    myFile.close();
    Serial.println("done");
  }
 
}

I've included some safety features and the group I'm with will have a professional monitor.

Also an example of the .txt data I'm getting out:

Code:
timestamp,date,time, cps
1310058629
,
2011
/
7
/
7
,
17
:
10
:
29
:
gmt
,
0
1310058631
,
2011
/
7
/
7
,
17
:
10
:
31
:
gmt
,
0
1310058632
,
2011
/
7
/
7
,
17
:
10
:
32
:
gmt
,
0
Excel cant seem to wrap its head around the above (also I will hit the 65,000 row limit very quickly)
What I'm hoping for is something formated timestamp,date, time, cps
so 2011/xx/xx,xx:xx:xx:gmt, cps
Any tips would be greatly appreciated!
« Last Edit: July 07, 2011, 01:33:03 pm by UrbexArch » Logged

Denver
Offline Offline
God Member
*****
Karma: 20
Posts: 778
Inactive - PM
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

UberxArch
I have Geiger logging sketch for the Adafruit data logging shield, that you might find useful . . .
https://sites.google.com/site/diygeigercounter/logging-with-the-geiger-kit

It's not "Chernobyl certified", so take appropriate cautions with anything you will bring there.
John

Logged

"Data is not information, information is not knowledge, knowledge is not understanding, understanding is not wisdom."
~ Clifford Stoll

Berkeley, CA
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

John,
Thats really impressive work! I was considering doing a more integrated solution like that using the board itself then opted for the more simple one that I can have the logger isolated from the sensor.
Ya that sketch is intense, I guess what I'm trying to understand is how the string works, I can't get them to include the data I want in a usable format, I see you used the one from the logger example, I'm still lost...any tips?
Thanks
Bryan
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


change myFile.println() in  myFile.print():  The ln stands for newline...
Code:
  if (myFile) {
    Serial.print("logging...");
    //note consistant data structure here
    //timestamp, date, time, cps<frq>
    myFile.print(now.unixtime());
    myFile.print(',');
    myFile.print(now.year(), DEC); 
    myFile.print('/');
    myFile.print(now.month(), DEC);
    myFile.print('/');
    myFile.print(now.day(), DEC);
    myFile.print(',');
    myFile.print(now.hour(), DEC);
    myFile.print(':');
    myFile.print(now.minute(), DEC);
    myFile.print(':');
    myFile.print(now.second(), DEC);
    myFile.print(':');
    myFile.print("gmt");
    myFile.print(',');
    myFile.println(frq);
   // close the file:
    myFile.close();
    Serial.println("done");
  }

Alternative you could use sprintf() to get better formatted lines. (leading zero's etc)

Code:
char buffer[80];  // size can be adjusted of course
sprintf(buffer, " %ld, %04d/%02d/%02d, %02d:%02dd:%02d:gmt, %ld", now.unixtime(), now.year(), now.month(), now.day(), now.hour(), mow.minute(), now.second(), frq);
myFile.println(buffer);
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Berkeley, CA
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Wow this is great! Thanks so much for the help John and robtillaart.   I did a test today using the logger and my GPS unit looks promising. I'll post some data when I get back.
Thanks again!
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I'll post some data when I get back

Yes, do get back safely.  Chernobyl is a very nice enviroment in the visible spectrum  - saw a documentary last year, BBC??? amazing nature - but still radioactive!!
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Pages: [1]   Go Up
Jump to: