Richard Cullen
/
as3935
This is a working demo of the AS3935 Lightning detector using the NUCLEO-L013K6.
Revision 0:75defe5eed80, committed 2017-06-20
- Comitter:
- madelectroneng
- Date:
- Tue Jun 20 08:36:25 2017 +0000
- Commit message:
- Working demo on nucleo-l031k6
Changed in this revision
diff -r 000000000000 -r 75defe5eed80 AS3935.cpp --- /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; +} + + +
diff -r 000000000000 -r 75defe5eed80 AS3935.h --- /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
diff -r 000000000000 -r 75defe5eed80 main.cpp --- /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
diff -r 000000000000 -r 75defe5eed80 mbed.bld --- /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