본문으로 바로가기

MATLAB을 이용한 시리얼 통신

category Software/MATLAB 2013. 6. 5. 18:43

이 글 이전의 제 블로그에서 MATLAB관련 최신글이 2011년 5월 17일이더군요. 캬~~ 지금이 2013년 6월 초인걸 감안하면 참으로 오랜만에 MATLAB 관련글을 올릴려고 합니다. 뭐 거창한건 아니구요. 오늘 문득 뭔가를 확인할려고 MATLAB으로 시리얼통신을 할 일이 있었는데, 하도 오랜만이라 명령이 기억이 안나서, 제 블로그를 살짝 확인했더니 어라~ 시리얼통신에 대한 이야기를 한 적이 없더군요. 그래서 올립니다. ㅎㅎ 뭐 좋은 많은 스킬을 공개하면 좋겠지만, 그렇지는 않구요. 그냥 기초만 알려드릴려구요. 그리고, 뭔가 실습 대상이 있어야하니, 제가 예전에 개발했던 ARS를 대상으로 할려고 합니다.[바로가기]

당시는 제가 입사한지 초반이라 참 재미있게 진행했던 프로젝트였는데요. 오랜만에 다루니까 느낌이 새롭네요^^ 아무튼 이 아이는 시리얼통신으로 데이터를 보내주는데요.

핀맵이 이렇게 되어있습니다. CAN통신도 지원하지만, 저는 시리얼통신으로 사용할거니 1,2,3,6번핀만 매핑해주면 됩니다.

PC쪽 시리얼포트에 데이터라인과 GND를 연결하고, 전원은 별도로 연결해야합니다. 그리고, 요즘은 시리얼포트가 있는 PC가 없으니, 시리얼-USB 변환 젠더를 사용해야합니다. 뭐 몇 천원에서 만원이 조금 넘는 가격으로 다양하게 판매들을 하고 있더군요.

아무튼 이렇게 연결이 끝나고 나면 MATLAB에서 통신을 시도해보죠

언제나 그렇듯 기본이 되는 명령은 정말 별것 없습니다.

s = serial('COM6')

시리얼 통신을 사용할거라고 살짝 알려주구, 본인이 사용할 com port 번호를 COM6의 6에 적으면 됩니다. 저는 6번 포트를 열었거든요.

set(s, 'BaudRate', 115200)

set(s, 'Terminator', 'CR')

그리고, 시리얼통신으로 선언한 변수 s의 세팅을 해줍니다. 뭐 많이 할 것도 없구요. 통신속도(BaudRate)와 종료문자(CR = Carrige Return)만 선언합니다.

이게, 기본 사용 준비가 끝난겁니다. 응? 간단하죠^^

그리고 이제

fopen(s)

명령으로 시리얼포트를 열고,

작업을 하면 됩니다. 저는 ARS에 각도를 한 세트만 날려달라고 명령을 할 건데, 그 명령이 <CAO>거든요. 그래서 PC에서 센서로 <CAO>라는 명령을 시리얼 통신으로 날리면 됩니다. 명령은 fprint입니다.

fprint(s, '<CAO>')

그럼 ARS 센서 모듈은 현재의 pitch과 roll값과 각속도 이렇게 4개의 값을 날려줍니다. 그걸 읽어야죠.

out = fscanf(s);

이렇게 읽습니다. 이렇게 읽은 값을 가지고 원하는데로 작업을 하면 되겠죠. 그리고 작업이 다 끝나면

fclose(s)

이렇게 명령을 내려서 열린 com port를 닫아주면 됩니다.

그러면, 이제 위 명령을 가지고 작성한 full-code를 한번 보죠.

s = serial('COM6');
set(s, 'BaudRate', 115200)
set(s, 'Terminator', 'CR')
fopen(s);

fprintf(s, '<CAO>')
out = fscanf(s);

result = zeros(1,4);
tmpCounter = 1;
tmpResult = 0;

for tmp = 2:(length(out)-1)
    if out(tmp) == '-'
        tmp1 = -1;
    end
    if (out(tmp) == ',') || (out(tmp) == '>')
        result(tmpCounter) = tmpResult*tmp1;
        tmpCounter = tmpCounter + 1;
        tmp1 = 1;
        tmpResult = 0;
    end
    if (out(tmp)>='0') && (out(tmp)<='9')
        tmpResult = tmpResult*10 + str2double(out(tmp));
    end
end

result = result*0.001*180/pi

fclose(s)

응? 실컷 설명은 간단하다고 하구선 의외로 긴데? 하고 느끼실 수도 있습니다만, 사실 그렇지 않습니다. 제가 개발한 ARS 모듈은 그 결과를 한 문자씩 시리얼로 날려서 눈에 보기엔 숫자로 잘 나옵니다만, 사실 그건 문자거든요. 그래서, 위 코드 9번행부터 28번행까지 작업해서 그걸 숫자로, 그것도 degree 혹은 degree/sec로 표현한 겁니다. 

