CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Has anyone done any work with the AS3935 lightning sensor??

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

Has anyone done any work with the AS3935 lightning sensor??
PostPosted: Fri Jul 14, 2017 4:17 pm     Reply with quote

Hi all,
I just started working on a project for myself just out of curiosity. A few months back I happen to find a module from Mikroelektronika called the thunder click that contains the AS3935 lightning sensor from Austrian Micro Systems.

I purchased one of these and started writing code for it using a PIC24. I have written most of the code for the AS3935 using a PIC24 platform. I have ported some of the code from a working example of a Mikroelektronika PIC32 application which I have modified and works quite well with their lightning board.

So far my code runs with the AS3935 and I am able to write and read the registers on the AS3935 with no problems, however I do have a problem that when I execute my code. The AS3935 goes through the initialization routines and then when the first lightning interrupt that comes out of the AS3935 which goes from low to high just stays high continuously and every now and then it does some toggling but it seems to always idle high which I do not believe is a normal condition.

I truly believe that this issue has got something to do with my driver code because this same module works perfectly on my Mikroelektronika demo board using their PIC32 code. I have not posted my code, but if anyone here has worked with this device and has some familiarity with it I would appreciate any help. Unfortunately the manufacturer of the chip does not give you much info other than data sheets and getting help from them is kind of difficult Crying or Very sad
temtronic



Joined: 01 Jul 2010
Posts: 9093
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Jul 14, 2017 4:46 pm     Reply with quote

Just some general comments...
Hardware: have you the correct VDD( 3V , I assume), rock stable, bypass caps, etc.....

Software: Since you've ported the code .... what about PIC clock speed? If not same there may be some 'timing' issues to deal with. SPI interface ? If so, check for correct CS levels, data stream, etc.

Assuming an IRQ for a strike... got the proper pullup in the IRQ line ?

Silly things... any other peripherals 'attached' to the I/O pins used for the sensor? Maybe a comparator, ADC, etc.?? ALL peripherals NOT used on an I/O pin should be disabled...

Jay
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

AS3935
PostPosted: Fri Jul 14, 2017 6:26 pm     Reply with quote

Thank you for your response.
And to answer your question or suggestion; YES, I did have another IO pin, actually the interrupt pin being shared with one of the pins on the LCD display and I fixed that and have checked it various times to make sure there are no more IO conflicts...but you are right that is probably one of the most obvious issues that would cause this. So far I have not identified it.
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Sat Jul 15, 2017 12:16 am     Reply with quote

Are you reading the interrupt register?.

When the interrupt occurs, you are required to read the interrupt register, to determine what type of interrupt has happened. You need to do this even if you have it masked to only respond to the lightning event. It is the read of the register that resets the internal interrupt logic. There has to be a pause of >2mSec after the trigger before the read. An early read can cause problems.
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

AS3935
PostPosted: Sat Jul 15, 2017 6:07 am     Reply with quote

Yes, whenever an interrupt occurs I read the interrupt register contents.
I have decided to just post my code and maybe someone may see something that may be causing the problem.

NOTE: I originally translated this code to work with a PIC18F45K22 but then moved it to a PIC24 development board, so I kept things like int8 and int16

Code:
/////////////////// the header file ////////////////////////////////////

#include <24HJ128GP502.h>
#device ICD=TRUE
#device ICSP=1
#use delay(crystal=8000000,restart_wdt)
#FUSES NOWDT, WPRES32, WPOSTS10, CKSFSM, NOJTAG


#pin_select IC1=PIN_C5   //Input capture1
#pin_select SDO1=PIN_B9  //MOSI
#pin_select SCK1OUT=PIN_B8 //CLK
#pin_select SDI1=PIN_B10   //MISO

#use spi(MASTER, FORCE_HW, SPI1, MODE=1, BITS=8)


#define THUNDER_CS  PIN_B15
#define THUNDER_LED PIN_B14
#define SELECT_SW   PIN_B13

Code:

/////////////// the main file /////////////////////////

#include <lightning2.h>
#include <FlexLCD_Easy24-33.c>
#include <AS3935.c>

#USE FAST_IO (b)
#ZERO_RAM

//int1  InterruptFlag = 0;   




#INT_EXT0
void  ext0_isr(void) ///pin RB7
{
   InterruptFlag = 1;   
}


#INT_IC1
void  ic1_isr(void)
{
  // not using so far
}


#INT_TIMER1
void  timer1_isr(void)
{
   // not using so far
}




void Init(void)
{
   set_tris_a(0xff13);   
   set_tris_b(0x2480);
   
   output_high(THUNDER_CS);
   output_low(THUNDER_LED);
   //setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);      //131 ms overflow
   enable_interrupts(INT_TIMER1);
   ext_int_edge( L_TO_H ); // rising edge interrupt mode
   setup_capture(1, CAPTURE_RE | INTERRUPT_FOURTH_CAPTURE | CAPTURE_TIMER2); // not using so far
   //enable_interrupts(INT_EXT0);
   //enable_interrupts(INT_IC1);
   //enable_interrupts(INT_TIMER1);
   enable_interrupts(INTR_GLOBAL);
   
}


 

void main()
{   unsigned int8 value,i; // dummy test variables for debug
   
    Init();
    lcd_init();
   
   
    lcd_putc("\f");   // Clear display
    lcd_gotoxy(1,1);   
    printf(lcd_putc,"Lightning sensor");
    lcd_gotoxy(1,2);   
    printf(lcd_putc,"by C Barberis");
    delay_ms(5000);

    lcd_putc("\f");   // Clear display
    lcd_gotoxy(1,1);   
   
    Thunder_Init();
   
    enable_interrupts(INT_EXT0);
    InterruptFlag = 0;
 
   

   while(1){
 
 
  if (!InterruptFlag ){ // nothing happens in otherwords no interrupts
      lcd_gotoxy(1,1); 
      printf(lcd_putc,"Waiting......");
      lcd_gotoxy(1,2);
      printf(lcd_putc,"#Strikes = %lu",Total_Lightings_Detected);
      delay_ms(150); }
 
  else {
     // We read the AS3935 registers to see what caused the interrupt
     delay_ms(2);   // 2ms delay between interrupt and reading of register 0x03
     // Time to read the 0x03 register which stores interupt codes
     interrupt_source = Thunder_Read(0x03) & 0x0F;
     delay_ms(2);
     
     switch (interrupt_source) {

    case 1:  //noise
       lcd_putc("\f");  // Clear display
       lcd_gotoxy(1,1);
       printf(lcd_putc,"just noise");
       delay_ms(2000);
       break;
       
    case 4:  //disturber
       lcd_putc("\f");  // Clear display
       lcd_gotoxy(1,1);
       printf(lcd_putc,"Disturbers");
       delay_ms(2000);
       break;

    case 8:  // is lightning
      lcd_putc("\f");   // Clear display
      lcd_gotoxy(1,1);
      printf(lcd_putc,"Lightning");         
      Total_Lightings_Detected++;
      if(Total_Lightings_Detected > 100)
      Total_Lightings_Detected =0;
      // now we get the distance to the lightning event         
      tmp1 = Thunder_Read_distance();
      lcd_gotoxy(1,2);
      printf(lcd_putc,"Dist = %u Km", tmp1);
      output_high(THUNDER_LED); 
      InterruptFlag = 0;
      Delay_ms(3000);
      output_low(THUNDER_LED);
      break;  }
   
     InterruptFlag = 0;
   
   
  }     
         if(!input(SELECT_SW) ) // push button to read various registers
            ReadInternalData();

}
}

Code:

//////////////////////////////// the AS3935 file ///////////////////////////////


// register access macros - register address, bitmask [ NOT Currently using these ]
#define AS3935_AFE_GB      0x00, 0x3E
#define AS3935_PWD      0x00, 0x01
#define AS3935_NF_LEV      0x01, 0x70
#define AS3935_WDTH      0x01, 0x0F
#define AS3935_CL_STAT      0x02, 0x40
#define AS3935_MIN_NUM_LIGH   0x02, 0x30
#define AS3935_SREJ      0x02, 0x0F
#define AS3935_LCO_FDIV   0x03, 0xC0
#define AS3935_MASK_DIST   0x03, 0x20
#define AS3935_INT      0x03, 0x0F
#define AS3935_DISTANCE   0x07, 0x3F
#define AS3935_DISP_LCO   0x08, 0x80
#define AS3935_DISP_SRCO   0x08, 0x40
#define AS3935_DISP_TRCO   0x08, 0x20
#define AS3935_TUN_CAP      0x08, 0x0F

// other constants
#define INDOOR 0x12
#define OUTDOOR 0x0E
 

unsigned int8 tmp1;
int32 tmp2;
int16 message_count = 0;
int16 Total_Lightings_Detected = 0;
int1 InterruptFlag = 0;
unsigned int8 interrupt_source, buffer;
char i;

//Func protos
void Thunder_Init(void);
void Thunder_Write(unsigned int8 address, unsigned int8 data1);
unsigned int8 Thunder_Read(unsigned int8 address);
int32 Thunder_Read_Energy(void);
unsigned int16 Thunder_Read_distance(void);
void ReadInternalData(void);



/*******************************************************************************
* Function Thunder_Init()
*
* These are the same functions from the PIC32 example from Mikroe which works fine
* ------------------------------------------------------------------------------
* Overview: Function Initializes Thunder chip
* Input: register address, data
* Output: Nothing
*******************************************************************************/
void Thunder_Init() {
unsigned int8 temp;

 
  output_high(THUNDER_CS);              // Set CS to idle

  Thunder_Write(0x3C, 0x96);           // set all registers in default mode
  delay_ms(3); 
  Thunder_Write(0x3D, 0x96);           // calibrate internal oscillator
  delay_ms(3);
  temp = Thunder_Read(0x00) & 0xC1;
  delay_ms(3);
  Thunder_Write(0x00, ((INDOOR  << 1) | temp)); // set to indoor
  delay_ms(3);
  temp = Thunder_Read(0x01) & 0x80;
  delay_ms(3);
  Thunder_Write(0x01, 0x22 | temp);    // set NFL and WDTreshold 0x44
  delay_ms(3);
  temp = Thunder_Read(0x02) & 0x80;    // clear statistics, min number of ligtning, spike rejection
  delay_ms(3);
  Thunder_Write(0x02, 0xD2);
  delay_ms(3);
  temp = Thunder_Read(0x03) & 0x1F;    // Frequency division ratio(antenna),mask disturber, interrupt
  delay_ms(3); 
  Thunder_Write(0x03, 0x00 | temp);
  delay_ms(3); 
  Thunder_Write(0x08, 0x00);           // LCO, SRCO, TRCO on IRQ, capacitors tuning
 
  delay_ms(1000);
}



/*******************************************************************************
* Function Thunder_Write(unsigned short address, unsigned short data1)
* ------------------------------------------------------------------------------
* Overview: Function writes desired byte into specified register address
* Input: register address, byte
* Output: Nothing
*******************************************************************************/
void Thunder_Write(unsigned int8 address, unsigned int8 data1)  {
   
  bit_clear(address,7);       // set both bits 6&7 to 0 to do a write                       
  bit_clear(address,6); 
  output_low(THUNDER_CS);     
  spi_xfer(address);         // spi_write(address);
  spi_xfer(data1);          // spi_write(data1);
  output_high(THUNDER_CS);   
}





/*******************************************************************************
* Function Thunder_Read(unsigned short address)
* ------------------------------------------------------------------------------
* Overview: Function reads byte from specified address
* Input: register address
* Output: desired byte
*******************************************************************************/
unsigned int8 Thunder_Read(unsigned int8 address) {
  unsigned int8 tmp = 0;
 
  bit_clear(address,7);      // set both bits 7 =0 and bit 6 = 1 to do a read 
  bit_set(address,6);       
  output_low(THUNDER_CS);   
  spi_xfer(address);            //spi_write(address); 
  tmp = spi_xfer(0);        // spi read data; 
  output_high(THUNDER_CS);   
  return tmp;
}



/*******************************************************************************
* Function Thunder_Read_Energy()
* ------------------------------------------------------------------------------
* Overview: Function reads energy of detected thunder
* Input: Nothing
* Output: Measured result
*******************************************************************************/
int32 Thunder_Read_Energy() {
  unsigned int8 low_byte, mid_byte;
  int32 Out_thunder_energy;
 
  Out_thunder_energy = Thunder_Read(0x06) & 0x1F;
  mid_byte = Thunder_Read(0x05);
  low_byte = Thunder_Read(0x04);
 
  Out_thunder_energy = (Out_thunder_energy << 8);
  Out_thunder_energy = (Out_thunder_energy | mid_byte);
  Out_thunder_energy = (Out_thunder_energy << 8);
  Out_thunder_energy = (Out_thunder_energy | low_byte);
 
  return Out_thunder_energy;
}
 
 
/*******************************************************************************
* Function Thunder_Read_distance()
* ------------------------------------------------------------------------------
* Overview: Function reads distance from detected thunder
* Input: Nothing
* Output: Measured result
*******************************************************************************/
unsigned int16 Thunder_Read_distance() {
  int16 Out_thunder_distance;
 
  Out_thunder_distance = Thunder_Read(0x07) & 0x3F;
 
  return Out_thunder_distance;
}


/////////////////////////////////// Routines to read internal registers ///////////////////////////


