Categories
Statistics
Flag Counter
Since 08.08.2014
Counts only, if "DNT = disabled".

Your IP is 3.133.124.161
ec2-3-133-124-161.us-east-2.
Info
Valid HTML 4.01 Transitional Creative Commons Lizenzvertrag
rss
เราจะทำแบบวิศวกรผู้ยิ่งใหญ่
We love the King
24. November 2024
YOU RATED THIS ...
avg = 0.0 ,  n = 0


November 2024 ∴ Live And Learn
Arduino-Shield-LEO.php    27708 Bytes    31-05-2023 09:37:41


Arduino/Genuino Project : Dial S for Shutdown


Shield "LEO"



This device will send a SMS to a list of subscribers, when the powerline fails. It is used at ETH Hönggerberg, because a power failure shuts down a lot of (critical) systems (UPS just bridges a gap of minutes). Usually friday night. Sharp tongues would say that engineers build such apparatus to get a girl's phone number :-)


Arduino Shield LEO


This Shield / Project is no longer in service, as 2G has been shut down in Switzerland by the end of April 2021. The yet unpublished replacement is "Dial S on Shutdown 3G".


This project is a Hack-together of an Arduino MEGA (others may need modifications), a GSM-shield, the Shield "LEO" and a powerline-good detection circuit. A powerful battery (UPS) as well as an lcd and some test-buttons (not used) round it up. The diagram below shows the building blocks.


Block Diagramm




✈ Powerline Detector




The powerline detection circuit consists mainly of an optocoupler (e.g. 4N32). The only trick here is the use of a capacitor (in series with a resistor) to limit the current. We used a 220 nF, 630 V type, which has an impedance of almost 15 kΩ @ 50 Hz. We assume the line frequency to be constant. The so generated pulses are used (on the shield "LEO") to discharge a capacitor, beeing charged by a resistor to + 5V.


Voltage @ A0 and the discharging pulses
rises to 5 V when the powerline fails






✈ Shield "LEO"




This shield is mainly a central connection unit. You may attach an lcd (16x4). It is also home to a beeper and an eeprom (24LC256) for the phonebook (you may assemble two of them). The phonebook is updated via USB, by that you have more control on the subscriber data. It is possible to send test-sms in order for the (prepaid) sim card not to become a "sleeper". The version before used subscription via sms, but that has turned out to be not that clear for the operator. The board also has an RTC (DS1307Z) which mayst be updated via a request to the gsm-shield.




The complete management is done via USB






✈ Arduino Sketch - The Code



Double click on code to select ...


/* ///////////////////////////////////////////////////////////////////// 
ARDUINO/Genuino MEGA Sketch for "LEO", Dial "S" on Shutdown
Software Version 2.0, 
20.07.2017, Alexander C. Frank, 
HELPFUL WEBSITES:
1) http://www.hobbytronics.co.uk/arduino-external-eeprom 
//////////////////////////////////////////////////////////////////////*/

#include <Wire.h>

#include <LiquidCrystal.h>
// RS, E, D4, D5, D6, D7
LiquidCrystal lcd(9, 8, 6, 5, 4, A1);

byte Antenna[8] = {
B011111,
B010101,
B001010,
B000100,
B000100,
B000100,
B000100,
B000100,
};

byte PowerDown[8] = {
B011100,
B000100,
B000100,
B000100,
B000100,
B000100,
B000111,
B000000
};

byte PowerUp[8] = {
B000111,
B000100,
B000100,
B000100,
B000100,
B000100,
B111100,
B000000
};

// Include the GSM library
#include <GSM.h>

#define PINNUMBER "7287"
const int BufferLength = 20 ;
char remoteNumb[BufferLength+1];  
char remoteName[BufferLength+1];  
char txtMsg[] = "Greetings ! We apologise, but it looks like there is a 
	severe problem regarding power grid availability. Sensor at 
	HPF-D16 :-( :-(";
char tstMsg[] = "Greetings ! This is just a general connectivity test. 
	If you see it, everything is fine. If not, please visit the 
	Gadgets Lab :-) :-)"; 

// initialize the library instance
GSM gsmAccess;
GSM_SMS sms;

