06_구현 2단계_퇴장 및 비밀번호 일치
프로젝트/스마트독서실 시스템

06_구현 2단계_퇴장 및 비밀번호 일치

728x90

저번에 입장 및 사용자 등록기능까지 구현했었다.

 

하드웨어 구성

추가적으로 하드웨어도 절반정도 꾸며보았다. 막상 꾸며가면서 느낀점은 독서실을 계획하고 만들었는데 주차장이 되어 있었다는것 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

 

그냥 스마트 주차장으로 주제를 잡을 껄 그랬다. 특히 문을 서브모터로 간단히 구현하려다 보니 더더욱 주차장 같아졌다.

 

나중에 시간이 되면 자동문 모듈도 한번 만들어보면 좋을 것 같다.

 

하드웨어는 그렇고 프로그램상으로는 퇴장을 할 때, 비밀번호가 일치하는지 확인을 하고 퇴장할 수 있게 되었다.

 

즉 기능을 서술하면 아래와 같다.

 

 

 

입력버튼은 *이다!

 

1. 1번 클릭

2. 핸드폰번호 입력 ( 만약 1번자리가 사용중이면 "Someone Used" 출력)

3. 입력한 번호가 맞는지 확인 (1.yes 2.No)

3-1. 만약 2번을 누르면 번호를 다시 입력받음

4. 독서실 상태가 1.O 2.X 3.X 로 바뀌게 된다.

5. 4번 클릭

6. 비어있는 좌석 선택 (화면에 사용중인 좌석만 표시되며 만약 빈좌석을 누르면 "Empty Seat"출력)

7. 핸드폰 번호 입력

8. 입력한 번호가 맞는지 확인 (1.yes 2.No)

8-1. 만약 2번을 누르면 번호를 다시 입력받음

9. 입력한 번호와 입장할때 등록한번호가 일치시 퇴장처리 및 상태 O -> X로 변경

9-1. 일치하지 않으면 "Wrong password" 출력 후 시작화면으로 돌아감

 

 

기타 예외가 생기는 기능들을 이것저것 처리하다보니 생각보다 오래걸렸다 ㅠㅠ

 

특히, 비밀번호를 처리하는 부분에서 애를 많이 먹었는데 fnd에서 값을 받아오는건 int형이고 비밀번호는 char의 배열형으로 받고싶었다. 그래야 LCD에 출력하기가 편하기 때문!

 

그래서 int형을 문자열로 바꾸는 과정이 필요했는데, sprintf를 사용했다. 왜냐하면 1,2,3,4 이렇게 들어오는 숫자를 "1234"라는 문자열로 바꾸기 위해서 1 * 1000 + 2 * 100 + 3 * 10 + 4 라는 과정없이, (%d%d%d%d,1,2,3,4) 처리로 간단하게 문자열로 바꿀수 있었기 때문이다.

 

그런데 이과정에서 알수없는 심각한 오류가 발생했는데 sprintf를 사용할때마다 그전에 사용했던 sprintf를 통해 값을 넣어준 변수에 쓰레기값이 들어가버렸다.... 

이유는 확인하기 어렵지만 sprintf를 쓰고 다른 변수에 깊은복사를 통하여 값을 전달함으로써 동작은 되게 구현하였다.

 

현재까지의 코드는 아래와 같다.

 

#include <mega128.h>
#include <delay.h>
#include <stdio.h>
#include "lcd.h"
#include "twi.h"
#include "srf02.h"
#include "Keypad.h"

#define NONE 0
#define START 1
#define INPUT_PHONE 2
#define INPUT_PHONE_INIT 3
#define CHECK_PNUM 4
#define CHECK_PNUM_INIT 5
#define EXIT_CHOOSE 6
#define CHECK_PNUM_OUT 7
#define CHECK_PNUM_OUT_INIT 8
#define INPUT_PHONE_OUT 9
#define INPUT_PHONE_OUT_INIT 10

unsigned char ti_Cnt_1ms;
unsigned char LCD_DelCnt_1ms;

void Timer0_Init()  //타이머 인터럽트
{
    TCCR0 = (1<<WGM01)|(1<<CS00)|(1<<CS01)|(1<<CS02);
    TCNT0 = 0x00;
    OCR0 = 100;
    TIMSK = (1<<OCIE0);
}

interrupt[TIM0_COMP] void timer0_comp(void)    //실제 카운트 증가
{
    ti_Cnt_1ms++;
    LCD_DelCnt_1ms++;
}



int SRF_Run(char Sonar_Addr){    //SRF 주소로 값을 받아옴
    unsigned char res;    
    unsigned int Sonar_range;  
    
    res = getRange(Sonar_Addr, &Sonar_range);
        if(res)
        {         
            return 0;
        }
        else if(LCD_DelCnt_1ms > 100)
        {              
            LCD_DelCnt_1ms = 0;            
            return Sonar_range;
        }        
}
 

