Garagentorsteuerung

Aus Dario's Home
Wechseln zu: Navigation, Suche
Außenansicht
Innenansicht
Platine AVR 2313

Projektdatum: 2005

Warum

Ich hatte einmal eine Garage, die nur ein Tor hat, aber kein zweiten Zugang. Nun habe ich einen Gragentoröffner gekauft, der sich mit einem 433MHz Sender fernsteuern lässt. Den muss man aber immer aus dem Auto mit in die Wohnung nehmen damit man morgens auch wieder in die Garage kommt. Oft stand ich vor der geschlossenen Garage und der Sender war in der zweiten Etage. Da musste Abhilfe geschaffen werden.

Die Idee

Nachdem ich die Steuerung aus dem Antrieb ausgebaut und analysiert habe, hatte ich folgenden Plan:

Tor auf, Tor Zu

Der extern anschliessbarer Schalter, der das Tor öffnet bzw. schließt, zieht das Potential einer Leitung auf Masse. Dieser Eingang soll nun von dem Handy aus gesteuert werden. Also habe ich anstelle des Schalters ein Transistor angeschlossen, den ich vom Atmel aus steuern kann.

Status abfragen

An dem mechanischen Antrieb ist ein Endeschalter, der eine Leitung auf GND zieht, wenn das Tor vollständif geöffnet ist. Diese Leitung habe ich auf einen Eingang des AVR gelegt und so weiss der Atmel, wann das Tor offen ist.

Das Handy

Aber wie teile ich dem Atmel mit, dass er das Tor öffnen oder schliessen soll? Ganz einfach: in der Schublade hatte ich noch ein altes Siemens S25 Handy und eine Prepaid-Karte von Loop hatte ich auch noch. Also das Handy an den Atmel angeschlossen, das Programm geschrieben und fertig.

Das 1. Programm

Das erste Programm habe ich in Bascom AVR geschrieben, es wartet einfach auf Anrufe. Rufe ich das Handy nun an, dann sendet es über die serielle Schnittstelle ein "RING". Dann öffnet der Atmel das Tor. Damit das nicht jeder öffnen kann, der die Handynummer kennt wird das Tor nur geöffnet, wenn ein Handy anruft, dessen Rufnummern vorher gespeichert ist. Der Atmel weist in jedem Fall das Gespräch ab, damit keine Kosten entstehen.

Das läuft jetzt schon seit Januar 2004 hier sehr zuverlässig

Das 2. Programm

Nachdem ich jetzt fast alle Leute, die die Garage steuern neue Handynummern hatten, diese aber hart in den Quelltext codiert waren, habe ich das ganze in C neu programmiert. Jetzt werden nach einem Reset die ersten 9 Telefonnummern von der SIM-Karte im Handy in das EEPROM des AT90S2313 kopiert. Die Nummern 2-9 werden bei einem eingehenden Anruf rechtsbündig verglichen. Ist die Nummer im EEPROM vorhanden, wird das Tor geöffnet bzw. geschlossen. Ist das Tor länger als 10 Minuten geöffnet, wird die erste Nummer auf der SIM-Karte angerufen.

Sourcecode

Hier der Quelltext dazu:

