Go Down

Topic: Geiger counter datalogger w/RTC for Chernobyl (Read 1 time) previous topic - next topic

UrbexArch

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: [Select]
// 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);
}

liudr

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: [Select]

  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: [Select]

  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.

robtillaart


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: [Select]

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

Rob Tillaart

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

UrbexArch

#3
Jul 07, 2011, 08:30 pm Last Edit: Jul 07, 2011, 08:33 pm by UrbexArch Reason: 1
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: [Select]
#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: [Select]
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!

bHogan

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

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

UrbexArch

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

robtillaart


change myFile.println() in  myFile.print():  The ln stands for newline...
Code: [Select]
  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: [Select]

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

Rob Tillaart

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

UrbexArch

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!

robtillaart

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

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

Go Up