Greg Voronin
/
gammaCanary02
This version is the one to be submitted as a part the Hackster.io contest, Unleash Invisible Intelligence
Diff: main.cpp
- Revision:
- 0:a761fba7f8a8
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue Jul 31 16:30:32 2018 +0000 @@ -0,0 +1,392 @@ +#include "mbed.h" +#include "LoRa.h" +#include "MBed_Adafruit_GPS.h" +#include "MAX17055.h" + +Serial pc (USBTX, USBRX); // debug serial port +DigitalOut led1(LED1); // debug blinker + +/******************************************************************************/ +/*************************** Power & Fuel Gauge *******************************/ +/******************************************************************************/ +DigitalOut powerHLD(P2_2, 1); //keep power on when connected to battery +I2C i2c(I2C2_SDA, I2C2_SCL); +MAX17055 max17055(i2c); +int gaugeStatus; +int stateOfCharge, timeToEmpty; +float batteryVoltage, batteryCurrent, boardTemperature, tteReport; +#define FUEL_REFRESH 30 // 120 secs, 2 minutes for now, testing . . . + +Timer fuelTimer; +Timer batteryEmergencyPause; // avoid sending alert right after starting unit up! +bool startBatteryEmergency; +bool inBatteryEmergencyState; +#define EMERBEGIN 180000 // 3 minutes in millissecond after setup runs +void readFuelGauge(void); +/************************* End Power & Fuel Guage *****************************/ + +/******************************************************************************/ +/***************************** LoRa TxRx **************************************/ +/******************************************************************************/ +#define GATEWAYID 0x30 // LoRa Gateway ID +#define LOCALADDRESSID 0x31 // this gamma canary ID +#define GPSDATA 0x40 +#define CPMDATA 0x41 +#define FUELDATA 0x42 +#define LOWBATTERY 0x43 +// #define CPMALERT 0x44 + +// data transmission/report intervals +// #define LOCATION_INTERVAL 15.0 // GPS location every 120 secs +// #define CPM_INTERVAL 60.0 // CPM every 60 secs +// #define FUEL_INTERVAL 90.0 // Fuel Gauge every 90 secs + +// data transmission/report intervals +float LOCATION_INTERVAL = 15.0; // GPS location every 120 secs +float CPM_INTERVAL = 60.0; // CPM every 60 secs +float FUEL_INTERVAL = 90.0; // Fuel Gauge every 90 secs + +volatile int locationCountDown, cpmCountDown, fuelCountDown; + +Ticker transmissionTicker; +void transmitLoRaTicker(void) +{ + if (locationCountDown > 0) locationCountDown--; + if (cpmCountDown > 0) cpmCountDown--; + if (fuelCountDown >0) fuelCountDown--; +} + +void transmitLocation(void); +void transmitCPM(void); +void transmitFuel(void); +void batteryLowTransmit(); +void onReceive(int packetSize); +/*************************** End LoRa *****************************************/ + +/******************************************************************************/ +/******************************** GPS *****************************************/ +/******************************************************************************/ +double currentLatitude, currentLongitude, previousLatitude, previousLongitude; +Serial * _gpsSerial; + +#define GPS_REFRESH 5000 // 2000 millisecs??? +Timer gpsTimer; // GPS data collection/refresh timer + +void transformGPSData(double lat, char p, double lon, char m); +// GPS command list at http://www.adafruit.com/datasheets/PMTK_A08.pdf +/**************************** End GPS *****************************************/ + +/******************************************************************************/ +/*********************** Begin Radiation Monitoring ***************************/ +/******************************************************************************/ +// PMOD Port 1 pins for radiation sensor +volatile int signalCounter, noiseCounter; +InterruptIn signalPin(P1_0); +InterruptIn noisePin(P1_1); +// interrupt service routines(ISR) which count are called whenever signal or noise pins are triggered +void signalISR(){ signalCounter++; led1 = !led1;} +void noiseISR(){ noiseCounter++; } + +// #define CPMALERTLEVEL 50 // set very low or testing purposes. +// #DEFINE CPMMAXALERTS 3 // only three at a time to not bomb SMS network! +#define CPM_REFRESH 60 // 60 seconds in a minute +Timer cpmTimer; // CPM data collection, determine total current counts per minute + +int currentSignalCount, currentNoiseCount, previousCPM, currentCPM; +int previousTotalSignalCount, previousTotalNoiseCount; + +void calculateCPM(); +/*********************** End Radiation Monitoring *****************************/ + + +int main() +{ + /****************************** Setup *************************************/ + pc.printf(" ********* gamma canary v001 ********* \n"); + + /** 0. Confirm running on battery power **/ + if (powerHLD.is_connected()) {pc.printf("Battery power connected...\n");} + + /** 1. LoRa TxRx initialization **/ + if (!LoRa.begin(915E6)) {pc.printf("LoRa not found!");} + else { pc.printf("LoRa started...\n");} + // LoRa.onReceive(onReceive); + // LoRa.receive(); + transmissionTicker.attach(&transmitLoRaTicker,1.0); + + /** 2. GPS/NMEA Initialization **/ + currentLongitude = 0.00; + previousLongitude = currentLongitude; + currentLatitude = 0.00; + previousLatitude = currentLatitude; + + _gpsSerial = new Serial(P3_1,P3_0); //serial object for use w/ GPS + Adafruit_GPS myGPS(_gpsSerial); + myGPS.begin(9600); + char c; + myGPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); //these commands are defined in MBed_Adafruit_GPS.h; a link is provided there for command creation + myGPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); + myGPS.sendCommand(PGCMD_ANTENNA); + gpsTimer.start(); + pc.printf("GPS setup done...\n"); + + //** 3. Radiation Detecton - CPM(Counts Per Minute) + currentSignalCount = 0; + previousTotalSignalCount = 0; + currentNoiseCount = 0; + previousTotalNoiseCount = 0; + currentCPM = 0; + previousCPM = 0; + signalPin.rise(&signalISR); // attach ISR function to the rising edge + noisePin.rise(&noiseISR); // attach ISR function to the rising edge + cpmTimer.start(); + pc.printf("Starting radiation monitoring...\n"); + + /** 4. Fuel Gauge/Battery Monitoring **/ + max17055.init(0.05f); + max17055.status(&gaugeStatus); + fuelTimer.start(); + startBatteryEmergency = false; + inBatteryEmergencyState = false; + batteryEmergencyPause.start(); + pc.printf("MAX17055 status: %04X\r\n", (uint16_t)gaugeStatus); + wait(3.0); + pc.printf("Setup complete...\n"); + + /***************************** End Setup **********************************/ + // loop() + while(1) + { + + /** GPS/Location Data Collection"loop" here **/ + c = myGPS.read(); //queries the GPS + if ( myGPS.newNMEAreceived() ) + { + if ( !myGPS.parse(myGPS.lastNMEA()) ) { + continue; + } + } + + //check if enough time has passed to warrant printing GPS info to screen + //note if refresh_Time is too low or pc.baud is too low, GPS data may be lost during printing + if (gpsTimer.read_ms() >= GPS_REFRESH) + { + gpsTimer.reset(); + if (myGPS.fix) { + // pc.printf("Location: %5.2f%c, %5.2f%c\n", myGPS.latitude, myGPS.lat, myGPS.longitude, myGPS.lon); + // previousLatitude = currentLatitude; + // previousLongitude = currentLongitude; + // currentLatitude = myGPS.latitude; + // currentLongitude = myGPS.longitude; + transformGPSData(myGPS.latitude, myGPS.lat, myGPS.longitude, myGPS.lon); + } + } + + if (cpmTimer.read() >= CPM_REFRESH) + { + cpmTimer.reset(); + calculateCPM(); + } + + if (fuelTimer.read() >= FUEL_REFRESH) + { + fuelTimer.reset(); + readFuelGauge(); + } + + // special 1 time timer to begin battery monitoring for emergency lo battery warning + + if( batteryEmergencyPause.read_ms() >= EMERBEGIN ) + { + batteryEmergencyPause.stop(); + startBatteryEmergency = true; + } + + /** LoRa Data Transmision **/ + if (locationCountDown == 0) + { + locationCountDown = LOCATION_INTERVAL; + transmitLocation(); + } + if (cpmCountDown == 0) + { + cpmCountDown = CPM_INTERVAL; + transmitCPM(); + } + if (fuelCountDown == 0) + { + fuelCountDown = FUEL_INTERVAL; + transmitFuel(); + } + + } // end loop + +} + +/** GPS Functions **/ +void transformGPSData(double lat, char parallel, double lon, char meridian) +{ + float degrees = floor(lat/100.00); + double minutes = lat - (100.00*degrees); + minutes /= 60.00; + degrees += minutes; + if (parallel=='S') { degrees *= -1.00; } + + double dLatitude = degrees; + + degrees = floor(lon/100.00); + minutes = lon - (100.00*degrees); + minutes /= 60.00; + degrees += minutes; + if (meridian == 'W') { degrees *= -1.00; } + + double dLongitude = degrees; + currentLatitude = dLatitude; + currentLongitude = dLongitude; + pc.printf("LAT: %f ", dLatitude); + pc.printf("LON: %f\n", dLongitude); +} + +/** CPM functions **/ +void calculateCPM() +{ + + currentSignalCount = signalCounter - previousTotalSignalCount; + previousTotalSignalCount = signalCounter; + + currentNoiseCount = noiseCounter - previousTotalNoiseCount; + previousTotalNoiseCount = noiseCounter; + + previousCPM = currentCPM; + currentCPM = currentSignalCount - currentNoiseCount; + + pc.printf("signal: %d, noise: %d, ", currentSignalCount, currentNoiseCount); + pc.printf("Current CPM: %d\n", currentCPM); + +} + +/** Fuel Guage Functions **/ +void readFuelGauge() +{ + max17055.v_cell(&batteryVoltage); + printf("%6.3fV ", batteryVoltage); + + max17055.current(&batteryCurrent); + printf("%6.3fI ", batteryCurrent); + + max17055.temp(&boardTemperature); + printf("%6.3fC ", boardTemperature); + + max17055.reportSOC(&stateOfCharge); + if (startBatteryEmergency and !inBatteryEmergencyState) + { + pc.printf("emergency battery monitoring set\n"); + if (stateOfCharge < 51.0) + { + inBatteryEmergencyState = true; // prevents sending messages over and over again, future versions to reset this when bat > 50 again; + batteryLowTransmit(); + } + } + printf(" SOC:%d\\% ",stateOfCharge); + + // max17055.tte1(&timeToEmpty); + // tteReport = ((5.625)*timeToEmpty)/120.0; + // printf(" TTE:%6.2fhours \n", tteReport); + +} + +/** LoRa TxRx Functions **/ +void transmitLocation() +{ + // transmite GPS/Location data, lat/lon + LoRa.beginPacket(); + + // Packet Header + LoRa.printf("%c",LOCALADDRESSID); LoRa.printf("**"); + LoRa.printf("%c",GPSDATA); LoRa.printf("**"); + + // Packet Contents + LoRa.printf("%f",currentLatitude);LoRa.printf("**"); + LoRa.printf("%f",currentLongitude);LoRa.printf("**"); + + LoRa.endPacket(); + pc.printf("LoRa GPS Packet Sent\n"); +} + +void transmitCPM() +{ + // Transmit Radiation data: CPM = Counts Per Minute, current reading + LoRa.beginPacket(); + + // Packet Header + LoRa.printf("%c",LOCALADDRESSID); LoRa.printf("**"); + LoRa.printf("%c",CPMDATA); LoRa.printf("**"); + + // Packet Contents + LoRa.printf("%d",currentCPM);LoRa.printf("**"); + LoRa.printf("%d", "-1");LoRa.printf("**"); + + LoRa.endPacket(); + pc.printf("LoRa CPM Packet Sent\n"); +} +void transmitFuel() +{ + // Transimet Battery/Fuel Gauge data: voltage, current, temp + LoRa.beginPacket(); + + // Packet Header + LoRa.printf("%c",LOCALADDRESSID); LoRa.printf("**"); + LoRa.printf("%c",FUELDATA); LoRa.printf("**"); + + LoRa.printf("%d",stateOfCharge);LoRa.printf("**"); + LoRa.printf("%f",tteReport);LoRa.printf("**"); // time to empty in hours + LoRa.printf("%f",boardTemperature);LoRa.printf("**"); + + // Packet Contents + + LoRa.endPacket(); + pc.printf("LoRa Fuel Gauge Packet Sent\n"); +} + +void batteryLowTransmit() +{ + /** broadcast warning low battery/increased transmisson intervals **/ + + // extend transmission intervals to conserve power + LOCATION_INTERVAL = 150.0; + CPM_INTERVAL = 600.0; + FUEL_INTERVAL = 900.0; + + // Transimet Battery/Fuel Gauge data: voltage, current, temp + LoRa.beginPacket(); + + // Packet Header + LoRa.printf("%c",LOCALADDRESSID); LoRa.printf("**"); + LoRa.printf("%c",LOWBATTERY); LoRa.printf("**"); + + LoRa.printf("%d",stateOfCharge);LoRa.printf("**"); + + LoRa.endPacket(); + pc.printf("LoRa Low Battery Packet Sent\n"); + +} + +void onReceive(int packetSize) +{ + char msg[45]; + pc.printf("PACKET RECEIVED, SIZE:%d \n", packetSize); + for (int i = 0; i<packetSize; i++) + { if ( i < 45) + { + msg[i] = (char)LoRa._getc(); + } + } + pc.printf("RSSI: %d, ", LoRa.packetRssi()); pc.printf("MSG:%s \n",msg); + if (msg[0] == LOCALADDRESSID) + { + pc.printf("received from %x\n", msg[0]); + } + else { + pc.printf("dont know who, %x is, ignore msg\n", msg[0]); + } +}