Geiger counter Data logger project.

I am using an Uno with the SD shield as a stand alone data collection system.

The GM-10 is the actual Geiger counter or sensor, its readings compare with Background, a Cs-137 calibration source and Ra-226.

Its spending the night in my basement sniffing for Radon gas.

Here is the sketch.

// Geiger Counter Lib 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 <SdFat.h>
#include <SdFatUtil.h>

Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;
void setup (void);
unsigned long frq;
int cnt;
int pinLed=13

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

void writeCRLF(SdFile &f)
{
  f.write((uint8_t *)"\r\n", 2);
}
/*
 * Write an unsigned number to a file
 */
void writeNumber(SdFile &f, uint32_t n)
{
  uint8_t buf[10];
  uint8_t i = 0;do {
    i++;
    buf[sizeof(buf) - i] = n%10 + '0';
    n /= 10;
  } while (n);
  f.write(&buf[sizeof(buf) - i], i);
}
/*
 * Write a string to a file
 */
void writeString(SdFile &f, char *str)
{
  uint8_t n;
  for (n = 0; str[n]; n++);
  f.write((uint8_t *)str, n);
}
void setup(void){
  pinMode(pinLed, OUTPUT);

  Serial.begin(9600);        // connect to the serial port
  Serial.println("Geiger Counter");
 
  // initialize the SD card
  if (!card.init()) error("card.init");
  
  // initialize a FAT volume
  if (!volume.init(card)) error("volume.init");
  
  // open the root directory
  if (!root.openRoot(volume)) error("openRoot");

  
}
  void loop(){
// create a new file
  char name[] = "WRITE00.TXT";
  // wait if any serial is going on
  FreqCounter::f_comp=10;   // Cal Value / Calibrate with professional Freq Counter
  FreqCounter::start(60000);  // 1 minuit Gate Time
  while (FreqCounter::f_ready == 0) 
   frq=FreqCounter::f_freq;
  Serial.print(cnt++);
  Serial.print("  cpm: ");
  Serial.println(frq);
    delay(100);
  digitalWrite(pinLed,!digitalRead(pinLed));  // blink Led
 
//-----------------------------------------------------

  for (uint8_t i = 0; i< 1000; cnt++){
   name[5] = i/10 + '0';
   name[6] = i%10 + '0';
   if (file.open(root, name, O_CREAT | O_APPEND | O_WRITE)) break;
   
  if (!file.isOpen()) error ("file.create");}
  // write 100 line to file
  for (uint8_t i = 0; i < 100; i++){ 
    writeNumber(file, cnt);
    writeString(file, " cpm ");
    writeNumber(file, frq);
    writeCRLF(file);
  
  // close file and force write of all data to the SD 

card
  file.close();}
 
}

Thanks for sharing,

Please modify your post using the # button to wrap the code in [ code] [ /code] tags.

A few comments:

  1. The logging will be faster if you first build up a string to write to the SD card

char buffer[32];
sprintf(buffer, "%ld, cpm, %ld, Hz \r\n", cnt, frq); // all fields comma separated so Excel can make a graph
f.write(file, buffer, strlen(buffer)); // just one call

  1. Now all the code in within loop(), think you should try to split it up in several functions to keep the overview.

  2. Use CTRL-t in the IDE to get your indentation right.

What are the results of the measurements?

Thanks I will play with that Modification. Here are some results from the testing.

