Geiger counter datalogger w/RTC for Chernobyl

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 Data-Logger Shield for Arduino
GM-10 geiger counter GM-10 Geiger Counter Radiation Detector and Software

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:

// 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);
}

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:

  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.

  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.

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,

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

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): radiation data logger | schematic here: www.flickr.com/photo… | Flickr

Schematic for the device:
Imgur

And the new 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:

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!

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

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

change myFile.println() in myFile.print(): The ln stands for newline...

  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)

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);

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!

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!!