void main(void)
{
    unsigned char res;
    char Sonar_Addr = 0xE0;
    unsigned int Sonar_range_1 = 0,Sonar_range_2 = 0,Sonar_range_3 = 0;   
    char Message[40];
    int readCnt = 0;  
    int t=0; //키패드로 받은 숫자 
    int count =0; //count 변수 
    int finalnum=0; //FND에 출력으로 넣어줄 변수 
    int fnd[12]={0,};
    signed int angle=0; // 서브모터 각도로 넣을 변수 
    char STATE = START;                
    char user_state[3] = {'X','X','X'}; 
    int i = 0;  
    char user_pnumber[3][11]; //유저 비밀번호 저장 
    char check_pnumber[11]; //비밀번호 일치확인을위한 공간
    char user_name; //1~3번중 어느좌석 유저를 가르키는지 저장
    char num[3][11];
    
    DDRD |= 0x03;    
    LCD_Init();
    Timer0_Init(); 
    FND_PORT_Init(); // 포트들 입출력 초기 설정 
    Init_TWI(); 
    Init_Timer1();
    delay_ms(1000);
    SREG |= 0x80;  
    
    OCR1A =4710;
    startRanging(Sonar_Addr);
    ti_Cnt_1ms = 0; 
    LCD_DelCnt_1ms = 0; 
     
    
    
    while(1)
    {     
        if(ti_Cnt_1ms > 100)
        {               
            if (Sonar_Addr == 0xE0){
                Sonar_Addr = 0xEC;
                startRanging(Sonar_Addr);
                Sonar_range_1 = SRF_Run(Sonar_Addr);
            } 
            else if (Sonar_Addr == 0xEC) {
                Sonar_Addr = 0xE2;
                startRanging(Sonar_Addr);
                Sonar_range_2 = SRF_Run(Sonar_Addr);
            }
            else{
                Sonar_Addr = 0xE0;
                startRanging(Sonar_Addr);
                Sonar_range_3 = SRF_Run(Sonar_Addr);
            }
            
             
            /*   초음파 확 인 *//* 
            LCD_Clear();
            sprintf(Message, "%03dcm", Sonar_range_1);
            LCD_Pos(0,0);
            LCD_Str(Message);
                
            sprintf(Message, "%03dcm", Sonar_range_2);
            LCD_Pos(1,0);
            LCD_Str(Message); 
            
            sprintf(Message, "%03dcm", Sonar_range_3);
            LCD_Pos(1,5);
            LCD_Str(Message); */ 
                
            LCD_DelCnt_1ms = 0;             
            ti_Cnt_1ms = 0;
        } 
        t= Changenum(KeyScan()); 
        if(t<11 & t>0 ) //숫자가 눌리면 새로운 값을 저장하도록 count값 설정 
            {
                count++; 
                delay_ms(50);
            }
        else if(t==0 & zero_flag) //zero_flag가 실행된 경우에만 0으로 입력 
            {
                count++;
                zero_flag =0; //계속 0으로 입력된 상태가 안되게 zero_flag를 다시 0으로
                delay_ms(50);
            }    
        else if(t==13) // FND 출력숫자 리셋버튼 기능 
            { 
                fnd[0]=0,fnd[1]=0,fnd[2]=0,fnd[3]=0;               
            }
        else if (t ==14)  
            {
               STATE = START;
            } 
            
        if((count%2) ==0){ //count가 짝수일때 들어온 t값을 저장하고
                            //다시 count를 홀수로 만듬 
            for(i=11;i>0;i--) {       
                fnd[i] = fnd[i-1];
                delay_us(10);
            }
            fnd[0] = t;
            count++;
            delay_ms(50);
        }
        finalnum = 1000*fnd[3] + 100*fnd[2] + 10*fnd[1] + fnd[0];
        OUTFND(finalnum); //FND 출력
        buzzer_play_function(t); //숫자에 맞는 음 출력
     
        switch (STATE) {
        
            case NONE: //기본 상태
                if (fnd[1] <=3 && fnd[1] >0 && fnd[0] == 10) {
                    user_name = fnd[1]-1;
                    STATE=INPUT_PHONE_INIT ;
                }
                if (fnd[1]==4 && fnd[0] == 10) { //탈출 모드
                    LCD_Clear();
                    LCD_Pos(0,0);
                    LCD_Str("Choose Seat");
                    LCD_Pos(1,0);
                    if (user_state[0] == 'O') LCD_Str("1  ");
                    if (user_state[1] == 'O') LCD_Str("2  ");
                    if (user_state[2] == 'O') LCD_Str("3  ");
                    STATE=EXIT_CHOOSE ;
                }
                break;

            case START: //업로드
                LCD_Pos(0,0);
                LCD_Str("StudyRoom  4:OUT");
                sprintf(Message, "1:%c 2:%c 3:%c", user_state[0],user_state[1],user_state[2]);
                LCD_Pos(1,0);
                LCD_Str(Message); 
                STATE = NONE;
                break;
                
            case INPUT_PHONE: //입장 : 폰번호 입력
                
                if (fnd[0] == 10){
                    sprintf(user_pnumber[user_name], "%d%d%d%d%d%d%d%d%d%d%d", fnd[11],fnd[10],fnd[9],fnd[8],fnd[7],fnd[6],fnd[5],fnd[4],fnd[3],fnd[2],fnd[1]);
                    user_state[user_name] ='X';
                    for(i=0;i<11;i++){
                        num[user_name][i] = user_pnumber[user_name][i];
                    }
                    STATE = CHECK_PNUM_INIT;                     
                } 
                delay_ms(10);                 
                break;         
                
            case INPUT_PHONE_INIT:
                fnd[0]=0;
                LCD_Clear();
                LCD_Pos(0,0);
                LCD_Str("Input PhoneNum") ;
                STATE = INPUT_PHONE;
                
                if (user_state[user_name] == 'O'){
                    LCD_Clear();
                    LCD_Pos(0,0);
                    LCD_Str("Someone Used");
                    delay_ms(1000);
                    STATE = START;
                }

                break; 
            case CHECK_PNUM:
                
                if (fnd[1] == 1 && fnd[0] == 10){
                    user_state[user_name] = 'O';
                    /*OCR1A = 3000;
                    LCD_Clear();
                    LCD_Pos(0,0);
                    LCD_Str("Door Open") ;    
                    delay_ms(5000);
                    OCR1A = 4710;*/
                    STATE = START;
                    fnd[0]=0;     
                    user_name = 4;
                }
                else if (fnd[1] == 2 && fnd[0] == 10) STATE = INPUT_PHONE_INIT;
            break;
            case CHECK_PNUM_INIT:
                fnd[0]=0;
                LCD_Clear();
                LCD_Pos(0,0);
                LCD_Str(user_pnumber[user_name]); 
                LCD_Pos(1,0);
                LCD_Str("1:Yes  2:No");
                fnd[1] = 0;
                STATE = CHECK_PNUM;
            break;
            
            case EXIT_CHOOSE:  
            
                user_name = fnd[1]-1;
                if (fnd[1] <=3 && fnd[1] >0 && fnd[0] == 10){
                    
                    STATE = INPUT_PHONE_OUT_INIT;
                    
                    if (user_state[user_name] == 'X'){
                        LCD_Clear();
                        LCD_Pos(0,0);
                        LCD_Str("Empty Seat");
                        delay_ms(1000);
                        fnd[0]=0;
                        STATE = START;
                    }
                }
                
                

            break;
             case CHECK_PNUM_OUT_INIT: 
                 fnd[0]=0;
                 fnd[1] = 0;
                 LCD_Clear();
                 LCD_Pos(0,0);
                 LCD_Str(check_pnumber); 
                 LCD_Pos(1,0);
                 
                 LCD_Str("1:Yes  2:No");
                 STATE = CHECK_PNUM_OUT;
               
                
            break;
            case CHECK_PNUM_OUT: 
            
                 if (fnd[1] == 1 && fnd[0] == 10){
                   int cnt=0;
                   LCD_Clear();
                   LCD_Pos(0,0);
                   for(i=0;i<11;i++){
                      if(num[user_name][i] == check_pnumber[i] ) cnt ++;  } 
                   
                    if (cnt == 11 ){
                       LCD_Clear();
                       LCD_Pos(0,0);
                       LCD_Str("User Check") ; 
                       LCD_Pos(1,0);
                       LCD_Str("Good Bye") ;
                       OCR1A = 3000;
                        LCD_Clear();
                        LCD_Pos(0,0);
                        LCD_Str("Door Open") ;    
                        delay_ms(5000);
                        OCR1A = 4710; 
                      user_state[user_name] ='X';
                      STATE = START;
                      fnd[0] = 0;
                    } 
                }
                else if (fnd[1] == 2 && fnd[0] == 10) STATE = INPUT_PHONE_OUT_INIT;
                
                
            break;
            case INPUT_PHONE_OUT: //입장 : 폰번호 입력
                
                if (fnd[0] == 10){
                    sprintf(check_pnumber, "%d%d%d%d%d%d%d%d%d%d%d", fnd[11],fnd[10],fnd[9],fnd[8],fnd[7],fnd[6],fnd[5],fnd[4],fnd[3],fnd[2],fnd[1]); 
                    
                    STATE = CHECK_PNUM_OUT_INIT;                     
                } 
                delay_ms(10);                 
                break;  
             
             case INPUT_PHONE_OUT_INIT: //입장 : 폰번호 입력
                
                
                fnd[0]=0;
                LCD_Clear();
                LCD_Pos(0,0);
                LCD_Str("Input PhoneNum") ;
                STATE = INPUT_PHONE_OUT;            
                break;         
                
           
        }
     
    } 
}

 

코드를 쓰다보니까 느낀게 LCD를 클리어하고, 출력하는걸 하나의 함수로 만들어 두는게 헷갈리지 않을거 같다. 그렇게도 만들어야 할 것 같다.

728x90

'프로젝트 > 스마트독서실 시스템' 카테고리의 다른 글

07_프로그램 구현 3단계 완성!!!  (0) 2021.12.10
06_프로그램 구현 1단계  (0) 2021.12.02
05_구동함수_Keypad,FND,Buzzer  (0) 2021.11.19
04_구동함수_Servo motor  (0) 2021.11.19
03_구동함수_ONE025  (0) 2021.11.19