Hello, I want to make a radiation detector for a scientific paper. I have a ready assembled geiger muller detector kit from rhelectronics company. I want to connect the kit to the arduino board and to an I2C LCD display.I can't make the code. Can you help me?
This is the code, but it doesn't work and just gives me errors
#include <SPI.h>
#include "LiquidCrystal_I2C.h"
#define Conv_Fac 0.0057 // Conversion factor for CPM to uSV/h !!!For the SBM-20 Soviet G-M Tube!!!
LiquidCrystal_I2C lcd(0x27, 16, 2);
const long Period = 10000; // Time for which particles are counted in milliseconds, higher time is more accurate but taker longer
const float multiplier = 60000.0 / Period; // muultiplied by the count to esimate CPM
long count = 0;
long CPM = 0;
long lastmeasurement_time = 0;
float Dose = 0.0;
void setup() {
sei();
lcd.begin(16, 2);//initializes LCD
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Get out of here");//Start up message shown while first reading is being taken
lcd.setCursor(0, 1);
lcd.print("S.T.A.L.K.E.R.");
}
ISR(PCINT0_vect)
{
/*
When a radioactive particle passes though the G-M tube there will be a pulse from the Geiger counter's output pin
RH electronic's circuit sends HIGH LOW HIGH but this will work with LOW HIGH LOW
The pulse is counted and multiplied by the multiplier to estimate the count per minute
*/
byte pinState;
pinState = (PINB >> PINB4) & 1; // read PINB register to check state of pins
if (pinState > 0) { // will return 1 if high, only acts on rising edge
count++;
}
}
void loop() {
if (millis() - lastmeasurement_time > Period) {
CPM = multiplier * count; // Estimation of CPM
Dose = CPM * Conv_Fac; // Doesage is esimated by multiplying the CPM by your tube's conversion factor
lastmeasurement_time = millis();
lcd.clear(); //Displays your dosage and CPM
lcd.setCursor(0, 0);
lcd.print("CPM=");
lcd.setCursor(4, 0);
lcd.print(CPM);
lcd.setCursor(0, 1);
lcd.print(Dose, 4);
lcd.setCursor(6, 1);
lcd.print(" uSv/h");
count = 0;
}
}
#define LOG_PERIOD 15000 //Logging period in milliseconds, recommended value 15000-60000.
#define MAX_PERIOD 60000 //Maximum logging period
unsigned long counts; //variable for GM Tube events
unsigned long cpm; //variable for CPM
unsigned int multiplier; //variable for calculation CPM in this sketch
unsigned long previousMillis; //variable for time measurement
void tube_impulse(){ //procedure for capturing events from Geiger Kit
counts++;
}
void setup(){ //setup procedure
counts = 0;
cpm = 0;
multiplier = MAX_PERIOD / LOG_PERIOD; //calculating multiplier, depend on your log period
Serial.begin(9600); // start serial monitor
// uncommennt if you have time-out problem to connect with Radiation Logger
// delay(2000);
// Serial.write('0'); // sending zero to avoid connection time out with radiation logger
// delay(2000);
// Serial.write('0'); // sending zero to avoid connection time out with radiation logger
pinMode(2, INPUT); // set pin INT0 input for capturing GM Tube events
digitalWrite(2, HIGH); // turn on internal pullup resistors, solder C-INT on the PCB
attachInterrupt(0, tube_impulse, FALLING); //define external interrupts
}
void loop()
{ //main cycle
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > LOG_PERIOD){
previousMillis = currentMillis;
cpm = counts * multiplier;
Serial.print(cpm); // send cpm data to Radiation Logger
Serial.write(' '); // send null character to separate next data
counts = 0;
}
}
You are repeating the void setu(), the void loop() and the definition of some variables.
There can only be one void setup() and one void loop(), and you cannot repeatedly create global variables with the same name.
Like this? Still doesn't Work. Can you help me to fix it ?
#include <SPI.h>
#include "LiquidCrystal_I2C.h"
#define Conv_Fac 0.0057 // Conversion factor for CPM to uSV/h !!!For the SBM-20 Soviet G-M Tube!!!
LiquidCrystal_I2C lcd(0x27, 16, 2);
const long Period = 10000; // Time for which particles are counted in milliseconds, higher time is more accurate but taker longer
const float multiplier = 60000.0 / Period; // muultiplied by the count to esimate CPM
long count = 0;
long CPM = 0;
long lastmeasurement_time = 0;
float Dose = 0.0;
void setup() {
sei();
lcd.begin(16, 2);//initializes LCD
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Get out of here");//Start up message shown while first reading is being taken
lcd.setCursor(0, 1);
lcd.print("S.T.A.L.K.E.R.");
counts = 0;
cpm = 0;
multiplier = MAX_PERIOD / LOG_PERIOD; //calculating multiplier, depend on your log period
Serial.begin(9600); // start serial monitor
// uncommennt if you have time-out problem to connect with Radiation Logger
// delay(2000);
// Serial.write('0'); // sending zero to avoid connection time out with radiation logger
// delay(2000);
// Serial.write('0'); // sending zero to avoid connection time out with radiation logger
pinMode(2, INPUT); // set pin INT0 input for capturing GM Tube events
digitalWrite(2, HIGH); // turn on internal pullup resistors, solder C-INT on the PCB
attachInterrupt(0, tube_impulse, FALLING); //define external interrupts
}
}
ISR(PCINT0_vect)
{
/*
When a radioactive particle passes though the G-M tube there will be a pulse from the Geiger counter's output pin
RH electronic's circuit sends HIGH LOW HIGH but this will work with LOW HIGH LOW
The pulse is counted and multiplied by the multiplier to estimate the count per minute
*/
byte pinState;
pinState = (PINB >> PINB4) & 1; // read PINB register to check state of pins
if (pinState > 0) { // will return 1 if high, only acts on rising edge
count++;
}
}
void loop() {
if (millis() - lastmeasurement_time > Period) {
CPM = multiplier * count; // Estimation of CPM
Dose = CPM * Conv_Fac; // Doesage is esimated by multiplying the CPM by your tube's conversion factor
lastmeasurement_time = millis();
lcd.clear(); //Displays your dosage and CPM
lcd.setCursor(0, 0);
lcd.print("CPM=");
lcd.setCursor(4, 0);
lcd.print(CPM);
lcd.setCursor(0, 1);
lcd.print(Dose, 4);
lcd.setCursor(6, 1);
lcd.print(" uSv/h");
count = 0;
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > LOG_PERIOD){
previousMillis = currentMillis;
cpm = counts * multiplier;
Serial.print(cpm); // send cpm data to Radiation Logger
Serial.write(' '); // send null character to separate next data
counts = 0;
}
}
#define LOG_PERIOD 15000 //Logging period in milliseconds, recommended value 15000-60000.
#define MAX_PERIOD 60000 //Maximum logging period
unsigned long counts; //variable for GM Tube events
unsigned long cpm; //variable for CPM
unsigned int multiplier; //variable for calculation CPM in this sketch
unsigned long previousMillis; //variable for time measurement
void tube_impulse(){ //procedure for capturing events from Geiger Kit
counts++;
}
}
C:\Users\ioana\OneDrive\Desktop\COD_LIC_1\COD_LIC_1.ino: In function 'void setup()':
COD_LIC_1:26:4: error: 'counts' was not declared in this scope
counts = 0;
^~~~~~
C:\Users\ioana\OneDrive\Desktop\COD_LIC_1\COD_LIC_1.ino:26:4: note: suggested alternative: 'count'
counts = 0;
^~~~~~
count
COD_LIC_1:28:3: error: 'cpm' was not declared in this scope
cpm = 0;
^~~
COD_LIC_1:30:16: error: 'MAX_PERIOD' was not declared in this scope
multiplier = MAX_PERIOD / LOG_PERIOD; //calculating multiplier, depend on your log period
^~~~~~~~~~
COD_LIC_1:30:29: error: 'LOG_PERIOD' was not declared in this scope
multiplier = MAX_PERIOD / LOG_PERIOD; //calculating multiplier, depend on your log period
^~~~~~~~~~
COD_LIC_1:44:22: error: 'tube_impulse' was not declared in this scope
attachInterrupt(0, tube_impulse, FALLING); //define external interrupts
^~~~~~~~~~~~
C:\Users\ioana\OneDrive\Desktop\COD_LIC_1\COD_LIC_1.ino: At global scope:
COD_LIC_1:49:1: error: expected declaration before '}' token
}
^
exit status 1
'counts' was not declared in this scope
I solved the problem, but I still have errors and it does not compile .
The errors are these :
C:\Users\ioana\OneDrive\Desktop\COD_LIC_1\COD_LIC_1.ino: In function 'void setup()':
COD_LIC_1:30:16: error: 'MAX_PERIOD' was not declared in this scope
multiplier = MAX_PERIOD / LOG_PERIOD; //calculating multiplier, depend on your log period
^~~~~~~~~~
COD_LIC_1:30:29: error: 'LOG_PERIOD' was not declared in this scope
multiplier = MAX_PERIOD / LOG_PERIOD; //calculating multiplier, depend on your log period
^~~~~~~~~~
COD_LIC_1:44:22: error: 'tube_impulse' was not declared in this scope
attachInterrupt(0, tube_impulse, FALLING); //define external interrupts
^~~~~~~~~~~~
C:\Users\ioana\OneDrive\Desktop\COD_LIC_1\COD_LIC_1.ino: At global scope:
COD_LIC_1:49:1: error: expected declaration before '}' token
}
^
exit status 1
'MAX_PERIOD' was not declared in this scope
and the code is this
#include <SPI.h>
#include "LiquidCrystal_I2C.h"
#define Conv_Fac 0.0057 // Conversion factor for CPM to uSV/h !!!For the SBM-20 Soviet G-M Tube!!!
LiquidCrystal_I2C lcd(0x27, 16, 2);
const long Period = 10000; // Time for which particles are counted in milliseconds, higher time is more accurate but taker longer
const float multiplier = 60000.0 / Period; // muultiplied by the count to esimate CPM
long count = 0;
long CPM = 0;
long lastmeasurement_time = 0;
float Dose = 0.0;
void setup() {
sei();
lcd.begin(16, 2);//initializes LCD
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Get out of here");//Start up message shown while first reading is being taken
lcd.setCursor(0, 1);
lcd.print("S.T.A.L.K.E.R.");
count = 0;
CPM = 0;
multiplier = MAX_PERIOD / LOG_PERIOD; //calculating multiplier, depend on your log period
Serial.begin(9600); // start serial monitor
// uncommennt if you have time-out problem to connect with Radiation Logger
// delay(2000);
// Serial.write('0'); // sending zero to avoid connection time out with radiation logger
// delay(2000);
// Serial.write('0'); // sending zero to avoid connection time out with radiation logger
pinMode(2, INPUT); // set pin INT0 input for capturing GM Tube events
digitalWrite(2, HIGH); // turn on internal pullup resistors, solder C-INT on the PCB
attachInterrupt(0, tube_impulse, FALLING); //define external interrupts
}
}
ISR(PCINT0_vect)
{
/*
When a radioactive particle passes though the G-M tube there will be a pulse from the Geiger counter's output pin
RH electronic's circuit sends HIGH LOW HIGH but this will work with LOW HIGH LOW
The pulse is counted and multiplied by the multiplier to estimate the count per minute
*/
byte pinState;
pinState = (PINB >> PINB4) & 1; // read PINB register to check state of pins
if (pinState > 0) { // will return 1 if high, only acts on rising edge
count++;
}
}
void loop() {
if (millis() - lastmeasurement_time > Period) {
CPM = multiplier * count; // Estimation of CPM
Dose = CPM * Conv_Fac; // Doesage is esimated by multiplying the CPM by your tube's conversion factor
lastmeasurement_time = millis();
lcd.clear(); //Displays your dosage and CPM
lcd.setCursor(0, 0);
lcd.print("CPM=");
lcd.setCursor(4, 0);
lcd.print(CPM);
lcd.setCursor(0, 1);
lcd.print(Dose, 4);
lcd.setCursor(6, 1);
lcd.print(" uSv/h");
count = 0;
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > LOG_PERIOD){
previousMillis = currentMillis;
CPM = count * multiplier;
Serial.print(CPM); // send cpm data to Radiation Logger
Serial.write(' '); // send null character to separate next data
count = 0;
}
}
#define LOG_PERIOD 15000 //Logging period in milliseconds, recommended value 15000-60000.
#define MAX_PERIOD 60000 //Maximum logging period
unsigned long count; //variable for GM Tube events
unsigned long CPM; //variable for CPM
unsigned int multiplier; //variable for calculation CPM in this sketch
unsigned long previousMillis; //variable for time measurement
void tube_impulse(){ //procedure for capturing events from Geiger Kit
count++;
}
}
ok, can you please help me with a better code? The rhelectronics company gave the code for that geiger tube module, but I can't figure out how to combine the codes for the I2C LCD and the tube so that the device compiles and works.
I ordered this kit together with the SBM-20 tube.I'm trying to make the code to display CPM and radiation in microsievert but I can't. This type of LCD I want to use.
The code they offered is only for that geiger tube module.
#include <SPI.h>
#define LOG_PERIOD 15000 //Logging period in milliseconds, recommended value 15000-60000.
#define MAX_PERIOD 60000 //Maximum logging period
unsigned long counts; //variable for GM Tube events
unsigned long cpm; //variable for CPM
unsigned int multiplier; //variable for calculation CPM in this sketch
unsigned long previousMillis; //variable for time measurement
void tube_impulse(){ //procedure for capturing events from Geiger Kit
counts++;
}
void setup(){ //setup procedure
counts = 0;
cpm = 0;
multiplier = MAX_PERIOD / LOG_PERIOD; //calculating multiplier, depend on your log period
Serial.begin(9600); // start serial monitor
// uncommennt if you have time-out problem to connect with Radiation Logger
// delay(2000);
// Serial.write('0'); // sending zero to avoid connection time out with radiation logger
// delay(200);
// Serial.write('0'); // sending zero to avoid connection time out with radiation logger
pinMode(2, INPUT); // set pin INT0 input for capturing GM Tube events
digitalWrite(2, HIGH); // turn on internal pullup resistors, solder C-INT on the PCB
attachInterrupt(0, tube_impulse, FALLING); //define external interrupts
}
void loop(){ //main cycle
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > LOG_PERIOD){
previousMillis = currentMillis;
cpm = counts * multiplier;
Serial.print(cpm); // send cpm data to Radiation Logger
Serial.write(' '); // send null character to separate next data
count = 0;
}
}
I kept trying to add the code for the LCD but nothing is displayed
The code in post 13 is a subset of the code in post 1. I could put the LCD in, but I am not sure of the ISR call which only increments a counter. The documents say the pulse on Pin 2 will be HIGH, LOW, HIGH, but I can't see how this code deciphers it. I "made it compile" but I am unsure if it will work.
[edit]corrected a few of the mistakes [/edit]
// https://forum.arduino.cc/t/geiger-kit-and-arduino/1135092/
// https://www.rhelectronics.store/radiation-detector-geiger-counter-diy-kit-second-edition
// https://wokwi.com/projects/366838327360162817
#include <SPI.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#define Conv_Fac 0.0057 // Conversion factor for CPM to uSV/h !!!For the SBM-20 Soviet G-M Tube!!!
#define LOG_PERIOD 15000 // Logging period in milliseconds, recommended value 15000-60000.
#define MAX_PERIOD 60000 // Maximum logging period
#define GMtube 2 // GM Tube on Pin 2
unsigned long count; //variable for GM Tube events
unsigned long CPM; //variable for CPM
unsigned long previousMillis = 0; //variable for time measurement
unsigned long currentMillis;
float multiplier = MAX_PERIOD / LOG_PERIOD; // muultiplied by the count to esimate CPM
long lastmeasurement_time = 0;
float Dose = 0.0;
void setup() {
Serial.begin(9600); // start serial monitor
// uncommennt if you have time-out problem to connect with Radiation Logger
// delay(2000);
// Serial.write('0'); // sending zero to avoid connection time out with radiation logger
// delay(2000);
// Serial.write('0'); // sending zero to avoid connection time out with radiation logger
pinMode(GMtube, INPUT); // set pin INT0 input for capturing GM Tube events
digitalWrite(GMtube, HIGH); // turn on internal pullup resistors, solder C-INT on the PCB
attachInterrupt(0, tube_impulse, FALLING); //define external interrupts
sei();
lcd.begin(16, 2);
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Get out of here"); //Start up message shown while first reading is being taken
lcd.setCursor(0, 1);
lcd.print("S.T.A.L.K.E.R.");
}
void loop() {
currentMillis = millis();
if (currentMillis - previousMillis >= LOG_PERIOD) { // test elapsed time
previousMillis = currentMillis; // set the new timer
CPM = multiplier * count; // Estimation of CPM
Dose = CPM * Conv_Fac; // Doseage = CPM * tube's conversion factor
lastmeasurement_time = millis();
lcd.clear(); //Displays your dosage and CPM
lcd.setCursor(0, 0);
lcd.print("CPM =");
lcd.setCursor(5, 0);
lcd.print(CPM);
lcd.setCursor(0, 1);
lcd.print("Dose=");
lcd.setCursor(5, 1);
lcd.print(Dose, 4);
lcd.setCursor(11, 1);
lcd.print("uSv/h");
count = 0;
}
}
ISR(PCINT0_vect)
{
/*
When a radioactive particle passes though the G-M tube there will be a pulse
from the Geiger counter's output pin
RH electronic's circuit sends HIGH LOW HIGH but this will work with LOW HIGH LOW
The pulse is counted and multiplied by the multiplier to estimate the count per minute
*/
byte pinState;
pinState = (PINB >> PINB4) & 1; // read PINB register to check state of pins
if (pinState > 0) { // will return 1 if high, only acts on rising edge
count++;
}
}
void tube_impulse() { //procedure for capturing events from Geiger Kit
count++;
}
//***************************************************
// THESE LINES WERE INSIDE THE PASTED CODE.
// MOVED THEM OUT OF THE WAY. DELETE WHEN NOT NEEDED
//***************************************************
// multiplier = MAX_PERIOD / LOG_PERIOD; //calculating multiplier, depend on your log period
// counts = 0;
// cpm = 0;
// unsigned int multiplier; //variable for calculation CPM in this sketch
// const long Period = 10000; // Time for which particles are counted in milliseconds, higher time is more accurate but taker longer
// const float multiplier = 60000.0 / Period; // muultiplied by the count to esimate CPM
// void loop()
// {
// unsigned long currentMillis = millis();
// if (currentMillis - previousMillis > LOG_PERIOD) {
// previousMillis = currentMillis;
// cpm = counts * multiplier;
// Serial.print(cpm); // send cpm data to Radiation Logger
// Serial.write(' '); // send null character to separate next data
// counts = 0;
// }
// }
The count variable should be qualified "volatile", and because it cannot be accessed atomically, it must be read within the loop function and copied with interrupts disabled.
This is how I connected the wires between the arduino, the tube and the display.With this code it displays values but I don't think it displays the correct values because I don't have any radiation source nearby.
After reading post @anon56112670 post #15 I noticed the attachInterrupt() used "0" as the interrupt pin... which is A0... which floats if not programmed otherwise. I corrected the attachInterrupt() in the sim (post 14)... and here is the updated sketch.
// https://forum.arduino.cc/t/geiger-kit-and-arduino/1135092/
// https://www.rhelectronics.store/radiation-detector-geiger-counter-diy-kit-second-edition
// https://wokwi.com/projects/366838327360162817
#include <SPI.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#define Conv_Fac 0.0057 // Conversion factor for CPM to uSV/h !!!For the SBM-20 Soviet G-M Tube!!!
#define LOG_PERIOD 15000 // Logging period in milliseconds, recommended value 15000-60000.
#define MAX_PERIOD 60000 // Maximum logging period
#define GMtube 2 // GM Tube on Pin 2
volatile unsigned long count; //variable for GM Tube events
// unsigned long count; //variable for GM Tube events
unsigned long CPM; //variable for CPM
unsigned long previousMillis = 0; //variable for time measurement
unsigned long currentMillis;
float multiplier = MAX_PERIOD / LOG_PERIOD; // muultiplied by the count to esimate CPM
long lastmeasurement_time = 0;
float Dose = 0.0;
void setup() {
Serial.begin(9600); // start serial monitor
// uncommennt if you have time-out problem to connect with Radiation Logger
// delay(2000);
// Serial.write('0'); // sending zero to avoid connection time out with radiation logger
// delay(2000);
// Serial.write('0'); // sending zero to avoid connection time out with radiation logger
pinMode(GMtube, INPUT); // set pin INT0 input for capturing GM Tube events
digitalWrite(GMtube, HIGH); // turn on internal pullup resistors, solder C-INT on the PCB
attachInterrupt(digitalPinToInterrupt(GMtube), tube_impulse, FALLING); //define external interrupts
// attachInterrupt(0, tube_impulse, FALLING); // this was not correct
sei();
lcd.begin(16, 2);
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Get out of here"); //Start up message shown while first reading is being taken
lcd.setCursor(0, 1);
lcd.print("S.T.A.L.K.E.R.");
}
void loop() {
currentMillis = millis();
if (currentMillis - previousMillis >= LOG_PERIOD) { // test elapsed time
previousMillis = currentMillis; // set the new timer
noInterrupts(); // disable interrupts to access count in ISR
CPM = multiplier * count; // Estimation of CPM
interrupts(); // enable interrupts after access to count in ISR
Dose = CPM * Conv_Fac; // Doseage = CPM * tube's conversion factor
lastmeasurement_time = millis();
lcd.clear(); //Displays your dosage and CPM
lcd.setCursor(0, 0);
lcd.print("CPM =");
lcd.setCursor(5, 0);
lcd.print(CPM);
Serial.print(CPM); // send cpm data to Radiation Logger
Serial.write(' '); // send null character to separate next data
lcd.setCursor(0, 1);
lcd.print("Dose=");
lcd.setCursor(5, 1);
lcd.print(Dose, 4);
lcd.setCursor(11, 1);
lcd.print("uSv/h");
noInterrupts();
count = 0;
interrupts();
}
}
ISR(PCINT0_vect)
{
/*
When a radioactive particle passes though the G-M tube there will be a pulse
from the Geiger counter's output pin
RH electronic's circuit sends HIGH LOW HIGH but this will work with LOW HIGH LOW
The pulse is counted and multiplied by the multiplier to estimate the count per minute
*/
byte pinState;
pinState = (PINB >> PINB4) & 1; // read PINB register to check state of pins
if (pinState > 0) { // will return 1 if high, only acts on rising edge
count++;
}
}
void tube_impulse() { //procedure for capturing events from Geiger Kit
count++;
}
//***************************************************
// THESE LINES WERE INSIDE THE PASTED CODE.
// MOVED THEM OUT OF THE WAY. DELETE WHEN NOT NEEDED
//***************************************************
// multiplier = MAX_PERIOD / LOG_PERIOD; //calculating multiplier, depend on your log period
// counts = 0;
// cpm = 0;
// unsigned int multiplier; //variable for calculation CPM in this sketch
// const long Period = 10000; // Time for which particles are counted in milliseconds, higher time is more accurate but taker longer
// const float multiplier = 60000.0 / Period; // muultiplied by the count to esimate CPM
// void loop()
// {
// unsigned long currentMillis = millis();
// if (currentMillis - previousMillis > LOG_PERIOD) {
// previousMillis = currentMillis;
// cpm = counts * multiplier;
// Serial.print(cpm); // send cpm data to Radiation Logger
// Serial.write(' '); // send null character to separate next data
// counts = 0;
// }
// }
[edit] Looking which ISR is meant to be used:
ISR(PCINT0_vect)
was not called from either original sketch
uses PCINT0 (pins 8 to 13 on Uno and Nano) - was the GM tube not on pin 2 in one sketch?
looks for a rising edge of pinState - which is the pin that caused the interrupt