basic lightning detector with gps and sd card logging

Dependencies:   AS3935 AdafruitGPS SDFileSystem TSI mbed ConfigFile

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            
+    }
+  
+}