Richard Cullen
/
as3935
This is a working demo of the AS3935 Lightning detector using the NUCLEO-L013K6.
Diff: AS3935.cpp
- Revision:
- 0:75defe5eed80
--- /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; +} + + +