센서의 출력을 아무 가공없이 그냥 받은 것이 위 코드에서 7번행의 out이라는 변수인데 그걸 workspace에서 확인해보면 위 그림처럼 char형으로 됩니다. 그것도 1*15의 크기니까 15개의 문자가 들어간거죠. 게다가 애초 ARS는 원 데이터에 1000을 곱해서 radian 혹은 radian/sec로 데이터를 보내기 때문에 약간의 수정이 프로그램적으로 필요한 겁니다. 

그래서 위 코드의 for문에서 그걸 하고 있습니다. 뭐 저부분은 꼭 제가 설명할 건 없어 보여서, 또 블로그에 언능 올릴려고 개발새발 작성한거라 뭐 이렇게 하면 되는군... 정도로만 알아 주시면 됩니다.

그리고 마지막으로, serial 버퍼에 들어온 데이터가 없는데 fscanf로 데이터를 읽겠다고 하시면, 꽤 오랜시간 MATLAB이 멈춘듯이 보입니다. 그럼... 초 간단 MATLAB 시리얼 통신 설명을 언능 끝내고, 전 살짝 퇴장합니다. 저희 회사는 샌드위치 데이인 이번주 금요일이 쉬는 날이라 4일간의 연휴거든요..  아싸~~~~


댓글을 달아 주세요

  1. BlogIcon 소스킹 2013.06.06 02:23

    으핫+_+; 뭔가 어렵네요. ㅠㅠ 샌드위치로 4일 연속 쉬시는군요.ㅎㅎ 부럽습니다. 혹시 이번 연휴 어디 여행 계획 있으신지!

  2. BlogIcon 핑구야 날자 2013.06.06 05:33 신고

    정말 오랜만에 어려운 공부를 하게 되네요ㅋㅋ

  3. BlogIcon 어듀이트 2013.06.06 16:23

    시리얼 통신 잘 보고 갑니다`
    행복한 하루 되시길 바래요`

  4. BlogIcon 금융연합 2013.06.07 07:03

    즐거운 하루되세요

  5. BlogIcon S매니져 2013.06.07 19:10

    저에게는 너무 어려운..ㅠ
    행복한 금요일 되시길 바래요~

  6. 2013.08.06 16:08

    비밀댓글입니다

    • BlogIcon PinkWink 2013.08.07 19:27 신고

      '사례'는 무지장 좋아합니다.^^
      그러나 과연 제가 어떤 도움을 드릴 수 있을 지는 미지수 입니다.
      간단히 연결만 하면 됩니다라고 하지만,
      실제로 더 간단할 수도 있고
      생각보다 오랜 시간이 걸릴 수도 있으며,
      심지어는 개발이라는 단어를 붙여야할 수도 있습니다.
      간단히, 제 개인 메일로 말씀하신 로드셀의 제원과 작업 프로세스를 간략히 요약해서 보내주세요.
      아 그리고, 전 이번주 수요일 목요일은 출장이라 답변을 못해 드릴 수도 있습니다.

  7. 2014.03.28 20:59

    비밀댓글입니다

    • BlogIcon PinkWink 2014.03.29 14:18 신고

      글쎄요. 에러메세지는 정확하진 않아도 자기 입장에서는 정직하니까요. 분명 MATLAB은 해당 포트를 사용할 수없다는 거고, 그 이유로 혹시 다른 장비가 연결되어 있는지 INSTRFIND 명령을 사용해보라고 권고하고 있군요.^^

  8. 2014.04.07 17:25

    비밀댓글입니다

    • BlogIcon PinkWink 2014.04.07 18:30 신고

      어차피 시리얼 통신이니 한줄로 오죠^^
      데이터를 어떻게 나눠서 저장할 지를 고민하시면 될듯합니다.
      딱 맞진 않겠지만 비슷하게
      http://pinkwink.kr/582
      이렇게도 구현을 했었는데요.
      라벨에 맞춰 잘 들어온 데이터를 첫번째는 어디, 두번째는 어디 이렇게 사용자가 나눠주면 되지 않나요?

    • 2014.04.08 17:17

      비밀댓글입니다

    • BlogIcon PinkWink 2014.04.09 09:59 신고

      아닙니다. 그러나 저는 코드나 결과를 분석하는건 잘 하지 않습니다. 일단 저도 시간이 소중한데다 그게 직접 돌려보지 않으면 꽤 많은 시간이 소요되거든요.^^.
      일단 제가 본문에 올린 코드는 데이터를 딱 한 번 받는 겁니다. 테스트 대상으로 잡은 ARS의 명령중 <CAO>라는 명령이 데이터를 한번만 주거든요. 그 한번 받은 데이터를 어떻게 나누고 가공하는가가 내용입니다.
      아두이노는 loop()함수에 의해 사실상 무한반복하자나요.
      그러니 MATLAB에서도 일단 데이터가 잘 들어온다는 것만 확인하고 싶으시면 while(1)안에 넣어서 무한 반복으로 데이터를 받아서 화면에 뿌려만 보세요. 그러면 데이터가 잘 들어온다는 것은 알 수 있을 겁니다.^^

  9. onemore 2014.05.09 23:46

    혹시 GUI를 이용해서 시리얼 통신이 가능하게 만들수 있습니까??

  10. onemore 2014.05.10 21:29

    혹시 GUI를 이용해서 시리얼 통신이 가능하게 코드를 작성했는데
    도움이 필요해서 그러는데...한번 봐주실수 있나요??

  11. JM 2014.06.17 15:14

    종료 문자를 사용하지 않을 수도 있나요? 그런 설정이 있는지 궁금합니다. ^-^

    • BlogIcon PinkWink 2014.06.18 08:56 신고

      종료문자를 쓰는가 아닌가는 사용자 마음이죠.
      단 어떤 제품과의 통신을 하시는 거라면
      그 제품의 매뉴얼을 잘 보셔야할듯합니다.
      일종의 약속이니까요^^

  12. ggoma 2014.07.09 14:25

    처음 수치가 음수가 아니라면 음수체크하는 if문을 통과하게 되고
    첫 콤마 체크 루프에서 result(tmpCounter) = tmpResult*tmp1; 여기서 tmp1이 정의 되지 않는 문제가 생깁니다.
    이것저것 해보다가 for문 밖에서 처음 수치만 따로 양수체크하는 부분을
    tmp = 2;
    if out(tmp) ~= '-'
    tmp1 = 1;
    end
    이렇게 따로 만들었는데 혹시 for문 안에서 해결 할 수 있는 방안이 있을까요?
    이제 처음으로 matlab을 다루기 시작해서 머리가 잘 안돌아가네요 ㅜㅜ

    • BlogIcon PinkWink 2014.07.10 12:46 신고

      죄송합니다만, 본문의 예제 코드에서도 음수인지 아닌지를 체크하고 있습니다만...

    • ggoma 2014.07.10 17:18

      제가 아직 잘 몰라서 그럴 수도 있어서 죄송합니다.
      그런데 음수 체크 부분이 중요한게 아니라 tmp1의 초기값을 어떤 시점에 어떻게 지정하는냐가 궁금해서 질문 드렸습니다.

      만약 데이터가 <23.55,-56.12,34.55> 이렇게 나왔다고 치면
      2 3 5 5 가 차례대로 세번째 if를 통해 2355가 저장되고
      그 다음에 콤마가 나옴으로써 두번째 if문으로 들어가는데 result(tmpCounter)=tmpResult*tmp1;에서 tmp1은
      그다음다음 줄에 tmp1=1;라고 입력되기 때문에
      맨 처음 데이터가 양수라서 데이터*1(tmp1값)이 되야 되는데
      tmp1=?(입력x)인 상황이어서 에러가 나왔습니다.
      그래서 해결 방법을 고민하고자 답글을 달았습니다.

      tmp1=1;의 위치를 바꿔보았지만 음수일때도 모든 값이 양수로 나오는 등 for문 안에서의 해결방법을 찾지 못해서 할 수 없이 따로 for문을 만들어봤습니다.

      위의 내용 중에 혹시 제가 잘못 알고 있는 부분이 있으면
      따끔한 충고 부탁드립니다. 감사합니다.

    • BlogIcon PinkWink 2014.07.10 21:15 신고

      음 그러셨군요 제가 약간 가독성이 떨어지게 코드를 작성해서 그럴수도 있습니다 ㅠ
      일단 for문안에는 세개의 조건문이 있습니다
      시작 괄호와 콤마등을 처리하는 조건문이 있는데 거기서 말씀하신 변수를 일로 초기화해두었구요
      또하나는 음수인지 아닌지를 판정하구요
      또하나는 숫자만 받아서 자리올림을하지요

      괄호가 시작되고 tnp1은 일이 되구요
      마이너스 기호가 나오면 그걸 -1로 바꾸죠

      숫자는 그다음에 나오니까요

  13. 신입사원 2015.08.19 10:03

    혹시 매트랩을 이용해 시리얼 통신을 할때
    fwrite, fread는 어떻게 사용하는건가요?
    제가 갖고있는 모듈에다가 제가 입력한 값의 dac 결과를 띄우고싶은데
    매트랩 초보라서 명령어들을 잘 모르겠네요 ㅠㅠ

    • BlogIcon PinkWink 2015.08.19 15:30 신고

      흠. .그냥 저는 본문에 있는 대로 사용했답니다ㅠㅠ. 그것 말고는 설명드릴 수 있는게 없어요ㅠㅠ. 왜냐면 딱 요렇게만 썼거든요^^