Mega & AS3935 Lightning Detector

I just got one of these sensors to use for a project, and tested it first on a Genuine UNO using the example code from this library: GitHub - raivisr/AS3935-Arduino-Library: AS3935 Franklin Lightning Sensor™ IC by AMS Arduino library

It works fine on the UNO, I moved it over to the Mega that I’m using and used the same example code, and it doesn’t work. From what I can tell it doesn’t calibrate.



I’ve been through the wiring a dozen times, and it’s wired correctly. I’ve check the continuity through all the connections and it’s getting power. I’m completely out of ideas as to why it isn’t working. Am I missing something obvious?

Here’s the code, I made no changes to it.

/*
  LightningDetector.pde - AS3935 Franklin Lightning Sensor™ IC by AMS library demo code
  Copyright (c) 2012 Raivis Rengelis (raivis [at] rrkb.lv). All rights reserved.
  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 <SPI.h>
#include <AS3935.h>

void printAS3935Registers();

// Function prototype that provides SPI transfer and is passed to
// AS3935 to be used from within library, it is defined later in main sketch.
// That is up to user to deal with specific implementation of SPI
// Note that AS3935 library requires this function to have exactly this signature
// and it can not be member function of any C++ class, which happens
// to be almost any Arduino library
// Please make sure your implementation of choice does not deal with CS pin,
// library takes care about it on it's own
byte SPItransfer(byte sendByte);

// Iterrupt handler for AS3935 irqs
// and flag variable that indicates interrupt has been triggered
// Variables that get changed in interrupt routines need to be declared volatile
// otherwise compiler can optimize them away, assuming they never get changed
void AS3935Irq();
volatile int AS3935IrqTriggered;

// First parameter - SPI transfer function, second - Arduino pin used for CS
// and finally third argument - Arduino pin used for IRQ
// It is good idea to chose pin that has interrupts attached, that way one can use
// attachInterrupt in sketch to detect interrupt
// Library internally polls this pin when doing calibration, so being an interrupt pin
// is not a requirement
AS3935 AS3935(SPItransfer,SS,2);

void setup()
{
  Serial.begin(9600);
  // first begin, then set parameters
  SPI.begin();
  // NB! chip uses SPI MODE1
  SPI.setDataMode(SPI_MODE1);
  // NB! max SPI clock speed that chip supports is 2MHz,
  // but never use 500kHz, because that will cause interference
  // to lightning detection circuit
  SPI.setClockDivider(SPI_CLOCK_DIV16);
  // and chip is MSB first
  SPI.setBitOrder(MSBFIRST);
  // reset all internal register values to defaults
  AS3935.reset();
  // and run calibration
  // if lightning detector can not tune tank circuit to required tolerance,
  // calibration function will return false
  if(!AS3935.calibrate())
    Serial.println("Tuning out of range, check your wiring, your sensor and make sure physics laws have not changed!");

  // since this is demo code, we just go on minding our own business and ignore the fact that someone divided by zero

  // first let's turn on disturber indication and print some register values from AS3935
  // tell AS3935 we are indoors, for outdoors use setOutdoors() function
  AS3935.setIndoors();
  // turn on indication of distrubers, once you have AS3935 all tuned, you can turn those off with disableDisturbers()
  AS3935.enableDisturbers();
  printAS3935Registers();
  AS3935IrqTriggered = 0;
  // Using interrupts means you do not have to check for pin being set continiously, chip does that for you and
  // notifies your code
  // demo is written and tested on ChipKit MAX32, irq pin is connected to max32 pin 2, that corresponds to interrupt 1
  // look up what pins can be used as interrupts on your specific board and how pins map to int numbers

  // ChipKit Max32 - irq connected to pin 2
  attachInterrupt(1,AS3935Irq,RISING);
  // uncomment line below and comment out line above for Arduino Mega 2560, irq still connected to pin 2
  // attachInterrupt(0,AS3935Irq,RISING);
}

void loop()
{
  // here we go into loop checking if interrupt has been triggered, which kind of defeats
  // the whole purpose of interrupts, but in real life you could put your chip to sleep
  // and lower power consumption or do other nifty things
  if(AS3935IrqTriggered)
  {
    // reset the flag
    AS3935IrqTriggered = 0;
    // first step is to find out what caused interrupt
    // as soon as we read interrupt cause register, irq pin goes low
    int irqSource = AS3935.interruptSource();
    // returned value is bitmap field, bit 0 - noise level too high, bit 2 - disturber detected, and finally bit 3 - lightning!
    if (irqSource & 0b0001)
      Serial.println("Noise level too high, try adjusting noise floor");
    if (irqSource & 0b0100)
      Serial.println("Disturber detected");
    if (irqSource & 0b1000)
    {
      // need to find how far that lightning stroke, function returns approximate distance in kilometers,
      // where value 1 represents storm in detector's near victinity, and 63 - very distant, out of range stroke
      // everything in between is just distance in kilometers
      int strokeDistance = AS3935.lightningDistanceKm();
      if (strokeDistance == 1)
        Serial.println("Storm overhead, watch out!");
      if (strokeDistance == 63)
        Serial.println("Out of range lightning detected.");
      if (strokeDistance < 63 && strokeDistance > 1)
      {
        Serial.print("Lightning detected ");
        Serial.print(strokeDistance,DEC);
        Serial.println(" kilometers away.");
      }
    }
  }
}

void printAS3935Registers()
{
  int noiseFloor = AS3935.getNoiseFloor();
  int spikeRejection = AS3935.getSpikeRejection();
  int watchdogThreshold = AS3935.getWatchdogThreshold();
  Serial.print("Noise floor is: ");
  Serial.println(noiseFloor,DEC);
  Serial.print("Spike rejection is: ");
  Serial.println(spikeRejection,DEC);
  Serial.print("Watchdog threshold is: ");
  Serial.println(watchdogThreshold,DEC);  
}

// this is implementation of SPI transfer that gets passed to AS3935
// you can (hopefully) wrap any SPI implementation in this
byte SPItransfer(byte sendByte)
{
  return SPI.transfer(sendByte);
}

// this is irq handler for AS3935 interrupts, has to return void and take no arguments
// always make code in interrupt handlers fast and short
void AS3935Irq()
{
  AS3935IrqTriggered = 1;
}

Thanks a lot!

A fresh start this morning and a bit of reading and I found the problem is here:/

AS3935 AS3935(SPItransfer,10,2); //change to AS3935(SPITransfer,9,3) if using slot #2

If I change the '10' to '53' per the hookup diagram with the library, it still doesn't work, but if I move the CS connection to pin 10, it does work.

Now I just need to sort out the noise floor issues.

Is there a certain order in which multiple SPI devices need to be initialized? I have the AS3935 and a Data logger, and I was neatening up my code when I moved the init code for the AS3935 further down in the void setup. After I did that, neither one would initialize. I moved it up before the Data logger init, and now they both initialize fine. Can’t really see a good reason for it to work in one spot and not in another.

Hopefully someone can help out, this is still related to the AS3935 device. I also have this shield:

https://www.amazon.com/gp/product/B014PFXKNO/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1

The SD card uses SPI, and when I had it running on my UNO it was using pins 10,11,12,13 of course. I got all the example code working on the UNO first and then started integrating the code into my main project on the Mega. At the time I never changed the SD.Begin line which told it to use pints 10,11,12,13. But it worked, so I never looked into it any further. After I got the AS3935 I did some checking on it and that's when I realized that there shouldn't be any SPI on those pins on the Mega, but it works there.

After I started working with the AS3935 the SD card would no longer function on those pins with the AS3935 being connected to 50,51,52,53. So I added a header onto the bottom of the board to connect to the ICSP near the Reset Switch. I then made set of jumpers to jump over to pints 11,12,13 on the shield since the SD circuit seems to be hardwired to those pins.

I got the two devices working in concert, sort of. It was a little flakey but changing the order of which device got initialized first seemed to resolve that. Then yesterday I connected my 4x20 I2C LCD display, that already had been completely coded. With that connected, every time the AS3935 would hit the subroutine for detecting lightning, the entire Mega would lock up. With the LCD disconnected, it would run fine.

At this point, I have pulled out all the code related to the AS3935 and everything is working, and the SD is again running on pins 10,11,12,13 on the Mega. Can someone explain why I'm accessing the SPI bus when I shouldn't be? I suspect that's part of the problem, and the only solution would be is to clip those pins on the shield where they go into the Mega.

Thanks.

I had similar problem with that sensor. It is not worth it to buy that sensor since it gave me many problems.

Instead I went for this other sensor instead (With Software + Lightning Strike Storm Distance Sensor AS3935 MA5532 Arduino | eBay). It has sufficient documentation and works pretty well.