#include <GSM3ShieldV1DirectModemProvider.h>
GSM3ShieldV1DirectModemProvider modemAccess;

String reply ;

float PREPAIDCHF = 10.0 ;
String CARRIER ;
String RECEIVERSIGNALSTRENGTH ;
unsigned long Last_ALARM_off = 0 ;
unsigned long Last_ALARM_on = 0 ;
unsigned long Last_SMS_out = 0 ;

// Save data variables
String IMEI = "";

// serial monitor result messages
String errortext = "ERROR";

volatile bool isrTriggered = false ;
volatile bool ALARM = false ;
bool StatusOLD = false ;

const int BEEP = 13 ;
const int PageSize = 256 ;

char Buffy[BufferLength+1] ;      // holds User Input from Serial
byte byteRead ;
int EEPROMADR  = 0x50 ;  // THE 24C01, HOLDING SENSOR INFORMATION
int eeaddress = 0 ; 

//   1 kBit     128 Bytes    3 names
//   2 kBit     256 Bytes    6 Names <<< TESTMODE
//   4 kBit     512 Bytes   12 Names 
//   8 kBit    1024 Bytes   25 Names
//  16 kBit    2048 Bytes   51 Names 
//  32 kBit    4096 Bytes  102 Names 
//  64 kBit    8192 Bytes  204 Names
// 128 kBit   16384 Bytes  408 Names
// 256 kBit   32768 Bytes  916 Names

const byte NameOffset = 0x00 ;
const byte NameLength = 0x10 ;
const byte CountryOffset = NameOffset + NameLength ;
const byte CountryLength = 0x03 ;
const byte NumberOffset = CountryOffset + CountryLength ;
const byte NumberLength = 0x10 ;
const byte DatasetLength = NameLength + CountryLength + NumberLength  ;
const int  EEPROMSIZE = 256 - DatasetLength ;

const char Version[] = "1807.2560" ; // DDMM.YYYY  
byte data ;
unsigned int DeleteWhat = 99 ;
int aux ;
unsigned int MaximumUsers = EEPROMSIZE / DatasetLength ;

void setup() 
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(115200);  // start serial for output
  print_title();
  lcd.begin(16, 4);
  lcd.clear();
  lcd.setCursor(0,0); lcd.print("DIAL S FOR");
  lcd.setCursor(0,1); lcd.print("SHUTDOWN V3.X");
  lcd.setCursor(0,2); lcd.print("QUANTUMOPTICS");
  lcd.setCursor(0,3); lcd.print("28.07.2017");
  delay(1000);
  lcd.clear();

  pinMode(BEEP, OUTPUT);
  digitalWrite(BEEP, LOW);

  // SPECIAL CHARACTER DEFINITION
  lcd.createChar(0, Antenna);
  lcd.createChar(1, PowerDown);
  lcd.createChar(2, PowerUp);

  // connection state
  boolean notConnected = true;

  // Start GSM shield
  // If your SIM has PIN, pass it as a parameter of begin() in quotes
  while (notConnected) 
  {
    if (gsmAccess.begin(PINNUMBER) == GSM_READY) 
    {
      notConnected = false;
    } 
    else 
    {
      Serial.println("Not connected");
      delay(1000);
    }
  }
    
  Serial.println("GSM initialised");

  Serial.println("Ask for Credit ...  ");
  reply = "Ooops, no answer ?!?" ;
  if (gsmAccess.getStatus() == GSM_READY) 
  {
    modemAccess.writeModemCommand("AT+CMGF=0",1000);
    reply = modemAccess.writeModemCommand("AT+CUSD=1,\"*130#\"",5000);
    modemAccess.writeModemCommand("AT+CMGF=1",1000);
  }
  // String reply="+CUSD: 2, \"Ihr Restguthaben ist CHF 35,70\",15";
  Serial.println(reply);
  

  Serial.println("===============================================");   

  // initialize timer1 
  noInterrupts();           // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;

  TCNT1 = 34286;            // preload timer 65536-16MHz/256/2Hz
  TCCR1B |= (1 << CS12);    // 256 prescaler 
  TIMSK1 |= (1 << TOIE1);   // enable timer overflow interrupt
  interrupts();             // enable all interrupts

  print_options();


}


