Collegamento SPI tra Esp8266 e sensore fulmini AS3935

Per definizione una IRQ DEVE essere la più breve possibile e NON dovrebbe neanche usare la seriale, figuriamoci fare altre cose.

Un modo pratico è quello di utilizzare una flag ... quando scatta la IRQ semplicemente la flag viene messa a true, poi, nel loop(), che deve girare sempre senza ritardi, si controlla la flag e se vera, si fa quello che si deve fare e la si rimette falsa.

Guglielmo

Ok ho capito il concetto, la flag si intende una variabile?
Quando scatta interrupt irq mette la variabile flag a True, nel loop quando la variabile flag è True eseguo il mio codice e le mie operazioni e la rimetto in false, giusto?

Si, basta una variabile "byte" ...

Esatto ... la ISR è velocissima (mette solo a true la variabile) e poi fai il tutto nel loop().

Guglielmo

Ho seguito tutti i consigli e settato il codice che riporto di seguito nel caso possa tornare utile a qualcuno:

#include <SPI.h>
#include <AS3935.h>
#include <ESP8266WiFi.h>          //per gestire WifiClientSecure (collegamento ad xyz.it)
#include <WiFiClient.h>           //per gestire la connessione alla rete Wifi

//dati per la connessione alla rete Wifi 
const char* MY_SSID = "xxx"; 
const char* MY_PWD = "yyy";

//dati per la connessione ad xyz.it
const char* host = "www.xyz.it";
const uint16_t port = 443;  

int distanza_fulmine;
bool variabile_flag = false;          //variabile che diventa true solo quando viene rilevato un fulmine

void printAS3935Registers();          //rileva e stampa i parametri del sensore (rumore di fondo, spike rejection, soglia di controllo)

byte SPItransfer(byte sendByte);      //funzione che si occupa del traferimento dei dati via SPI
int valore_calibrazione;

void AS3935Irq();                     //funzione che verifica se ci sono disturbi o fulmini e causa l'interrupt
                                                      
AS3935 AS3935(SPItransfer,D4,D3);     //primo parametro: funzione per il trasferimento dei dati via SPI     
                                      //secondo parametro: pin CS collegato ad Arduino
                                      //terzo parametro:pin IRQ collegato ad Arduino

void setup(){
  
  Serial.begin(9600);

  //connessione Wifi
  connectWifi();
  
  SPI.begin();
  SPI.setDataMode(SPI_MODE1);
  SPI.setClockDivider(SPI_CLOCK_DIV16);
  SPI.setBitOrder(MSBFIRST);
  AS3935.reset();                             //ripristina tutti i valori di registro interni ai valori predefiniti
  delay(10);
  AS3935.setOutdoors();                       //setta il sensore per il funzionamento all'esterno
  AS3935.registerWrite(AS3935_NF_LEV,2);      //scrive 2 nel Noise Level register 
  
  //se il sensore non riesce a stare nel range di tolleranza la calibrazione non andrà a buon fine e restituirà false
  if(!AS3935.calibrate()) {
    Serial.println("La calibrazione non è andata a buon fine, controllare il cablaggio");
  }
  
  valore_calibrazione=AS3935.registerRead(AS3935_TUN_CAP);  //il range è compreso tra 0 e 15
  Serial.print("La calibrazione rilevata è (range concesso tra 0 e 15): ");
  Serial.println(valore_calibrazione);

  //AS3935.enableDisturbers();      //turn on indication of distrubers, once you have AS3935 all tuned, you can turn those off with disableDisturbers()
  AS3935.disableDisturbers();

  printAS3935Registers();           //rileva e stampa i parametri del sensore (rumore di fondo, spike rejection, soglia di controllo)
  
  //usare interrupt significa che non serve controllare lo stato del pin continuamente, lo fa il chip da solo
  attachInterrupt(digitalPinToInterrupt(D3), AS3935Irq, RISING);
}

