An Introduction To Storm Detector Modules

Lightning storm detectors have been around for a surprisingly long time. The early designs consisted of a pair of metal bells and a pendulum. When there was a charge applied, for example by connecting one bell to the ground and the other to a lightning rod, the bells would ring when a lightning storm was close by. In the mid 18th century, these devices were only practical for demonstration and research purposes, but very likely represent the earliest devices that convert electrostatic charge to mechanical force. A bit over a hundred years later, the first lightning detector was considered by some as the first radio receiver as well.

As soon as I found out about storm detector chips, I knew I would have to get one working. For about $25, I ordered an AMS AS3935 module from China. This chip has been featured before in a number of excellent projects such as Twittering lightning detectors, and networks of Sub-Saharan weather stations. While there’s an Arduino library for interfacing with this IC, I’m going to be connecting it up to an ESP8266 running the NodeMCU firware, which means digging into the datasheet and writing some SPI code. If any of the above tickles your fancy, read on!

Unlike the earliest charge-based detectors, this one works by picking up the RF signal produced by distant lightning strikes using a small 500 kHz antenna and doing some digital signal processing.

The detector is capable of differentiating between lightning strikes and other types of RF noise, then using the signal from the lightning strikes to estimate the distance to the stormfront, up to 40 kilometers away. This is quite nice for two reasons: it detects active storms from quite a bit further than you can with your eyes and ears, and it gives you a reasonable idea of how fast the storm is coming in.

It’s easy to think of possible applications. Golf courses, sports fields, pools, and beaches would all benefit from earlier storm detection. Besides outdoor activities, datacenters, airports, and construction crews also need to know about incoming lightning storms.

On my end, I live in Southeast Asia and rainy season can be a little epic. Downpours are very localized, incredibly intense, often cause floods, and occur with little warning. Like most residents I drive a motorbike, and being stuck in traffic or on the highway in that intensity of rain is miserable. Given the option, it’s usually better to stop, have a coffee, and let it pass.

Weather reporting isn’t terribly useful for planning trips because most showers are very localized, short, and frequent. The weather report throughout rainy season is simply “28 degrees Celsius, 75% chance of showers” every day, so adding a storm detector to my motorbike seemed practical and fun. Even if it only works some of the time, it would be fantastic. In fact, I’m surprised I’ve never seen this as a product – if it works, someone please do this.

To the Lab!

Back to our detector, there exists an Arduino library to interface with it, if that’s your style. It looks easy enough to use, but my personal preference is to use NodeMCU and the ESP8266, although it has no built-in library for this chip.

Luckily, we have a datasheet (PDF) for the AS3935, and the chip supports both SPI and I2C interfaces. I had been looking for an excuse to explore SPI in Lua on the NodeMCU, and this was perfect. Since we’re just using plain SPI, hopefully the code will be easier to port to other platforms as well.

Let’s start with the basic setup. To use SPI, the datasheet says that the Select Interface (SI) pin needs to be pulled to ground. I also wanted to use the on-chip voltage regulator, so the EN_V chip needed to be pulled high. Finally, the chip pulls an interrupt pin high on every event detection to let the connected microcontroller know that something interesting has happened.

To improve noise immunity on this pin, I used a 1kΩ pull down resistor to ground (not shown below). The latter was probably not necessary but helped reduce false positives during testing while handling the circuit without an enclosure.

Default pins for SPI 1. Source: NodeMCU Documentation

Next, we connect all the pins required by SPI. There are 4: Master Out Slave In (MOSI), Master In Slave Out (MISO), clock (SCK) and Chip Select (CS). I’ve included a small table detailing what these pins are under NodeMCU, keep in mind they’re likely to be different on other platforms.

An important point is that the CS pin is not automatically managed by the NodeMCU during SPI communications. You’ll need to set its value like any other GPIO pin, which we’ll cover later. Before you begin programming, I highly recommend you double-check all your pins are connected correctly. I lost an hour that way and felt silly.

We start by initializing SPI and the relevant pins:

spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 256);
IRQ = 2
gpio.mode(CS, gpio.OUTPUT)
gpio.mode(IRQ, gpio.INPUT)