/********************************************************************
 *  Title:    Garagentorsteuerung mit Siemens S25 Handy
 *  Author:   Dario Carluccio
 *            You might find more AVR related stuff at my homepage:
 *                http://www.carluccio.de
 *  Date:     10/2005
 *  Version:  v2.0
 *  Purpose:  Controls a Garage Gate with a Cellular Phone
 *  Software: AVR-GCC to compiler
 *  Hardware: ATS90S2313
 *            B.0 = Output  LED Init          (1= Init LED On)
 *            B.1 = Output  LED Ready         (1= Ready LED On)
 *            B.2 = Output  LED Gate Open     (1= Gate Open LED On)
 *            B.3 = Output  Gate Control      (1= open/close Gate Impulse [1s])
 *            B.4 = Input   Status Gate Open  (1= Gate Open)
 *            D.0 = RXD     UART Input  connected to Cellphone Siemens S25
 *            D.1 = TXD     UART Output connected to Cellphone Siemens S25
 *
 * The Gate Open/Close Control Line is triggered for one second everytime
 * the Celular Phone receives an incoming call from one of the Caller IDs
 * stored on the SIM Card on Place 2-10. (Stored without Arecode [+49|0]
 * to avoid malfunction when Provider does not transmit full Number)
 *
 * If the Gate is Open for more than 600 Seconds the Phone calls the Number
 * Stored on Place 1, which is stored with Arecode [+49]
 *
 * Status LED Init:      On during Init
 * Status LED Ready:     Flashing when Idle
 * Status LED Gate Open: On when the Gate is Open
 *
 *******************************************************************************
 * The Phone has to support the following Commands:
 *
 * Activate Cellular result codes (extended Format of RING-Message)
 * -> at+clip=1<cr><lf>
 * <- OK<cr><lf>
 *
 * Select SIM phonebook
 * -> at+cpbs=SM<cr><lf>
 * <- OK<cr><lf>
 *
 * Read Entry "1" from SIM phonebook
 * -> at+cpbr=1<cr><lf>
 * <- +CPBR: 1,"01234567890",145,"name"<cr><lf>
 * <- <cr><lf>
 * <- OK<cr><lf>
 *
 * Issue outgoing Call to first Number in SIM-Memory:
 * -> atd>SM1;<cr><lf>
 *
 * Incoming Call is signalised:
 * <- <cr><lf>
 * <- +CRING: VOICE<cr><lf>
 * <- <cr><lf>
 * <- +CLIP: +492327957555,145<cr><lf>
 ******************************************************************************
 *
 * LEDs, Laser and Switch are connected as Follows:
 *                           +------+      +----------+
 * AVR-Pin 12 (B0)    o------| 330R |------| Init-LED |-------------+
 *                           +------+      +----------+             |
 *                                                                  |
 *                           +------+      +-----------+            |
 * AVR-Pin 13 (B1)    o------| 330R |------| Ready-LED |------------+
 *                           +------+      +-----------+            |
 *                                                                  |
 *                           +------+      +-----------------+      |
 * AVR-Pin 14 (B2)    o--+---| 330R |------| Gate-Status-LED |------+
 *                       |   +------+      +-----------------+      |
 *                       |                                          |
 *                       |                      +-------+           |
 *                       |                 ,----| Laser |---o +5V   |
 *                       |   +------+   | / C   +-------+           |
 *                       +---| 10 K |---|<                          |
 *                           +------+ B | \ E                       |
 *                                         `------------------------+
 *                                     BC547                        |
 *                                                                  |
 *                           +------+      +-----------------+      |
 * AVR-Pin 15 (B3)    o--+---| 330R |------| Gate-Action-LED |------+--o GND
 *                       |   +------+      +-----------------+
 *                       |
 *                       |                 ,--------------------o Open Button +
 *                       |   +------+   | / C
 *                       +---| 10 K |---|<
 *                           +------+ B | \ E
 *                                         `--------------------o Open Button -
 *                                     BC547
 *
 ******************************************************************************/

// ********************************************************************
// * Includes
// ********************************************************************

#include <inttypes.h>
#include <avr/io.h>
#include <avr/eeprom.h>
#include <avr/signal.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>


// ********************************************************************
// * Prototypes
// ********************************************************************

int  main (void);
int  EEP_eq_SB (uint8_t Ptr);
void Flash_Ready_LED (uint8_t Times);
void Init_Chip (void);
void Open_Gate (void);
void Phone_Init (void);
void Phone_ReadSimPhonebook (void);
void Str_Cpy (uint8_t* Destination, const uint8_t* Source);
int  Str_Len (uint8_t* StringVar);
void UART_Print (uint8_t* Message, uint8_t Number);
void Wait_for_OK (void);


// ********************************************************************
// * Defines
// ********************************************************************