1 cpm 0
2 cpm 65547
_______I never understood why this second reading is so high since I added the SD card, it even shows up on the serial port? Below is background.
3 cpm 13
4 cpm 15
5 cpm 10
6 cpm 12
7 cpm 15
8 cpm 19
9 cpm 23
10 cpm 12
11 cpm 17
___________CS-137
12 cpm 906
13 cpm 1556
14 cpm 1553
15 cpm 1538
16 cpm 1564
17 cpm 1556
18 cpm 1605
19 cpm 1658
____________Ra-226
20 cpm 46176
21 cpm 59645
22 cpm 59445
23 cpm 59567
24 cpm 59568
25 cpm 59635
26 cpm 59442
27 cpm 59571
28 cpm 59367
29 cpm 59702
30 cpm 59676
31 cpm 59793
32 cpm 59596
33 cpm 59646
34 cpm 59574
35 cpm 59787
36 cpm 59526
37 cpm 59785
38 cpm 59736
39 cpm 23244
40 cpm 61100
41 cpm 61226
42 cpm 61106
43 cpm 61167
44 cpm 61249
45 cpm 61391
46 cpm 61335
47 cpm 61031
48 cpm 61063
49 cpm 61159
50 cpm 61209
51 cpm 61509
52 cpm 62050
53 cpm 61994
54 cpm 62242
55 cpm 62030
56 cpm 62029
57 cpm 61984
58 cpm 61961
59 cpm 62127
60 cpm 42656
________Background
61 cpm 48
cpm 60
63 cpm 24
64 cpm 15
65 cpm 18
66 cpm 16
67 cpm 10
68 cpm 12
69 cpm 15
70 cpm 16
71 cpm 13
72 cpm 18
73 cpm 11
74 cpm 8
75 cpm 19
76 cpm 17
77 cpm 12
78 cpm 13
79 cpm 16
80 cpm 22
81 cpm 14
82 cpm 9
83 cpm 20
84 cpm 16
85 cpm 12
86 cpm 9
87 cpm 14
__________Cs-137 Again
88 cpm 529
89 cpm 1608
90 cpm 1663
91 cpm 1655
92 cpm 1685
93 cpm 1608
94 cpm 1637
95 cpm 1536
96 cpm 1594
97 cpm 1733
98 cpm 1608
99 cpm 1586
100 cpm 1717
101 cpm 1568
102 cpm 1618
103 cpm 1608
104 cpm 1556
105 cpm 1588
106 cpm 1623
107 cpm 1648
108 cpm 1672
109 cpm 1638
110 cpm 1636
111 cpm 1606
112 cpm 1574
113 cpm 1584
114 cpm 1614
115 cpm 1664
116 cpm 1608
117 cpm 1688
118 cpm 1565
119 cpm 1646
120 cpm 1629
121 cpm 1600
122 cpm 1615
123 cpm 1630
124 cpm 1627
125 cpm 1609
126 cpm 1681
127 cpm 1597
128 cpm 1669
129 cpm 1671
130 cpm 1642
131 cpm 1641
132 cpm 1565
133 cpm 1543
134 cpm 1596
135 cpm 1566
136 cpm 1590
137 cpm 1609
138 cpm 1523
139 cpm 1624
140 cpm 1598
141 cpm 1623
142 cpm 1618
143 cpm 1709
144 cpm 1626
145 cpm 1670
146 cpm 1588
147 cpm 1611
148 cpm 1669
149 cpm 1541
150 cpm 1611
151 cpm 1605
152 cpm 1593
153 cpm 1631
154 cpm 1645
155 cpm 1571
156 cpm 1582
157 cpm 1607
158 cpm 1602
159 cpm 1578
160 cpm 1677
161 cpm 1644
162 cpm 1661
163 cpm 1582
164 cpm 1564
165 cpm 1642
[/table]

Instead of the delay(100) in the loop() you might do some extra measurements and do some averaging, although the samples seem quite stable. The first reading when holding the sample Radon/ cesium can be lower as they approach the Geiger counter.

About averaging: - Arduino Playground - RunningAverage

  1. The logging will be faster if you first build up a string to write to the SD card

char buffer[32];
sprintf(buffer, "%ld, cpm, %ld, Hz \r\n", cnt, frq); // all fields comma separated so Excel can make a graph
f.write(file, buffer, strlen(buffer)); // just one call

  1. Now all the code in within loop(), think you should try to split it up in several functions to keep the overview.

  2. Use CTRL-t in the IDE to get your indentation right.

What are the results of the measurements?

I keep getting the error.

No matching function for call to 'SD file::write(SDFile&, Char&, Size_t)

I am kind of at a loss as to what to do next? Any help is appreciated.

I keep getting the error.

Can you explain in more detail what the error is? So far I only saw that the second reading was quite high. Is this repeatable?

Do you have an URL to the freqCounter library?

Rob

Sorry for the mess here. The previous sketch worked fine with the exception that it wrote the data to a .txt file, I want to write the data in a .cvs file for export to excel.

Here is the entire sketch that fails to complie.

// Geiger Counter Lib 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 <SdFat.h>
#include <SdFatUtil.h>
#include <f>

//SD card error 1,ff fix also in void setup.
#define CS 8
#define MOSI 11
#define MISO 12
#define SCK 13

Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;
SdFile f;
// macros to use PSTR
#define putstring(str) SerialPrint_P(PSTR(str))
#define putstring_nl(str) SerialPrintln_P(PSTR(str))






void setup (void);
unsigned long frq;

int cnt;
int pinLed=13;
// create a new file
char name[] = "LOGGER00.CSV";


char buffer[32];

// 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);
  }
  while(1);
}
/*
 * Write CR LF to a file
 */
void writeCRLF(SdFile &f)
{
  f.write((uint8_t *)"\r\n", 2);
}
/*
 * Write an unsigned number to a file
 */
void writeNumber(SdFile &f, uint32_t n)
{
  uint8_t buf[10];
  uint8_t i = 0;
  do {
    i++;
    buf[sizeof(buf) - i] = n%10 + '0';
    n /= 10;
  } 
  while (n);
  f.write(&buf[sizeof(buf) - i], i);
}
/*
 * Write a string to a file
 */
