Introduction: ⚡Iuppiter: Proteggi La Tua Casa Dai Fulmini

Il problema delle fulminazioni spesso si traduce in gravi danni ad apparecchi elettrici ed elettronici, nonché nell'interruzione, a lungo termine, dei servizi in area critica. E' proprio in queste circostanze che interviene Iuppiter.

Iuppiter è un importante device che in caso di imminenti scariche atmosferiche isola l'impianto elettrico dell'abitazione, riarmandolo a cessato pericolo. Poiché anche la linea telefonica può essere oggetto di sovratensioni, l'apparecchio in caso di pericolo imminente ne provvede il distacco; infatti una sovratensione sulla linea telefonica porta molto spesso danni a modem e computer ai quali è connessa. Il dispositivo, attraverso un display seriale LCD, segnalerà inoltre scariche elettriche, visualizzandone il numero e, se ne rileva la causa meteorologica, visualizza la distanza-evento nel raggio di circa 40 km.

La scelta dunque è vostra: deciderete di mettere in sicurezza il vostro impianto elettrico con un semplice device DIY o rischierete tutto decidendo di sfidare l'iram Iovis?

Step 1: Componenti Utilizzati

Ecco un'utile lista di tutti i materiali che ho impiegato per la realizzazione di Iuppiter. La maggior parte di essi si possono facilmente trovare nel vostro negozio di elettronica di fiducia:

  • Spina con cavo tripolare 1.5 m
  • Gommino passacavo
  • Fusibile 250 mA con porta fusibile volante
  • Trasformatore 220-15V 30VA
  • Fusibile 1.5 mAh con porta fusibile volante
  • Ponte raddrizzatore
  • 3 A condensatore elettrolitico 2200 microfarad 25 V
  • Integrato stabilizzatore 7805
  • Integrato regolatore LM317
  • Condensatore 47 microfarad 25 V
  • Resistore 6 ohm 2 watt
  • 4 diodi 1N4007
  • 4 transitor BC207B
  • Integrato stabilizzatore 7812
  • Arduino Uno
  • Scheda di futura elettronica FT1324M
  • Batteria 12V 2Ah piombo gel
  • LCD seriale futura elettronica codice LCDSER16*2NV
  • Relè 12V 5 A
  • 2 scambi funzione deviatore
  • Interruttore di rete
  • Deviatore

Step 2: Un Po' Di Teoria...

Iuppiter utilizza un particolare chip, l'AMS AS3935, con il quale monitora costantemente i fulmini e discrimina le scariche meteorologiche dalle scariche di origine artificiale e, attraverso un algoritmo implementato, ne calcola la distanza. Il chip calcola, in parole povere, le onde elettromagnetiche generate dal fulmine. Il flusso di dati digitali, in uscita e entrata, viene veicolato attraverso un protocollo di comunicazione detto SPI (serial peripheral interface). Mediante questo bus (binary unit System), il chip comunica con la scheda di Arduino Uno,che si occupa della gestione del display e dei vari azionamenti.

Step 3: Programmare Arduino

Ecco il codice che ho utilizzato per programmare Arduino: guardalo qui sotto o scaricalo qui!

Codice essenziale Arduino per il funzionamento di Iuppiter

