[아두이노 기초] 전체 글 목록


이번시간에는 시리얼통신을 사용하는 방법과 시리얼통신을 활용해 led등의 장치를 조작해보는 일을 해보도록 하겠습니다.

시리얼(RS232) 통신은 무엇인가?

rs232 통신은 주로 ibm 호환 pc에서 쓰이는 시리얼 통신 방법입니다.

예전에는 모뎀연결에 rs232통신을 많이 사용하였으며 최장 1.5m정도로 다소 짧은 통신 거리를 가지고 있습니다.

최근에 나오는 노트북들은 두께,무게를 줄이기 위해서 UART포트를 없애고 있는 추세입니다.

아두이노에서는 기본으로 제공하고 있는 usb포트를 이용해서 UART통신이 가능합니다.

빨간부분이 시리얼통신을 가능하게 해주는 칩입니다.


시리얼 통신 시작하기

1. 우노보드와 pc를 동봉되어있는 usb케이블로 연결합니다.

2. pc에 연결된 usb의 포트번호를 아두이노 ide에서 설정해 줍니다.

3. 아래의 코드를 작성해 줍니다.

void setup()

{

Serial.begin(9600);//시리얼 통신을 보드레이트 9600으로 시작

// Serial.println(“Hellow Arduino”);

}

 

void loop()

{

char read_data;

 

if (Serial.available())//시리얼통신으로 수신된 데이터가 있을때 true

{

read_data = Serial.read();//read_data에 Serial.read()함수로 한글자 불러와 저장

Serial.print(read_data);//read_data를 시리얼로 출력

}

delay(10);

}

설명 : ide의 시리얼통신 창에서 메세지를 입력하면 그메세지가 그대로 ide의 시리얼통신창에 뜨도록 하는 코드입니다.

10ms마다 반복하며 수신된 데이터가 있을때 다시 그데이터를 송신해주는 방식입니다.

4. ide의 시리얼 모니터 실행후 메세지 입력

시리얼 모니터 - 오른쪽위의 돋보기아이콘

5. 시리얼 모니터에 메세지 출력되는지 확인


시리얼 통신으로 LED제어하기

우리는 위에서 시리얼통신이 이상없이 동작하는 것을 확인하였습니다.

그럼 이번에는 시리얼로 아두이노에 명령을 입력했을때 아두이노에서 그 명령에 맞는 동작을 할수 있도록 만들어 보도록 합시다.


1. 회로구성

기본 LED제어 회로와 다른것이 없습니다.

2. 코드 작성

int led1 = 7;

int led2 = 6;

int led1_status = LOW; // LED1 상태

int led2_status = LOW; // LED2 상태

void setup()

{

pinMode(led1, OUTPUT);//핀모드 설정 출력

pinMode(led2, OUTPUT);

digitalWrite(led1, LOW);//핀의 초기값 LOW = LED OFF

digitalWrite(led2, LOW);

Serial.begin(9600);//시리얼 통신 시작

}

void loop()

{

char read_data;

if (Serial.available())

{

read_data = Serial.read();//시리얼통신으로 수신한데이터 read_data에 저장


if( read_data == '1' && led1_status == LOW)//read_data값이 1이고 led1이 off상태일때

{

digitalWrite(led1, HIGH);//led1 on

led1_status = HIGH;

Serial.println("LED1 ON");

}

else if( read_data == '1' && led1_status == HIGH )//led1이 on상태일때

{

digitalWrite(led1, LOW);//led2 on

led1_status = LOW;

Serial.println("LED1 OFF");

}

if( read_data == '2' && led2_status == LOW)

{

digitalWrite(led2, HIGH);

led2_status = HIGH;

Serial.println("LED2 ON");

}

else if( read_data == '2' && led2_status == HIGH )

{

digitalWrite(led2, LOW);

led2_status = LOW;

Serial.println("LED2 OFF");

}

}

delay(10);

}

 


설명 : 시리얼로 메세지를 받아 1일때는 led1에대한 동작을 하고 2일때는 led2에대한 동작을 하도록 하였고 동작정보를 시리얼로 출력하도록 하였다.

이때 led현재상태를 저장하는 변수(led1_status, led2_status)를 만들어 off상태일때는 on하고 on상태일때는 off하도록 설정 하였다.

코드를 업로드 한뒤 시리얼모니터에 1 또는 2를 입력하면 아두이노에 연결된 led가 동작할 것이다.