void writeString(SdFile &f, char *str)
{
  uint8_t n;
  for (n = 0; str[n]; n++);
  f.write((uint8_t *)str, n);
}
void setup(void){
  pinMode(pinLed, OUTPUT);
  //and in void setupSD card error 1,ff fix.
  pinMode(CS, OUTPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(SCK, OUTPUT);
  pinMode(10, OUTPUT);

  Serial.begin(9600);        // connect to the serial port
  //Serial.println("Geiger Counter");
  //writeString(file, " Geiger Counter ");

  //Repair for SD card errors.
  if (!card.init(true)) error("card.init");

  // initialize the SD card
  //if (!card.init()) error("card.init");

  // initialize a FAT volume
  if (!volume.init(card)) error("volume.init");

  // open the root directory
  if (!root.openRoot(volume)) error("openRoot");

  char name[] = "LOGGER00.CSV";
  for (uint8_t i = 0; i < 100; i++) {
    name[6] = i/10 + '0';
    name[7] = i%10 + '0';
    if (file.open(&root, name, O_CREAT | O_EXCL | O_WRITE)) break;
  }

}
void loop(){
  // create a new file
  //char name[] = "WRITE00.TXT";
  // wait if any serial is going on
  FreqCounter::f_comp=10;   // Cal Value / Calibrate with professional Freq Counter
  FreqCounter::start(60000);  // 1 minuit Gate Time
  while (FreqCounter::f_ready == 0) 
    frq=FreqCounter::f_freq;
  Serial.print(cnt++),
  Serial.print("  cpm: "),
  Serial.println(frq),
  delay(100);
  digitalWrite(pinLed,!digitalRead(pinLed));  // blink Led


    //-----------------------------------------------------------------------------------------------  

  for (uint8_t i = 0; i< 100; cnt++){
    name[5] = i/10 + '0';
    name[6] = i%10 + '0';
  }
  //for (uint8_t; i=0; i<100; i++);
  //write 100 line to file
  for (uint8_t i = 0; i < 100; i++)


    char buffer[32];
  {
    sprintf(buffer, "%ld,  cpm,  %ld, Hz \r\n", cnt, frq);   // all fields comma separated so Excel can make a graph
    //f.write((uint8_t *)"\r\n", 2);
    f.write(file,buffer[32], strlen(buffer));
  }    // just one call

  //if (file.open(root, name, O_CREAT | O_APPEND | O_WRITE))break;

  if (!file.isOpen()) error ("file.create");

  //if (uint8_t f = 0; f < 100; f++){  




  //if (file.open(root, name, O_CREAT | O_APPEND | O_WRITE))break;
  // writeString(file, " Geiger Counter "); 
  // close file and force write of all data to the SD card
  //file.close(); 
  //}    
  //writeNumber(file, cnt);
  //writeString(file, " cpm ");
  //writeNumber(file, frq);
  //writeCRLF(file);



  // close file and force write of all data to the SD card
  file.close();
}

The error is on this line near the end of the sketch.

f.write(file,buffer[32], strlen(buffer));

The error given is.

(ERROR)No matching function for call to 'SD file::write(SDFile&, Char&, Size_t)(ERROR)***

I hope this helps? I am use to Qbasic and line numbers.

The error is on this line near the end of the sketch.

f.write(file,buffer[32], strlen(buffer));

Please post the error message next time.

use - f.write(buffer, strlen(buffer));

I noticed that there is quite some strange logic in the application wrt opening /closing files, comments and for loops. I assume you did a copy/paste from an example without really understanding what the example did, resulting in a lot of code in your sketch I think you just don't need.

Advise: Take paper and pencil, make a flow diagram what steps the sketch has to do and then rewrite the sketch from scratch , without copy and paste.

If you can't get it to work, let us know.

Q: What SD card (shield ?) are you using?

Back to my own projects,
Rob

use - f.write(buffer, strlen(buffer));

Yeah thats where I started and I still got the same error!

This is the error I am getting!

""No matching function for call to 'SD file::write(SDFile&, Char&, Size_t)""

Its a sparkfun SD Shield and my on arduino did not like it at first, That is why I needed to add.

//SD card error 1,ff fix also in void setup.
#define CS 8
#define MOSI 11
#define MISO 12
#define SCK 13

And

//and in void setupSD card error 1,ff fix.
  pinMode(CS, OUTPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(SCK, OUTPUT);
  pinMode(10, OUTPUT);

To even get it to write a text file to the SD shield.

This sketch runs flawlessly for days at a time.

// Geiger Counter Lib 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 <SdFat.h>
#include <SdFatUtil.h>

//SD card error 1,ff fix also in void setup.
#define CS 8
#define MOSI 11
#define MISO 12
#define SCK 13

Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;
void setup (void);
unsigned long frq;
int cnt;
int pinLed=13;
// create a new file
  char name[] = "WRITE00.TXT";




// 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);
  }
  while(1);
}
/*
 * Write CR LF to a file
 */