On the NodeMCU, SPI 0 is used to communicate with the onboard flash memory, so we’ve selected SPI 1, with mostly default features and 8 bits per data item. Of note is that we’ve set a clock divider of 256 on the SPI frequency. This is because the AS3935 supports a maximum SPI frequency of 2 Mhz and the NodeMCU defaults to a much faster speed (at least 20 Mhz). Note that the chip should not be set to an SPI frequency of 500 kHz, as this is the resonant frequency of the lightning detector antenna(!).

We’ve also set the chip select pin as an output on D8, and connected the interrupt pin (IRQ) as an input. IRQ will be raised high on each new event, and remain high until you read the interrupt register to determine the event type. Using it as a proper interrupt or trigger on the NodeMCU did not work reliably, so a normal input pin that we can poll will have to do for now.

Referring to the datasheet, reading from and writing to the AS3935 requires that we send eight bytes over SPI. The first two bits determine whether you are requesting a read or write, and the next six determine the target register. If you are reading from the chip, you first need to set CS low to initiate the read (before sending a request), then raise CS high-low-high when done. Let’s extend our program to read the interrupt register each time the chip outputs an event:

function reason()
    gpio.write(CS, gpio.LOW)


    read = spi.recv(1, 8)
    gpio.write(CS, gpio.HIGH)
    gpio.write(CS, gpio.LOW)
    gpio.write(CS, gpio.HIGH)

function poll()
    x =
    if x == 1
        then reason()

    tmr.alarm(1, 100, 1, function() poll(0) end)

In the code above, we poll the IRQ pin every 100 ms to see if it is high. If so, we set CS to low to indicate we are about to request a read. Then we send the command 0x43, which translates to binary 01000011. The first two bits (01) request a read, and the last six bits (000011) indicate we want to read register address 0x03. The last four bits of the response will contain the detected event type. Once the command is sent, we read eight bits from the SPI port and print the result, then finally set the CS pin high-low-high to signal we’re done reading.

The result of the above code is an irregular stream of ‘4’ (0100) to the terminal. If I touch the antenna, it outputs a ‘1’ instead. Looking at the datasheet, an interrupt reason of 0100 is a ‘disturber’: a radio signal at the frequency of interest, but not lightning. In big Asian cities, there’s always someone arc welding nearby; it twinkles like stars below when arriving on a nighttime flight. Interrupt reason 0001 means a problem with high electrical noise, which makes sense as well. A lightning event would output ‘8’ (1000), but it’s presently dry season so that’s unlikely at this time.

We can now successfully receive data from the device, but it’s not particularly useful yet. Next time, we’ll cover how to write to the configuration registers to set it up to work more practically, and have a bit of creative fun with what we do with the data.