ISR(TIMER1_OVF_vect)        
{
  TCNT1 = 34286;            // preload timer
  isrTriggered = true ;
}






// ///////////////////////////////////////////////////////////// 
// Prints a list of Options
// ///////////////////////////////////////////////////////////// 
void print_options()
{
  Serial.print(" >>> WAS GUCKST DU ???\n");
  Serial.print("-----------------------------------------------\n");
  Serial.print("[s] Show complete phonebook\n");
  Serial.print("[e] show Eeprom contents\n");
  Serial.print("[f] Format phonebook\n");
  Serial.print("[d] Delete entry\n");
  Serial.print("[a] Add entry\n");
  Serial.print("-----------------------------------------------\n");
  Serial.print("[b] test Beeper\n");
  Serial.print("[t] Test SMS\n");
  Serial.print("-----------------------------------------------\n");
}

// ///////////////////////////////////////////////////////////// 
// Prints the title block when program first starts.
// ///////////////////////////////////////////////////////////// 
void print_title()
{
  Serial.println("===============================================");   
  Serial.println("Welcome to Dial S on Shutdown Phonebook Manager");  
  Serial.print("Software Version : "); Serial.println(Version);
  Serial.println("by Alexander C. Frank, ETH QUANTUMOPTICS 2017"); 
  Serial.println("===============================================");   
}

// ///////////////////////////////////////////////////////////// 
// Clears the Input Buffer
// ///////////////////////////////////////////////////////////// 
void InitBuffy()
{
  for (int i=0; i<20; i++)
  Buffy[i] = 32 ;   // SPACE
}

// ///////////////////////////////////////////////////////////// 
// Read User Input from Serial
// ///////////////////////////////////////////////////////////// 
void ReadUserInput()
{
  int pointer = 0 ;
  boolean ende = false ;
  while ( ( Serial.available() ) || ( ende == false ) ) 
      {
      if(isrTriggered)
      {
        TaskScheduler();
        isrTriggered = false;
      }
      byteRead = Serial.read();
      if ( byteRead == 10 ){ ende = true ; }
      if ( byteRead < 255 )
        { 
        Buffy[pointer] = byteRead ; 
        if ( pointer < 19 ) pointer++ ;
        }
      }
}

// ///////////////////////////////////////////////////////////// 
// WRITE A SINGLE BYTE TO THE EEPROM
// ///////////////////////////////////////////////////////////// 
void writeEEPROMbyte(unsigned int eeaddress, byte data ) 
{
  Wire.beginTransmission(EEPROMADR);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.write(data);
  Wire.endTransmission();
 
  delay(5);
}

// ///////////////////////////////////////////////////////////// 
// READ A SINGLE BYTE FROM THE EEPROM
// ///////////////////////////////////////////////////////////// 
byte readEEPROMbyte( unsigned int eeaddress ) 
{
  byte rdata = 0xFF;
 
  Wire.beginTransmission(EEPROMADR);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
 
  Wire.requestFrom(EEPROMADR,1);
 
  if (Wire.available()) rdata = Wire.read();
 
  return rdata;
}

void readName( unsigned int nummer ) 
{
  // EMPTY STRING
  for ( int a = 0 ; a < BufferLength ; a++ ) remoteName[a] = '\0' ;
  for ( int a = 0 ; a < NameLength ; a++ ) 
  {
    remoteName[a] = readEEPROMbyte( nummer * DatasetLength 
    + NameOffset + a );
  }

  for ( int a = NameLength ; a < BufferLength ; a++ ) 
  {
    remoteName[a] = 0x20;
  }
}

