'2010/06/15'에 해당되는 글 1건

  1. 2010.06.15 Matlab의 Serial 통신 기능을 이용한 실시간 그래프 그리기 (10)
Programing/Matlab2010.06.15 17:05
 예전에 작성하였던 코드지만 블로그를 살려보고자 하는 마음에 정리를 해봅니다.

이번 작업을 하게 되면...
1. 매트랩의 External Interface 기능중에 시리얼 기능을 통하여 PC외부의 장치(MCU)와 시리얼 통신(UART)을 하여 데이터를 주고 받을 수 있습니다. 굳!!!
2. 매트랩의 실시간 그래프 기능을 이해할 수 있습니다. 사실 이해는 아니고 그냥 경험정도^^;;
3. 매트랩에서 전달 받은 데이터를 이용해서 자유롭게 매트랩 코드를 이용하여 테스트 할 수 있습니다. (FIR과 FFT등 엄청난 기능을...ㄷㄷㄷ)

테스트 결과는 다음과 같습니다.



매트랩에서 어떻게 MCU에 있는 데이터를 얻어올 수 있을까요..
PC에서 데이터를 가장 많이 사용하는 방법은 시리얼 통신이죠.
그럼 시리얼 통신을 해야되는데요..
시리얼을 혹시 모르시는 분들은 여기를.. http://en.wikipedia.org/wiki/Serial_port

그럼 어떻게 해야되나요..

일단 데이터를 주고 받는 프로토콜?? 이라고 하긴 조금 그렇지만 형식이 필요합니다.
일반적으로 시리얼 통신 패킷은 STX, ETX, CRC 체크 등등이 있지만 우린 필요없죠.. 적어 지금은요 ㅎㅎ

그럼 저만의 프로토콜을 만듭니다.
저는 다음과 같이 시작은 문자열 'a', 끝은 문자열 'b'를 넣고 그 사이에 데이터를 ASCII 값으로 넣습니다. 각 데이터간의 구분은 ','를 이용하구요. 
ASCII 가 궁금하신 분들은 다음을 참고하세요. http://en.wikipedia.org/wiki/Ascii

그럼 예를 볼까요? MCU에서 시리얼 데이터를 다음과 같이 PC로 보내게 됩니다.
a100,200,120b

해석해보면... 가장 처음에 100을 넘기고 그담에 200 그담에 120을 넘기게 되네요!
코드는 다음과 같이 아주 쉽게 작성할 수 있겠죠?

MCU 측의 코드는 다음과 같습니다.

adc에서 값을 읽어온 데이터가 adcbuff[3]라는 공간에 저장되게 된다면..
char adcbuff[4];
char sendbuff[80];

// 어디선가 adc 버퍼를 갱신하겠죠? 

char datasend(){
  sprintf(sendbuff, "a%d,%d,%db", adcbuff[0], adcbuff[1], adcbuff[2]);
  uartsend(sendbuff, strlen(sendbuff));
}



sprintf함수는 printf의 기능을 변수에 만들어 주는 기능을 하구요. stdio.h 를 추가하셔야 됩니다.
uartsend함수는 uart를 통하여 sendbuff에 있는 내용을 전송합니다. 

좋습니다. 이제 준비가 되었어요.


이제는 MATLAB 쪽의 코드를 볼까요?
전체 코드는 다음과 같습니다.
COMPORT = 'COM2';
s = serial(COMPORT, 'BaudRate', 57600, 'Timeout',0.002);
fopen(s)


f = figure(1);

x = 1:100;
y_angle = zeros(1,100);
y_acc = zeros(1,100);
y_gyro = zeros(1,100);

figure(f)

subplot(3,1,1)
grid on
axis([0 100 -100 100])
lh=line(x,y_angle,...
            'marker','.',...
            'markersize',5,...
            'linestyle','-');
subplot(3,1,2)
grid on
axis([0 100 -100 100])
lj=line(x,y_acc,...
            'marker','.',...
            'markersize',5,...
            'linestyle','-');
subplot(3,1,3)
grid on
axis([0 100 -100 100])
lk=line(x,y_gyro,...
            'marker','.',...
            'markersize',5,...
            'linestyle','-');

for i = 1:inf
    data=''; 
    while isempty(strmatch('a',data)) 
    data = fscanf(s); 
    end

    idn = data;
    stringlength = size(idn,2);

    clear value;
    clear cnt;
    
    
    if(idn(1) =='a')
        if(idn(stringlength) =='b')
            packet = idn(2:stringlength-1);
            [value cnt] = string2valuearray(packet,',') ; 


    y_angle = [y_angle(2:100) value(1)]; % <- new data
    y_acc = [y_acc(2:100) value(2)]; % <- new data
    y_gyro = [y_gyro(2:100) value(3)]; % <- new data
    set(lh,...
        'xdata', x,...
        'ydata', y_angle);
    pause(0.001);
    set(lj,...
        'xdata', x,...
        'ydata', y_acc);
    pause(0.001);
        set(lk,...
        'xdata', x,...
        'ydata', y_gyro);
    pause(0.001);
    
        end
    end
end
    
fclose(s)

serialTest.m



코드는 매우 간단합니다.
라인 1에서 PC의 포트의 번호를 입력하시고, serial 함수를 통해서 포트를 열게 됩니다.
자세한 serial함수의 내용은 help 고고싱!
현재는 timeout 기반으로 시리얼 값을 가져오기 때문에 조금 문제가 있지만 serial 함수에서 end 문자열을 지정한다던지 해서 해결 할 수 있습니다.
한마디로 아직 완성된 코드는 아니라는거죠 ㅠㅠ  버그는 많습니다.. ㄷㄷ

라인 13부터 35까지는 실시간 그래프를 그리기 위한 준비 작업입니다. 자세한 내용은 help 고고..

그다음 37에서 부터 74까지 무한 루프를 돌면서 그래프를 그리게 되죠..
실제 그래프를 그리는 부분은 59~70까지고, 50~58까지는 파싱과 데이터 준비 입니다.

이렇게 하면 3개의 데이터를 그래프로 확인할 수 있습니다.
아직 버그는 조금 있지만 그래도 간단히 테스트 용으로는 쓸만했습니다^^
중간에 그래프 보는것을 중단하고 싶으시면 콘솔창을 클릭하시고 Ctrl+C를 클릭하시면 됩니다~


-----------------------------------------------------------------------------------------------------
- 수정 : 2011-08-21, string2valuearray 부분 추가합니다^^;
-----------------------------------------------------------------------------------------------------


function [value, cnt] = string2valuearray(string)

stringlength = size(string,2);

if(string(1) =='a')
    if(string(stringlength) =='b')
        packet = string(2:stringlength-1);
          
        cntComma = size( strfind(packet, ','), 2);
        cnt = cntComma + 1;
        
        
        value = zeros(1, cntComma + 1);
        
        for i = 1 : 1 : cntComma+1
            [a packet] = strtok(packet, ','); %#ok<STTOK>
            value(i) = str2double(a);
        end
        
        
    end
end

string2valuearray.m


시리얼로 받은 내용을 파싱해주는 부분입니다~
이 부분을 빠트렸었네요 ㄷㄷㄷ


신고
Posted by Frys

티스토리 툴바