HEM     INFORMATION     KOD     RAPPORT  
   
   

Larm System

   

Ett projekt av Adnan Mehmedagic & Mattias Sönnerup.

    boy  
   
   

Information

   
   

Vi har har under kursen, EITF40, gång skapat ett larmsystem från konceptfas till en väl fungerande produkt. Det vi har skapat är en larmanläggning med sensorer både för rörelse och temperatur. Vår produkt har stöd för upp till 8 digitala rörelsesensorer och 4 analoga temperatursensorer.

Man sätter helt enkelt på larmet med ON-knappen och stänger av det med OFF-knappen följt av en hemlig kod. Det går även att testa larmsystemet genom att trycka på test knappen. 

Larmsystemet har även support för att ställa in tiden och för att skicka ut en signal till en larmcentral eller dator. All information om systemet såsom om larmet är på eller av, vilken sensor som satte igång alarmet och vid vilken tid larmet utlöstes, visas på en LCD skärm.

I sin helhet är det ett larmsystem som tar hänsyn både till inbrottstjuvar och till bränder.

   
      
   

Kod

   
/*
 * alarm_system.c
 *
 * Created: 2017-02-13 13:05:51
 * Author : Mattias Sonnerup & Adnan Mehmedagic
 */ 
#include <avr/io.h>
#define F_CPU 1118000
#include<util/delay.h>
#include <stdio.h>
#include "hd44780.h" // Display lib.
#include "main.h"
#include <avr/interrupt.h>
#define row_one_start_index 40
int volatile state = 0;
int volatile larm_state = 0; // if the larm is triggered or not.
int volatile test_mode = 0; // Test mode variable. activates
char volatile code_entered_one = 'k'; // The code we enter. k = empty. 
char volatile code_entered_two = 'k';
char volatile code_entered_three = 'k';
const char code_correct_one = '1'; // The first number that needs to be entered.
const char code_correct_two = '5';
const char code_correct_three = '3';
int volatile minute_passed_ones = 3;
int volatile minute_passed_tens = 3;
int volatile hour_passed_ones = 6;
int volatile hour_passed_tens = 1;
/*******************************************************************
*
*      DISPLAY FUNCTIONS
*
********************************************************************/
void write_to_display(char *text, int line, int offset, int clear)
{
 PORTD |= _BV(PD7);// We are using A4-A5, D7 now for CS. Active low
 DDRB = 0xFF; // All B are outputs
 if (line > 0) {
  offset += 40;
 }
 if (clear == 1) lcd_init();
 lcd_goto(offset);
 lcd_puts(text);
 DDRB = 0x00; // All B are inputs again.
 PORTD &= ~_BV(PD7);// We are using A4-A5, D7 now for CS. Active low
}
void write_to_display_char(char text, int line, int offset, int clear)
{
 PORTD |= _BV(PD7);// We are using A4-A5, D7 now for CS. Active low
 DDRB = 0xFF; // All B are outputs
 if (line > 0) {
  offset += 40;
 }
 if (clear == 1) lcd_init();
 lcd_goto(offset);
 lcd_putc(text);
 DDRB = 0x00; // All B are inputs again.
 PORTD &= ~_BV(PD7);// We are using A4-A5, D7 now for CS. Active low
}
void display_time(void)
{
 write_to_display("Time: ", 1,0,0);
 write_to_display_char((char) (48 + hour_passed_tens), 1,6,0);
 write_to_display_char((char) (48 + hour_passed_ones), 1,7,0);
 write_to_display_char(':', 1, 8, 0);
 write_to_display_char((char) (48 + minute_passed_tens), 1,9,0);
 write_to_display_char((char) (48 + minute_passed_ones), 1,10,0);
}
void clear_display(int row)
{
 for (int i = 0; i < 16; i++)
 {
  write_to_display_char(' ', row, i, 0);
 }
}  
/*******************************************************************
*
*      LARM FUNCTIONS
*
********************************************************************/
void buzz() // For the siren
{
 PORTD |= _BV(PD4);
 _delay_ms(1);
 PORTD &= ~_BV(PD4);
 _delay_ms(1);
 
}
void larm_on(char larm_num){
 PORTA |= _BV(PA7); // diod on. 
 write_to_display("larm ", 0, 0, 0);
 write_to_display_char(larm_num, 0, 5, 0);
 write_to_display_char((char) (48 + hour_passed_tens), 0,7,0);
 write_to_display_char((char) (48 + hour_passed_ones), 0,8,0);
 write_to_display_char(':', 0, 9, 0);
 write_to_display_char((char) (48 + minute_passed_tens), 0,10,0);
 write_to_display_char((char) (48 + minute_passed_ones), 0,11,0);
 larm_state = 1; // The alarm is on. 
}
uint16_t adc_read()
{
 ADMUX = (ADMUX & 0xF8); //Selects PA0
 // start single convertion
    // write '1' to ADSC
 ADCSRA |= (1<<ADSC);
 // wait for conversion to complete
    // ADSC becomes '0' again
 // till then, run loop continuously
 while(ADCSRA & (1<<ADSC));
 return (ADC);
}
char check_larm(void) // REWRITE PORTS
{
 // ENABLE SIGNALS BUFFER ON others OFF.
 PORTA &= ~_BV(PA4);
 PORTA &= ~_BV(PA6);
 char larm = '0';
 uint16_t analog_level = adc_read(); 
 if (test_mode == 1) // In testing mode you see the values for analog sensor
 {   
  write_to_display_char((char) ((analog_level/100)+48), 1, 0, 0);
  write_to_display_char((char) (((analog_level % 100)/ 10) +48), 1, 1, 0);
  write_to_display_char((char) (((analog_level % 100)%10) + 48), 1, 2, 0);
 }
 if (PINB & (1<<PB0)) // If one of the digital sensor is on. 
 {
  larm = '1'; 
 }
 else if (PINB & (1<<PB1))
 {
  larm = '2';  
 }
 else if (PINB & (1<<PB2))
 {
  larm = '3'; 
 }
 else if (PINB & (1<<PB3))
 {
  PORTA |= _BV(PA7); 
  larm = '4'; 
 }
 else if (PINB & (1<<PB4))
 {
  larm = '5'; 
 }
 else if (PINB & (1<<PB5))
 {
  larm = '6'; 
 }
 else if (PINB & (1<<PB6))
 {
  larm = '7'; 
 }
 else if (PINB & (1<<PB7))
 {
   larm = '8'; 
 }
 else if(analog_level < 580){
  larm = '9';
 }
 // DISABLE SIGNALS BUFFER off.
 PORTA |= _BV(PA4);
 PORTA |= _BV(PA6);
 return larm;
}   
/*******************************************************************
*
*      KEYBOARD FUNCTIONS
*
********************************************************************/
char check_keyboard(void) // CHecks the keyboard and returns which key char it is.
{
 char key_pressed = 'k'; 
 // A5 for keyboard enable. ~ flips other bits to 1
 if ((PIND & 0x40) == 0x40) // & ~ 0 If data available.
 {
  // ENABLE SIGNALS BUFFER ON others OFF.
  PORTA &= ~_BV(PA5); //0xdf; // 0b11011111
  if ((PINB & 0x0F) == 0x0F)
  {
   key_pressed = 'f';
  }  
  else if((PINB & 0x0F) == 0x0E)
  {
   key_pressed = 'e';
  }
  else if((PINB & 0x0F) == 0x0D)
  {
   key_pressed = 'd';
  }
  else if((PINB & 0x0F) == 0x0C)
  {
   key_pressed = 'c';
  }
  else if((PINB & 0x0F) == 0x0B)
  {
   key_pressed = 'b';
  }
  else if((PINB & 0x0F) == 0x0A)
  {
   key_pressed = 'a';
  }
  else if((PINB & 0x0F) == 0x09)
  {
   key_pressed = '9';
  }
  else if((PINB & 0x0F) == 0x08)
  {
   key_pressed = '8';
  }
  else if((PINB & 0x0F) == 0x07) 
  {
   key_pressed = '7';
  }
  else if((PINB & 0x0F) == 0x06)
  {
   key_pressed = '6';
  }
  else if((PINB & 0x0F) == 0x05)
  {
   key_pressed = '5';
  }
  else if((PINB & 0x0F) == 0x04)
  {
   key_pressed = '4';
  }
  else if((PINB & 0x0F) == 0x03)
  {
   key_pressed = '3';
  }
  else if((PINB & 0x0F) == 0x02)
  {
   key_pressed = '2';
  }
  else if((PINB & 0x0F) == 0x01)
  {
   key_pressed = '1';
  }
  else if ((PINB & 0x0F) == 0x00)
  {
   key_pressed = '0';
  }
  PORTA |= _BV(PA5); // disable keyboard                             
 }
 return key_pressed; 
}
/*******************************************************************
*
*      CLOCK FUNCTIONS
*
********************************************************************/
void enter_set_clock(void) // When going to the set clock state in the state machine.
{
 write_to_display("Clock settings", 0,0,0);
 write_to_display("Time: ", 1,0,0);
 display_time(); // Displays the time
}