// Frequency + Bautrate
#define CRYSTAL_FREQ 9216000        // Crystal Frequency e.g. 9,216 Mhz
#define UART_BAUD_RATE 19200        // Baud Rate 19200
#define Max_Gate_Open 6000          // Gate-Open Time after Phone-Call is done x 100ms
#define SIM_Delimiter '\0'          // EEPROM Memory Delimiter Char

// Output LEDs and Gate Control
#define LED_Init_PORT    PORTB      // Init LED - PORT
#define LED_Init_PIN     PINB       // Init LED - PIN
#define LED_Init_BIT     0          // Init LED - BIT
#define LED_Ready_PORT   PORTB      // Ready LED - PORT
#define LED_Ready_PIN    PINB       // Ready LED - PIN
#define LED_Ready_BIT    1          // Ready LED - BIT
#define LED_Gate_PORT    PORTB      // Gate Open LED - PORT
#define LED_Gate_PIN     PINB       // Gate Open LED - PIN
#define LED_Gate_BIT     2          // Gate Open LED - BIT
#define Gate_Ctrl_PORT   PORTB      // Gate Control - PORT
#define Gate_Ctrl_PIN    PINB       // Gate Control - PIN
#define Gate_Ctrl_BIT    3          // Gate Control - BIT

// Input Gate Status
#define Gate_Status_PORT PORTB      // Gate Status - PORT
#define Gate_Status_PIN  PINB       // Gate Status - PIN
#define Gate_Status_BIT  4          // Gate Status - BIT

// EEPROM Access
#ifndef EEMEM
#define EEMEM  __attribute__ ((section (".eeprom")))
#endif


// ********************************************************************
// * Macros
// ********************************************************************

// BitSet sets the BitNo
#define BitSet(Byte, BitNo)     Byte |= (1<<BitNo)

// BitClear clears the BitNo
#define BitClear(Byte, BitNo)   Byte &= ~(1<<BitNo)

// Output Control
#define LED_Init_On    BitSet   (LED_Init_PORT, LED_Init_BIT)
#define LED_Init_Off   BitClear (LED_Init_PORT, LED_Init_BIT)
#define LED_Ready_On   BitSet   (LED_Ready_PORT, LED_Ready_BIT)
#define LED_Ready_Off  BitClear (LED_Ready_PORT, LED_Ready_BIT)
#define LED_Gate_On    BitSet   (LED_Gate_PORT, LED_Gate_BIT)
#define LED_Gate_Off   BitClear (LED_Gate_PORT, LED_Gate_BIT)
#define Gate_Ctrl_On   BitSet   (Gate_Ctrl_PORT, Gate_Ctrl_BIT)
#define Gate_Ctrl_Off  BitClear (Gate_Ctrl_PORT, Gate_Ctrl_BIT)

// Input Control
#define Gate_Is_Open   bit_is_clear (Gate_Status_PIN, Gate_Status_BIT)

// AT-Commands
#define CMD_atCLIP  "at+clip=1"
#define CMD_atSIM   "at+cpbs=SM"
#define CMD_atGetPB "at+cpbr="
#define CMD_atH0    "at+chup"
#define CMD_atDT    "atd>SM1;"


// ********************************************************************
// ***                                                              ***
// ***                  Global Variables in RAM                     ***
// ***                                                              ***
// ********************************************************************

// Counters
volatile uint8_t cnt_2ms;                          // Counter 5ms
volatile uint8_t cnt_Ready_Led;                    // Counter Ready LED
volatile uint8_t cnt_Pulse;                        // Counter for Pulse
volatile uint16_t cnt_Gate_Open;                   // Counter for GeteOpen (600s=6000x100ms)

