Working Arduino Code


Correct order of the blocks:  5 – 3 – 1 – 2 – 4

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