2012 m. rugpjūčio 27 d., pirmadienis

Software sketch for the Geiger counter with updated shield :DiY-GDC1.2.1

to upload the below sketch you need to download and place these libraries in your Arduino IDE installation's libraries folder

the sketch as a file can be downloaded here


/* GeigerKit_Default sketch (v.8.0)                                        bHogan 6/22/12
 * Adjusted for LCD shield P2-GCS1-040512               impexeris on ebay.com on 08/21/12
 * Adjustments for P2-GCS1-040512 only concern Alarm and button BUTTON_PIN change from 10 to 11 and ALARM_PIN change from 15 to 10
 * Tactile button should be used on the P2-GCS1-040512 PCB instead of the top-right alarm LED and corresponding current limiting resistor should be removed)
 * This sketch was written for the DIYGeigerCounter Kit.
 * It requires the Arduino IDE rel. 1.0.0 or above to compile.
 * FEATURES:
 * CPM & uSv/hr output to LCD display and serial port. Bar graph on LCD. Low voltage warning.
 * Counts are displayed every 5 sec using a moving average which is reset every 30 sec.
 * An alternate display shows a running average for the previous 1 and 10 minute periods.
 * One of 2 CPM to uSv/h conversion ratios can be selected via jumper. ACCURACY NOT VERIFIED
 * This version adds a configurable alarm, new alt screen, and a 'realtime' bargraph.
 * It also supports the SensorGraph app on the Android.
 * More info is available at: http://sites.google.com/site/diygeigercounter/home
 * SETUP: (Any 2x16 Hitachi HD44780 compatible LCD)
 *     +5V LCD Vdd pin 2             >>>     Gnd LCD Vss pin 1, and R/W pin 5
 *     LCD RS pin 4 to D3            >>>     LCD Enable pin 6 to D4
 *     LCD D4 pin 11 to D5           >>>     LCD D5 pin 12 to D6
 *     LCD D6 pin 13 to D7           >>>     LCD D7 pin 14 to D8
 *     LCD LEDA pin 15 to ~1K to +5  >>>     LCD LEDK pin 16 to GND
 *     10K pot: - ends to +5V and Gnd, wiper to LCD VO pin (pin 3)
 * *INT from Geiger circuit is connected to PIN 2 and triggered as FALLING.
 * PIN 9 - jumper to GND if secondary conversion ratio is desired
 * PIN 10 - use button for alt display and to set alarm. (see site)
 *
 * This program is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2.1 of the License, or any later version.
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 * Do not remove information from this header.
 *
 * THIS PROGRAM AND IT'S MEASUREMENTS IS NOT INTENDED TO GUIDE ACTIONS TO TAKE, OR NOT
 * TO TAKE, REGARDING EXPOSURE TO RADIATION. THE GEIGER KIT AND IT'S SOFTWARE ARE FOR
 * EDUCATIONAL PURPOSES ONLY. DO NOT RELY ON THEM IN HAZARDOUS SITUATIONS!
 */

#include <MeetAndroid.h>                // connects Geiger to SensorGraph on Android
#include <LiquidCrystal.h>              // HD44780 compatible LCDs work with this lib
#include <EEPROM.h>                     // alarm setting is stored in EEPROM
#define DEBUG         false             // if true, shows available memory
#define TUBE_SEL          9             // jumper to select alt conversion to uSv
#define BUTTON_PIN       11             // button to toggle alternate display and set alarm (Pin number changed from 10 to 11 for the LCD shield P2-GCS1-040512)
#define LED_PIN          13             // for debug only - flashes 5X at startup
#define ALARM_PIN        10             // Outputs HIGH when Alarm triggered (Pin number changed from 15 to 10 for the LCD shield P2-GCS1-040512)
#define ALARM_SET_ADDR    8             // address of alarm setting in EEPROM
#define MAX_ALARM        600            // max the alarm can be set for

// HOW MANY CPM =1 uSV? The commonly used ratios for the SBM-20 & LND712 are defined:
#define PRI_RATIO     175.43            // no TUBE_SEL jumper - SET FOR SBM-20
#define SEC_RATIO     100.00            // TUBE_SEL jumper to GND - SET FOR LND712