// UART Communication: Buffers and Vars
#define UART_Rec_Len 32
#define UART_Send_Len 24
#define EEP_Len 128
volatile uint8_t UART_Rec_Buffer[UART_Rec_Len];    // UART Receive-Buffer
volatile uint8_t UART_Rec_Ptr;                     // Actual Rec Position
volatile uint8_t UART_Rec_OK;                      // = 1 if 'O','K',<CR>,<LF> was received (Count 4-3-2-1)
volatile uint8_t UART_Rec_CLIP;                    // = 1 if 'C','L','I','P', [...] ',' was received (Count 5-4-3-2-1)
volatile uint8_t UART_Send_Buffer[UART_Send_Len];  // UART Send-Buffer
volatile uint8_t UART_Send_Active;                 // UART Send-Buffer Status: 0: Buffer empty, 1: Sending

// EEPROM Memory
uint8_t EEPROM_Array[EEP_Len] EEMEM;               // Buffer for Phonenumbers copied from Phone SIM (Space for 118 Digits)


// ********************************************************************
// ***                                                              ***
// ***                      Sting Functions                         ***
// ***                                                              ***
// ********************************************************************

// Calculate Length of Sting
int Str_Len (uint8_t* StringVar){
	int i = 0;
	while (StringVar[i] != '\0') i++;
	return i;
}

// Copy String: Destination = Source
void Str_Cpy (uint8_t* Destination, const uint8_t* Source) {
	int i=0;
	while (Source[i] != '\0') {
	   Destination[i] = Source[i];
	   i++;
	}
	Destination[i] = '\0';
}


// ********************************************************************
// ***                                                              ***
// ***                         Init Chip                            ***
// ***                                                              ***
// ********************************************************************

// ********************************************************************
// * Init Ports, Timers, UART and Interrupts
// *   - Port B: Bit4 Input, Others Output
// *   - Port D: Bit1 Input, Others Output
// *   - Timer 1: Interrupt every 10 ms
// *   - Enable Serial Port
// ********************************************************************
void Init_Chip (void) {
  // Port B:
  //     Bit 4  = Input
  //     Others = Output
  DDRB = 0xEF;              // DDR Port B: 1110 1111
  PORTB = 0;                // Init LED ON

  // Port D:
  //     Bit 0  = Input
  //     Others = Output
  DDRD = 0xFF;              // DDR Port D: 1111 1110

  // Timer 1: Interrupt every 10 ms
  //  - CK/64 (CS11 + CS 10)
  //  - CTC1  (Clear Timer on Compare match)
  //  - OCR1  (Output Compare Register: [ms]*CRYSTAL_FREQ/(1000*64)
  //  - OCIE1 (Output Compare Interrupt Enable)
  TCCR1A = 0;                               // No Output, No PWM
  TCCR1B = _BV(CS11)|_BV(CS10)|_BV(CTC1);   // CK/64 , CTC1
  OCR1 = 2 * CRYSTAL_FREQ / 64000L;         // 2ms: 5A0h = 1440d
  TIMSK = (1<<OCIE1A);                      // Interrupt Enable

  // Serial Port 1
  //  - Enable RxD and TxD
  //  - Enable interrupts for RxD and TxD
  //  - Set Baud Rate: UBRR= (F_CPU / (16*BAUD) )-1
  UCR = (1 << RXEN) | (1 << TXEN) | (1 << TXCIE) | (1 << RXCIE);
  UBRR = (CRYSTAL_FREQ / (UART_BAUD_RATE * 16L)) - 1;
}


// ********************************************************************
// ***                                                              ***
// ***                       Timer Interrupt                        ***
// ***                                                              ***
// ********************************************************************

// ********************************************************************
// * Timer / Counter Interrupt every 2ms
// *   - every 100ms
// *     - increment cnt_Ready_Led
// *     - decrement cnt_Pulse if cnt_Pulse > 0
// *     - increment 16Bit Gate Open Counter, if Gate is open
// ********************************************************************
SIGNAL (SIG_OUTPUT_COMPARE1A){
	if (++cnt_2ms==50){                 // every 50 x 2ms = 100ms
		cnt_2ms=0;                      // Reset 2ms Counter
		cnt_Ready_Led++;                // increment 100ms counter
		if (cnt_Pulse > 0) {            // decrement Pulse counter as long as positive
			cnt_Pulse--;
		}
		// Increment Gate Open Counter, if Gate is open
		// !!! Attention: Overflow is NOT detected, but it is 16Bit !!!
		if (cnt_Gate_Open > 0){
			cnt_Gate_Open++;
		}
	}
}