void writeCRLF(SdFile &f)
{
  f.write((uint8_t *)"\r\n", 2);
}
/*
 * Write an unsigned number to a file
 */
void writeNumber(SdFile &f, uint32_t n)
{
  uint8_t buf[10];
  uint8_t i = 0;
  do {
    i++;
    buf[sizeof(buf) - i] = n%10 + '0';
    n /= 10;
  } while (n);
  f.write(&buf[sizeof(buf) - i], i);
}
/*
 * Write a string to a file
 */
void writeString(SdFile &f, char *str)
{
  uint8_t n;
  for (n = 0; str[n]; n++);
  f.write((uint8_t *)str, n);
}
void setup(void){
  pinMode(pinLed, OUTPUT);
  //and in void setup…SD card error 1,ff fix.
pinMode(CS, OUTPUT);
pinMode(MOSI, OUTPUT);
pinMode(MISO, INPUT);
pinMode(SCK, OUTPUT);
pinMode(10, OUTPUT);

  Serial.begin(9600);        // connect to the serial port
  Serial.println("Geiger Counter");
  writeString(file, " Geiger Counter ");
  
  //Repair for SD card errors.
 if (!card.init(true)) error("card.init");
 
  // initialize the SD card
  //if (!card.init()) error("card.init");
  
  // initialize a FAT volume
  if (!volume.init(card)) error("volume.init");
  
  // open the root directory
  if (!root.openRoot(volume)) error("openRoot");
  
  
if (file.open(root, name, O_CREAT | O_APPEND | O_WRITE))// break;
 writeString(file, " Geiger Counter "); 
 // close file and force write of all data to the SD card
  file.close();
}
  void loop(){
// create a new file
  //char name[] = "WRITE00.TXT";
  // wait if any serial is going on
  FreqCounter::f_comp=10;   // Cal Value / Calibrate with professional Freq Counter
  FreqCounter::start(60000);  // 1 minuit Gate Time
  while (FreqCounter::f_ready == 0) 
   frq=FreqCounter::f_freq;
  Serial.print(cnt++);
  Serial.print("  cpm: ");
  Serial.println(frq);
    delay(100);
  digitalWrite(pinLed,!digitalRead(pinLed));  // blink Led
  
 
//-----------------------------------------------------------------------------------------------  

  for (uint8_t i = 0; i< 1000; cnt++){
   name[5] = i/10 + '0';
   name[6] = i%10 + '0';
   if (file.open(root, name, O_CREAT | O_APPEND | O_WRITE)) break;
   
  if (!file.isOpen()) error ("file.create");}
  // write 100 line to file
  for (uint8_t i = 0; i < 100; i++){ 
    writeNumber(file, cnt),
    writeString(file, " cpm "),
    writeNumber(file, frq),
    writeCRLF(file),
  
  // close file and force write of all data to the SD card
  file.close();}
 
}

But it writes to a .txt file.

I am very new at this and I know there is many aspects I do not understand yet, But I am learning.

use - f.write(buffer, strlen(buffer));

thinks it needs a typecast, like in writestring().

==> f.write((uint8_t*)buffer, strlen(buffer));

for generating a csv file you just need to need to have the filename right:

char name[] = "WRITE00.TXT"; ==> char name[] = "WRITE00.CSV";

I'll dive into the code later.

int pinLed=13;
You want to use pin 13 for the LED while it is already in use by the SPI bus ==> #define SCK 13

You need to use a free pin or remove this code for now

----- update -----

  • rewrote your code so it compiled (WIN7, Arduino 21)
  • split the main loop a bit in separate functions.
  • (most) things not needed removed.

Give it a try (cannot test it as I have not your SD-card or sensor).

// 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 <SdFat.h>
#include <SdFatUtil.h>


#define CS 8
#define MOSI 11
#define MISO 12
#define SCK 13


///////////////////////////////////////////////////
//
// 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);
  }
  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(60000L);           // 1 minuit 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);

  // 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()
{
  // GET MEASUREMENT
  frq = getFrequency();

  // DISPLAY IT ON SERIAL
  Serial.print(cnt++);
  Serial.print("  cpm: ");
  Serial.println(frq);

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

  writeToFile(name, buffer);
}

Hi!

Please, take a look to the new tutorial related to Radiation Sensor Board for Arduino launched by Libelium in Cooking Hacks. You can improve the code using the SD to storage the data received from this board.

Stay tuned!

thanks for the link above doomy. :slight_smile: very helpful for my project. :slight_smile: