sparkfun / SparkFun_AS3935_Lightning_Detector_Arduino_Library

Other
37 stars 19 forks source link

OUTDOOR setting not working with ESP32-S3 and SPIClass #22

Closed PureTek-Innovations closed 3 months ago

PureTek-Innovations commented 6 months ago

I'm using a Heltec Stick Lite ESP32-S3 LoRa module and I can set and check all of the settings apart from the INDOOR/OUTDOOR setting. I need to use the HSPI class as the LoRa module uses the SPI class. I've tried different baud rates with no success. The other settings can be changed and read back successfully. I've used the same sensor with a plain ESP32 on the default SPI port and everything worked properly including INDOOR/OUTDOOR.

Any ideas or help appreciated, thank you.

Your workbench

Steps to reproduce

This is the More Lightning Settings SPI example with HSPI added.

#include <SPI.h>
#include "SparkFun_AS3935.h"

#define INDOOR 0x12 
#define OUTDOOR 0xE
#define LIGHTNING_INT 0x08
#define DISTURBER_INT 0x04
#define NOISE_INT 0x01

SparkFun_AS3935 lightning;

const int lightningInt = 4;  
int spiCS = 7;
#define MISO  19
#define MOSI  21
#define SCK 17

SPIClass * hspi = NULL;

byte noiseFloor = 2;
byte watchDogVal = 2;
byte spike = 2;
byte lightningThresh = 1; 

byte intVal = 0; 

void setup()
{
  // When lightning is detected the interrupt pin goes HIGH.
  pinMode(lightningInt, INPUT); 

  Serial.begin(115200); 
  Serial.println("AS3935 Franklin Lightning Detector");

  hspi = new SPIClass(HSPI);
  hspi->begin(SCK, MISO, MOSI, spiCS);
  pinMode(spiCS, OUTPUT);

  if( !lightning.beginSPI(spiCS, 1000000, *hspi) ) { 
    Serial.println ("Lightning Detector did not start up, freezing!"); 
    while(1); 
  }
  else
    Serial.println("Schmow-ZoW, Lightning Detector Ready!\n");

  // "Disturbers" are events that are false lightning events. If you find
  // yourself seeing a lot of disturbers you can have the chip not report those
  // events on the interrupt lines. 

  lightning.maskDisturber(true); 

  int maskVal = lightning.readMaskDisturber();
  Serial.print("Are disturbers being masked: "); 
  if (maskVal == 1)
    Serial.println("YES"); 
  else if (maskVal == 0)
    Serial.println("NO"); 

  // The lightning detector defaults to an indoor setting (less
  // gain/sensitivity), if you plan on using this outdoors 
  // uncomment the following line:

  lightning.setIndoorOutdoor(OUTDOOR); 

  int enviVal = lightning.readIndoorOutdoor();
  Serial.print("Are we set for indoor or outdoor: ");  
  if( enviVal == INDOOR )
    Serial.println("Indoor.");  
  else if( enviVal == OUTDOOR )
    Serial.println("Outdoor.");  
  else 
    Serial.println(enviVal, BIN); 

  // Noise floor setting from 1-7, one being the lowest. Default setting is
  // two. If you need to check the setting, the corresponding function for
  // reading the function follows.    

  lightning.setNoiseLevel(noiseFloor);  

  int noiseVal = lightning.readNoiseLevel();
  Serial.print("Noise Level is set at: ");
  Serial.println(noiseVal);

  // Watchdog threshold setting can be from 1-10, one being the lowest. Default setting is
  // two. If you need to check the setting, the corresponding function for
  // reading the function follows.    

  lightning.watchdogThreshold(watchDogVal); 

  int watchVal = lightning.readWatchdogThreshold();
  Serial.print("Watchdog Threshold is set to: ");
  Serial.println(watchVal);

  // Spike Rejection setting from 1-11, one being the lowest. Default setting is
  // two. If you need to check the setting, the corresponding function for
  // reading the function follows.    
  // The shape of the spike is analyzed during the chip's
  // validation routine. You can round this spike at the cost of sensitivity to
  // distant events. 

  lightning.spikeRejection(spike); 

  int spikeVal = lightning.readSpikeRejection();
  Serial.print("Spike Rejection is set to: ");
  Serial.println(spikeVal);

  // This setting will change when the lightning detector issues an interrupt.
  // For example you will only get an interrupt after five lightning strikes
  // instead of one. Default is one, and it takes settings of 1, 5, 9 and 16.   
  // Followed by its corresponding read function. Default is zero. 

  lightning.lightningThreshold(lightningThresh); 

  uint8_t lightVal = lightning.readLightningThreshold();
  Serial.print("The number of strikes before interrupt is triggerd: "); 
  Serial.println(lightVal); 

  // When the distance to the storm is estimated, it takes into account other
  // lightning that was sensed in the past 15 minutes. If you want to reset
  // time, then you can call this function. 

  //lightning.clearStatistics(); 

  // The power down function has a BIG "gotcha". When you wake up the board
  // after power down, the internal oscillators will be recalibrated. They are
  // recalibrated according to the resonance frequency of the antenna - which
  // should be around 500kHz. It's highly recommended that you calibrate your
  // antenna before using these two functions, or you run the risk of schewing
  // the timing of the chip. 

  //lightning.powerDown(); 
  //delay(1000);
  //if( lightning.wakeUp() ) 
   // Serial.println("Successfully woken up!");  
  //else 
    //Serial.println("Error recalibrating internal osciallator on wake up."); 

  // Set too many features? Reset them all with the following function.
  // lightning.resetSettings();

}