// ********************************************************************
// ***                                                              ***
// ***                           U A R T                            ***
// ***                                                              ***
// ********************************************************************

// ********************************************************************
// * UART Receive Interrupt
// *   - If 0-9 of ";" ist received write Value to UART_Rec_Buffer
// *   - Detect OK Received
// ********************************************************************
 SIGNAL (SIG_UART_RECV){
	int i;
	i = UDR;
	// Save only '0' to '9' and ',' and '+'
	if ( ((i >= '0') && (i <= '9')) || (i == ',') || (i == '+') ) {
		UART_Rec_Buffer[UART_Rec_Ptr] = i;
		if (UART_Rec_Ptr < UART_Rec_Len) {
			UART_Rec_Ptr++;
		}
	}
	// UART_Rec_OK counts down from 4 to 1 while receiving 'O' 'K' <cr> <lf>
	if ((UART_Rec_OK == 0) && (i == 'O'))
		UART_Rec_OK = 4;
	else if ((UART_Rec_OK == 4) && (i == 'K'))
		UART_Rec_OK = 3;
	else if ((UART_Rec_OK == 3) && (i == 0x0d))
		UART_Rec_OK = 2;
	else if ((UART_Rec_OK == 2) && (i == 0x0a))
		UART_Rec_OK = 1;
	else if (UART_Rec_OK != 1){
		UART_Rec_OK = 0;
		UART_Rec_Buffer[UART_Rec_Ptr] = '\0';
		}
	// UART_Rec_CLIP counts down from 4 to 1 while receiving 'C' 'L' 'I' 'P'
	if ((UART_Rec_CLIP == 0) && (i == 'C'))
		UART_Rec_CLIP = 5;
	else if ((UART_Rec_CLIP == 5) && (i == 'L'))
		UART_Rec_CLIP = 4;
	else if ((UART_Rec_CLIP == 4) && (i == 'I'))
		UART_Rec_CLIP = 3;
	else if ((UART_Rec_CLIP == 3) && (i == 'P'))
		{
		UART_Rec_CLIP = 2;
		UART_Rec_Ptr = 0;               // If CLIP Received Reset Pointer
		}
	else if ((UART_Rec_CLIP == 2) && (i == ','))
		UART_Rec_CLIP = 1;
	else if (UART_Rec_CLIP > 2)
		UART_Rec_CLIP = 0;
	// Reset Pointer after ':'
	// if (i == ':'){
	//	 UART_Rec_Ptr = 0;               // Reset Pointer
	// }
 }


// ********************************************************************
// * UART Transmit Complete Interrupt Function
// *   - Send the Rest of UART_Send_Buffer
// *   - UART_Send_Active is used as Pointer to UART_Send_Buffer
// *   - When finished set UART_Send_Active = 0
// ********************************************************************
SIGNAL (SIG_UART_TRANS) {
	if (UART_Send_Active > 0){
		/* Go to next character in string */
		if (UART_Send_Buffer[UART_Send_Active] == '\0') {
			/* String has been sent */
			UART_Send_Active = 0;
		} else {
			/* Send next character in string */
			UDR = UART_Send_Buffer[UART_Send_Active];
			UART_Send_Active++;
		}
	}
}


