Gravity: Lightning Sensor (SEN0290)

This is a placeholder topic for “Gravity: Lightning Sensor” comments.

The Gravity Lightning Sensor employs AMS’s AS3935 lightning sensor IC and a Coilcraft MA5532-AE dedicated antenna to detect lightning distance, intensity, and frequency within a radius of 40km both indoors or outdoors.

Read more

I had a lot of problems getting this to work with an ESP32. Different ESP’s would see the sensor, but not communicate with it. I finally got it working on one particular ESP32 (but not a second identical one), but it was always a bit flaky.

Then I stopped using the DFRobot Library and switched to the Sparkfun Library. All the issues went away. All models of ESP32 I tried seem to work fine and the detection seems a lot more reliable.

2 Likes

Sparkfun library it is then!

Thank you for sharing your experiences with this module, @Greig63365. Hopefully you have saved someone down the line a lot of hassle.

Just to save someone else the effort……here’s my code in MicroPython to run this on a Pico W.

When I say “my code” I mean Co-pilot’s code with a gazillion rewrites, error fixes, adjustments, clarification/modification/deletion of CP’s assumptions, explanations and explanatory notes.

The code will write both the register event and the IRQ event (when there is one) to the shell with each loop.

Requires the library file “DFRobot_AS3935_Lib.py” on the Pico.

I can image there’d be a LOT of tuning required to make this work in the field, spitting out reasonable data.

from machine import I2C, Pin
import time
from DFRobot_AS3935_Lib import DFRobot_AS3935

i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=100000)

SEN0290_ADDR = 0x03   # DFRobot AS3935 default I2C address

# -----------------------------------------------------------
# AS3935 presence check (correct for SEN0290)
# -----------------------------------------------------------
def startup_as3935_presence_check(sensor):
    print("=== AS3935 Presence Check ===")
    print("Expected I2C address: 0x{:02X}".format(SEN0290_ADDR))

    try:
        noise = sensor.getNoiseFloorLv1()
        print("AS3935 responded correctly on I2C.")
        print("Initial Noise Floor Level:", noise)
    except Exception as e:
        print("AS3935 did NOT respond:", e)

    print("================================\n")

# -----------------------------------------------------------
# AS3935 register sanity dump (only valid DFRobot getters)
# -----------------------------------------------------------
def dump_as3935_registers(sensor):
    print("=== AS3935 Register Sanity Check ===")

    try:
        noise = sensor.getNoiseFloorLv1()
        wd = sensor.getWatchdogThreshold()
        spike = sensor.getSpikeRejection()
    except Exception as e:
        print("AS3935 not responding:", e)
        print("====================================\n")
        return

    print("Noise Floor Level:   {}".format(noise))
    print("Watchdog Threshold:  {}".format(wd))
    print("Spike Rejection:     {}".format(spike))

    print("====================================\n")

# -----------------------------------------------------------
# Sensor init
# -----------------------------------------------------------
sensor = DFRobot_AS3935(i2c=i2c, address=SEN0290_ADDR)

sensor.reset()
sensor.powerUp()
time.sleep_ms(5)   # allow oscillator + I2C interface to stabilise

sensor.setIndoors()

# ---------------------- Indoor tuning ----------------------
sensor.disturberDis()          # disable disturber events indoors
sensor.setNoiseFloorLv1(4)     # raise noise floor (0–7)
sensor.setWatchdogThreshold(2) # filter weak EMI (0–10)
sensor.setSpikeRejection(2)    # filter short spikes (0–10)
sensor.setMinStrikes(1)        # report lightning immediately
# -----------------------------------------------------------

print("AS3935 ready (tuned for indoor use)\n")

# -----------------------------------------------------------
# Perform diagnostics AFTER sensor is alive
# -----------------------------------------------------------
startup_as3935_presence_check(sensor)
dump_as3935_registers(sensor)

# -----------------------------------------------------------
# IRQ HANDLING
# -----------------------------------------------------------
last_irq_event = 0   # 0 = none, 1 = noise, 2 = disturber, 3 = lightning

def irq_handler(pin):
    global last_irq_event
    last_irq_event = sensor.getInterruptSrc()

# IRQ pin on GP2
irq_pin = Pin(2, Pin.IN)
irq_pin.irq(trigger=Pin.IRQ_RISING, handler=irq_handler)

# -----------------------------------------------------------
# EXTENDED TELEMETRY LOOP
# -----------------------------------------------------------
while True:
    # Timestamp
    t = time.localtime()
    timestamp = "%04d-%02d-%02d %02d:%02d:%02d" % (t[0], t[1], t[2], t[3], t[4], t[5])

    # Read telemetry
    irq = last_irq_event
    dist = sensor.getLightningDistKm()
    energy = sensor.getStrikeEnergyRaw()
    noise = sensor.getNoiseFloorLv1()

    # Extended telemetry line
    print("%s  IRQ:%d  Distance:%s km  Energy:%s  Noise:%d" %
          (timestamp, irq, dist, energy, noise))

    # Separate lightning alert
    if irq == 3:
        print("%s  *** LIGHTNING EVENT DETECTED!  Distance:%s km  Energy:%s ***" %
              (timestamp, dist, energy))

    # Clear stored IRQ so new events are visible
    last_irq_event = 0

    time.sleep(1)
2 Likes

Thanks for paying that forward, @Mark285907.

Hopefully if anyone needs to make those tuning changes, they will also upload it here.

1 Like