#include
#include
#include
#define LCD_pin 5 // LCD data signal
const int NoDetect=30;
int counter;
int NumDisturber=0;
SoftwareSerial LCD = SoftwareSerial(0, LCD_pin);
void printAS3935Registers();
// Function prototype that provides SPI transfer and is passed to
// AS3935 to be used from within library, it is defined later in main sketch.
// That is up to user to deal with specific implementation of SPI
// Note that AS3935 library requires this function to have exactly this signature
// and it can not be member function of any C++ class, which happens
// to be almost any Arduino library
// Please make sure your implementation of choice does not deal with CS pin,
// library takes care about it on it's own
byte SPItransfer(byte sendByte);
// tunecap is needed to display the calibration register value
int tunecap;
// Iterrupt handler for AS3935 irqs
// and flag variable that indicates interrupt has been triggered
// Variables that get changed in interrupt routines need to be declared volatile
// otherwise compiler can optimize them away, assuming they never get changed
void AS3935Irq();
// volatile int AS3935IrqTriggered; - not needed anymore
// First parameter - SPI transfer function, second - Arduino pin used for CS
// and finally third argument - Arduino pin used for IRQ
// It is good idea to chose pin that has interrupts attached, that way one can use
// attachInterrupt in sketch to detect interrupt
// Library internally polls this pin when doing calibration, so being an interrupt pin
// is not a requirement
AS3935 AS3935(SPItransfer,3,2); //change to AS3935(SPITransfer,9,3) if using slot #2
// AS3935 AS3935(SPItransfer,77,26); //if using Flip & Click socket A
void setup()
{
serLCDInit();
backlightOn();
clearLCD();
lcdPosition(0,3);
delay(3000);
LCD.print("Rivelatore");
delay(2000);
clearLCD();
lcdPosition(0,0);
LCD.print("Di Fulmini");
delay(2000);
clearLCD();
lcdPosition(0,0);
LCD.print("G.Carneglia");
delay(1500);
clearLCD();
pinMode(7,OUTPUT);
pinMode(8,OUTPUT);
Serial.begin(9600);
// first begin, then set parameters
SPI.begin();
// NB! chip uses SPI MODE1
SPI.setDataMode(SPI_MODE1);
// NB! max SPI clock speed that chip supports is 2MHz,
// but never use 500kHz, because that will cause interference
// to lightning detection circuit
SPI.setClockDivider(SPI_CLOCK_DIV16);
// and chip is MSB first
SPI.setBitOrder(MSBFIRST);
// reset all internal register values to defaults
AS3935.reset();
delay(10);
AS3935.setIndoors();
AS3935.registerWrite(AS3935_NF_LEV,2); //write 2 in the Noise Level register
//AS3935.registerWrite(AS3935_SREJ,0); //write 2 in the Noise Level register
// and run calibration
// if lightning detector can not tune tank circuit to required tolerance,
// calibration function will return false
if(!AS3935.calibrate())
Serial.println("Controllare il dispositivo1");
// now we print the value in the calibration register TUN_CAP
// it is in the range 0 - 15
tunecap=AS3935.registerRead(AS3935_TUN_CAP); //Internal calibration
Serial.print("Il Reg. tuningcap e' ");
Serial.println(tunecap);
// since this is demo code, we just go on minding our own business and ignore the fact that someone divided by zero
// first let's turn on disturber indication and print some register values from AS3935
// tell AS3935 we are indoors, for outdoors use setOutdoors() function
// AS3935.setOutdoors();
// turn on indication of distrubers, once you have AS3935 all tuned, you can turn those off with disableDisturbers()
AS3935.enableDisturbers();
printAS3935Registers();
// AS3935IrqTriggered = 0;
// Using interrupts means you do not have to check for pin being set continiously, chip does that for you and
// notifies your code
// demo is written and tested on ChipKit MAX32, irq pin is connected to max32 pin 2, that corresponds to interrupt 1
// look up what pins can be used as interrupts on your specific board and how pins map to int numbers
// ChipKit Max32 - irq connected to pin 2, or Arduino with irq connected to pin 3
// Uncomment the next line if using slot #2 of the Arduino mikroBUS adapter
// attachInterrupt(1,AS3935Irq,RISING);
// uncomment line below and comment out line above for Arduino Mega 2560, irq still connected to pin 2
attachInterrupt(0,AS3935Irq,RISING);
// attachInterrupt(digitalPinToInterrupt(26),AS3935Irq,RISING); // if using Flip & Click socket A
}
void loop()
{
// here we go into loop checking if interrupt has been triggered, which kind of defeats
// the whole purpose of interrupts, but in real life you could put your chip to sleep
// and lower power consumption or do other nifty things
// I prefer to move this code inside the interrupt routine itself
// Here I leave only some code to display "Waiting..." so I know everything works
delay(1000);
Serial.println("In attesa...");
if (counter==0)
{
NumDisturber=0;
counter=NoDetect;
clearLCD();
lcdPosition(0,1);
LCD.print("Nessun Fulmine");
lcdPosition(1,4);
LCD.print("Rilevato");
Serial.println("nessun fulmine rilevato");
}
else
{
counter=counter - 1;
}
}
void printAS3935Registers()
{
int noiseFloor = AS3935.getNoiseFloor();
int spikeRejection = AS3935.getSpikeRejection();
int watchdogThreshold = AS3935.getWatchdogThreshold();
Serial.print("Rumore di Fondo: ");
Serial.println(noiseFloor,DEC);
Serial.print("lo Spike Rejection e': ");
Serial.println(spikeRejection,DEC);
Serial.print("Il Watchdog Threshold e': ");
Serial.println(watchdogThreshold,DEC);
}
// this is implementation of SPI transfer that gets passed to AS3935
// you can (hopefully) wrap any SPI implementation in this
byte SPItransfer(byte sendByte)
{
return SPI.transfer(sendByte);
}
// this is irq handler for AS3935 interrupts, has to return void and take no arguments
// always make code in interrupt handlers fast and short
void AS3935Irq()
{
// there is no need for this flag anymore
// AS3935IrqTriggered = 1;
// I move all the code for dysplaiying events inside the interrupt routine
// again there is no need for this flag
// reset the flag
// AS3935IrqTriggered = 0;
// first step is to find out what caused interrupt
// as soon as we read interrupt cause register, irq pin goes low
int irqSource = AS3935.interruptSource();
// returned value is bitmap field, bit 0 - noise level too high, bit 2 - disturber detected, and finally bit 3 - lightning!
if (irqSource & 0b0001)
Serial.println("Rumore Elevato, settare il rumore di fondo");
if (irqSource & 0b0100)
{
NumDisturber+=1;
Serial.println("Scarica Rilevata");
clearLCD();
lcdPosition(0,0);
LCD.print("Scar. Ril: ");
LCD.print(NumDisturber,DEC);
Serial.println("Scar. Ril");
Serial.println(NumDisturber,DEC);
digitalWrite(7,HIGH);
delay(1000);
digitalWrite(7,LOW);
counter=NoDetect;
}
if (irqSource & 0b1000)
{
// need to find how far that lightning stroke, function returns approximate distance in kilometers,
// where value 1 represents storm in detector's near victinity, and 63 - very distant, out of range stroke
// everything in between is just distance in kilometers
int strokeDistance = AS3935.lightningDistanceKm();
if (strokeDistance == 1)
{
Serial.println("Tempesta, Attenzione!");
lcdPosition(1,1);
Serial.println("PERICOlO!!");
lcdPosition(1,3);
Serial.println("ALLONTANARSI!");
counter=NoDetect;
digitalWrite(8,HIGH);
delay(3000);
digitalWrite(8,LOW);
}
if (strokeDistance == 63)
{
Serial.println("Fulmini Lontani.");
lcdPosition(0,2);
Serial.println("Fulmini");
lcdPosition(1,0);
Serial.println("Oltre Portata");
counter=NoDetect;
}
if (strokeDistance < 63 && strokeDistance > 1)
{
Serial.print("Fulmine Rilevato a ");
Serial.print(strokeDistance,DEC);
Serial.println("Kilometri");
lcdPosition(1,0);
LCD.print("Distanza:");
LCD.print(strokeDistance,DEC);
LCD.print("km");
counter=NoDetect;
}
}
}
/*
SensorMower Arduino serLCD
*/
const int LCDdelay=2; // conservative, 2 actually works
void lcdPosition(int row, int col)
{
LCD.write(0xFE); //command flag
LCD.write((col + row*64 + 128)); //position
delay(LCDdelay);
}
void clearLCD()
{
LCD.write(0xFE); //command flag
LCD.write(0x01); //clear command.
delay(LCDdelay);
}
void serCommand()
{ //a general function to call the command flag for issuing all other commands
LCD.write(0xFE);
}
void backlightOn()
{ //turns on the backlight
LCD.write(0x7C); //command flag for backlight stuff
LCD.write(157); //light level.
delay(LCDdelay);
}
void backlightOff()
{ //turns off the backlight
LCD.write(0x7C); //command flag for backlight stuff
LCD.write(128); //light level for off.
delay(LCDdelay);
}
/*
void splashSet()
{ //set the splash display text to memory
LCD.write(0x7C); //command flag
LCD.write(10); //this is the j char or line feed
}
*/
void serLCDInit()
{
LCD.begin(9600);
backlightOff();
}
view rawLCD seriale hosted with ❤ by GitHub