// mS between writes to serial - counts also accumulate seperately for this period
#define LOGGING_PEROID    60000         // 1 min (60000 mS) best - unless testing
// mS between writes to display - counts/period are averaged to CPM
#define DISP_PERIOD      5000.0         // (5 sec) mS sample & display
#define FULL_SCALE         1000         // max CPM for all 7 bars
#define LOW_VCC            4200 //mV    // if Vcc < LOW_VCC give low voltage warning
#define ONE_MIN_MAX          12         // elements in the oneMinute accumulater array
#define TEN_MIN_MAX         120         // elements in the tenMinute accumulater array
#define DEBOUNCE_MS          50         // buttom debounce period in mS

boolean lowVcc = false;                 // true when Vcc < LOW_VCC
boolean altDispUsed = false;            // used to start counts from zero
boolean altDispOn = false;              // true when SW_1 on, and in continous count mode
boolean dispOneMin = false;             // true if enough time passed to begin displaying counts
boolean dispTenMin = false;
boolean AlarmOn = false;                // CPM > set alarm
byte sampleCnt;                         // the number of samples making up the average
byte altDispCnt = 0;                    // controls when alt display is on
int oneMinute[ONE_MIN_MAX];             // used to accumulate 1 & 10 minute counts
int oneMinuteIndex = 0;
int tenMinute[TEN_MIN_MAX];
int tenMinuteIndex = 0;
int AlarmPoint;                         // CPM alarm is set for
int Vcc_mV;                             // mV of Vcc from last check
int androidReturn = 0;                  // reads the slider on Android SensorGraph.

volatile unsigned long dispCnt, logCnt; // inc by ISR
volatile unsigned long runCnt, barCnt;
long runCountStart;
unsigned long tempSum;
unsigned long dispPeriodStart, dispCPM; // counters for the display period . . .
unsigned long logPeriodStart, logCPM;
unsigned long checkVccTime;             // counter for how often to check voltage
unsigned long altDispStart;             // counter for alt display refresh period
unsigned long lastButtonTime;           // counter for pressing the button to quickly
unsigned long barGraphStart;            // counter for bargraph refresh period
float uSv = 0.0;                        // display CPM converted to "unofficial" uSv
float uSvLogged = 0.0;                  // logging CPM converted to "unofficial" uSv
float uSvRate;                          // holds the rate selected by jumper
float avgCnt = 0.0;                     // holds the previous average count
float temp_uSv = 0.0;

//Custom characters used for bar graph
byte bar_0[8] = {
  0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00}; //blank
byte bar_1[8] = {
  0x10, 0x10, 0x18, 0x18, 0x18, 0x10, 0x10, 0x00}; //1 bar
byte bar_2[8] = {
  0x18, 0x18, 0x1c, 0x1c, 0x1c, 0x18, 0x18, 0x00}; //2 bars
byte bar_3[8] = {
  0x1C, 0x1C, 0x1e, 0x1e, 0x1e, 0x1C, 0x1C, 0x00}; //3 bars
byte bar_4[8] = {
  0x1E, 0x1E, 0x1f, 0x1f, 0x1f, 0x1E, 0x1E, 0x00}; //4 bars
byte bar_5[8] = {
  0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00}; //5 bars
byte bar_6[8] = {
  0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00}; //6 bars (same)

// instantiate the library and pass pins for (RS, Enable, D4, D5, D6, D7)
LiquidCrystal lcd(3, 4, 5, 6, 7, 8);    // default layout for the Geiger board
MeetAndroid Android;