또한 위와 같이 시리얼로 아두이노가 어떤 동작을 하였는지 출력되는 것을 볼수 있다.


시리얼 통신 복습하기

1. LED를 전 후 좌 우 4방향에 배치 한뒤 숫자키패드의 화살표 키를 이용하여 4개의 LED를 제어하기

위의 코드의 if문만 조금 수정하면 쉽게 성공하실수 있을 것입니다.


오늘은 시리얼 통신에 대해 알아보았습니다. pc와 아두이노 간의 통신이 생각보다 정말 간단하죠.

다음시간에는 아날로그 입출력에 대해 공부해보도록 하겠습니다.


플레이페어 암호화를 C언어로 직접 구현해 보았습니다.

리눅스 centos 6 에서 작성하였습니다. 실행파일과 코드 올려드리겠습니다.

많이 부족하니 참고용으로만 봐주세요.

코드 다운로드 

playfair

Playfair.c

a. 프로그램 시작및 키설정


b. 암호화 및 복호화


c. assassinator가 아닌 다른키로 수행


d. 프로그램 종료



c언어는 기본적으로 순차적진행 이에요. a->b->c이러한 순서로 내려가면서 차례대로 수행하게 되죠

예를들어 

printf("hello world\n");

printf("c언어 시작!\");

이문장은

hello world

c언어 시작!

이렇게 출력이 되죠

그렇다면 만약에 ~~~이면 a를 실행하고 ~~~가 아니면 b를 실행하게 할수있는 방법이 있을까요?

그방법이 바로 if문이에요.

if문은 괄호 안에 내용이 참이면 아래부분을 실행하고 거짓이면 {}안에 부분을 실행하지않고 내려가게 된답니다.

 if(조건내용)

{실행될부분}


그럼 if문을 이용한 간단한 코드를 보도록 해요.

#include<stdio.h>

int main()

{

int a, b, c, big;

printf("비교할 숫자 3개를 입력하세요\n");

scanf("%d%d%d",&a,&b,&c);

if(a>b)

big=a;

else

big=b;

if(big<c)

big=c;

printf("%d,%d,%d중 가장큰수는 %d 입니다.\n",a,b,c,big);

return 0;

}


3가지 수를 입력받아 가장큰수를 비교하는 코드에요.

a랑 b를 비교해서 큰수를 big안에 넣고 그 big과 c를 비교해서 big보다 c가 더크면 big=c 를 해주게되죠.

그런데 여기서 else는 무엇일까요?

else는 if안에 조건이 거짓이면 나를 실행해!!하고 이야기해주는 부분이에요.

그러니까 a=1 b=2일때 a>b이면 이것은 거짓이죠.

이때 else문이 실행되어 big=b가 되는 거에요.


이번엔 이 예제를 보도록 해요.

#include<stdio.h>

main()

{

int score;

char grade;

puts("성적을 입력하세요:");

scanf("%d",&score);

if(score>=90)

grade='A';

else if(score>=80)

grade='B';

else if(score>=70)

grade='C';

else if(score>=60)

grade='D';

else

grade='F';

printf("%d%c입니다\n",score, grade);

}

성적을 socre에 입력받고 그결과를 if문으로 비교해서 내성적이 A인지 B인지 C인지 계속 비교해 나가고 있어요.

방금 if와 else는 봤는데 else if는 무엇일까요?

else if는 위에있는 if문이 거짓이면 날 비교해!! 하는 함수에요. 

if-> else if-> else if-> else

if가아니면 else if 안에 조건을 비교해! 얘도 아니면 다음 else if안에 조건을 비교해! 다아니면 else야!

결국 위에 코드는 90이상이면 A 90이상은 아닌데 80이상이면 B 80이상도 아닌데 70이상이면 C 이런식으로 계속비교해 나가는 거죠.


오늘은 if문에대해서 살짝 살펴봤어요. 다음 시간에는 if문과 비슷한 switch문에대해 살펴보도록 해요.


Tetris20131476.c

테트리스게임, 누구나 한번쯤 해봤던 게임일 텐데요.

이것을 우리가 직접 개발해본다면 어떨까요? 윈도우에서가 아니라 리눅스에서요.

전체적인 틀은 가져다 쓴것이었지만 이것을 보며 이해하고 기능들을 추가해나가면 많은 도움이 될수 있을 것이라고 생각해요.

그럼 이테트리스게임의 구성도를 보도록 해요.

-이름 및 기능 기술 (함수 부분)

int display_menu(void) : 메뉴화면을 띄워준다. (main함수 안)

int game_manual(void) : 게임설명 화면을 띄워준다 (main함수 안 2번 누름)

int init_tetris_table(void) : 테트리스판의 벽과 공간을 초기화해준다. (game_start, item_use안에 사용)

int display_tetris_table(void) :현재 블록의 상태 및 쌓여진 블록들을 보여준다.(refresh 함수 안)

int game_start(void) : 게임시작시 호출 게임 시작시 refresh함수 콜백함수로 설정, 타이머 등록

int refresh(int) : 타이머에 콜백함수로 등록되어 계속 새로고침 하면서 호출되는 함수. 키입력 확인, display_tetris_table, check_one_line등의 계속 상태가 변함을 확인해야 되는 함수를 호출한다.

int item_use(void) : q키 입력시 3줄삭제 (점수증가) 및 현재블록 삭제시켜주는 함수

int hidden_key(void) : 1누르면 테이블 초기화 함수 치트키

int move_block(int) : 이동, 회전키가 입력되면 이동전에 충돌검사 (collision_test가 포함)

int drop(void) : 충돌되기 전까지 블록을 아래로 내린다.

int collision_test(int) : 블록이 이동, 회전하기 전에 충돌되는 블록이나 벽이 없는지 확인하는 함수

int check_one_line(void) : 한줄이 완성되었는지 확인하는 함수. 완성되면 한줄삭제(1000점 추가)

int print_result(void) : 메뉴에서 기록출력시 호출되어 기록을 출력하는 함수

int search_result(void) : 메뉴에서 기록검색시 호출되어 기러고을 검색하는 함수

int getch(void) : 리눅스에 getch함수가 없어 가져온 함수

-이름 및 기능 기술 (변수 부분)

char tetris_table[21][12] : 테트리스판 배열로 정의(양옆, 아래는 벽 진짜벽 크기=20*10)

int block_number = 0 : 블록 넘버 변수 switch문으로 블록선택

int next_block_number = 0 : 다음 블록 넘버 변수 switch문으로 블록선택

int block_state = 0 : 0~3까지 블록 회전했을 때 모양 변수

int x = 3, y = 0 : 블록의 현재위치 좌표 변수

int game = GAME_END : 게임이 시작되면 1 종료되면 0 초기값은 0

int best_point = 0 : 게임 최고점수 알려주는 변수

long point = 0 : 현재 점수 변수

int item=0 : 획득 아이템 개수 변수

int emp=0 : item 획득 기준 점수 위한 변수

 

static struct result

{

char name[30];

long point;

int year;

int month;

int day;

int hour;

int min;

int rank;

}temp_result; - 게임 결과값을 저장하는 구조체


각각의 함수들을 보며 이해해주면 좋을 것 같네요.

아래는 이코드를 실행했을때의 모습들이에요. 많이 이용해주시고 더 발전시켜주시면 감사해요.


'[c언어]' 카테고리의 다른 글

[C언어] 만약에 ~~ if문 익히기  (0) 2016.11.04
[c언어] 난수 rand(), srand() 이해하기!  (2) 2016.05.16
[c언어] 마방진 함수 만들기  (122) 2016.05.16

리눅스에서 c파일을 컴파일하다보면 여러개를 계속해서 해줘야하는 불편함을 느껴 본적 있을 텐데요.

그럴때 쓰는 것이 MAKE파일입니다.

MAKE는 소스 프로그램 하나씩 수작업으로 처리하는 번거로움을 줄여주는 것으로 자동적으로 재컴파일 하고 

링크해주는 것입니다.

make도구를 이용할 때 가장 중요한 파일은 Makefile 인데 이것을 작성하는 규칙은 아래와 같습니다.


대상(TARGET)...:의존하는 파일들(PREREQUISTITES).......

명령(COMMAND)

....

....

....

만약 소스 및 생성 파일이 아래와 같은 의존관계를 가지고 있으면

의존관계는 이렇게 표현할수 있습니다.

foobar : main.o foo.o bar.o

main.o : main.c

foo.o : foo.c

bar.o : bar.c

그럼 이걸 이용하여 makefile을 만들어 볼까요?

foobar : main.o foo.o bar.o

gcc -o foobar main.o foo.o bar.o

main.o : main.c

gcc -c main.c

foo.o : foo.c

gcc -c foo.c

bar.o : bar.c

gcc -c bar.c

clean : //이 명령어를 실행하려면 터미널에 make clean를 입력하면 됩니다.

rm -f foobar main.o foo.o bar.o


만든 make파일을 실행하려면 터미널에 make라고 입력해주면 컴파일이 자동으로 됩니다.


1.rand()

난수를 발생시키는 함수인 rand()에요.

rand()에 의해 생성되는 정수는 (0,n) 즉 0부터 n까지 임의의 정수죠.

참고로 stdlib.h 파일에 정의되어있는 RAND_MAX의 초기값은 32767이랍니다.

그럼 rand()함수를 이용한 예제를 볼까요?

#pragma warning(disable:4996) //이건 비쥬얼 스튜디오 상위버전에서 나는 에러를 무시해주는 코드에요.

//0.00~99.99.사이의 실수 난수를 20개 만들어 소수 부분의 합과 정수 부분의 합을 구하시오.

#include<stdio.h>

#include<stdlib.h>

#include<time.h>

main()

{

float rdata[20], fsum=0.0;

int i, isum=0,temp;

srand(time(NULL)); //이부분은 밑에서 다시 설명할께요!

for(i=0;i<20;i++){

rdata[i]=rand()%100+rand()%100/100.0;

printf("%.2f\n",rdata[i]);

if((i+1)&7==0)printf("\n");

}

for(i=0;i<20;i++){

temp=rdata[i];

isum+=temp;

fsum+=(rdata[i]-temp);

}

printf("\n\n정수부분의 합 :%d\n",isum);

printf("\n소수부분의 합 : %.3f\n",fsum);


}

2.srand()

다른건 알겠는데 srand()는 뭘까요?

rand()함수만 쓰고 실행해보세요. 그럼 어떻게 나오나요?

계속 같은 값이 나올꺼에요.

이걸 해결해주는게 srand()함수랍니다.

srand()함수는 매번 다른 난수를 발생시키기 위한 시드(seed)값을 주는 거에요.

그럼 time(NULL)은 무슨의미일까요? 이건 1970년 1월1일 이후의 경과된 시간을 초단위로 반환하는 함수랍니다.

마지막으로 정리할수 있는 예제드릴께요.

#pragma warning(disable:4996)

//0.00~99.99.사이의 실수 난수를 20개 만들어 소수 부분의 합과 정수 부분의 합을 구하시오.

#include<stdio.h>

#include<stdlib.h>

#include<time.h>

main()

{

srand(time(NULL));

float frand[20], fsum = 0;

char crand[20];

int irand[20], i, temp, isum = 0, cnum = 'a';

for (i = 0; i < 20; i++)

{

irand[i] = rand() % 101 + 100;

crand[i] = rand() % 26 + cnum;

frand[i] = rand() % 100 + rand() % 100 * 0.01;

 

printf("%d, %c, %.2f\n", irand[i], crand[i], frand[i]);

}

for (i = 0; i < 20; i++)

{

temp = frand[i];

isum += temp;

fsum = frand[i] - temp + fsum;

}

printf("\n\n정수부분의 합 :%d\n", isum);

printf("\n소수부분의 합 : %.2f\n", fsum);

}

마방진 만드는 소스입니다. 참고해주세요~

 

 

#pragma warning(disable:4996)//scanf등등 warning제거용 코드

#include<stdio.h>

#include<stdlib.h>

void make_msquare(int **table, int n);

void display(int **table, int n);

main()

{

 int i, j, n;

 int **Msquare;

 do {

 printf("n*n 마방진 홀수 n입력 :");

 scanf("%d", &n);

 } while (n % 2 == 0);

 Msquare = (int**)malloc(sizeof(int)*n);

 for (i = 0; i < n; i++)

 {

 Msquare[i] = (int*)malloc(sizeof(int)*n);

 }

 make_msquare(Msquare, n);

 display(Msquare, n);

 free(Msquare);

}

void make_msquare(int **table, int n)

{

 int i, a = 0, b = n / 2;

 for (i = 1; i <= n*n; i++)

 {

 table[a][b] = i;

 if (i % n == 0)

 a++;

 else {

 if (a > 0)

 a--;

 else

 a = n - 1;

 if (b > 0)

 b--;

 else

 b = n - 1;

 }

 }

}

void display(int **table, int n)

{

 int i, j;

 for (i = 0; i < n; i++)

 {

 for (j = 0; j < n; j++)

 {

 printf("%3d ", table[i][j]);

 }

 printf("\n");

 }

}

 

+ Recent posts