void readNumber( unsigned int nummer ) 
{
  char aux ;
  // EMPTY STRING
  for ( int a = 0 ; a < BufferLength ; a++ ) remoteNumb[a] = '\0' ;
  remoteNumb[0] = readEEPROMbyte( nummer * DatasetLength 
  + CountryOffset + 0 );
  remoteNumb[1] = readEEPROMbyte( nummer * DatasetLength 
  + CountryOffset + 1 );
  remoteNumb[2] = readEEPROMbyte( nummer * DatasetLength 
  + CountryOffset + 2 );

  for ( int a = 0 ; a < NumberLength ; a++ ) 
  {
    aux = readEEPROMbyte( nummer * DatasetLength + NumberOffset + a );
    if (aux > 0x20) remoteNumb[a+3] = aux ;
  }
}
// ///////////////////////////////////////////////////////////// 
// DELETE ENTRY
// ///////////////////////////////////////////////////////////// 
void deleteUSER (unsigned int WhichOne ) 
{
  unsigned int StartPointer = WhichOne * DatasetLength ;
  unsigned int EndPointer = EEPROMSIZE + DatasetLength ;
  byte data = 0x00 ;
  for (int m = StartPointer ; m < EndPointer ; m++)
  {
    data = readEEPROMbyte( m + DatasetLength );
    writeEEPROMbyte( m , data );
  }
   
Serial.println("\nO.K.\n\n");
}

// ///////////////////////////////////////////////////////////// 
// ADD ENTRY
// ///////////////////////////////////////////////////////////// 
void addUSER ( ) 
{
  // FIND A FREE PLACE IN THE PHONEBOOK : FIRST LETTER IN THE NAME
  // IS A SPACE, aka 32 DEC or 0x20
  unsigned int POsition = MaximumUsers + 1;
  unsigned int FREEposition = MaximumUsers ;
  byte data = 0x00 ;
  do
  {
    POsition -= 1;
    data = readEEPROMbyte( (POsition * DatasetLength) + NameOffset );
    // Serial.print("Position : ");Serial.print(POsition,DEC); 
    Serial.print("Data : ");Serial.println(data,HEX);
    if ( data == 0x20 ) 
    {
      FREEposition = POsition ;  
    }
  }
  while ( POsition > 0 ) ;
  
  if ( FREEposition < MaximumUsers ) 
  {
    // THERE IS SPACE IN THE PHONEBOOK
	// /////////////////////////////////////////////////////////////////////
    // ASK FOR NAME
    Serial.print("\nName :         ");
    InitBuffy();
    ReadUserInput(); 
    aux = -1;
    do 
    {
      aux += 1 ;
      writeEEPROMbyte( (( FREEposition * DatasetLength) 
      + NameOffset + aux ), Buffy[aux] ) ;
    }
    while (( aux < NameLength ) && ( Buffy[aux] != 0x20 ) );
	// /////////////////////////////////////////////////////////////////////
    // ASK FOR COUNTRY CODE
    Serial.print("\nCountry Code : ");
    InitBuffy();
    ReadUserInput(); 
    aux = -1;
    do 
    {
      aux += 1 ;
      writeEEPROMbyte( (( FREEposition * DatasetLength) 
      + CountryOffset + aux ), Buffy[aux] ) ;
    }
    while (( aux < CountryLength ) && ( Buffy[aux] != 0x20 ) );
	// /////////////////////////////////////////////////////////////////////
    // ASK FOR PHONE NUMBER
    Serial.print("\nPhone Number : ");
    InitBuffy();
    ReadUserInput(); 
    aux = -1;
    do 
    {
      aux += 1 ;
      writeEEPROMbyte( (( FREEposition * DatasetLength) 
      + NumberOffset + aux ), Buffy[aux] ) ;
    }
    while (( aux < NumberLength ) && ( Buffy[aux] != 0x20 ) );
    
  }
  else 
  {
    // PHONEBOOK FULL
    Serial.println("Oooops - looks like this thing is already full.\n");
  }
   
Serial.println("\nO.K.\n\n");
}

// ///////////////////////////////////////////////////////////// 
// READ AND DISPLAY ENTIRE EEPROM
// ///////////////////////////////////////////////////////////// 
void ReadEeprom()
{
  for (int address = 0; address < EEPROMSIZE; address+=8) 
  {  
    if (address<256) Serial.print("0");
    if (address<16) Serial.print("0");
    Serial.print(address,HEX);  
    Serial.print("\t"); 
    // One row, HEX
    for (int add = 0; add < 8; add++) 
    { 
    data = readEEPROMbyte( address+add );
    if (data<16) Serial.print("0");  
    Serial.print(data, HEX);
    Serial.print(" ");
    }
    Serial.print("\n"); 
  } 
   
Serial.println("\nO.K.\n\n");
}