void setup(){
  Serial.begin(9600);                   // comspec 96,N,8,1
  attachInterrupt(0,GetEvent,FALLING);  // Geiger event on pin 2 triggers interrupt
  pinMode(LED_PIN,OUTPUT);              // setup LED pin
  pinMode(TUBE_SEL,INPUT);              // setup tube select jumper pin
  pinMode(BUTTON_PIN,INPUT);            // setup menu button
  pinMode(ALARM_PIN, OUTPUT);           // setup Alarm pin
  digitalWrite(TUBE_SEL, HIGH);         // set 20K pullup on jumper pins(low active)
  digitalWrite(BUTTON_PIN, HIGH);
  Blink(LED_PIN,4);                     // show it's alive
  lcd.begin(16,2);                      // cols, rows of display (8x2, 16x2, etc.)
  lcd.createChar(0, bar_0);             // load 7 custom characters in the LCD
  lcd.createChar(1, bar_1);
  lcd.createChar(2, bar_2);
  lcd.createChar(3, bar_3);
  lcd.createChar(4, bar_4);
  lcd.createChar(5, bar_5);
  lcd.createChar(6, bar_6);
  lcd.setCursor(0,0);

  Android.registerFunction(androidInput,'o'); // calls androidInput() when new input frpm droid
  clearDisp();                          // clear the screen
  lcd.print("    Ver. 8.0");           // display a simple banner
  lcd.setCursor(0,1);                   // set cursor on line 2
  lcd.print(" LCD Shield rev.");            // display the version
  delay (1500);                         // leave the banner up for a bit
  clearDisp();                          // clear the screen
  if(digitalRead(TUBE_SEL)){            // read jumper to select conversion ratio
    uSvRate = PRI_RATIO;                // use the primary ratio defined
  }
  else{                                 // jumper is set to GND . . .
    uSvRate = SEC_RATIO;                // use the secondary ratio defined
  }
  lcd.print(uSvRate,0);                 // display conversion ratio in use
  lcd.print(" CPM to uSv");
  lcd.setCursor(0,1);                   // set cursor on line 2
  Vcc_mV = readVcc();                   // read Vcc voltage
  lcd.print("Running at ");             // display it
  lcd.print(Vcc_mV/1000. ,2);           // display as volts with 2 dec. places
  lcd.print("V");
  delay (2000);                         // leave info up for a bit
#if (DEBUG)                             // show available SRAM if DEBUG true
  clearDisp();
  lcd.print("RAM Avail: ");
  lcd.print(AvailRam());
  delay (2000);
#endif
  // this section tests if button pressed to set alarm threshold and calls a function to change it
  AlarmPoint = EEPROM.read(ALARM_SET_ADDR); // get last alarm value from EEPROM
  if (AlarmPoint == 255) AlarmPoint = 0;    // deal with virgin EEPROM
  AlarmPoint = AlarmPoint * 10;             // values stored are 1/10th
  clearDisp();                              // put up new alarm set screen
  lcd.print("Set Alarm?");
  lcd.setCursor(0, 1);
  if (AlarmPoint >0){
    lcd.print("Now ");
    lcd.print(AlarmPoint);
    lcd.print(" CPM");
  }
  else lcd.print("Now Off");

  long timeIn = millis();               // you have 3 sec to push button or move on
  while (millis() < timeIn + 3000) {
    if (readButton(BUTTON_PIN)== LOW) setAlarm(); // alarm is to be set
  }                                     // if no button press continue
  clearDisp();                          // clear the screen
  lcd.print("CPM? ");                   // display beginning "CPM"
  Serial.println("CPM \t uSv \t Vcc");  // print header for log
  dispPeriodStart = millis();           // start timing display CPM
  logPeriodStart = dispPeriodStart;     // start logging timer
  checkVccTime = dispPeriodStart;       // start Vcc timer
  runCountStart = dispPeriodStart;      // start alternate timer
  barGraphStart = dispPeriodStart;      // start bargraph timer
  dispCnt = 0;                          // start with fresh totals
  logCnt= 0;
  runCnt = 0;
  barCnt = 0;
}


void loop(){
  //uncomment 5 lines below for self check - you should see very close to 360 CPM
  //dispCnt++;
  //logCnt++;
  //runCnt++;
  //barCnt++;
  //delay(167);                           // 167 mS = 6 Hz `= X 60 = 360 CPM

  if (millis() >= lastButtonTime + 500){ // wait a bit between button pushes
    lastButtonTime = millis();          // reset the period time
    if (readButton(BUTTON_PIN)== LOW){  // start alt display mode if button pin is low
      clearDisp();                      // clear the screen when switching displays
      altDispOn = !altDispOn;           // toggle altDispOn state
      if (altDispUsed == false){
        altDispUsed = true;             // false until first used
        runCnt = 0;                     // clear counts until used
        runCountStart = millis();
      }
      if (altDispOn) DispRunCounts();   // start alt display immediately - or
      else DispCounts(dispCnt);         // start main display immediately
    }
  }

  if (millis() >= barGraphStart + 1000){ // refresh bargraph, alarm and Vcc if in main display
    if (!altDispOn)fastDisplay();       // display quick response data    
    barCnt = 0;                         // reset counts
    barGraphStart = millis();           // reset the period time
  }

  if (millis() >= altDispStart + 5000){ // refresh alt display if it's on
    if (altDispOn) DispRunCounts();     // display running counts
    altDispStart = millis();            // reset the period time
  }

  if (millis() >= runCountStart + 5000){ // Collect running counts every 10 sec.
    RunningCounts(runCnt);              // add counts
    runCnt = 0;                         // reset counts
    runCountStart = millis();           // reset the period time
  }

  if (millis() >= dispPeriodStart + DISP_PERIOD){ // DISPLAY PERIOD
    if (!altDispOn) DispCounts(dispCnt);// period is over - display counts
    dispCnt = 0;                        // reset counter
    dispPeriodStart = millis();         // reset the period time
  }

  if (millis() >= logPeriodStart + LOGGING_PEROID){ // LOGGING PERIOD
    logCount(logCnt);                   // pass in the counts to be logged
    logCnt = 0;                         // reset log event counter
    dispCnt = 0;                        // reset display event counter too
    dispPeriodStart = millis();         // reset display time too
    logPeriodStart = millis();          // reset log time
  }

  if (millis() >= checkVccTime + 6000){ // timer for check battery (every 6 sec.)
    checkVccTime = millis();            // reset timer
    Vcc_mV = readVcc();
    if (Vcc_mV <= LOW_VCC) lowVcc = true; // check if Vcc is low
    else lowVcc = false;
  }
}