void clock_init() // Config clock 
{
 // CTR
 TIMSK = _BV(OCIE1A); // Interrupt when the timer value for timer 1 is the same as A
 TCCR1A = _BV(WGM01); // Clears timer register on compare.
 TCNT1 = 0; // Reset the timer register for counting. 
 TCCR1B |= (1 << WGM12) | (1 << CS12) | (1 << CS10); // prescaling 1024
 OCR1A = 58688; // compare value
 sei(); // Enables everything for interrupts
}
ISR(TIMER1_COMPA_vect) 
{
 minute_passed_ones ++; 
 if (minute_passed_ones >= 10) // NOTE: '>=' used instead of '=='
 {
  minute_passed_ones = 0;
  minute_passed_tens ++;
  if (minute_passed_tens >= 6)
  {
   minute_passed_tens = 0;
   hour_passed_ones ++;
   if (hour_passed_ones >= 10 && hour_passed_tens < 2)
   {
    hour_passed_ones = 0;
    hour_passed_tens ++;
   }
   else if (hour_passed_ones >= 4 && hour_passed_tens >= 2)
   {
    hour_passed_tens = 0; // reset time
    hour_passed_ones = 0; // reset time.
   }
  }
 }
}
/*******************************************************************
*
*      STATE FUNCTIONS
*
********************************************************************/
void larm_off(void)
{
 code_entered_one = 'k';
 code_entered_two = 'k';
 code_entered_three = 'k';
 test_mode = 0;
 larm_state = 0; // The alarm gets turned off.
 PORTA &= ~_BV(PA7); // led turned off.
 clear_display(0);
 clear_display(1);
}
/*******************************************************************
*
*      MAIN 
*
********************************************************************/
   
   // Analog signals: A0-A3
   // Data bus: B0-B7. (Digitala signaler in, Display out, Knappsats in 4 bits)
   // CS : A4 - A7 (out). A4 = Buffer enable, A5 = keyboard enable. D7 = Display Enable
   // DA : D6 (in).
   // Diod: A7 (out)
   // Display extra: D5 (out)
   // Larm central: D0 (in), D1 (out)
   // Siren: D4 (out)
   // latch enable buffer: A6 (out)

    