// ********************************************************************
// * Print Strint to UART
// *   - Wait until last Sting is send completly
// *   - If Number >0 and Number <10 then attach Number to String
// *   - Add 'CR' to String
// *   - Add 'LF' to String
// *   - Send first Char of String
// *   - Rest of Buffer will be send by SIGNAL(SIG_UART_TRANS)
// ********************************************************************
void UART_Print (uint8_t* Message, uint8_t Number)
{
    while(UART_Send_Active);				       // wait for UART_Send_Activeto become 0
	UART_Send_Active=1;                            // Active
	Str_Cpy ((uint8_t*)UART_Send_Buffer, Message); // copy Message to Buffer
	int i = Str_Len((uint8_t*)UART_Send_Buffer);   // UART_Send_Buffer &= [ASC(Number)]
	if ((Number > 0) && (Number < 10)){
		UART_Send_Buffer[i++] = Number + '0';
	}
	UART_Send_Buffer[i++] = 0xd;                   // UART_Send_Buffer &= <CR>
	UART_Send_Buffer[i++] = 0xa;                   // UART_Send_Buffer &= <LF>
	UART_Send_Buffer[i] = '\0';
	UDR = UART_Send_Buffer[0];                     // Send first character
}


// ********************************************************************
// ***                                                              ***
// ***                         Subroutines                          ***
// ***                                                              ***
// ********************************************************************

// ********************************************************************
// * Open The Gate:
// *   - Set Gate Control High
// *   - Set Counter to release Gate Control after one second
// ********************************************************************
void Open_Gate (void) {
	Gate_Ctrl_On;                       // Activate Gate Control
	cnt_Pulse = 10;                     // Set Counter
	while (cnt_Pulse>0);                // Wait 1s
	Gate_Ctrl_Off;                      // Release Gate Control
	cnt_Pulse = 10;                     // Set Counter
	while (cnt_Pulse>0);                // Wait 1s
}


// ********************************************************************
// * Flash the Ready-LED
// *   - Flash Ready-LED Times = Counter
// ********************************************************************
void Flash_Ready_LED (uint8_t Times) {
	uint8_t Flash_Cnt;
	for (Flash_Cnt=1;Flash_Cnt<=Times;Flash_Cnt++){
		LED_Ready_On;                   // Switch Ready LED On
		cnt_Pulse = 2;                  // Set Counter
		while (cnt_Pulse>0);            // Wait 0.2s
		LED_Ready_Off;                  // Switch Ready LED Off
		cnt_Pulse = 2;                  // Set Counter
		while (cnt_Pulse>0);            // Wait 0.2s
	}
}


// ********************************************************************
// * Init the Phone
// *   - Activate CLIP Mesages
// *   - Select SIM Phonebook
// ********************************************************************/
void Phone_Init (void) {
	Flash_Ready_LED(1);                 // Flash Ready LED
	UART_Print(CMD_atCLIP,0);           // Activate CLIP
	while (UART_Rec_OK != 1);           // Wait until UART_Rec_OK = 1
	UART_Rec_OK = 0;                    // Clear UART_Rec_OK Flag
	Flash_Ready_LED(1);                 // Flash Ready LED
	UART_Print(CMD_atSIM,0);            // Select SIM Phonebook
	while (UART_Rec_OK != 1);           // Wait until UART_Rec_OK = 1
	UART_Rec_OK = 0;                    // Clear UART_Rec_OK Flag
}


// ********************************************************************
// * Read SIM-Numbers
// *   - Read 9 Phonebook Entrys
// *   - Store Numbers in EEPROM
// *   - Divider = ","
// ********************************************************************/
void Phone_ReadSimPhonebook (void) {
	uint8_t i = 0;
	uint8_t j;
	uint8_t EE_Ptr = 0;                 // Pointer to EEPROM_Array
	uint8_t Comma_Cnt;                  // Conter for ',' in UART_Rec_Buffer
	for (i=1;i<10;i++){                 // Read 9 Phonebook Entrys
		Flash_Ready_LED(1);             // Flash Ready LED
		UART_Rec_Ptr=0;                 // Clear Receive Buffer
		UART_Print(CMD_atGetPB,i);      // Send SIM-Number Request
		while (UART_Rec_OK != 1);       // Wait until UART_Rec_OK = 1
		UART_Rec_OK = 0;                // Clear UART_Rec_OK Flag
		Comma_Cnt=0;                    // Reset Counter for ','
		j = 0;
		// Store Number in EEPROM
		while ((Comma_Cnt < 2) && (UART_Rec_Buffer[j] != '\0')){
			// Search for ','
		    if (UART_Rec_Buffer[j++] == ','){
				Comma_Cnt++;
			}
			// Store only Numbers between first and for second ','
		    if ((Comma_Cnt == 1) && (UART_Rec_Buffer[j] != ',')){
				eeprom_write_byte(&EEPROM_Array[EE_Ptr++],UART_Rec_Buffer[j]);
			}
		}
		// Store Delimiter between each Phone Number
		eeprom_write_byte(&EEPROM_Array[EE_Ptr++],SIM_Delimiter);
	}
}


