Feather with the Thunder Click

Hello, I am using the Feather WiFi with a Cortex M0+ processor, and I was wondering how to use it with a Thunder Click, probably the only lightning detection breakout board out there. I am running this code,(I want to datalog too) and I have downloaded the AS3935 library from GitHub:

#include <Wire.h> //I2C library
#include <SPI.h> //SPI library
#include <SD.h> //SD card library
#include <WiFi101.h>
#include <Adafruit_Sensor.h> //Import Adafruit Sensors
#include <Adafruit_BMP280.h> //Import BMP280 library
#include "DHT.h" //Import DHT11 sensor library
#define DHTPIN 5 //Initialize the pin used for the DHT11 sensor
#define DHTTYPE DHT11 //The DHT sensor used is the DHT11 sensor
DHT dht(DHTPIN, DHTTYPE); //Initialize the DHT type and the pin used
#include "RTClib.h" //Initialize the RTC clock library
RTC_PCF8523 rtc;//The RTC type used
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; //The days of the week used
Adafruit_BMP280 bmp; //Initialize the I2C used for the BMP280 sensor.
const int chipSelect = 10; //The chip select pin used for the SD card

char ssid[] = "error:/notWorking";        // your network SSID (name)
char pass[] = "yesittis";    // your network password (use for WPA, or use as key for WEP)

int led =  LED_BUILTIN;
int status = WL_IDLE_STATUS;
WiFiServer server(80);

