This is a working demo of the AS3935 Lightning detector using the NUCLEO-L013K6.

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
madelectroneng
Date:
Tue Jun 20 08:36:25 2017 +0000
Commit message:
Working demo on nucleo-l031k6

Changed in this revision

AS3935.cpp Show annotated file Show diff for this revision Revisions of this file
AS3935.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AS3935.cpp	Tue Jun 20 08:36:25 2017 +0000
@@ -0,0 +1,360 @@
+/*
+AS3935.cpp - AS3935 Franklin Lightning Sensor™ IC by AMS library
+Copyright (c) 2012 Raivis Rengelis (raivis [at] rrkb.lv). All rights reserved.
+Porté sur MBED par Valentin, version I2C
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "AS3935.h"
+#include "pinmap.h"
+
+unsigned long sgIntrPulseCount = 0; 
+
+
+AS3935::AS3935(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name, int hz) :  m_Spi(mosi, miso, sclk), m_Cs(cs, 1),  m_FREQ(hz)
+{
+ 
+    //Enable the internal pull-up resistor on MISO
+    pin_mode(miso, PullUp);
+
+    //Configure the SPI bus
+    m_Spi.format(8, 1);
+    printf("spi bus frequency set to %d hz\r\n",hz);
+    m_Spi.frequency(hz);
+  
+}
+ 
+char AS3935::_SPITransfer2(char high, char low)
+{
+    m_Cs = 0;
+    m_Spi.write(high);
+    char regval = m_Spi.write(low);
+    m_Cs = 1;
+    return regval;  
+}
+
+char AS3935::_rawRegisterRead(char reg)
+{
+    return _SPITransfer2((reg & 0x3F) | 0x40, 0);
+}
+
+
+char AS3935::_ffsz(char mask)
+{
+    char i = 0;
+       
+    while(!(mask & 1)) {
+           mask >>= 1;
+          i++;
+    }
+ 
+    return i;
+}
+
+void AS3935::registerWrite(char reg, char mask, char data)
+{
+   
+    char regval;
+    regval = _rawRegisterRead(reg);
+    regval &= ~(mask);
+    regval |= (data << (_ffsz(mask)));
+    m_Cs = 0;
+    m_Spi.write(reg);
+    m_Spi.write(regval);
+    //printf("raw transfer for reg %x is 0x%02x\r\n", reg, regval);
+    m_Cs = 1;
+    wait_ms(2);
+}
+
+char AS3935::registerRead(char reg, char mask)
+{
+    char regval;
+    regval = _rawRegisterRead(reg);
+    // printf("raw regval is 0x%02x\r\n", regval);
+    regval = regval & mask;
+    regval >>= (_ffsz(mask));
+    return regval;
+}
+
+void AS3935::presetDefault()
+ {
+    m_Cs = 0;
+    m_Spi.write(0x3C);
+    m_Spi.write(0x96);
+    m_Cs = 1;
+    wait_ms(2);
+}
+
+void AS3935::init()
+ {
+    presetDefault();
+    registerWrite(AS3935_WDTH, 0x04);  // set WDTH level to 4 
+}
+ 
+void AS3935::powerDown()
+{
+    registerWrite(AS3935_PWD,1);
+}
+
+
+
+int AS3935::interruptSource()
+{
+    return registerRead(AS3935_INT);
+}
+
+void AS3935::disableDisturbers()
+{
+    registerWrite(AS3935_MASK_DIST,1);
+}
+
+void AS3935::enableDisturbers()
+{
+    registerWrite(AS3935_MASK_DIST,0);
+} 
+
+int AS3935::getMinimumLightnings()
+{
+    return registerRead(AS3935_MIN_NUM_LIGH);
+}
+
+int AS3935::setMinimumLightnings(int minlightning)
+{
+    registerWrite(AS3935_MIN_NUM_LIGH,minlightning);
+    return getMinimumLightnings();
+}
+
+int AS3935::lightningDistanceKm()
+{
+    return registerRead(AS3935_DISTANCE);
+}
+
+void AS3935::setIndoors()
+{
+    registerWrite(AS3935_AFE_GB,AS3935_AFE_INDOOR);
+}
+
+int AS3935::getGain()
+{
+    return registerRead(AS3935_AFE_GB);
+}
+
+void AS3935::setOutdoors()
+{
+    registerWrite(AS3935_AFE_GB,AS3935_AFE_OUTDOOR);
+}
+
+int AS3935::getNoiseFloor()
+{
+    return registerRead(AS3935_NF_LEV);
+}
+
+int AS3935::setNoiseFloor(int noisefloor)
+{
+    registerWrite(AS3935_NF_LEV,noisefloor);
+    return getNoiseFloor();
+}
+
+int AS3935::getSpikeRejection()
+{
+    return registerRead(AS3935_SREJ);
+}
+
+int AS3935::setSpikeRejection(int srej)
+{
+    registerWrite(AS3935_SREJ, srej);
+    return getSpikeRejection();
+}
+
+int AS3935::getWatchdogThreshold()
+{
+    return registerRead(AS3935_WDTH);
+}
+
+int AS3935::setWatchdogThreshold(int wdth)
+{
+    registerWrite(AS3935_WDTH,wdth);
+    return getWatchdogThreshold();
+}
+
+int AS3935::getTuneCap()
+{
+    return registerRead(AS3935_TUN_CAP);    
+}
+        
+int AS3935::setTuneCap(int cap)
+{
+    registerWrite(AS3935_TUN_CAP,cap);
+    return getTuneCap();   
+}
+
+void AS3935::clearStats()
+{
+    registerWrite(AS3935_CL_STAT,1);
+    registerWrite(AS3935_CL_STAT,0);
+    registerWrite(AS3935_CL_STAT,1);
+}
+    
+static void intrPulseCntr(void)    {sgIntrPulseCount++;} 
+
+int AS3935::calibrateRCOs (InterruptIn &intrIn)
+{
+    int rc;
+    uint8_t trco;
+    uint8_t srco;
+    Timer pulseTimer;
+    int timeNow; 
+    unsigned long measFreq; 
+    
+    intrIn.rise(intrPulseCntr); 
+    
+    _SPITransfer2(0x3D, 0x96);                        // send command to calibrate the internal RC oscillators           
+    registerWrite(AS3935_DISP_TRCO, 1);               // put TRCO on the IRQ line for measurement   
+    wait_ms(20);                                      // wait for the chip to output the frequency, ususally ~2 ms 
+    
+    pulseTimer.reset(); 
+    pulseTimer.start(); 
+    sgIntrPulseCount = 0;                             // reset the interrupt counter which serves as our frequency\pulse counter     
+    
+    timeNow = 0; 
+    while (timeNow < 500)                             // wait for 0.5 seconds
+    {
+      timeNow = pulseTimer.read_ms(); 
+    }
+    
+    registerWrite(AS3935_DISP_TRCO, 0);               // stop the output of the frequncy on IRQ line       
+    measFreq = sgIntrPulseCount << 1;                 // calculate the measure frequency based upon period of capture and freq scaler
+
+    printf("timer RCO: %ld Hz\n\r", measFreq);
+    
+    trco=registerRead(0x3A, 0x80);                    // Read out Calibration of TRCO done
+    srco=registerRead(0x3B, 0x80);                    // Readout Calibration of SRCO done
+    if(trco != 0x00 && srco != 0x00)
+    {
+        rc = 1;
+        printf("cal is done\r\n");
+    }
+    else
+    {
+        printf("cal is not done\r\n");
+        rc = 0;
+    }
+
+    return rc;
+}
+
+
+unsigned long AS3935::tuneAntenna(InterruptIn &intrIn)
+{
+#define ANTENA_RES_FREQ     (unsigned long)500000
+Timer pulseTimer;
+int timeNow; 
+unsigned long measFreq; 
+unsigned long measFreqBest = 0; 
+unsigned char tunCapCnt    = 0; 
+unsigned char tunCapBest   = 0;     
+unsigned long minError     = ANTENA_RES_FREQ; 
+unsigned long error; 
+    
+    intrIn.rise(intrPulseCntr); 
+    _SPITransfer2(3, 0x80);                             // set frequency division to 64  
+    
+    for (tunCapCnt = 0; tunCapCnt < 16; ++tunCapCnt)    // loop for all possible values of the tuning capacitor
+    {
+      _SPITransfer2(8, 0x80+tunCapCnt);                 // set the tuning cap and have the frequency output to the IRQ line 
+      wait_ms(20);                                      // wait for the chip to output the frequency, ususally ~2 ms 
+
+      pulseTimer.reset(); 
+      pulseTimer.start(); 
+      sgIntrPulseCount = 0;                             // reset the interrupt counter which serves as our frequency\pulse counter     
+    
+      timeNow = 0; 
+      while (timeNow < 500)                             // wait for 0.5 seconds
+      {
+        timeNow = pulseTimer.read_ms(); 
+      }
+      
+      _SPITransfer2(8, 0x00);                           // stop the output of the frequncy on IRQ line 
+      
+      measFreq = sgIntrPulseCount << 7;                 // calulate the measure frequency based upon period of capture and freq scaler
+      
+      if (measFreq < ANTENA_RES_FREQ)                   // calculate error between actual and desired frequency 
+        error = ANTENA_RES_FREQ - measFreq; 
+      else 
+        error = measFreq - ANTENA_RES_FREQ; 
+        
+      if (error < minError)                             // update the best capacitor tuning so far 
+      {
+        tunCapBest = tunCapCnt; 
+        minError = error; 
+        measFreqBest = measFreq; 
+      }
+      
+      printf("sgIntrCount[%ld] measFreq[%ld] timeNow[%ld] tunCapBest[%d]\n\r", sgIntrPulseCount, measFreq, timeNow, tunCapBest);
+    }
+    setTuneCap(tunCapBest); //  500kHz);                // set the best capacitor tuning that was found 
+    return measFreqBest; 
+}
+
+
+void AS3935::_rawRegisterRead(unsigned char reg, unsigned char mask, unsigned char *rxBuff, unsigned char numBytes)
+{
+    mask = mask; // unused 
+    
+    m_Cs = 0;
+    m_Spi.write((reg & 0x3F) | 0x40);
+    
+    for (unsigned char idx = 0; idx < numBytes; ++idx) 
+    {
+        rxBuff[idx] = m_Spi.write(0);
+    }
+    m_Cs = 1;
+}
+
+unsigned long AS3935::getEnergy(void)
+{
+    unsigned long retVal; 
+    unsigned char rxBuff[3];
+    
+    #if 0 
+    rxBuff[0] = registerRead(AS3935_S_LIG_L); 
+    rxBuff[1] = registerRead(AS3935_S_LIG_M); 
+    rxBuff[2] = registerRead(AS3935_S_LIG_MM); 
+    #else 
+    _rawRegisterRead(AS3935_S_LIG_L, rxBuff, 3); 
+    #endif 
+    
+    retVal = ((unsigned long)rxBuff[2] << 16) | ((unsigned long)rxBuff[1] << 8) | (unsigned long)rxBuff[0]; 
+    retVal &= 0x001fffff; 
+    return retVal; 
+}
+
+bool AS3935::getConfigRegisters(unsigned char *pBuff, unsigned char buffLen)
+{
+    unsigned char cnt = 0; 
+    
+    if (NULL == pBuff)    
+        return false; 
+    
+    for (cnt = 0; cnt < buffLen && cnt < MAX_CONFIG_REGS; ++cnt) 
+    {
+        pBuff[cnt] = _rawRegisterRead(cnt); 
+    }
+    return true; 
+}    
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AS3935.h	Tue Jun 20 08:36:25 2017 +0000
@@ -0,0 +1,210 @@
+/*
+AS3935.h - AS3935 Franklin Lightning Sensor™ IC by AMS library
+Copyright (c) 2012 Raivis Rengelis (raivis [at] rrkb.lv). All rights reserved.
+Portée sur MBED par Valentin
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _AS3935_H
+#define _AS3935_H
+
+#include "mbed.h"
+#include <stdint.h>
+
+//#include "i2c.hpp"
+
+// register access macros - register address, bitmask
+#define AS3935_AFE_GB 0x00, 0x3E
+#define AS3935_PWD 0x00, 0x01
+#define AS3935_NF_LEV 0x01, 0x70
+#define AS3935_WDTH 0x01, 0x0F
+#define AS3935_CL_STAT 0x02, 0x40
+#define AS3935_MIN_NUM_LIGH 0x02, 0x30
+#define AS3935_SREJ 0x02, 0x0F
+#define AS3935_LCO_FDIV 0x03, 0xC0
+#define AS3935_MASK_DIST 0x03, 0x20
+#define AS3935_INT 0x03, 0x0F
+#define AS3935_S_LIG_L  0x04, 0xff
+#define AS3935_S_LIG_M  0x05, 0xff
+#define AS3935_S_LIG_MM 0x06, 0x1f
+#define AS3935_DISTANCE 0x07, 0x3F
+#define AS3935_DISP_LCO 0x08, 0x80
+#define AS3935_DISP_SRCO 0x08, 0x40
+#define AS3935_DISP_TRCO 0x08, 0x20
+#define AS3935_TUN_CAP 0x08, 0x0F
+#define MAX_CONFIG_REGS     9 
+
+// other constants
+#define AS3935_AFE_INDOOR 0x12 
+#define AS3935_AFE_OUTDOOR 0x0E
+
+#define AS3935_EVENT_NOISE     1 
+#define AS3935_EVENT_DISTURBER 4 
+#define AS3935_EVENT_LIGHTNING 8 
+
+
+
+
+class AS3935 {
+    
+    public:
+             
+    /** Create a virtual file system for accessing SD/MMC cards via SPI
+     *
+     * @param mosi The SPI data out pin.
+     * @param miso The SPI data in pin.
+     * @param sclk The SPI clock pin.
+     * @param cs The SPI chip select pin.
+     * @param name The name used to access the spi bus.
+     * @param hz The SPI bus frequency (defaults to 1MHz).
+    */
+     
+    AS3935(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name, int hz = 2000000);
+     
+    //destruction         
+    //~AS3935();   
+        
+    //write to specified register specified data using specified bitmask,     
+    //the rest of the register remains intact
+    void registerWrite(char reg, char mask, char data);
+        
+    //read specified register using specified bitmask and return value aligned     
+    //to lsb, i.e. if value to be read is in a middle of register, function     
+    //reads register and then aligns lsb of value to lsb of byte
+    char registerRead(char reg, char mask);
+        
+    //reset all the registers on chip to default values
+    void reset();
+        
+    //set preset defaults
+    void presetDefault();
+        
+    //initialization
+    void init();
+    
+    // replicate the acurite sequece
+    void acurite();
+      
+    //put chip into power down mode
+    void powerDown();
+    
+    //bring chip out of power down mode and perform RCO calibration
+    void powerUp();
+    
+    //return interrupt source, bitmask, 0b0001 - noise, 0b0100 - disturber,     
+    //0b1000 - lightning
+    int interruptSource();
+        
+    //disable indication of disturbers
+    void disableDisturbers();
+    
+    //enable indication of distrubers
+    void enableDisturbers();
+    
+    //return number of lightnings that need to be detected in 17 minute period     
+    //before interrupt is issued
+    int getMinimumLightnings();
+    
+    //set number of lightnings that need to be detected in 17 minute period     
+    //before interrupt is issued
+    int setMinimumLightnings(int minlightning);
+    
+    //return distance to lightning in kilometers, 1 means storm is overhead,     
+    //63 means it is too far to reliably calculate distance
+    int lightningDistanceKm();
+        
+    // load gain preset to operate indoors
+    void setIndoors();
+        
+    //load gain preset to operate outdoors
+    void setOutdoors();
+    
+    //get gain preset 
+    int getGain();
+        
+    //return noise floor setting - refer to datasheet for meaning and range
+    int getNoiseFloor();
+        
+    //set noise floor setting
+    int setNoiseFloor(int noisefloor);
+        
+    //return spike rejection value - refer to datasheet for meaning and range
+    int getSpikeRejection();
+        
+    //set spike rejection value
+    int setSpikeRejection(int srej);
+        
+    //return watchdog threshold value - refer to datasheet for meaning and range
+    int getWatchdogThreshold();
+        
+    //set watchdog threshold value
+    int setWatchdogThreshold(int wdth);
+        
+    //return tune Capacity value 
+    int getTuneCap();
+        
+    //set tune Capacity value
+    int setTuneCap(int cap);
+        
+    //clear internal accumulated lightning statistics
+    void clearStats();
+
+    int calibrateRCOs (InterruptIn &intrIn);
+
+    unsigned long tuneAntenna(InterruptIn &intrIn); 
+    unsigned long getEnergy(void);
+    bool          getConfigRegisters(unsigned char *pBuff, unsigned char buffLen);
+
+    
+    /** Attach a function, lightning interrupt
+     * @param fptr pointer to a void function, or 0 to set as none
+     */
+    void attach(void (*fptr)(void)) { 
+//        _func.attach(fptr);
+    }
+    /** Attach a member function, lightning interrupt
+     * @param tptr pointer to the object to call the member function on
+     * @param mptr pointer to the member function to be called
+     */
+    template<typename T>
+    void attach(T *tptr, void (T::*mptr)(void)) { 
+        _func.attach(tptr, mptr); 
+    }
+    
+         
+    private:
+    //I2C i2c;   
+    //DigitalOut _irq;
+    SPI m_Spi;
+    DigitalOut m_Cs;
+    //InterruptIn m_Cd;
+    
+    int m_CdAssert;
+    const int m_FREQ;
+    int _adress;
+    FunctionPointer _func;
+    char _rawRegisterRead(char reg);
+    void _rawRegisterRead(unsigned char reg, unsigned char mask, unsigned char *rxBuff, unsigned char numBytes);
+    char _SPITransfer2(char high, char low);
+    char _ffsz(char mask);
+    
+
+
+
+};
+
+/* !_AS3935_H_ */
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jun 20 08:36:25 2017 +0000
@@ -0,0 +1,68 @@
+#include "mbed.h"
+#include "AS3935.h"
+ 
+AS3935 ld(D11, D12, D13, D10, "ld", 2000000); // MOSI, MISO, SCK, CS, SPI bus freq (hz) 
+InterruptIn IntLightning(D2); //IRQ AS3935
+Serial pc(USBTX, USBRX);
+ 
+void DetectLightning()
+{
+    char OriginInt;
+     wait_ms(2); 
+    OriginInt = ld.interruptSource();
+    if (OriginInt == 1) { //
+        pc.printf(" Noise level too high\r\n");
+        }
+    if (OriginInt == 4) { //
+        pc.printf(" Disturber\r\n");
+        }
+    if (OriginInt == 8) { // detection
+        // pc.printf(" Lightning detection\r\n");
+        pc.printf("Lightning detection, distance=%dkm\r\n", ld.lightningDistanceKm());
+        pc.printf("Energy %d\r\n", ld.getEnergy());
+        ld.clearStats();
+ 
+        }
+}
+ 
+ 
+int main() {
+    pc.baud(9600);
+    pc.printf("\r\nstart lightning detector\r\n");
+    
+    //initialisations
+//    ld.reset();
+    ld.setTuneCap(1); // 500kHz
+//    ld.powerUp();
+    ld.setIndoors();  
+    ld.setMinimumLightnings(1);
+    //ld.setSpikeRejection(2);
+    ld.setNoiseFloor(2);
+  ld.disableDisturbers();
+ //   ld.enableDisturbers();
+    ld.setWatchdogThreshold(2);
+    wait_ms(10);
+    IntLightning.rise(&DetectLightning);
+    int MinBlysk = ld.getMinimumLightnings();
+    int Noise = ld.getNoiseFloor();
+    int TuneCap = ld.getTuneCap();
+    int SpikeRej = ld.getSpikeRejection();
+    int WatchDog = ld.getWatchdogThreshold();
+     
+    pc.printf(" Min wylad: %i", MinBlysk);
+    pc.printf("\r\n");
+    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");
+    while(1) {
+   //     led1 = ! led1;
+        wait(0.2);
+     }
+    
+ 
+ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Jun 20 08:36:25 2017 +0000
@@ -0,0 +1,1 @@
+https://mbed.org/users/mbed_official/code/mbed/builds/0f02307a0877
\ No newline at end of file