# include <Wire.h>
# include <Adafruit_GFX.h>
# include <Adafruit_SSD1306.h>
// #include <LiquidCrystal_I2C.h> //从库管理器添加1602I2C库
# include <SPI.h>
# define LOG_PERIOD 1000 //Logging period in milliseconds, recommended value 15000-60000.
# define MAX_PERIOD 60000 //Maximum logging period
# define RED_LED 5 // danger led
# define YELLOW_LED 4 // warning led
// # define Foot_SW 3 //foot switch interrupt for reset counts
# define pin_Tick 2
unsigned long counts; // GM 变量
unsigned long cpm; // CPM 变量
unsigned int multiplier; //设置换算变量
unsigned long previousMillis; //测量时间
int conversion_factor;
float usv;
// LiquidCrystal_I2C lcd(0x27, 16, 2); //设置LCD地址为 0x27 (1602显示器)
#define OLED_RESET 13
Adafruit_SSD1306 display(128, 32, & Wire, OLED_RESET);
void tick() // GM tube impulse
{
counts++;
}
//const unsigned char radiation 32x32 bw logo1 pngtobmp32 [] =
static const unsigned char PROGMEM radiation_bmp[] =
{
0x00, 0x03, 0xC0, 0x00, 0x00, 0x3E, 0x7C, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x03, 0x80, 0x01, 0x80,
0x06, 0x00, 0x00, 0x60, 0x0C, 0x80, 0x03, 0x30, 0x1B, 0xC0, 0x03, 0x90, 0x13, 0xE0, 0x07, 0xC8,
0x27, 0xE0, 0x07, 0xEC, 0x2F, 0xF0, 0x0F, 0xF4, 0x4F, 0xF8, 0x1F, 0xF6, 0x5F, 0xF8, 0x1F, 0xFA,
0x5F, 0xF8, 0x3F, 0xFA, 0xDF, 0xF9, 0x9F, 0xFA, 0x9F, 0xF3, 0xCF, 0xFA, 0x9F, 0xF7, 0xEF, 0xFB,
0x80, 0x07, 0xE0, 0x03, 0xC0, 0x03, 0xC0, 0x02, 0x40, 0x01, 0x80, 0x02, 0x40, 0x00, 0x00, 0x02,
0x40, 0x07, 0xE0, 0x02, 0x60, 0x0F, 0xE0, 0x06, 0x20, 0x0F, 0xF0, 0x04, 0x30, 0x1F, 0xF8, 0x0C,
0x10, 0x1F, 0xF8, 0x08, 0x08, 0x3F, 0xFC, 0x10, 0x0C, 0x7F, 0xFE, 0x30, 0x06, 0x7F, 0xFE, 0x60,
0x01, 0x9F, 0xF9, 0x80, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x03, 0xC0, 0x00
};
static const unsigned char PROGMEM NTI [] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x07, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x2D, 0xFF, 0xFF, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x11, 0x8F, 0x3C, 0xE6, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xA7, 0x3E, 0xDB, 0x7B, 0x40, 0x00, 0x00, 0xFF, 0xF8, 0x3E, 0x00, 0xF8, 0xFF, 0xF8,
0x00, 0x01, 0xEF, 0x7F, 0xFF, 0xBF, 0xE0, 0x00, 0x00, 0x30, 0x1C, 0x0F, 0x00, 0xE0, 0x30, 0x1C,
0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x30, 0x0E, 0x0F, 0x01, 0xE0, 0x30, 0x04,
0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x30, 0x0E, 0x0B, 0x81, 0x60, 0x30, 0x44,
0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x30, 0x0C, 0x0D, 0x83, 0x60, 0x30, 0xC0,
0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x30, 0x38, 0x0D, 0xC2, 0x60, 0x30, 0xC0,
0x00, 0x2F, 0x7F, 0xFF, 0xFF, 0xFF, 0xBA, 0x00, 0x00, 0x3F, 0xF8, 0x0C, 0xC6, 0x60, 0x3F, 0xC0,
0x00, 0x2D, 0x3F, 0xFF, 0xFF, 0xFF, 0x6D, 0x00, 0x00, 0x30, 0x0C, 0x0C, 0xC4, 0x60, 0x30, 0xC0,
0x00, 0x7B, 0xB8, 0x7E, 0x3F, 0x87, 0x77, 0x80, 0x00, 0x30, 0x06, 0x0C, 0x6C, 0x60, 0x30, 0x40,
0x00, 0x77, 0xE0, 0x3C, 0x0F, 0x03, 0xFB, 0x80, 0x00, 0x30, 0x06, 0x0C, 0x6C, 0x60, 0x30, 0x02,
0x00, 0x3F, 0xF0, 0x38, 0x06, 0x03, 0xFB, 0x00, 0x00, 0x30, 0x0E, 0x0C, 0x78, 0x60, 0x30, 0x06,
0x01, 0x1F, 0xFF, 0x10, 0x06, 0x3F, 0xFE, 0x00, 0x00, 0x30, 0x1E, 0x0C, 0x38, 0x60, 0x30, 0x1C,
0x5E, 0x07, 0xBF, 0xFF, 0xFF, 0xFF, 0xF8, 0x0C, 0x00, 0xFF, 0xF8, 0x3E, 0x31, 0xF8, 0xFF, 0xFC,
0x60, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x0C, 0x07, 0xFF, 0xFF, 0xF8, 0x18, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1C, 0x09, 0x80, 0x00, 0x00, 0x00, 0x06, 0x0E, 0x00, 0x00, 0x08, 0x04, 0x08, 0x00, 0x00, 0x00,
0x0F, 0x02, 0x00, 0xC0, 0x00, 0x20, 0x00, 0x3C, 0x00, 0x82, 0x6A, 0x45, 0xAD, 0x92, 0x12, 0xD5,
0x03, 0xE0, 0x00, 0x80, 0x00, 0xD0, 0x01, 0xF0, 0x00, 0x4A, 0x42, 0xA5, 0x00, 0x16, 0x12, 0x88,
0x00, 0xFE, 0x01, 0x80, 0x01, 0x08, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1F, 0xFC, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
//**************************** Setup *************************************//
void setup()
{
Serial.begin(9600);
// pins settings
pinMode(RED_LED, OUTPUT);
pinMode(YELLOW_LED, OUTPUT);
// pinMode(Foot_SW, INPUT_PULLUP);
pinMode(pin_Tick, INPUT_PULLUP);
// OLED setting
delay(400); // This delay is needed to let the display to initialize
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // OLED display initialize
// basic settings
counts = 0;
cpm = 0; //计数
multiplier = MAX_PERIOD / LOG_PERIOD; //计算乘数,取决于周期
attachInterrupt(0, tick, FALLING); //中断为下降沿触发
conversion_factor = 151; // setting GM tube conversion factor
// OLED boot screen
display.display();
display.clearDisplay();
display.drawBitmap(0, 0, NTI, 128, 32, WHITE);
delay(1500);
/* // LCD boot animation
lcd.init();
lcd.backlight();
lcd.setCursor(5, 0);
lcd.print("Boot...");
lcd.setCursor(0, 1);
for(int i=0;i<16;i++)
{
lcd.write(0xff);
delay(250);
}
*/
}
//********************************* Loop **********************************//
void loop()
{
digitalWrite(YELLOW_LED, LOW);
digitalWrite(RED_LED, LOW);
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > LOG_PERIOD)
{
previousMillis = currentMillis;
cpm = counts * multiplier; //得出技术次数
usv = float(cpm) / conversion_factor; //带入公式计算出辐射强度
/* // 1602 LCD display
lcd.clear();
lcd.print("CPM=");
lcd.print(cpm); //输出cpm值
lcd.setCursor(0, 1); //第二行
lcd.print(usv);
lcd.print(" uSv/h"); //输出强度值
counts = 0; // only uSv range display 复位
*/
display.display();
display.clearDisplay();
display.drawRoundRect(72,0,55,32,3,WHITE);
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(1, 1);
display.print("count:");
display.print(counts);
display.setCursor(1, 13);
display.print("CPM:");
display.print(cpm); //输出cpm值
display.setCursor(1, 24); //第二行
display.print(usv);
display.print("uSv/h"); //输出强度值
// counts = 0; // only uSv range display 复位
/*
// (uSv, LCD) normal, warning, danger range display setting
if (usv >= 10)
{
lcd.setCursor(9, 0);
lcd.print("Danger!");//如果辐射大于10则显示危险
delay(0.1);
}
else if (usv < 10 && usv >= 0.52)
{
lcd.setCursor(10, 0);
lcd.print("Unsafe");//在0.52-10这个范围显示不安全
delay(0.1);
}
else if (usv < 0.52)
{
lcd.setCursor(10, 0);
lcd.print("Safety");//在这个值以下显示安全
delay(0.1);
}
*/
/*
// (counts, OLED) normal, warning, danger range display setting
if (counts >= 600)
{
// display.invertDisplay(true);
display.fillRoundRect(72,0,55,32,6,WHITE);
display.setTextColor(BLACK);
display.setTextSize(1);
display.setCursor(80,12);
display.print("DANGER!"); //如果辐射大于10则显示危险
delay(0.1);
}
else if (counts < 600 && counts >= 300)
{
//display.invertDisplay(false);
display.drawRoundRect(72,0,55,32,6,WHITE);
display.setTextSize(1);
display.setCursor(80,12);
display.print("warning"); //如果辐射大于10则显示危险
delay(0.1);
}
else if (counts < 300)
{
//display.invertDisplay(false);
display.drawRoundRect(72,0,55,32,6,WHITE);
display.setTextSize(1);
display.setCursor(82,12);
display.print("safety"); //如果辐射大于10则显示危险
delay(0.1);
}
counts = 0; // only OLED range display 复位
*/
// (CPM, OLED) normal, warning, danger range display setting
if (cpm >= 400)
{
//display.fillRoundRect(72,0,55,32,6,WHITE);
display.drawBitmap(83, 0, radiation_bmp, 32, 32, WHITE);
//display.setTextColor(BLACK);
//display.setTextSize(1);
//display.setCursor(80,12);
//display.print("DANGER!");
digitalWrite(RED_LED, HIGH);
delay(100);
}
else if (cpm < 400 && cpm >= 200)
{
//display.drawRoundRect(72,0,55,32,6,WHITE);
display.setTextSize(1);
display.setCursor(80,12);
digitalWrite(YELLOW_LED, HIGH);
display.print("warning");
delay(100);
}
else if (cpm < 200)
{
//display.drawRoundRect(72,0,55,32,6,WHITE);
display.setTextSize(1);
display.setCursor(82,12);
display.print("safety");
//delay(0.1);
}
counts = 0; // only OLED range display
/*
// (counts, led) normal, warning, danger display setting
if (counts >= 10000)
{
pinMode(RED_LED) HIGH; //danger red led on
delay(0.1);
}
else if (counts < 10000 && counts >= 5000)
{
pinMode(YELLOW_LED) HIGH; //warning yellow led on
delay(0.1);
}
else if (counts < 5000)
{
pinMode(RED_LED) LOW; //danger red led off
pinMode(YELLOW_LED) LOW; //warning yellow led off
}
// counts = 0; // only led range display 复位
*/
}
}