// ///////////////////////////////////////////////////////////// 
// READ AND DISPLAY ENTIRE PHONEBOOK
// ///////////////////////////////////////////////////////////// 
void ReadPhonebook()
{
  int lfdNR = 0;
  do
  {  
    // DISPLAY I
    Serial.print("Data :         ");
    Serial.println(lfdNR,DEC);
    // DISPLAY NAME
    Serial.print("Name :         ");
    readName(lfdNR);
    Serial.println(remoteName);
    // DISPLAY PHONE NUMBER
    Serial.print("Number :       ");
    readNumber(lfdNR);
    Serial.println(remoteNumb);
    
    lfdNR += 1;
    Serial.println("--------------------------------"); 
    readName(lfdNR);
  } 
  while ( remoteName[0] != 0x20 ) ;

   
Serial.println("\nO.K.\n\n");
}

// ///////////////////////////////////////////////////////////// 
// SEND TEST SMS
// ///////////////////////////////////////////////////////////// 
void SendTestSMS()
{
  for ( int lfdNR = 0 ; lfdNR < MaximumUsers; lfdNR++ ) 
  {
    readName(lfdNR);    // remoteName
    readNumber(lfdNR);  // remoteNumb
    if (remoteName[0] != 0x20)
    {
      // send the message
      sms.beginSMS(remoteNumb);
      sms.print(tstMsg);
      sms.endSMS();
      Serial.print(remoteNumb);Serial.println(" DONE.");
    }
    delay(499);
  }
Serial.println("\nO.K.\n\n");
}

// ///////////////////////////////////////////////////////////// 
// SEND ALARM SMS
// ///////////////////////////////////////////////////////////// 
void SendAlarmSMS()
{
  Serial.print("\nALARM @ T = ");
  Serial.println(millis());
  for ( int lfdNR = 0 ; lfdNR < MaximumUsers; lfdNR++ ) 
  {
    readName(lfdNR);    // remoteName
    readNumber(lfdNR);  // remoteNumb
    if (remoteName[0] != 0x20)
    {
      // send the message
      sms.beginSMS(remoteNumb);
      sms.print(txtMsg);
      sms.endSMS();
      Serial.print(remoteNumb);Serial.println(" SENT.");
    }
    delay(499);
  }
Serial.println("\nO.K.\n\n");
}

// ///////////////////////////////////////////////////////////// 
// FORMAT ENTIRE PHONEBOOK
// ///////////////////////////////////////////////////////////// 
void formatEEPROM() 
{
  Serial.println("FORMATTING EEPROM.");  
  for (int j=0; j < (EEPROMSIZE + DatasetLength) ; j++) 
  {
  eeaddress = j ;
  Wire.beginTransmission(EEPROMADR);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.write(0x20);
  Wire.endTransmission();
 
  delay(10);    
  }
   
Serial.println("\nO.K.\n\n");
}

// ///////////////////////////////////////////////////////////// 
// UPDATE LINEVOLTAGE STATUS

void UpDatePowerStatus()
{
float PGV = 5.0 * analogRead(A0) / 1023 ; 
lcd.setCursor(0,3); lcd.print("# "); lcd.print(PGV,2);
lcd.setCursor(7,3);lcd.print(" [0-5]   ");
StatusOLD = ALARM ;
if (PGV > 4.5) ALARM = true ;
if (PGV < 1.9) ALARM = false ;
if ((StatusOLD == true) && (ALARM == false )) Last_ALARM_off = millis() ;
if ((StatusOLD == false) && (ALARM == true )) Last_ALARM_on  = millis() ;
digitalWrite(BEEP, ALARM);
if (ALARM == true)  { lcd.setCursor(0,0); lcd.print("STATUS: OOOOPS "); }
else { lcd.setCursor(0,0); lcd.print("STATUS: NORMAL "); }
lcd.setCursor(0,1); lcd.write(byte(1)); lcd.setCursor(2,1); 
lcd.print(Last_ALARM_on/1000);
lcd.setCursor(0,2); lcd.write(byte(2)); lcd.setCursor(2,2); 
lcd.print(Last_ALARM_off/1000);
delay(10);
}