void loop(){ 
  if (variabile_flag) {     //diventa true quando viene rilevato un fulmine

    //collegamento all'host xyz.it
    WiFiClientSecure client;
    client.setInsecure();       //non si utilizzano certificati di sicurezza

    //verifica se il collegamento non è andato a buon fine
    if (!client.connect(host, port)) {
      delay(5000);
      return;
    }

    //se la connessione all'host xyz.it è avvenuta 
    if (client.connected()) {

      String url1 = "GET /aggiungi_fulmini.php?distanza_fulmine="; 
      String url2 = " HTTP/1.1";

      //Serial.print(url1);
      //Serial.print(distanza_fulmine, DEC);
      //Serial.println(url2);

      //invio url all'host xyz.it per il salvataggio dei dati sul database mysql
      client.print(url1);
      client.print(distanza_fulmine, DEC);
      client.println(url2);
      client.println("Host: www.xyz.it");
      client.println("Access-Control-Allow-Origin: *");
      client.println("Connection: close");
      client.println();
      client.stop();
    }

    variabile_flag= false;

  }

}


void printAS3935Registers(){
  int noiseFloor = AS3935.getNoiseFloor();
  int spikeRejection = AS3935.getSpikeRejection();
  int watchdogThreshold = AS3935.getWatchdogThreshold();
  //Serial.print("Il rumore di fondo è: ");
  //Serial.println(noiseFloor,DEC);
  //Serial.print("Lo spike rejection è: ");
  //Serial.println(spikeRejection,DEC);
  //Serial.print("La soglia di controllo è: ");
  //Serial.println(watchdogThreshold,DEC);  
}

byte SPItransfer(byte sendByte){
  return SPI.transfer(sendByte);
}

ICACHE_RAM_ATTR void AS3935Irq(){            //ICACHE_RAM_ATTR serve per caricare nella ram altrimenti con esp non funzionano gli interrupt

  //verifica cosa ha causato l'interrupt
  //appena leggiamo l'interrupt, il pin IRQ diventa LOW
  int irqSource = AS3935.interruptSource();   //restituisce bit 0: livello rumore troppo alto
                                              //            bit 2: rilevato disturbo
                                              //            bit 3: rilevato fulmine
    
  //if (irqSource & 0b0001){
  //  Serial.println("Livello rumore troppo alto");
  //}
  //if (irqSource & 0b0100){
  //  Serial.println("Disturbo rilevato");     
  //}  
  if (irqSource & 0b1000){
    distanza_fulmine = AS3935.lightningDistanceKm();    //determina la distanza del fulmine in km
      
    if (distanza_fulmine < 41 && distanza_fulmine > 0){        //40 km è la distanza di rilevamento massima
      
      //Serial.print("Fulmine rilevato a ");
      //Serial.print(distanza_fulmine,DEC);
      //Serial.println(" km");

      variabile_flag = true;
      
   }
  }
}


//funzione per la connessione alla rete wifi
void connectWifi()
{
  WiFi.begin(MY_SSID, MY_PWD);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
  }
  Serial.println("Connesso");
}

Approfitto per chiedere una ultima cosa: ho notato che il codice, funzionante, quando lo trasmetto alla scheda a volte non si avvia e devo spegnerla e riaccenderla o resettarla pù volte e poi funziona senza problemi. A cosa può essere dovuto?

Grazie mille

... premesso che io ho abbandonao da molto tempo gli ESP8266 a favode dei molto più performati ed affidabili ESP32 (ormai li trovi praticamente allo stesso prezzo e, volendo nello stesso formato di schede), comunque è strano.

Io ho preso da tantissimo tempo l'abitudine di mettere un delay(500) subito come prima cosa all'inizio del setup() (tanti anni fa, con i vecchi arduino, se si usava la seriale, era meglio farlo) e ... non ho mai avuto problemi ... puoi provare, ma se non risolvi ... potrebbe essere qualche problema nel codice o qualche difetto delle schede ... :roll_eyes:

Potresti mettere qualche Serial.println() di diagnostica in vari punti e capire dove si ferma ...

Guglielmo

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.