// ********************************************************************
// * Compare String in EEPROM with UART_Send_Buffer                   *
// *   - Compares String in EEPROM after Pointer Ptr                  *
// *   - Lenght Ptr minus SIM_Delimiter afer Ptr                      *
// *               Pos: 0123456789 123456789 123456789 123456789      *
// *        eg: EEPROM: 012341213156X1245412X1212122154X14514XXX      *
// *     1. Call: j=12: right() must be '1245412'    [13-19]          *
// *     2. Call: j=20: right() must be '1212122154' [21-30]          *
// *     3. Call: j=31: right() must be '145144'     [32-36]          *
// *     4. Call: j=37: length = 0 -> return 0                        *
// *     5. Call: j=38: length = 0 -> return 0                        *
// ********************************************************************
int EEP_eq_SB (uint8_t Ptr) {
	uint8_t i;
	uint8_t ee_len=0;
	uint8_t sb_len=0;
	uint8_t result=1;
	// ee_len = Lenght of String in EEPROM between this and next
	while (eeprom_read_byte(&EEPROM_Array[Ptr+1+ee_len]) != SIM_Delimiter) ee_len++;
	// if ee_len = 0 then result = 0
	if (ee_len == 0 ) {
		result = 0;
	} else {
		// Length of String mut be at least ee_len
		sb_len = Str_Len((uint8_t*)UART_Send_Buffer);
		// Compare ee_len=4 Chars:
		//   - EEProm [Ptr+(ee_len-0)] == UART_Send_Buffer [sb_len-1-0]
		//   - EEProm [Ptr+(ee_len-1)] == UART_Send_Buffer [sb_len-1-1]
		//   - EEProm [Ptr+(ee_len-2)] == UART_Send_Buffer [sb_len-1-2]
		//   - EEProm [Ptr+(ee_len-3)] == UART_Send_Buffer [sb_len-1-3]
		result = 1;
		for (i=0;i<ee_len;i++){
			if (eeprom_read_byte(&EEPROM_Array[Ptr+ee_len-i]) != UART_Send_Buffer[sb_len-1-i])
			result = 0;
		}
	}
	return result;
}