void DispCounts(long dcnt){  // calc and display predicted CPM & uSv/h
  byte maxSamples = (60000 / DISP_PERIOD) / 2;   // number of sample periods in 30 seconds                  
  sampleCnt++;                                   // inc sample count - must be at least 1
  avgCnt += (dcnt - avgCnt) / sampleCnt;         // CALCULATE AVERAGE COUNT - moving average
  dispCPM = (avgCnt * 60000.0) / DISP_PERIOD;    // convert to CPM
  //handle reset of sample count - sample is for 1/2 min and reset. Options for reset value are:
  // "0" - throw away last average, "1" - keeps last average, "maxSamples -1" - keeps running avg.
  if (sampleCnt >= maxSamples) sampleCnt = 0;    // start a fresh average every 30 sec.
  // the following line gives a faster response when counts increase or decrease rapidly
  if ((dcnt - avgCnt) > 9 || (avgCnt - dcnt) > 9) sampleCnt = 0;
  uSv = dispCPM / uSvRate;                       // make uSV conversion
  //Blink(LED_PIN,1);                              // uncomment to blink each didplay

  Android.receive();                    // looks for new input from Android
  // don't send data via BT if not using app (no input) else it screws up serial output
  if (androidReturn >0)Android.send((dispCPM * androidReturn) / 100);

  clearArea (0,0,9);                    // clear count area
  lcd.print("CPM ");                    // display static "CPM"
  clearArea (0,1,16);                   // clear line 2
  lcd.print("uSv/hr ");                 // display static "uSv/hr"
  lcd.print(uSv,2);                     // display uSv/hr on line 1
  lcd.setCursor(4,0);                   // CPM LAST TO DISPLAY - NEVER PARTIALLY OVERWRITTEN
  lcd.print(dispCPM);                   // display CPM on line 1
  lcd.print(" ");
  if (dispCPM > AlarmPoint && AlarmPoint > 0) {  // Alarm takes priority over low Vcc
    AlarmOn = true;
    digitalWrite(ALARM_PIN, HIGH);      // turn on alarm (set alarm pin to Vcc)
  }
  else {
    digitalWrite(ALARM_PIN, LOW);       // turn off alarm (set alarm pin to Gnd)
    AlarmOn = false;
  }
}


void fastDisplay(){ // quick response display on 2nd half of line 1
  barCnt = barCnt * 60;                 // scale CPS to CPM

  if (barCnt <= FULL_SCALE && !AlarmOn){
    clearArea (9,0,7);                  // move cursor to 9th col, 1st line for lcd bar
    lcdBar(barCnt);                     // display bargraph on line 1
  }
  if (lowVcc) {                         // overwrite display with battery voltage if low
    clearArea (11,0,5);
    lcd.print(Vcc_mV/1000.,2);          // display as volts with 2 dec. place
    lcd.print("V");
  }
  if (AlarmOn) {                        // overwrite display with alarm if on
    clearArea (10,0,6);
    lcd.setCursor(11,0);
    lcd.print("ALARM");
  }
}


