Lightning detection using AS3935 and PIC18F4520 microcontroller

Some of the links on this blog are affiliated links. READ MORE

The article about lightning detection using Arduino and the AS3935 sensor quickly became the most accessed blog post. Today I will make a step further and write about lightning detection on 8-bit PIC microcontrollers. The hardware I will use is a PICDEM2 Plus demo board from Microchip, equipped with a PIC18F4520 microcontroller, and a Thunder Click board from MikroElektronika.

The PICDEM2 Plus is a 5V demo board, so the microcontroller used should be able to work on 5V power and should be in 40-pin PDIP capsule. Second, the microcontroller used should have hardware SPI. Software SPI will not work, as the software SPI library will conflict with the ISR routine for lightning detection. I do prefer a PIC microcontroller from the high-range PIC18 range, as those microcontrollers are able to perform hardware multiplication and work faster in this application. Considering those constraints and what I already had in my parts box, my choice was the PIC18F4520. The [the_ad id=”4872″]  is modified to work on 5V voltage, similar to the Arduino example.

By using the PICDEM2 Plus demo board there are several constraints that must be met:
– LCD is connected to PORTD, with LCD power being controlled by pin RD7, and R/W line connected to pin RD5, instead of being grounded as it is usually done.
– the INT pin of the AS3935 is connected to pin RB0, which corresponds to external interrupt INT0. There is also a LED connected to pin RB0, so the jumper J6 on PICDEM2 Plus demo board must be disconnected. The button connected also to RB0 cannot be disconnected, and this is a big issue since the button comes also with a pull-up external circuit which will interfere with the way AS3935 interrupt works. There is no other way then to physically remove R19, thus disabling the button.
– SDI pin is RC5
– SDO pin is RC4
– SCK pin is RC3
– CS pin is connected to RC2 (not critical).
– I used an external 4MHz external oscillator. This is not critical, but remember to change the CONFIG registers if you use another option. I would not suggest the internal oscillator though, as a precise clock frequency is needed when performing the AS3935 calibration.

With the above considerations, the connection diagram is at follows:

MikroC code for PIC18F4520

The code is heavily inspired from the PIC32 example from Libstock. Actually, most functions from the PIC32 example work directly with the PIC18F4520.

The following (important) settings were made in the CONFIG registers:
– EC oscillator, port function on RA6
– Watchdog timer disabled
– CCP2 multiplexed with RC1
– PORTB A/D disabled
– Extended instruction set disabled. I don’t now why, buy if I enable this nothing works anymore.

What I have added is a calibration function. This is extremely important, as a correct calibration has a great impact on the success of lightning detection. To perform the calibration, in AS3935 we must set LCO_FDIV = 00, which corresponds to bits 7:6 of register 0x03. Then, we must set  DISP_LCO = 1, which corresponds to bit7 of register 0x08. At his point on INT pin we should have the LCO frequency divided by 16.

Next, we use TIMER1 to count the pulses coming from the INT pin over a 100ms period of time. Considering an optimal frequency of 500KHz, divided by 16 it gets 31250 Hz. Over 100 ms we should have 3125 if the sensor is calibrated correctly. So, we swap all the range of calibrating capacitor by altering bits 3:0 of AS3935 register 0x08, we measure the LCO frequency, and we choose the closest value to 3125.

The AS3935 datasheet specifies a 3.5% maximum deviation from this frequency for the sensor to work. 3.5% of 3125 is 109. So, we check if the difference between the desired frequency and the measured frequency is greater than 109. If it is, then we display “Calibration error” and we enter an infinite loop.

The main program displays some internal parameters of AS3935, then it re-enables external interrupts and starts monitoring the AS3935. A counter and a “Waiting…” message are displayed if nothing happens, so I know that the whole think is not stuck :). If an interrupt occurs, then we read the content of bits 3:0 of register 0x03, and we check against the interrupt codes.

If Reg 0x03 is 0001, then we have noise. If Reg 0x03 is 0100 then we have disturbers (man made perturbations). If Reg 0x03 is 1000 than we have lightning. In this case we read also the content of bits 5:0 in register 0x07 and determine the distance to the lightning event.

The code is not optimized, and I know that for some variables I’m allocation more memory space than needed. Second, the LCD size is a big limitation, as I can’t display much information on it. In the future, there will be a better version for 4×20 lines LCDs, and maybe with an audible alarm for approaching storms.

This code is still in its alpha version, so please feel free to post in the comments section any mistakes you find in this code.



  1. Hi. I have a question:
    // Power up the sensor
    tmp1 = Thunder_Read(0x00) | 0x01;
    Thunder_Write(0x00, tmp1);

    Why set you the bit PWD (0x00[0]) (Power-down)?
    I´ve read AS3935 Datasheet and i think that:
    PWD = 0 –> AS3935 turned-on
    PWD = 1 –> AS3935 turned-off

    But im not sure, ill appreciate your answer.

    • Teodor Costachioiu on

      I’ll have to check too. When I wrote this code I had as a starting point the Arduino code. which is based on the AS3935 Arduino library by Raivis Rengelis. In that library we have:

      It looks that to power down the AS3935 we have to write “1” into PWD, and we have to set PWD to “0” to power the AS3935 on. And I know for sure that Arduino code works.

      I also took a look into the AS3935 keychain reference design. There, they initialize register 0x00 with value 0x1C, which means the PWD bit is set to 0. Once again, this confirms that 0 is for power up.

      Thanks for pointing this out!

      • When i set PWD=1 –> I do not receive interrupts (noise, disturb or lightnings)
        When i set PWD=0 –> I receive interrupts.

        I´ve checked it! Thanks a lot!

  2. When i try to build i have this errors. I am using mikroc 6.63, what old version did you use?? or do you know why i have this errors? Thanks a lot for this project. Both of them libraries are checked in the library manager

    0 360 Unresolved extern ‘TFT_16bit_RS’ __Lib_TFT_16bit_Defs.c
    0 360 Unresolved extern ‘TFT_DataPort’ __Lib_TFT_Defs.c

    • Hi!

      In MikroC in Library Manager you have to uncheck everything TFT-related. Then it should compile fine.

      I’m using version 6.6.2 of MikroC Pro for PIC


      • Thanks for you help teodor, yesterday there was a storm here, i could not receive anything the display show 1,2,3,4 Waiting when the number arrive to 99, the loop resets. The only difference is that i am using the AS3935 BOARD form playing with fusion ( i bought this before find this project (the thunder is best than this). Someone knows what can be bad? i dont receive anything in the middle of a storm! Thank you very much

Leave A Reply