// ///////////////////////////////////////////////////////////// 
// UPDATE RSSI DISPLAY

void UpDateRSSI()
{
lcd.setCursor(0,2); lcd.write(byte(0)); // ANTENNA SYMBOL
lcd.setCursor(2,2); // lcd.print(scannerNetworks.getSignalStrength());
lcd.setCursor(7,2);lcd.print(" [0-31] ");
delay(10);
}

// ///////////////////////////////////////////////////////////// 

void TaskScheduler()
{
  lcd.clear();
  UpDatePowerStatus() ;
  // UpDateRSSI(); 
  if (ALARM) 
  {
    //  IS THE LAST ALARM OLDER THAN 60 MINUTES = 3600 SEC ???
    if (( Last_SMS_out == 0) || (abs(millis()-Last_SMS_out)>3600000) ) 
    {
      SendAlarmSMS();
      Last_SMS_out = millis();
    }
  }
  if ( sms.available() )
  {
    Serial.println("Message received from:");
    // Get remote number
    sms.remoteNumber(remoteNumb, 20);
    Serial.println(remoteNumb);
    // An example of message disposal
    // Any messages starting with # should be discarded
    if (sms.peek() == '#') {
      Serial.println("Discarded SMS");
      sms.flush();
    }
    // Read message bytes and print them
    while (char c = sms.read()) {
      Serial.print(c);
    }
    Serial.println("\nEND OF MESSAGE");
    // Delete message from modem memory
    sms.flush();
    Serial.println("MESSAGE DELETED");
  }

}
// ///////////////////////////////////////////////////////////// 

void loop()
{
    InitBuffy();
    ReadUserInput();
    int WhatsUp = Buffy[0] ;               
    UpDatePowerStatus();
    switch (WhatsUp)
    {
      case 97 : // a - add entry
        Serial.print("Add new Phonebook entry.\n");
        addUSER();
        print_options();        
        break;

      case 98 : // b - beeper test
        digitalWrite(BEEP, HIGH);
        delay(999);
        digitalWrite(BEEP, LOW);
        break;

      case 100 : // d - delete entry
        Serial.print("Delete which entry [0 ... ");
        Serial.print(MaximumUsers,DEC); Serial.print("]  ???\n");
        InitBuffy();
        ReadUserInput();
        DeleteWhat = Buffy[0] - 48 ;
        aux = Buffy[1] - 48 ; if ((aux >= 0) && (aux <= 9)) 
        { DeleteWhat = DeleteWhat * 10 + aux ; }
        aux = Buffy[2] - 48 ; if ((aux >= 0) && (aux <= 9)) 
        { DeleteWhat = DeleteWhat * 10 + aux ; }
        aux = Buffy[3] - 48 ; if ((aux >= 0) && (aux <= 9)) 
        { DeleteWhat = DeleteWhat * 10 + aux ; }
        if ( DeleteWhat < MaximumUsers )  deleteUSER( DeleteWhat );
        else Serial.println("Oooops - that number was slightly too large.\n");
        print_options();        
        break;

      case 101 : // e - show eeprom
        ReadEeprom();
        print_options();
        break;

      case 102 : // f - format eeprom
        formatEEPROM();
        print_options();
        break;

      case 115 : // s - show phonebook
        ReadPhonebook();
        print_options();
        break;

      case 116 : // t - Test sms :-)
        SendTestSMS();
        print_options();
        break;

      default:
        Serial.println("\nOOOPS - Invalid Input.\n");
        print_options();
        delay(10);
        break;
    }

delay(200);  


}

// ///////////////////////////////////////////////////////////////////// 
// END OF FILE.
// /////////////////////////////////////////////////////////////////////




Arduino Shield LEO




✈ Share your thoughts



The webmaster does not read these comments regularely. Urgent questions should be send via email. Ads or links to completely uncorrelated things will be removed.


Your Browser says that you allow tracking. Mayst we suggest that you check that DNT thing ?

 
t1 = 6709 d

t2 = 231 ms

★ ★ ★  Copyright © 2006 - 2024 by changpuak.ch  ★ ★ ★

Impressum