Detecting Lightning with a Raspberry Pi
rious methods can be used to detect lightning. Commonly it involves sensing the electromagnetic radiation generated by a strike. Most people have probably heard this at some point as static, crackles, and popping sounds on an AM radio. Some detectors are capable of picking up the flashes of light produced within a cloud, even during the day when they usually can’t be seen by the human eye due to sunlight. Occasionally lightning will emit a brief pulse of gamma radiation — something a new instrument aboard the International Space Station is set to study.
In this post I’ll explore using a RaspberryPi to interface the AS3935 Franklin Lightning Sensor IC from ams (Austria Mikro Systeme). The AS3935 is a programmable sensor that can detect lightning activity up to 40km away. It uses a proprietary hardwired algorithm to filter out noise and man-made “disturbers” and estimate the distance to the leading edge of the storm; has programmable detection levels, threshold settings, and antenna tuning; and unlike many previous terrestrial lightning sensors can detect both cloud-to-ground and intra-cloud lightning activity.
Rather than rounding up the specific components in small quantities, laying out a PCB, and trying to hand-solder the rather small (4x4mm) MLPQ-16 package, I used the MOD-1016 breakout board from Embedded Adventures. The AS3935 requires a supply voltage range of 2.4 – 5.5V, which will work perfectly with the RaspberryPi’s 3.3v GPIO logic levels. It can be interfaced through SPI or I2C. By default the MOD-1016 comes configured to use I2C but can easily be switched to use SPI through a couple of solder jumpers on the board. In my setup I’ll be sticking with the default I2C configuration.
This project served as a nice introduction to the I2C protocol for me. I had used the 1-Wire protocol before to interface some DS18B20 temperature sensors, but I2C is much more widely used and so I was glad to have the opportunity to dive into it. In this post I’ll be covering the details necessary to communicate with the AS3935 from the RaspberryPi over I2C, but if you’d like more information, Byte Paradigm provides a wonderful introduction to I2C and SPI.
If you don’t already have your RaspberryPi configured to use the I2C protocol you’ll have to install a couple packages and load a couple kernel modules. Adafruit has a wonderful guide here, but basically you just need to install the python-smbus and i2c-tools packages, and load the i2c-bcm2708 and i2c-dev kernel modules. Doing this on the Raspbian distro might go something like this:
### Installs the packages ~ $ sudo apt-get install python-smbus ~ $ sudo apt-get install i2c-tools ### Loads the kernel modules ~ $ sudo modprobe i2c-bcm2708 ~ $ sudo modprobe i2c-dev ### Make sure modules load on boot ~ $ echo "i2c-bcm2708 i2c-dev" | sudo tee -a /etc/modules
Wiring up the MOD-1016 to the RaspberryPi is relatively simple. With I2C you only need two wires (SDA & SCL) — besides power and ground, of course — to communicate with multiple devices. The AS3935 issues interrupts to alert the microcontroller to events, so we’ll need one additional wire for that. I used a standard breadboard and a RaspberryPi Cobbler from Adafruit to mock-up the circuit. The MOD-1016 (AS3935) connects to the RaspberryPi as such:
|VCC||3.3v (pin 1)|
|IRQ||GPIO 17 (pin 11)|
|SCL||SCL (pin 5)|
|SDA||SDA (pin 3)|
One thing to note about I2C is that it was designed for inter-chip communication, often between integrated-circuits found on the same PCB. In I2C the lines are held high by pull-up resistors and pulled low to indicate the opposite state. The time it takes to bring the line back up to VCC varies depending on the value of the pull-up resistor and the bus capacitance. The I2C specification limits the maximum capacitance to 400pF, which typically restricts the practical distance to within a few meters. There are ways to extend the max length if needed. The most obvious being an I2C bus extender. Slowing down the clock rate can also help increase max distance. Also, be aware that if using twister-pair cable like CAT-5 for I2C connections not to run the SCL and SDA lines together over the same twisted-pair. Use separate pairs and tie the other line in each pair to ground.
Once everything is wired up you can use the command i2cdetect to see whether I2C is working and can communicate with the sensor. If using an older RaspberryPi (with 256MB ram) you will run the command as shown below with an I2C bus ID of 0. If using a newer RaspberryPi though use 1 instead. In the output below you can see the AS3935 (0x03) and the MS5611 (0x76) has been properly detected.
~ $ sudo i2cdetect -y 0 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: 03 -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- 76 --
Now to actually use the sensor we’re going to need to be able to interact with it. This is done by reading and writing to registers within the chip. Registers are memory locations used to store bits for things like configuration and input/output. In a way they are like digital DIP switches, where bits or series of bits are used to indicate or set various states. For example, with the AS3935 it is possible to clear the statistics built up by the algorithm by toggling the 7th bit (bit 6) of the 3rd register (0x02). Tables and mappings describing the register locations and functionality can be found in a device’s datasheet. For example,
Most languages and platforms have tools or libraries available for working with I2C. On Linux for instance, the i2c-tools package provides utilities like i2cdetect, i2cget, i2cdump,and i2cset that can be used from the command line. For python, the SMBus module provided by the python-smbus package offers the bindings needed for accessing the I2C bus. Often though there are higher-level libraries available for devices that abstract away the details of working with individual registers. Instead of having to know which bits to read or write to which registers you can often just instantiate a class and call methods to interact with the particular device.
For working with the the AS3935 in python, the RaspberryPi-AS3935 library written by Phil Fenstermacher is available. Installation instructions can be found on the GitHub page. It provides useful methods as well as a nice demo script to get you up and running. To see available methods and their arguments take a look through the RPi_AS3935.py file.
The AS3935 uses a parallel RLC circuit as an antenna and needs to be tuned to a resonant frequency of 500kHz ±3.5%. To compensate for variances there is up to 120pF available internally though tuning capacitors that can be activated in steps of 8pF. Through a register setting the AS3935 can output the resonant frequency on the IRQ pin allowing an external device to measure it and tune the antenna appropriately by activating the necessary tuning capacitors. Luckily the MOD-1016 breakouts from Embedded Adventures comes with the tuning capacitor value displayed on the outside of the anti-static bag. This makes the calibration routine much simpler. When using the above library it is as simple as calling the calibrate() method and passing the tuning capacitor value as an argument. More details on the antenna design can be found in the AS3935 AMS Hardware Design Guide.
For more detail: Detecting Lightning with a Raspberry Pi