void ReadInternalData() {
  unsigned int test1, test2,i;   
 
   
      tmp1 = Thunder_Read(0x00) & 0x20;
      delay_ms(10);
      lcd_putc("\f");   // Clear display
      lcd_gotoxy(1,1);
      printf(lcd_putc,"Disturbers");
      lcd_gotoxy(1,2);
      if(tmp1 == 0x20)
      printf(lcd_putc,"Enabled");
      else
      printf(lcd_putc,"Disabled");
      delay_ms(5000);
     
      tmp1 = Thunder_Read(0x00) & 0x3E;
      tmp1 = tmp1 >> 1;
      delay_ms(10);
      lcd_putc("\f");   // Clear display
      lcd_gotoxy(1,1);
      printf(lcd_putc,"Sensor set to:");
      lcd_gotoxy(1,2);
      if(tmp1 == INDOOR)
      printf(lcd_putc,"Indoor mode");
      else if(tmp1 == OUTDOOR )
      printf(lcd_putc,"Outdoor mode");
      //printf(lcd_putc," = %u", tmp1);
      delay_ms(5000);
     
      tmp1 = Thunder_Read(0x01) & 0x70;
      delay_ms(10);
      lcd_putc("\f");   // Clear display
      lcd_gotoxy(1,1);
      printf(lcd_putc,"Noise Level:");
      lcd_gotoxy(1,2);
      printf(lcd_putc," = %u", tmp1);     
      delay_ms(5000);
     
      tmp1 = Thunder_Read(0x01) & 0x0F;
      delay_ms(10);
      lcd_putc("\f");   // Clear display
      lcd_gotoxy(1,1);
      printf(lcd_putc,"WatchDog set to:");
      lcd_gotoxy(1,2);
      printf(lcd_putc," = %u", tmp1);     
      delay_ms(5000);
     
      tmp1 = Thunder_Read(0x02) & 0x0F;
      delay_ms(10);
      lcd_putc("\f");   // Clear display
      lcd_gotoxy(1,1);
      printf(lcd_putc,"Spike Rejection:");
      lcd_gotoxy(1,2);
      printf(lcd_putc," = %u", tmp1);     
      delay_ms(5000);
     
     
      lcd_putc("\f");   // Clear display
      lcd_gotoxy(1,1);
      printf(lcd_putc,"All done");
      lcd_gotoxy(1,2);
      printf(lcd_putc,"Reading registers");
      delay_ms(4000);
     
 

}
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Sat Jul 15, 2017 8:39 am     Reply with quote

First thing, you should specify a clock rate.
On these chips you have a programmable PLL. So you need CRYSTAL=8MHz, CLOCK=xxMHz where the second figure is what you want the PLL programmed to give. Then (this may well be the problem), you need to specify the SPI rate (BAUD=2000000). The chip supports a maximum SPI rate of 2Mhz. Even at 8Mhz, your new PIC is capable of clocking the SPI at 4MHz, and the default unless you specify a clock rate, is always as fast as possible....
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Sat Jul 15, 2017 10:21 am     Reply with quote

I see another problem.

When you are sending values, and then raising the CS after the send, you need to code as:
Code:

void Thunder_Write(unsigned int8 address, unsigned int8 data1)  {
  int8 dummy;
  bit_clear(address,7);       // set both bits 6&7 to 0 to do a write                       
  bit_clear(address,6);
  output_low(THUNDER_CS);     
  spi_xfer(address);         // spi_write(address);
  dummy=spi_xfer(data1);          // spi_write(data1);
  output_high(THUNDER_CS);   
}


Adding the read here, ensures the transfer completes before you raise CS. Otherwise the line will go up while the data is still sending.
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

PostPosted: Sat Jul 15, 2017 1:42 pm     Reply with quote

I only want to use the crystal at 8.00MHz not really interested in using the PLL so that is why I left just the crystal figure
I'm I supposed to use CRYSTAL=8MHz, CLOCK=8MHz ??

As far as the SPI writes and reads, I monitored all the MISO and MOSI traffic on my logic analyzer and there is ~ 20 uS from the last data bit transferred to the point where the CS line gets raised. Also Every value I write to any register I am able to read later, so the SPI data transfer seems to work fine. The thing that I noticed is that my interrupt output from my AS3935 once it goes high it stays high something that the other system (PIC32) does not do, that line stays low and transitions high for about 50uS then it goes low until the next interrupt happens. In this case this is not working correctly because on the first interrupt the line goes high and stays high forever until I do a read of the interrupt status register, it then goes low for a short period and back to high again and stays there. Definitely something stupid that I am doing. I have checked all the working registers and they appear to have the correct values? ...so I am lost.
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Wed Jul 19, 2017 2:57 am     Reply with quote

Yes. On the PLL, the problem is that a lot of components like this _must_ be configured. Can't just be ignored. Setting CRYSTAL=8MHz, CLOCK=8MHz, ensures the compiler sets it up to disable the PLL. Smile

Beware on looking at the CS with the scope. The transaction _will_ be correct on all 'read' transfers (since these use tmp = spi_xfer(0) for the second transfer). It is only on the last byte of a write transfer that the dummy is needed. So only on the transfer at the end of the Thunder_write. You may be missing this being wrong... :(
This could easily cause some errors.

The line staying high, is saying that the interrupt has not been cleared. So something is preventing this. Question is what....
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group