void DispRunCounts(){ // create the screen that shows the running counts
  clearDisp();
  lcd.print(" 1M ");                    // display 1 & 10 min lits
  lcd.setCursor(0,1);
  lcd.print("10M ");

  // 1 MINUTE DISPLAY LINE . . .
  tempSum = 0;
  for (int i = 0; i <= ONE_MIN_MAX-1; i++){ // sum up 1 minute counts
    tempSum = tempSum + oneMinute[i];
  }
  temp_uSv = tempSum / uSvRate;         // calc uSv/h
  if (dispOneMin){                      // disp first so it can be overwritten by high counts
    lcd.setCursor(9, 0);
    lcd.print("/");
    lcd.setCursor(13 - getLength(temp_uSv), 0); // right justify the uSv!
    lcd.print(temp_uSv,2);              // display 1 minute uSv
  }
  else {                                // for running counts
    lcd.setCursor(10, 0);
    lcd.print(" COUNT");
  }
  lcd.setCursor(4, 0);
  lcd.print(tempSum,DEC);               // display 1 minute CPM or running count

  // 10 MINUTE DISPLAY LINE . . .
  tempSum = 0;
  for (int i = 0; i <= TEN_MIN_MAX-1; i++){ // sum up 10 minute counts
    tempSum = tempSum + tenMinute[i];
  }
  if (dispTenMin) tempSum = tempSum / 10; // sum over 10 minutes so divide by that when CPM is displayed
  temp_uSv = tempSum / uSvRate;

  if (dispTenMin){                     // disp first so it can be overwritten by high counts
    lcd.setCursor(9, 1);
    lcd.print("/");
    lcd.setCursor(13 - getLength(temp_uSv), 1); // right justify the uSv!
    lcd.print(temp_uSv,2);              // display 1 minute uSv
  }
  else {
    lcd.setCursor(13, 1);               // right justify
    lcd.print(5*tenMinuteIndex,DEC);    // show seconds count
  }
  lcd.setCursor(4, 1);
  lcd.print(tempSum,DEC);               // display 10 minute CPM

  // give the display a little more time for fast display periods
  if (DISP_PERIOD < 5000) delay(1500);  // a delay is OK here - interrupts are still handled
}


void setAlarm(){ // RECURSIVE FUNCTION to change alarm set point when button repeatidly pushed
  long timeIn = millis();               // capture the time you got here
  while (millis() < timeIn + 2000) {    // you got 2 sec. to push button again - else done
    if (readButton(BUTTON_PIN)== LOW){  // button pushed
      if (AlarmPoint < 100) AlarmPoint = AlarmPoint +10; // inc by 10 up to 100 CPM
      else AlarmPoint = AlarmPoint +50;                  // inc by 50 over 100 CPM
      if (AlarmPoint > MAX_ALARM) AlarmPoint = 0;        // start over if max point reached - zero is off
      EEPROM.write(ALARM_SET_ADDR, AlarmPoint /10);      // store new setting in EEPROM
      lcd.setCursor(0, 1);                               // display what's going on
      clearArea (0,1,16);
      if (AlarmPoint >0){
        lcd.print(AlarmPoint);
        lcd.print(" CPM");
      }
      else lcd.print("Alarm Off");
      delay(500);
      setAlarm();  // call this function recursively if button was pushed
    }
  }                // button not pushed - done use last setting for alarm point
}


void lcdBar(int counts){  // displays CPM as bargraph on 2nd line
  // Adapted from DeFex http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1264215873/0
  unsigned int scaler = FULL_SCALE / 41;      // 7 char=41 "bars", scaler = counts/bar
  unsigned int cntPerBar = (counts / scaler); // amount of bars needed to display the count
  unsigned int fullBlock = (cntPerBar / 6);   // divide for full "blocks" of 6 bars
  unsigned int prtlBlock = (cntPerBar % 6 );  // calc the remainder of bars
  if (fullBlock >7){                    // safty to prevent writing >7 blocks
    fullBlock = 7;
    prtlBlock = 0;
  }
  for (int i=0; i<fullBlock; i++){
    lcd.write(5);                       // print full blocks
  }
  lcd.write(prtlBlock);                 // print remaining bars with custom char
  for (int i=(fullBlock + 1); i<8; i++){
    lcd.print(" ");                     // blank spaces to clean up leftover
  }
}