41 thoughts on “An Introduction To Storm Detector Modules

    1. I was just wondering if there are any populated areas on earth which don’t have lightning detectors. When I view doppler radar I see all the strikes on the map. I’d love to have a source of that data which was real-time and specific, reading out data that could be formatted however I want.

    1. Well, the cool thing here is all the signal processing voodoo done on the chip. So it can tell you where the stormfront is. You can even configure it to only alert your controller if a stormfront is approaching.

    1. Interesting, I see that all the receiving stations in my State are within 20 miles of my house, so I am not sure if putting a receiver up would increase overall accuracy or precision.

  1. Although it requires Internet access, there are a number of places that display lightning maps.
    Back in the early 90’s this was done by radios that detected lightning static and triangulated the strike through the use of high accuracy timebases. (GPS or whatever)

    I’m aware of airports that cease “ramp operations” when a strike is detected within a certain distance, and mining operations cease dynamite operations under similar rules.

    1. “…mining operations cease dynamite operations under similar rules.”

      Since blasting caps are basically a dipole (2 wires) with an explosive charge at the feedpoint, that seems like a good strategy. :-)

      I’ve had several garage door openers blown up through currents induced in the lengthy “child sensor” and “manual button” wires by nearby lightning hits.

      Also, cheap consumer ethernet switches (my house is wired for network), which don’t have the ESD protection built into units designed for commercial use.

      1. Normal ethernet over copper has to have a transformer either in the socket or close to it, otherwise it can’t meet the 1.5kV for several minutes that’s defined in the standard.

        My employer’s sister company is an ISP and they did some research on why ports in their switches died during storms – turns out that it was almost exclusively the transformer having open windings from the induced currents…so it did it’s job – protecting the electronics, but what good is it if you can’t realistically replace it? ;-)

      2. Hmm, maybe it isn’t worth the effort, but I’m wondering what could be added to the child sensor wires to reduce the possibility of damage. A capacitor? A spark gap? A combination thereof?

        While I’m typing about Garage Door Openers (GDO) I’ve noticed the one in our house is less sensitive to receiving a “close” signal since about the time I replaced the light bulbs with LED equivalents. I’m guessing the LEDs are emitting RFI. When the door is closed (LED bulbs are off) I can signal “open” from about 5 or more times the distance than a “close” signal…

        1. RFI from LED bulbs has been identified as an issue particularly on boats. Cheap LED marine navigation lights typically have switching voltage converters that generate so much interference that they dramatically impact the sensitivity of marine VHF receivers. I can understand how they would also interfere with your garage door openers.

  2. I’d had less-than-perfect experience with one of these modules and the Arduino library. The chip communicated with my Arduino and even complained about “noise” when I put it near some powered devices, but it failed to detect lightning strikes even when they were literally above my head. I would have gotten better results by attaching vibration sensors to my window glass…

    1. That’s an interesting problem. Register 0x01 contains bits that let you set the noise floor, which affects sensitivity, but that doesn’t explain the lack of detection with a storm overhead.

      Maybe an antenna problem? It should resonate at 500kHz. The chip has on board tuning capacitors that can be enabled, which is sort of neat, along with other tuning features. They’re not super well documented in the datasheet but looks not too hard to figure out with trial and error.

      The datasheet also warns us constantly not to use 500khz frequency to communicate with the chip, but that also seems unlikely to be the problem here.

      Of course could just be a bad module. Best of luck with it.

  3. Aviators know of a device called a “Storm Scope.” The amplitude of the strike gives you some idea of the range. A pair of orthogonal loop-stick antennas can also tell you which direction the strike came from. Each strike is assigned a distance and bearing. Heading information is usually part of most GPS systems in the airplane, so these strikes can then be plotted on a moving map display.

    So you don’t have to have a network of these things to visualize where the strikes are. You just need phase information from the two crossed antennas.

  4. I hope this works out, I was recently thinking about a project like this. Was always curious how websites and services gathered their data for lightening strikes . Supposedly good accuracy but that has proven incorrect. Do the sensors mention a way of testing besides simply waiting and hoping?

  5. Looking forward to seeing how the module actually performs. I’ve had conversations with users regarding this device that suggest its actual lightning detection (and false alarm rejection) ability is pretty poor. Change my mind!

    1. That looks like a lot of fun, but how do I test it?

      For that matter… how did they test it? I’m tempted to email them and ask, I’m curious now.

      If the range was a couple hundred kilometers, you might have luck at a resort in Changbaishan, nearby but not in a certain country. Sounds like a terrible idea though (and the datasheet doesn’t seem to specify a range), so there must be a better way, maybe medical isotopes or something?

  6. Being in Central Florida we get lots of lightning. I have watched the sites that show the lightning but they are delayed. I did order the AcuRite 02020 on amazon for $30 to play with looks like fun. Maybe I can do a hack to interface it. Maybe later I will get the AS3935 to play with also.

  7. Interesting that the devices Tesla has worked with were not mentioned.
    In his Colorado Springs lab he was routinely detecting, as described on the pages of (his notes) “Colorado Springs Notes 1899-1900”, lighting storms in 200-250 mile radius. Interestingly his main source of information, were not the dielectric disturbances (EM radiation) through the air, but the currents in the ground, where most of the atmospheric power discharge goes.

  8. Using the sensor as shown on the photo (CJMCU AS-3935) I discover problems with calibrating short near the required 500 kHZ. The problem seems there is no information on the board with capacity and all Arduino libraries I have found need that information :-(

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.