void loop()
{
  if(digitalRead(lightningInt) == HIGH){
    // Hardware has alerted us to an event, now we read the interrupt register
    // to see exactly what it is. 
    intVal = lightning.readInterruptReg();
    if(intVal == NOISE_INT){
      Serial.println("Noise."); 
    }
    else if(intVal == DISTURBER_INT){
      Serial.println("Disturber."); 
    }
    else if(intVal == LIGHTNING_INT){
      Serial.println("Lightning Strike Detected!"); 
      // Lightning! Now how far away is it? Distance estimation takes into
      // account previously seen events. 
      byte distance = lightning.distanceToStorm(); 
      Serial.print("Approximately: "); 
      Serial.print(distance); 
      Serial.println("km away!"); 

      // "Lightning Energy" and I do place into quotes intentionally, is a pure
      // number that does not have any physical meaning. 
      long lightEnergy = lightning.lightningEnergy(); 
      Serial.print("Lightning Energy: "); 
      Serial.println(lightEnergy); 

    }
  }
}

Expected behavior

The INDOOR/OUTDOOR setting should change to OUTDOOR

Actual behavior

The INDOOR/OUTDOOR setting remains on INDOOR

PureTek-Innovations commented 6 months ago

It was pointed out to me that GPIO19 is also USB_D- https://resource.heltec.cn/download/Wireless_Stick_Lite_V3/HTIT-WSL_V3.png https://resource.heltec.cn/download/Wireless_Stick_Lite_V3/HTIT-WSL_V3_Schematic_Diagram.pdf I have now swapped GPIO19 to GPIO18 The behavior is the same.

JZiZu commented 3 months ago

I'm having the same issue. Are there any solutions yet? I've tried I2C and SPI

edspark commented 3 months ago

I'll be taking a look at this problem today, thanks for you patience.

edspark commented 3 months ago

Sorry for the late response on this @PureTek-Innovations. The solution was a lot more simple:

void SparkFun_AS3935::setIndoorOutdoor(uint8_t _setting)

{
    if (((_setting != INDOOR) && (_setting != OUTDOOR)))
        return
    _writeRegister(AFE_GAIN, GAIN_MASK, _setting, 1);
}

The return statement above was lacking a semicolon which forced the _writeRegister function call to act as part of the return statement. Meaning that it would only ever write the setting if the value passed to the function was incorrect. So whenever you passed the correct setting it wouldn't write anything to the register.

Sorry for the troubles, this is fixed in this commit and will be in the Arduino Library under 1.4.9 shortly.