void logCount(unsigned long lcnt){ // unlike logging sketch, just outputs to serial
  if (millis() < logPeriodStart + LOGGING_PEROID) return; // period not over
  logCPM = float(lcnt) / (float(LOGGING_PEROID) / 60000);
  uSvLogged = logCPM / uSvRate;         // make uSV conversion

  // Print to serial in a format that might be used by Excel
  Serial.print("  ");  
  Serial.print(logCPM,DEC);
  Serial.print(",\t");  
  Serial.print(uSvLogged,4);
  Serial.print(",\t"); // comma delimited
  Serial.print(Vcc_mV/1000. ,2);        // print as volts with 2 dec. places
  //Serial.print("V");                  // removed for better graphing
  Serial.println(",");  
  Blink(LED_PIN,2);                     // show it logged
}


void RunningCounts(unsigned long dcnt){ // Add CPM of period to 1M and 10M array
  if (altDispUsed == false)return;      // keep the totals clean until first run
  oneMinute[oneMinuteIndex] = dcnt;
  if(oneMinuteIndex >= ONE_MIN_MAX-1) {
    oneMinuteIndex = 0;
    dispOneMin = true;                  // indicate that average is available
  }
  else oneMinuteIndex++;

  tenMinute[tenMinuteIndex] = dcnt;
  if(tenMinuteIndex >= TEN_MIN_MAX-1) {
    tenMinuteIndex = 0;
    dispTenMin = true;                  // indicate that average is available
  }
  else tenMinuteIndex++;
  dcnt = 0;
}


long readVcc() { // SecretVoltmeter from TinkerIt
  long result;
  // Read 1.1V reference against AVcc
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = 1126400L / result; // Back-calculate AVcc in mV
  return result;
}


///////////////////////////////// UTILITIES ///////////////////////////////////
void clearArea (byte col, byte line, byte nspaces){
  // starting at col & line, prints n spaces then resets the cursor to the start
  lcd.setCursor(col,line);
  for (byte i=0; i<nspaces; i++){
    lcd.print(" ");
  }
  lcd.setCursor(col,line);
}


void clearDisp (){
  // The OLED display does not always reset the cursor after a clear(), so it's done here
  lcd.clear();                          // clear the screen
  lcd.setCursor(0,0);                   // reset the cursor for the poor OLED
  lcd.setCursor(0,0);                   // do it again for the OLED
}


void Blink(byte led, byte times){ // just to flash the LED
  for (byte i=0; i< times; i++){
    digitalWrite(led,HIGH);
    delay (150);
    digitalWrite(led,LOW);
    delay (100);
  }
}


int AvailRam(){
  int memSize = 2048;                   // if ATMega328
  byte *buf;
  while ((buf = (byte *) malloc(--memSize)) == NULL);
  free(buf);
  return memSize;
}


byte getLength(unsigned long number){
  byte length = 0;

  for (byte i = 1; i < 10; i++){
    if (number > pow(10,i)) length = i;
    else return length +1;
  }
}


byte readButton(int buttonPin) { // reads LOW ACTIVE push buttom and debounces
  if (digitalRead(buttonPin)) return HIGH;    // still high, nothing happened, get out
  else {                                      // it's LOW - switch pushed
    delay(DEBOUNCE_MS);                       // wait for debounce period
    if (digitalRead(buttonPin)) return HIGH;  // no longer pressed
    else return LOW;                          // 'twas pressed
  }
}


void androidInput(byte flag, byte numOfValues){ // automatically called when input from Android
  androidReturn = Android.getInt();           // set global with value from slider
}

///////////////////////////////// ISR ///////////////////////////////////
void GetEvent(){   // ISR triggered for each new event (count)
  dispCnt++;
  logCnt++;
  runCnt++;
  barCnt++;
}




Geiger Counter with updated LCD shield :DiY-GDC1.2.1







2012 m. rugpjūčio 11 d., šeštadienis

Ways to connect SBT-9 tube

I have tried three different ways to connect the SBT-9 tube

#1


Strip two wires so that one part is long  and other is short 



bend one wire as shown this is to keep the wire in place when inserting into thermal tube 


Cut a piece of a thermal tube (the one which shrinks when heat is applied)





Hold the tube and insert it into the a piece  of a thermal tube


!Very carefully heat the thermal tube (do not overheat the SBT9)
I do it in several steps - heat a little so that thermal tube starts shrinking and then wait for the whole piece to cool. Then again heat it a little and so on. I have not ruined any tubes this way myself, however I assume it is easily possible if you overheat.


Same thing with Anode of the tube ...






then cut the remainder of the Cathode wire

#2

Similar but no heating - use a good isolation tape



#3

Using  clips




2012 m. rugpjūčio 10 d., penktadienis