// *********** BLOCK 5 ***********
/*
NAME
SpaceRadiationCode.uni
DESCRIPTION
This code is used to operate an Arduino Mega 2560 microcontroller as part of the
Wyoming NASA Space Grant Consortium's high-altitude balloon "Space Radiation" activity.
The code allows the Arduino to obtain Beta and Gamma radiation measurements from a
connected pocket Gieger radiation sensor. A connected GPS breakout board also allows GPS
measurements, such as latitude, longitude, and altitude, to be obtained and saved to an
SD card with the radiation measurements.
WIRING ASSEMBLY
- GPS BREAKOUT BOARD
Connect the GPS VIN pin to a 5V Power pin on Arduino
Connect the GPS GND pin to a GND pin on Arduino
Connect the GPS TX (transmit) pin to the Digital 11 pin on Arduino
Connect the GPS RX (receive) pin to the Digital 10 pin on Arduino
- GEIGER RADIATION SENSOR
Connect the Geiger +V pin to a 5V Power pin on Arduino
Connect the Geiger GND pin to a GND pin on Arduino
Connect the Geiger SIG pin to the Digital 2 pin on Arduino
Connect the Geiger NS pin to the Digital 3 pin on Arduino
- ETHERNET SHIELD SD CARD
The SD card pin uses Digital 4 pin on Arduino, however the Ethernet Shield should
already be mounted atop the Arduino (no wiring needed)
*/
// ------------------------------------------------
// -------- LIBRARIES, DEFINITIONS, & PINS --------
// ------------------------------------------------
// Call the various libraries that are needed to run this code
#include "RadiationWatch.h"
#include "SD.h"
#include "SPI.h"
#include "SoftwareSerial.h"
#include "Adafruit_GPS.h"
// Set the Arduino Digital pins for the radiation sensor (signal pin, noise pin)
RadiationWatch radiationWatch(2, 3);
// Set the Arduino Digital pin for the SD card (determined by Ethernet Shield)
const byte sdCardPin = 4;
// Set the Arduino Ditigal pins for the GPS board (TX pin, RX pin)
SoftwareSerial mySerial(11, 10);
Adafruit_GPS GPS(&mySerial);
// Name to be added to print statements when printing to SD card
File dataFile;
// *********** BLOCK 3 ***********
// ------------------------------------------------
// ----- FUNCTION: WRITES NEW DATA TO SD CARD -----
// ------------------------------------------------
/* This function "csvStatus" is called each time the radiation sensor detects a new
radiation measurement. It writes data both to Serial (i.e., the computer monitor)
as well as to the SD card. */
void csvStatus(RadiationWatch radiationWatch) {
// Set the names of several variables that will be used in this function
static long count;
static float cpm;
static float dose;
static float error;
// PRINT TO SERIAL MONITOR FIRST
// GPS date
Serial.println(" ");
Serial.println("--- GPS Measurements ---");
Serial.print("Date: ");
if (GPS.month < 10){Serial.print('0');}
Serial.print(GPS.month, DEC); Serial.print('/');
if (GPS.day < 10){Serial.print('0');}
Serial.print(GPS.day, DEC); Serial.print("/20");
Serial.println(GPS.year, DEC);
// GPS timestamp
Serial.print("Time: ");
if (GPS.hour < 10){Serial.print('0');}
Serial.print(GPS.hour, DEC); Serial.print(':');
if (GPS.minute < 10){Serial.print('0');}
Serial.print(GPS.minute, DEC); Serial.print(':');
if (GPS.seconds < 10){Serial.print('0');}
Serial.print(GPS.seconds, DEC); Serial.println(" UTC");
// GPS satellite fix
Serial.print("Fix: "); Serial.println((int)GPS.fix);
Serial.print("Quality: "); Serial.println((int)GPS.fixquality);
Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
// GPS latitude & longitude
Serial.print("Latitude (DDMM.dddd, degrees): ");
if (GPS.lat == 'S'){Serial.print('-');}
Serial.print(GPS.latitude, 4); Serial.print(", ");
if (GPS.lat == 'S'){Serial.print('-');}
Serial.println((int(GPS.latitude) / 100) + (float(int(GPS.latitude) % 100) + (GPS.latitude - float(int(GPS.latitude)))) / float(60), 4);
Serial.print("Longitude (DDDMM.dddd, degrees): ");
if (GPS.lon == 'W'){Serial.print('-');}
Serial.print(GPS.longitude, 4); Serial.print(", ");
if (GPS.lon == 'W'){Serial.print('-');}
Serial.println((int(GPS.longitude) / 100) + (float(int(GPS.longitude) % 100) + (GPS.longitude - float(int(GPS.longitude)))) / float(60), 4);
// GPS movement & altitude
float alt_feet = GPS.altitude*3.28;
Serial.print("Speed (mph): "); Serial.println(GPS.speed*1.15078, 2);
Serial.print("Heading (deg clockwise from N): "); Serial.println(GPS.angle, 2);
Serial.print("Altitude (m MSL, ft MSL): "); Serial.print(GPS.altitude, 2); Serial.print(", "); Serial.println(alt_feet, 2);
// Radiation sensor
Serial.println(" ");
Serial.println("--- Radiation Measurements (last 20 minutes) ---");
count = radiationWatch.radiationCount();
cpm = radiationWatch.cpm();
dose = radiationWatch.uSvh();
error = radiationWatch.uSvhError();
Serial.print("Count: "); Serial.println(count);
Serial.print("Counts per minute: "); Serial.println(cpm,3);
Serial.print("Dosage: "); Serial.print(dose,3); Serial.println(" uSv/hour");
Serial.print("Dosage error: +/- "); Serial.print(error,3); Serial.println(" uSv/hour"); Serial.println(" ");
Serial.println("*********************************");
// WRITE DATA TO SD CARD
// Open SD file for writing
dataFile = SD.open("data.csv", FILE_WRITE);
// GPS date
if (GPS.month < 10){dataFile.print('0');}
dataFile.print(GPS.month, DEC); dataFile.print('/');
if (GPS.day < 10){dataFile.print('0');}
dataFile.print(GPS.day, DEC); dataFile.print("/20");
dataFile.print(GPS.year, DEC); dataFile.print(',');
// GPS timestamp
if (GPS.hour < 10){dataFile.print('0');}
dataFile.print(GPS.hour, DEC); dataFile.print(':');
if (GPS.minute < 10){dataFile.print('0');}
dataFile.print(GPS.minute, DEC); dataFile.print(':');
if (GPS.seconds < 10){dataFile.print('0');}
dataFile.print(GPS.seconds, DEC); dataFile.print(',');
// Other GPS information
if (GPS.lat == 'S'){dataFile.print('-');}
dataFile.print(GPS.latitude, 4); dataFile.print(',');
if (GPS.lat == 'S'){dataFile.print('-');}
dataFile.print((int(GPS.latitude) / 100) + (float(int(GPS.latitude) % 100) + (GPS.latitude - float(int(GPS.latitude)))) / float(60), 4); dataFile.print(',');
if (GPS.lon == 'W'){dataFile.print('-');}
dataFile.print(GPS.longitude, 4); dataFile.print(',');
if (GPS.lon == 'W'){dataFile.print('-');}
dataFile.print((int(GPS.longitude) / 100) + (float(int(GPS.longitude) % 100) + (GPS.longitude - float(int(GPS.longitude)))) / float(60), 4); dataFile.print(',');
dataFile.print(GPS.altitude, 2); dataFile.print(',');
dataFile.print(alt_feet, 2); dataFile.print(',');
// Radiation measurements
dataFile.print(count); dataFile.print(',');
dataFile.print(cpm, 3); dataFile.print(',');
dataFile.print(dose, 3); dataFile.print(',');
dataFile.print(error, 3); dataFile.print(',');
// GPS speed and direction
dataFile.print(GPS.speed*1.15078, 2); dataFile.print(',');
dataFile.print(GPS.speed, 2); dataFile.print(',');
dataFile.print(GPS.angle, 2); dataFile.print(',');
// GPS satellite information
if ((int)GPS.fix == 1){dataFile.print("YES,");} else {dataFile.print("NO,");}
dataFile.print((int)GPS.fixquality); dataFile.print(',');
dataFile.print((int)GPS.satellites); dataFile.println(',');
// Close SD file for writing
dataFile.close();
}
// *********** BLOCK 1 ***********
// ------------------------------------------------
// ---- FUNCTION: DETECTS NEW RADIATION PULSE -----
// ------------------------------------------------
/* This function "onRadiationPulse" is called whenever a new pulse is detected by
the radiation sensor, and simply calls "csvStatus" to print the data to SD card. */
void onRadiationPulse() {
// For each radiation count, write the current values to the SD card
csvStatus(radiationWatch);
// Wait for the data to finish printing before moving on
dataFile.flush();
}
// *********** BLOCK 2 ***********
// ------------------------------------------------
// ------------- FUNCTION: CODE SETUP -------------
// ------------------------------------------------
/* This function "setup" runs only once at the beginning of the code
and sets up the SD card, GPS board, and radiation sensor. */
void setup() {
// Set Serial to print at a baud rate of 9600
Serial.begin(9600);
Serial.println("*** SETTING UP ARDUINO ***");
// SETTING UP SD CARD
Serial.println(" ");
Serial.println("Initializing SD card ...");
// Ensure SD card pin is working
if (!SD.begin(sdCardPin)) {
Serial.println("SD card not initialized!");
return; }
// Test the CSV file
Serial.println(" - Testing SD file ...");
dataFile = SD.open("data.csv", FILE_WRITE);
if (dataFile) {
Serial.println(" - SD file opened successfully!");
} else {
Serial.println(" - File opened unsuccessful!");
return; }
dataFile.close();
Serial.println("SD card initialization done!");
// SETTING UP GPS BOARD
Serial.println(" ");
Serial.println("Initializing GPS board ...");
// Allow GPS data to be read by Arduino at baud rate of 9600
GPS.begin(9600);
// Set the type of GPS data to retrieve
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
// Set the update rate to 5 Hz
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_5HZ);
// Request updates on antenna status
GPS.sendCommand(PGCMD_ANTENNA);
Serial.println("GPS board initialization done!");
// SETTING UP GEIGER COUNTER
Serial.println(" ");
Serial.println("Initializing Geiger counter ...");
// Run the radiationWatch setup code
radiationWatch.setup();
Serial.println("Geiger counter initialization done!");
Serial.println(" ");
Serial.println("*** ARDUINO SETUP COMPLETE ***"); Serial.println(" ");
Serial.println("*********************************************"); Serial.println(" ");
// WRITING THE CSV HEADER LINE
// Open SD file for writing
dataFile = SD.open("data.csv", FILE_WRITE);
// Write the CSV headers
dataFile.println("Date,Time(UTC),Lat(DDMM.dddd),Lat(degrees),Lon(DDMM.dddd),Long(degrees),"
"Altitude(m),Altitude(ft),Radiation Count(last 20 min),Counts Per Minute,Dosage(uSv/hr),Dosage Error(uSv/hr),"
"Speed(mph),Speed(kts),Heading(degrees clockwise from N),Satellite Fix,Fix Quality,Satellites,");
// Close SD file for writing
dataFile.close();
// PRINTING INITIAL RADIATION VALUES
// Call "csvStatus" to print initial radiation values to SD card
csvStatus(radiationWatch);
// Wait for the data to finish printing before moving on
dataFile.flush();
// Register callback and tells code to call "onRadiationPulse" function anytime a new pulse is detected
radiationWatch.registerRadiationCallback(&onRadiationPulse);
// Wait 3 seconds (3000 milliseconds) to begin loop
delay(3000);
}
// *********** BLOCK 4 ***********
// ------------------------------------------------
// ------------- FUNCTION: CODE LOOP --------------
// ------------------------------------------------
/* This function "loop" runs continuously after setup and
waits for a new radiation pulse from the sensor. */
void loop() {
// Read data continuously from GPS board, check to see if different from last received data
char c = GPS.read();
if (GPS.newNMEAreceived()) {
if (!GPS.parse(GPS.lastNMEA()))
return; }
// Runs through the radiation code loop checking for new radiation pulses
radiationWatch.loop();
}