이번에는 실제 프로그램 코드를 짜기 시작해 보았다.
자세한 코드정보는
https://github.com/supersfel/C_atmega128
깃허브에 올려두었다!
우선 해당 프로젝트의 사용자 등록 및 해제의 중간 부분까지 코드를 구현하였다.
#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 PHONE_NUM_CHECK 7
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 user_name;
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] == 'X') LCD_Str("1 ");
if (user_state[1] == 'X') LCD_Str("2 ");
if (user_state[2] == 'X') 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';
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;
delay_ms(5000);
OCR1A = 4710;
STATE = START;
fnd[0]=0;
}
else if (fnd[1] == 2 && fnd[0] == 10) STATE = INPUT_PHONE_INIT;
break;
case CHECK_PNUM_INIT:
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){
user_name = fnd[1]-1;
fnd[0]=0;
LCD_Clear();
LCD_Pos(0,0);
LCD_Str("Input PhoneNum") ;
STATE = PHONE_NUM_CHECK;
}
break;
case PHONE_NUM_CHECK:
break;
}
}
}
주석처리 된 부분은 연결한 3개의 초음파 센서를 확인하려고 쓰는 임시코드이다.
초음파 센서는 글을 따로 올리긴 하였지만, 주소가 맞는지 꼭 확인해야 한다.
가장 핵심은 구현 방식이다. 이전에 금고만드는 미니프로젝트를 진행한 적이 있는데, 그 당시에는 상태들을 모두 flag를 사용하여 처리하였었다. 그러다보니 머리도 많이 써야하고 flag들도 많아져서 저장공간도 많이차지하고 꽤 문제가 많아 보이는 코드였다. 그래서 이번에는 상태를 나타내는 STATE를 하나 설정해서 switch문으로 약간 SOC에서 프로그래밍하는것과 비슷한 느낌으로 코드를 짜보기로 마음먹었다.
중요한 부분은 fnd[0]나 fnd[1]값을 계속 0으로 수동으로 바꿔주는 부분이 있다는 건데, 입력버튼으로 키패드의 왼쪽 하단 버튼을 사용하는데 나는 이를 10으로 설정해 두었다. 그래서 이 값이 그대로 fnd[0]에 저장되면, fnd[1]에 숫자가 저장되는 방식이라 1을 누르고 *을 눌러서 (나는 키패드왼쪽하단이 *모양이다) 다음단계에 갔는데 그 다음상태에서도 1과 *이눌러지면 다음상태로 넘어가는 기능이 있을 수 있어 항상 초기화를 해주어야 한다.
해당 동작은 아래와 같다.
이때 문을 구현한 모터가 90도로 5초동안 내려왔다가(문해제) 다시 올라간다.
위처럼 1번을 하려고 하면 사용된다고 뜬다.
++
위에 코드로 하면 4번이 추가되어 있다. 4번은 나가는 사람을 위한 코드로 아직은 상태 입장까지만 적용을 해둔 상태이다. 앞으로 더 완성이되면 정리해서 올릴 예정이다!
'프로젝트 > 스마트독서실 시스템' 카테고리의 다른 글
07_프로그램 구현 3단계 완성!!! (0) | 2021.12.10 |
---|---|
06_구현 2단계_퇴장 및 비밀번호 일치 (0) | 2021.12.06 |
05_구동함수_Keypad,FND,Buzzer (0) | 2021.11.19 |
04_구동함수_Servo motor (0) | 2021.11.19 |
03_구동함수_ONE025 (0) | 2021.11.19 |