void setup() {
  // put your setup code here, to run once:
  //Initialize serial and wait for port to open:
  Serial.println("Access Point Web Server");

  pinMode(led, OUTPUT);      // set the LED pin mode

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue
    while (true);
  Serial.print("Creating access point named: ");

  // Create open network. Change this line if you want to create an WEP network:
  status = WiFi.beginAP(ssid);
  if (status != WL_AP_LISTENING) {
    Serial.println("Creating access point failed");
    // don't continue
    while (true);

  // wait 10 seconds for connection:

  // start the web server on port 80

  // you're connected now, so print out the status

  Serial.println(F("BMP280 test"));
  dht.begin();//Begin the DHT11 sensor
  if (!bmp.begin()) {  //Make sure the BMP280 sensor begins or display an error message
    Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
    while (1);
#ifndef ESP8266
  while (!Serial);
  if (! rtc.begin()) { //Make sure the rtc sensor begins or display an error message
      Serial.println("Couldn't find RTC");
      while (1);
  if (! rtc.initialized()) { ////Make sure the rtc begins or display an error message
    Serial.println("RTC is NOT running!");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  Serial.print("Initializing SD card...");

  if (!SD.begin(chipSelect)) { //Make sure the SD card is in and works or display an error message
    Serial.println("Card failed, or not present");
    // Don't do anything more:
  Serial.println("card initialized.");


void loop() {
  // put your main code here, to run repeatedly:
  // compare the previous status to the current status
  if (status != WiFi.status()) {
    // it has changed update the variable
    status = WiFi.status();

    if (status == WL_AP_CONNECTED) {
      byte remoteMac[6];

      // a device has connected to the AP
      Serial.print("Device connected to AP, MAC address: ");
      Serial.print(remoteMac[5], HEX);
      Serial.print(remoteMac[4], HEX);
      Serial.print(remoteMac[3], HEX);
      Serial.print(remoteMac[2], HEX);
      Serial.print(remoteMac[1], HEX);
      Serial.println(remoteMac[0], HEX);
    } else {
      // a device has disconnected from the AP, and we are back in listening mode
      Serial.println("Device disconnected from AP");
  WiFiClient client = server.available();   // listen for incoming clients

  if (client) {                             // if you get a client,
    Serial.println("new client");           // print a message out the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        if (c == '\n') {                    // if the byte is a newline character

          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");

            // the content of the HTTP response follows the header:
            client.print("Howdy y'all and welcome to a local public WiFi website based in Austin, TX. This site shows weather data!");
            String dataString = ""; //Create a data string for data to write on SD card
            float f = dht.readTemperature(true);//Read the temp as float f
            float h = dht.readHumidity();//Read the humidity as h
            float sensor1 = (bmp.readTemperature()*1.8 +28);//Read the temp as float sensor 1
            DateTime now = rtc.now(); //Make now the time NOW; in hours, minutes, days, etc.
            dataString += String(sensor1);// Next few print data
            float sensor2 = (bmp.readPressure());
            dataString += String("*F , ");
            dataString += String(sensor2);
            float sensor3 = (bmp.readAltitude(1013.25));
            dataString += String("pa , ");
            dataString += String(sensor3);
            float sensor4 = (dht.readHumidity());
            dataString += String("m , ");
            dataString += String(sensor4);
            float sensor5 = (dht.computeHeatIndex(f, h) -4);
            dataString += String("% ,Feels like: ");
            dataString += String(sensor5);
            dataString += String("*F , Current Time:");
            dataString += String(now.year(), DEC);
            dataString += String("/");
            dataString += String(now.month(), DEC);
            dataString += String("/");
            dataString += String(now.day(), DEC);
            dataString += String("(");
            dataString += String(daysOfTheWeek[now.dayOfTheWeek()]);
            dataString += String(")");
            dataString += String(now.hour(), DEC);
            dataString += String(":");
            dataString += String(now.minute(), DEC);

            File dataFile = SD.open("datalog.txt", FILE_WRITE); //Write data to SD card
            dataFile.println(dataString); //Print the data string that all data has been added before
            dataFile.flush(); //Flush all data in the SD card
            dataFile.close(); //Close the SD card
            Serial.println(dataString); //Print the data string on the serial monitor



This is the test sketch in the AS3935 library examples

However, when I run it, I get an error:
#error "Not an AVR MCU! Use ‘SlowSoftI2CMaster’ library instead of ‘SoftI2CMaster’!"

Any help would be appreciated. I have no idea what those mean. Thanks a lot.

However, when I run it, I get an error:

That error does NOT come from running the code. It comes from attempting to compile the code. The compiler told you EXACTLY which file caused it grief. Why didn’t you share that data with us?

I am fairly new, and do not completely understand this. Thanks.

Also, I changed my test code to this:

#include <AsyncDelay.h>
#include <SlowSoftI2CMaster.h>
#include <AS3935.h>

#ifdef JTD
#include <DisableJTAG.h>

SlowSoftI2CMaster i2c(14, 17);
uint8_t addr = 0x03;

void setup(void)
#ifdef JTD
  for (uint8_t reg = 0; reg < 0x10; ++reg) {
    i2c.start(addr, SlowSoftI2CMaster::writeMode);
    i2c.repeatedStart(addr, SlowSoftI2CMaster::readMode);
    //i2c.start(addr, SoftWire::readMode);
    uint8_t val;
    Serial.print("Reg: 0x");
    Serial.print(reg, HEX);
    Serial.print(": 0x");
    Serial.println(val, HEX);

void loop(void)

But I still got the same error.

And you still haven't shown us the error messages.

And you still haven't shown us the EXACT error messages.

I fixed that for you.

The error completely:

In file included from C:\Users\****\Documents\Arduino\libraries\SoftI2CMaster-master/SoftWire.h:23:0,

                 from C:\Users\****\Documents\Arduino\libraries\AS3935\src/AS3935.h:7,

                 from C:\Users\****\Documents\Arduino\LightningSensetest\LightningSensetest.ino:3:

C:\Users\****\Documents\Arduino\libraries\SoftI2CMaster-master/SoftI2CMaster.h:83:2: error: #error "Not an AVR MCU! Use 'SlowSoftI2CMaster' library instead of 'SoftI2CMaster'!"

 #error "Not an AVR MCU! Use 'SlowSoftI2CMaster' library instead of 'SoftI2CMaster'!"


exit status 1
Error compiling for board Adafruit Feather M0.

C:\Users****\Documents\Arduino\libraries\SoftI2CMaster-master/SoftI2CMaster.h:83:2: error: #error "Not an AVR MCU! Use 'SlowSoftI2CMaster' library instead of 'SoftI2CMaster'!"

So, that is the file that is generating the error message. If you WERE using SlowSoftI2CMaster as it suggests, that file wouldn't even be being compiled.

So what do I do now? I have SlowSoftI2CMaster library imported and there is no SoftI2CMaster library imported. Thanks.

I have downloaded the AS3935 library from GitHub

A Google search for "AS3935 library github" returned multiple possibilities. It would be helpful to know which one you downloaded.

Odd, it looks like “SoftWire.h” is #including “SoftI2CMaster.h” which is then generating the error message.

But, the version of “AS3935.h” that you claim to be using doesn’t #include “SoftWire.h”. Try posting the contents of “AS3935.h” in code tags.

Here is the contents of AS3935.h and I have attached the file as well as it is here:

#ifndef AS3935_H
#define AS3935_H

#define AS3935_VERSION "1.0.1"

#include <AsyncDelay.h>
#include <SoftWire.h>

class AS3935 {
  enum state_t {
    stateOff = 0,
    statePoweringUp = 1, // first 2ms wait after power applied
    stateInitialising1 = 2,
    stateInitialising2 = 3,
    stateListening = 4,
    stateWaitingForResult = 5,
    stateCalibrate = 6,

  static const uint8_t regAfeGain = 0x00;
  static const uint8_t regNoiseFloor = 0x01;
  static const uint8_t regSpikeRej = 0x02;
  static const uint8_t regInt = 0x03;
  static const uint8_t regDistance = 0x07;
  static const uint8_t regTunCap = 0x08;
  static const uint8_t regPresetDefault = 0x3c;
  static const uint8_t regCalibRCO = 0x3d;
  // Various delays for switching between different states
  // etc. Because timer accuracy is limited to nearest ms add 1ms to
  // datasheet values.
  static const uint8_t powerUpDelay_ms = 5;
  static const uint8_t initialisation1Delay_ms = 3;
  static const uint8_t initialisation2Delay_ms = 3;
  static const uint8_t interruptDelay_ms = 3;
  bool initialise(uint8_t sda, uint8_t scl, uint8_t address, uint8_t tunCap,
		  bool indoor, void (*timestampCB)(void) = NULL);
  void start(void);
  bool process(void); // Call often to process state machine
  void finish(void); // Force completion and power-down

  // Set up the interrupt handler to call this routine
  inline void interruptHandler(void);

  bool readRegister(uint8_t reg, uint8_t &val) const;
  bool writeRegister(uint8_t reg, uint8_t val) const;
  bool setRegisterBit(uint8_t reg, uint8_t bit, bool bitValue = true) const;

  inline bool presetDefault(void) const;
  inline bool calibrateRCO(void) const;
  bool setIndoor(bool indoor) const;
  bool setNoiseFloor(uint8_t level) const;
  bool setSpikeRejection(uint8_t spikes) const;
  bool setLCOFreqDiv16(void) const;
  inline bool setMaskDisturber(bool maskDist) const;
  inline state_t getState(void) const;
  inline uint8_t getInterruptFlags(void) const;
  inline uint8_t getDistance(void) const;
  inline bool getBusError(void) const;
  inline void clearBusError(void);
  inline bool getTriggered(void) const;

  bool calibrate(void);
  bool _busError;
  uint8_t _address;
  uint8_t _tunCap;
  bool _indoor;
  uint8_t _interruptFlags;
  uint8_t _distance;
  SoftWire _i2c;
  volatile state_t _state; // Read but not modified by interrupt handler
  volatile bool _triggered;
  volatile uint16_t _calibrateCounter;
  void (*_timestampCB)(void);

  // Timer used when changing state. Used by the interrupt handler
  // when in listening state. 
  volatile AsyncDelay _delay;

void AS3935::interruptHandler(void)
  if (_state == stateListening) {
    if (_timestampCB)
    _delay.start(interruptDelay_ms, AsyncDelay::MILLIS);
    _triggered = true;
    _state = stateWaitingForResult;
    if (_state == stateCalibrate) {

bool AS3935::presetDefault(void) const
  return writeRegister(regPresetDefault, 0x96);

bool AS3935::calibrateRCO(void) const
  return writeRegister(regCalibRCO, 0x96);

bool AS3935::setMaskDisturber(bool maskDist) const
  return setRegisterBit(regInt, 5, maskDist);

AS3935::state_t AS3935::getState(void) const
  return _state;

uint8_t AS3935::getInterruptFlags(void) const
  return _interruptFlags;

uint8_t AS3935::getDistance(void) const
  return _distance;

bool AS3935::getBusError(void) const
  return _busError;

void AS3935::clearBusError(void)
  _busError = false;

bool AS3935::getTriggered(void) const
  return _triggered;


AS3935.h (3.59 KB)

Well, that certainly doesn't match the version of "AS3935.h" located at the GitHub page you linked above.

Sorry, it is this:

Looks to me like you have a Cluster F*ck of libraries involved. There are multiple GitHub sources for AS3935 libraries. Some use I2C, some use SPI. There are also multiple Soft I2C libraries floating around. You appear to have cobbled together an incompatible combination for the processor you're using.

I’ve never used this device or any of the libraries. Maybe someone else on the forum has. Have you considered using SPI? If you must use I2C, why do you think you need Soft I2C verses hardware?

I’d start from scratch and work out these basic decisions before going further.

If you must use I2C, why do you think you need Soft I2C verses hardware?

Possibly because the hardware OP is using doesn't support hardware I2C.

Possibly because the hardware OP is using doesn't support hardware I2C.

According to OP's first post in this thread, the processor is a Feather M0. That supports both hardware I2C and hardware SPI.