int main(void)
{
 clock_init(); // Configs everything with the 1 minute timer
 lcd_init(); //
    
 DDRA = 0xF0; 
    /*A0 - A3 = Analoga in. 
    A4 = Enable buffer out, 
    A5= Enable Keyboard out, 
    D7 = enable display out
    */
 DDRB = 0x00; // All data buss ports are inputs as default.
   
 DDRD |= (1 << PD7)  | (1 << PD5) | (1 << PD4) | (1 << PD1); 
    /* D7 = Display EN 
    D5 = Display RS. 
    D4= Siren. 
    D1= Larm central ut. 
    D0 = Larm central in
    */
    
 PORTA |= (1 << PA4);
 PORTA |= (1 << PA5);
 PORTD &= ~_BV(PD7);
 ADMUX = (1<<REFS0);
 ADMUX = ADMUX & 0xf8;
 ADCSRA = (1<<ADEN) | (1<<ADPS2);
 while(1)
 { 
  if (test_mode == 1) write_to_display_char('T', 1, 15, 0);
  else write_to_display_char('N', 1, 15, 0);
   
  char volatile larm_num = '0'; // By default. 
        /* The alarm has not been triggered for the first time,since start or off code enter. 
        State 0 doesn't need to check the alarm either. 
        State 9 and up does not trigger the alarm either */
  if (larm_state == 0 && state != 0 && state <= 8) 
  {
   larm_num = check_larm();
  }
  if (larm_num != '0' && state != 0 && larm_state == 0)
  {
   clear_display(0); // clears row 0
   larm_on(larm_num);
  }
        if (larm_state == 1 && test_mode == 0) 
  {  // If the alarm is triggered and we are not testing.
   buzz(); // Activates the siren
  }
  char volatile key_num =check_keyboard(); 
  switch (state)
  {
   case 0: // OFF
    write_to_display("OFF STATE", 0,0,0);
    if (key_num == 'c') // On button
    {
     state = 1; // On state.
    }
    else if (key_num == 'e'){ // test button
     state = 1;
     test_mode = 1; // Siren won't run
    }
    else if (key_num == 'f') // Set clk
    {
     enter_set_clock(); // Sets the text and displays the time.
     state = 9;
    }
    break;
   case 1: // state on
    if (larm_state == 0) write_to_display("Alarm enabled", 0,0,0); 
    if (larm_num != '0') // If alarm on. 
    {
     state = 2;
    }
    else if (key_num == 'd') // off button
    {
     clear_display(1); // clears row 0
     write_to_display("code: ", 1, 0, 0);
     if (test_mode == 0) state = 3; // GO to enter keys.
     else
     {
      state = 0;
      larm_off();
     }
    }
    break;
     
   case 2: // Larm is on state
    if (key_num == 'd') // off button
    {
     clear_display(1); // clears row 0
     write_to_display("code: ", 1, 0, 0);
     if (test_mode == 0) state = 3; // GO to enter keys.
     else 
     {
      state = 0;
      larm_off();
     }
    }
    break;
     
   case 3: // HOld state
    if (key_num == 'k'){
     state = 4;
    }     
    break;
     
   case 4: // key 1 wait
    if(key_num >= '0' && key_num <= '9'){ // 0-0
      
     code_entered_one = key_num;
     write_to_display_char(key_num, 1, 6, 0);
     state = 5;
    }
    break;
     
   case 5: // key 1 hold
    if (key_num == 'k'){
     state = 6;
    }
    break;
     
   case 6: // key 2 wait
    if(key_num >= '0' && key_num <= '9'){
     code_entered_two = key_num;
     write_to_display_char(key_num, 1, 7, 0);
     state = 7;
    }
    break;
     
   case 7: // key 2 hold
    if (key_num == 'k'){
     state = 8;
    }
    break;
    
   case 8: // key 3 wait
    if(key_num >= '0' && key_num <= '9'){
     code_entered_three = key_num;
     write_to_display_char(key_num, 1, 8, 0);
     if (code_entered_one == code_correct_one 
                     && code_entered_two == code_correct_two
                     && code_entered_three == code_correct_three )
     {
      state = 0;
      larm_off();
     }
     else
     {
      clear_display(1);
      write_to_display("Wrong code", 1,0,0);
      if (larm_state == 1) state = 2; // The alarm is running so back to state 2.
      else state = 1; // The alarm has not yet been triggered. Going back. 
     }
    }     
    break;
   case 9: // Hold set clk button
    if (key_num == 'k'){
     state = 10;
    }
    break;
   case 10: // Set clk hour (tens)
    if (key_num >= '0' && key_num <= '2')
    {
     hour_passed_tens = (int) (key_num - '0');
     display_time();
     state = 11;
    }
    break;
     
   case 11: // Hold
    if (key_num == 'k'){
     state = 12;
    }
   break;
    
   case 12: // set clk hour (ones)
    if ((hour_passed_tens < 2 && key_num >= '0' && key_num <= '9') 
                 || (hour_passed_tens == 2 && key_num >= '0' && key_num <= '3' ))
    {
     hour_passed_ones = (int) (key_num - '0');
     clear_display(1);
     display_time();
     state = 13;
      
    }    
    break;
     
   case 13: // Hold
    if (key_num == 'k'){
     state = 14;
    }
   break;
    
   case 14: // Set clk minutes (tens)
    if (key_num >= '0' && key_num <= '5')
    {
     minute_passed_tens = (int) (key_num - '0');
     clear_display(1);
     display_time();
     state = 15;
      
    }     
    break;
     
   case 15: // Hold
    if (key_num == 'k'){
     state = 16;
    }
    break;
     
   case 16: // set clk minutes (ones)
    if (key_num >= '0' && key_num <= '9')
    {
     minute_passed_ones = (int) (key_num - '0');
     clear_display(0);
     clear_display(1);
     state = 0;
    }          
    break;    
  }
 }
}
 
   

Rapport

   
Länk till rapport