// ********************************************************************
// * Main
// *   - Init
// *     - Init Chip (Ports, Timers, UART and Interrupts)
// *     - Clear Buffers
// *     - Enable Interrupts
// *     - Init the Phone
// *     - Read Entrys 1-9 of SIM Phonebook
// *   - Main Loop
// *     - Check Gate State and Switch Gate-Open LED On and Off
// *     - Flash Ready LED every 3 Seconds
// *   - TODO:
// *     - If Gate is longer Open than 600 Seconds Call Entry 1
// *     - Check Incoming Calls and Open Garage if OK
// ********************************************************************/
int main (void)
{
	uint8_t i = 0;                      // Counter
	uint8_t j = 0;                      // Counter
	uint8_t CID_OK = 0;                 // Caller ID is on Auth-List
	Init_Chip();                        // Init Ports, Timers, UART and Interrupts
	LED_Init_On;                        // Switch Init LED On
	UART_Send_Active = 0;               // Clear Transmit-Buffer
	UART_Rec_Ptr = 0;                   // Clear Receive-Buffer
	cnt_Gate_Open = 0;                  // Reset Gate-Counter
	sei();                              // Emable Interrupts
	Phone_Init();	                    // Init the Phone
	Phone_ReadSimPhonebook();           // Read Entrys 1-9 of SIM Phonebook
	LED_Init_Off;                       // Switch Init LED On
	// Loop Forever
	for (;;) {
		// Check Gate State
		if (Gate_Is_Open) {
			LED_Gate_On;                // Switch Gate-Open LED On
			if (cnt_Gate_Open == 0){
				cnt_Gate_Open = 1;      // Start Gate-Open Counter
			}
		} else {
			LED_Gate_Off;               // Switch Gate-Open LED On
			cnt_Gate_Open = 0;          // Reset Gate-Open Counter
		}
		// Check if Gate is open Longer than Max_Gate_Open * 100ms
		// Then Call Phonennumber stored on SIM Position 1
		if (cnt_Gate_Open > Max_Gate_Open) {
			cnt_Gate_Open = 0;          // Reset Gate-Open Counter
			cnt_Ready_Led = 0;
			LED_Init_On;                // Switch Init LED On for 5 Secs.
			while(UART_Send_Active);	// Wait until UART Send Buffer Empty
			UART_Send_Active=1;         // UART Send Active
			// Call first Number in SIM-Memory copy CMD_atDT to Buffer
			Str_Cpy ((uint8_t*)UART_Send_Buffer, CMD_atDT);
			j = Str_Len((uint8_t*)UART_Send_Buffer);
			UART_Send_Buffer[j++]= 0xd; // Attach <CR>
			UART_Send_Buffer[j++]= 0xa; // Attach <LF>
			UART_Send_Buffer[j] = '\0'; // End Of String
			UDR = UART_Send_Buffer[0];  // Send first character
		}
		// Ready LED: Flash every 5 Seconds für 100ms
		if (cnt_Ready_Led > 50) {
			LED_Ready_On;
			if (cnt_Ready_Led > 51) {
				cnt_Ready_Led= 0;
				LED_Init_Off;
			}
		} else {
			LED_Ready_Off;
		}
		// If ',' and 'C','L','I','P' Received
		// Check if Number is in EEPROM, then open Gate
		if (UART_Rec_CLIP == 1){
			// Reset UART_Rec_CLIP
			UART_Rec_CLIP = 0;
			// Reset Gate-Open Counter
			cnt_Gate_Open = 0;
			// Copy Number without [+49|0] from Receive Buffer temporaly to Receivebuffer
			if (UART_Rec_Buffer[0] == '0') {
				i = 1;					//   01701234567 received, skip '0'
			} else {
				i = 3;					// +491701234567 received, skip '+49'
			}
			j = 0;
			while (UART_Rec_Buffer[i] != ','){
				// Copy Received CLIP-Message[j] to UART_Send_Buffer
				// DEBUG:
				// eeprom_write_byte(&EEPROM_Array[100+j],UART_Rec_Buffer[i]);
				UART_Send_Buffer[j++] = UART_Rec_Buffer[i++];
			}
			UART_Send_Buffer[j] = '\0';
			// Check if Number in UART_Send_Buffer is in EEPROM (right-justified)
			CID_OK = 0;
			// Browse Rest of EEPROM until SIM_End. On every SIM_Delimiter check String
			for (i=2;i<10;i++){         // i countd from 2 to 9
				if (CID_OK == 0) {      // Search Only until found first Number
					// Let j point to next SIM_Delimiter
					while (eeprom_read_byte(&EEPROM_Array[j]) != SIM_Delimiter) j++;
					// Check if EEPROM-String AFTER j is equal to UART_Send_Buffer (RIGHT JUSTIFIED)
					// DEBUG: eeprom_write_byte(&EEPROM_Array[100+i],j);
					CID_OK = EEP_eq_SB(j);
					j++;
				}
			}
			if (CID_OK != 0){
				Open_Gate();
			}
			// Hang UP
			UART_Print(CMD_atH0,0);
		}
	}
	return (0);
}