basic lightning detector with gps and sd card logging
Dependencies: AS3935 AdafruitGPS SDFileSystem TSI mbed ConfigFile
Diff: main.cpp.orig
- Revision:
- 12:7c58c7a6b25c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp.orig Wed Jul 01 19:39:05 2015 +0000 @@ -0,0 +1,502 @@ +#include "mbed.h" +#include "GPS.h" +#include "main.h" +#include "TSISensor.h" +#include "SDFileSystem.h" +#include "AS3935.h" +#include "ConfigFile.h" +#include "datetime.h" +#include "time.h" +#include <string> + +#define FW_VER 3 + + // frdm-kl25z as3935 connections for spi1 + // ------------------------------------------------ + // Header -- kl25z -- SD/MMC + // J2-20 -- PTE1 -- MOSI + // J9-13 -- PTE4 -- CS + // J2-14 -- GND -- Vss (GND) + // J9-9 -- PTE2 -- SCK + // J9-11 -- PTE3 -- MISO + +AS3935 ld(PTE1, PTE3, PTE2, PTE4, "ld", 1000000); // MOSI, MISO, SCK, CS, SPI bus freq (hz) +InterruptIn IntLightning(PTA12); //IRQ AS3935 + + + // frdm-kl25z sd card connections spi0 + // ------------------------------------------------ + // Header -- kl25z -- SPI + // J2-8 -- PTD2 -- MOSI + // J2-6 -- PTD0 -- CS + // J9-12 -- GND -- Vss (GND) + // J9-4 -- P3V3 -- Vdd (+3.3v) + // J2-12 -- PTD1 -- SCK + // J9-14 -- GND -- Vss (GND) + // J2-10 -- PTD3 -- MISO + +SDFileSystem sd(PTD2, PTD3, PTD1, PTD0, "sd"); // MOSI, MISO, SCK, CS + +Serial pc(USBTX, USBRX); +GPS gpsd(PTE20, PTE21); +DigitalOut red(LED_RED); +DigitalOut green(LED_GREEN); +//DigitalOut blue(LED_BLUE); don't use the blue led, due to a board error, writing to the blue led kills spi +bool debug=false; +void writeLogFile(int interruptSource, int distance, long energy); +char logName[]="lightning_data.csv"; +int rdistance, rinterrupt; +char directory[]="/sd/lightning_data"; +int OriginInt=-1; +int gDistance=-1; +long energy=-1; +struct tm Clock; + +typedef struct +{ +unsigned int bOutdoorMode; +unsigned int noiseFloor; +unsigned int wdogThresh; +unsigned int bClrStat; +unsigned int minNumLight; +unsigned int spikeRej; +unsigned int maskDisturber; +}sys_cfg_t; + +// default configuration values +sys_cfg_t sysCfg = { .bOutdoorMode = 1, + .noiseFloor = 2, + .wdogThresh = 2, + .bClrStat = 0, + .minNumLight = 0, + .spikeRej = 2, + .maskDisturber = 0, + }; + + +void DetectLightning() +{ + OriginInt = ld.interruptSource(); + gDistance = ld.lightningDistanceKm(); + energy = ld.getEnergy(); +} + + void writeLogFile(int interruptSource, int distance, long energy) +{ + char logFilePath[128]; + static bool header=false; + FILE *fp; + + sprintf(logFilePath, "%s/%s", directory,logName); + sd.mount(); + fp = fopen(logFilePath, "a"); + if(fp == NULL) { + // retry + wait_ms(200); + fp = fopen(logFilePath, "a"); + if (fp == NULL) + { + printf("Could not open file %s for writing\r\n",logFilePath); + sd.unmount(); + printf("unmount sd card \r\n"); + return; + } + } + if (debug) + pc.printf("Opened log file %s\r\n",logFilePath); + // write the log file header + if (header == false) + { + fprintf(fp,"# date,time,raw timestamp,latitude,longitude,distance,interrupt,energy\r\n"); + header = true; + } + // write to the current log file + char time_str[32]; + time_t seconds = time(NULL); + seconds -= 14400; // 14400 = 60*60*4, kludgy way of setting edt + struct tm *tminfo = localtime(&seconds); + strftime(time_str, 32, "%m/%d/%Y,%T", tminfo); + fprintf(fp,"%s,%ld,",time_str,seconds); + fprintf(fp,"%5.7f,%5.7f,", gpsd.lat_deg, gpsd.lon_deg); + fprintf(fp,"%d,",distance); + fprintf(fp,"%d,",interruptSource); + fprintf(fp,"%ld",energy); + fprintf(fp,"\r\n"); + fflush(fp); + f_sync((FIL*)fp); + fclose(fp); + sd.unmount(); + pc.printf("Event: "); + pc.printf(" %s - ", time_str); + switch (interruptSource) + { + case 1: + pc.printf("Noise level too high\r\n"); + break; + case 4: + pc.printf("Disturber\r\n"); + break; + case 8: + pc.printf("Lightning detection, distance=%dkm energy=%ld\r\n", distance, energy); + + if (sysCfg.bClrStat) + ld.clearStats(); + break; + default: + pc.printf("Unknown interrupt %d\r\n", OriginInt); + + } + + if (debug) + pc.printf("Closed log file %s\r\n",logFilePath); +} + + +void writeCfgFile(unsigned char *pBuff, unsigned char buffLen, unsigned char fwVer) +{ + char cfgFilePath[128]; + FILE *fp; + unsigned char cnt = 0; + + sprintf(cfgFilePath, "%s/%s", directory, "config_data.csv"); + sd.mount(); + fp = fopen(cfgFilePath, "w"); + if(fp == NULL) { + // retry + wait_ms(200); + fp = fopen(cfgFilePath, "w"); + if (fp == NULL) + { + printf("Could not open file %s for writing\r\n",cfgFilePath); + sd.unmount(); + printf("unmount sd card \r\n"); + return; + } + } + if (debug) + pc.printf("Opened log file %s\r\n",cfgFilePath); + + // write the header + fprintf(fp,"# FW_VER,REG0,REG1,REG2,REG3,REG4,REG5,REG6,REG7,REG8\r\n"); + + // write the firmware version + fprintf(fp,"%d,", fwVer); + + // write all the configuration registers + for (cnt = 0; cnt < buffLen && cnt < MAX_CONFIG_REGS; ++cnt) + fprintf(fp,"0x%x,", pBuff[cnt]); + + fflush(fp); + f_sync((FIL*)fp); + fclose(fp); + sd.unmount(); + + if (debug) + pc.printf("Closed cfg file %s\r\n",cfgFilePath); +} + + +bool readCfgFile(char *paDirectory, sys_cfg_t *paSysCfg) +{ + bool bRetVal = false; + FILE *fp; + sys_cfg_t lSysCfg; + typedef struct + { + const char *token; + unsigned int *value; + }token_map_t; + + token_map_t tokenMap[] = { {"outdoor_mode", &lSysCfg.bOutdoorMode}, + {"noise_floor", &lSysCfg.noiseFloor}, + {"watchdog_threshold", &lSysCfg.wdogThresh}, + {"clear_stat", &lSysCfg.bClrStat}, + {"minimum_num_light", &lSysCfg.minNumLight}, + {"spike_reject", &lSysCfg.spikeRej}, + {"mask_disturber", &lSysCfg.maskDisturber}, + }; + ConfigFile *plCfgFile; + string fileName; + int count = sizeof(tokenMap) / sizeof(token_map_t); + char szValue[8]; + + if ((NULL == paDirectory) || (NULL == paSysCfg)) + return false; + + // start with whatever configuration params are passed in, in case some params are not found in the file + lSysCfg = *paSysCfg; + + plCfgFile = new ConfigFile(); + fileName = paDirectory; + fileName += "/"; + fileName += "zeus.cfg"; + + sd.mount(); + fp = fopen(fileName.c_str(), "r"); + printf ("\n\rReading configuration file [%s]\n\r", fileName.c_str()); + + // try to read values from the configuration file + if (plCfgFile->read((char *)fileName.c_str())) + { + for (int i = 0; i < count; ++i) + { + if (plCfgFile->getValue((char *)tokenMap[i].token, szValue, sizeof(szValue))) + { + if (1 == sscanf(szValue, "%d", tokenMap[i].value)) + { + printf ("Convert success %s[%d]\n\r", tokenMap[i].token, *(tokenMap[i].value)); + } + } + } + + // copy out the new found values + *paSysCfg = lSysCfg; + bRetVal = true; + } + else + { + printf ("Failed to read configuration file[%s]\n\r", fileName.c_str()); + + // try to create a default configuration file + for (int i = 0; i < count; ++i) + { + if (snprintf(szValue, sizeof(szValue), "%d", *(tokenMap[i].value))) + { + if (plCfgFile->setValue((char *)tokenMap[i].token, szValue)) + { + printf ("Token creation success %s[%s]\n\r", tokenMap[i].token, szValue); + } + } + } + if (plCfgFile->write((char *)fileName.c_str(), NULL, DOS)) + printf ("Success: Created default configuration file [%s]\n\r", fileName.c_str()); + else + printf ("Failed to create default configuration file [%s]\n\r", fileName.c_str()); + } + + if (plCfgFile) + delete plCfgFile; + + if (fp != NULL) + fclose(fp); + + sd.unmount(); + return bRetVal; +} + + +int main() +{ + + unsigned char regBuff[MAX_CONFIG_REGS]; + char c; + Timer refresh_Timer; //sets up a timer for use in loop; how often do we print GPS info? + const int refresh_Time = 1000; //refresh time in ms + TSISensor tsi; // touch slider + unsigned long measFreq; + rdistance=-1; + rinterrupt=-1; + pc.baud(9600); + // initializations for gps + green = 1; + gpsd.setBaud(9600); + gpsd.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); + gpsd.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); + gpsd.sendCommand(PGCMD_ANTENNA); + gpsd.day=01; + gpsd.month=01; + gpsd.year=15; + gpsd.hour=1; + gpsd.minute=1; + gpsd.seconds=1; + red = 1; + green = 1; + pc.printf("Touch slider to start lightning detector application\r\n"); + while(1) { + green = 1; // turn led off + wait_ms(200); + if (tsi.readPercentage()) + break; + green = 0; // turn led on + wait_ms(200); + if (tsi.readPercentage()) + break; + } + //Mount the filesystem + sd.mount(); + mkdir(directory, 0777); + sd.unmount(); + + // read configuration values fro SD file system to allow override of defaults in sysCfg + readCfgFile(directory, &sysCfg); + + pc.printf("\r\nInitialize lightning detector\r\n"); + //initializations for lightning detector + ld.init(); + ld.clearStats(); + + /* The precision of the calibration will depend on the + accuracy of the resonance frequency of the antenna. It is + recommended to first trim the receiver antenna before the + calibration of both oscillators is done. + */ + measFreq = ld.tuneAntenna(IntLightning); + ld.calibrateRCOs(IntLightning); + + if (sysCfg.bOutdoorMode) + ld.setOutdoors(); + else + ld.setIndoors(); + + ld.setMinimumLightnings(sysCfg.minNumLight); + ld.setSpikeRejection(sysCfg.spikeRej); + ld.setNoiseFloor(sysCfg.noiseFloor); + + if (sysCfg.maskDisturber) + ld.disableDisturbers(); + else + ld.enableDisturbers(); + + ld.setWatchdogThreshold(sysCfg.wdogThresh); + IntLightning.rise(&DetectLightning); + + int MinLight = ld.getMinimumLightnings(); + int Noise = ld.getNoiseFloor(); + int TuneCap = ld.getTuneCap(); + int SpikeRej = ld.getSpikeRejection(); + int WatchDog = ld.getWatchdogThreshold(); + + pc.printf("\r\n Min lightning: %i", MinLight); + pc.printf("\r\n"); + pc.printf(" Gain: 0x%02x\r\n",ld.getGain()); + pc.printf(" Noise: %i", Noise); + pc.printf("\r\n"); + pc.printf(" Tune CAP: %i", TuneCap); + pc.printf("\r\n"); + pc.printf(" Spike rej: %i", SpikeRej); + pc.printf("\r\n"); + pc.printf(" Watchdog: %i", WatchDog); + pc.printf("\r\n"); + pc.printf(" LCO calibration: %ld Hz\n\r", measFreq); + + refresh_Timer.start(); //starts the clock on the timer + + // get a copy of all config registers + ld.getConfigRegisters(regBuff, sizeof(regBuff)); + + pc.printf("\n\rSystem Registers:\n\r"); + for (int i = 0; i < sizeof(regBuff); ++i) + pc.printf("REG%d [0x%02x]:\n\r", i, regBuff[i]); + pc.printf("\n\r"); + + // write to the config file + writeCfgFile(regBuff, sizeof(regBuff), FW_VER); + + bool gpsFix=false; + bool rtcRunning=false; + while (1) + { + if (OriginInt != -1) + { + // the ld detector generated an interrupt, log the event + IntLightning.disable_irq(); + writeLogFile(OriginInt,gDistance, energy); + //ld.clearStats(); + OriginInt = -1; + gDistance = -1; + energy = -1; + IntLightning.enable_irq(); + } + + c = gpsd.read(); //queries the GPS + if (debug) + { + if (c) { + printf("%c", c); //this line will echo the GPS data if not paused + continue; + } + } + + //check if we recieved a new message from GPS, if so, attempt to parse it, + if ( gpsd.newNMEAreceived() ) { + if ( !gpsd.parse(gpsd.lastNMEA()) ) { + continue; + } + } + + // if the rtc is not running, update the rtc clock with the latest gps time stamp + if ( rtcRunning == false ) + { + // update rtc with the lastest gps time stamp + SetDateTime(gpsd.year+2000, + gpsd.month-1, + gpsd.day, + gpsd.hour, + gpsd.minute, + gpsd.seconds); + } + + //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 (refresh_Timer.read_ms() >= refresh_Time) + { + if (gpsd.fix) { + // got a gps fix + if (gpsFix == false) + { + // first time fix obtained + gpsFix = true; + // bug check - rtc may not be running. check if it is incrementing + time_t seconds_a = time(NULL); // get the current rtc second count + wait(2); // wait two seconds + time_t seconds_b = time(NULL); // get the current rtc second count + if (seconds_a != seconds_b) + { + // rtc must be running + rtcRunning = true; + pc.printf("RTC is running\r\n"); + } + else + { + // rtc is not running, we need to update the rtc every pass through the while loop + rtcRunning = false; // the gps time will update the rtc + pc.printf("RTC is not running\r\n"); + } + + // set the rtc with the latest gps time + SetDateTime(gpsd.year+2000, + gpsd.month-1, + gpsd.day, + gpsd.hour, + gpsd.minute, + gpsd.seconds); + pc.printf("GPS fix obtained on %02d/%02d/20%02d_%02d:%02d:%02d (UTC)\r\n",gpsd.month,gpsd.day,gpsd.year,gpsd.hour,gpsd.minute,gpsd.seconds); + //pc.printf("Touch slider to suspend application\r\n"); + pc.printf("Waiting for lighting detection...\r\n"); + } + + //red = 1; // turn led off + //pc.printf("turn green on\r\n"); + green = 0; // turn led on + wait_ms(50); + } + else + { + gpsFix = false; + pc.printf("Waiting for GPS FIX\r\n"); + red = 0; // turn led on + } + + // restart the timer for the gps print loop + // writeLogFile(-2); + refresh_Timer.reset(); + } + else + { + //red = 0; // turn led on + //pc.printf("turn green off\r\n"); + green = 1; // turn green led off + } // end else refresh timer + } + +}