CAN Bus (controller area network) ဆိုသည်မှာ ဆက်သွယ်ရေး စနစ် တစ်ခုဖြစ်ပြီး မိုက်ခရိုကွန်ထရိုလာများ နှင့် အခြား အီလက်ထရွန်းနစ် ကိရိယာများကို ကွန်ပျူတာ မလိုအပ်ဘဲ အချင်းချင်း ဆယ်သွယ် နိုင်ရန် ပြုလုပ်ထားသော စနစ်ဖြစ်ပါတယ်။ CAN Bus ဟာ မက်ဆေ့ (message) အပေါ်တွင် အခြေခံသော ပရိုတိုကောလ်ဖြစ်ပြီး မော်တော်ယာဉ်များတွင် အဓိက အသုံးပြုလေ့ ရှိပေမယ့် စက်ရုံများနှင့် ဆေးဘက်ဆိုင်ရာ ကိရိယာများတွင်လည်း အသုံးပြုလေ့ ရှိပါတယ်။
Showing posts with label LabVIEW. Show all posts
Showing posts with label LabVIEW. Show all posts
Tuesday, July 9, 2013
Sunday, January 13, 2013
Changing sampling rate using quadratic regression
signal တစ်ခုရဲ့ sampling rate ကို 333Hz ကနေ 5000Hz ကို ပြောင်းဖို့ အတွက် လုပ်ကြည့်ထားပါတယ်။ ပိုမို ချောမွေ့တဲ့ ရလာဒ် ရချင်တာမို့ ပုံမှန် zero order hold (ZOH) ကို သုံးမယ့်အစား second order hold ကို သုံးကြည့်ထားတာပါ။ ဒီမှာ sampling rate ကို တင်ဖို့လုပ်ထားပေမယ့်၊ ဒီနည်းကို down sampling လုပ်ဖို့လည်း သုံးလို့ရပါတယ်။ အခြား ဖြစ်နိုင်ချေတွေကတော့ noise ကို phase delay မရှိပဲ filter လုပ်တဲ့ဟာမျိုးတွေ အတွက်လည်း သုံးလို့ ရနိုင်ပါတယ်။ real-time application တွေအတွက်ပေါ့။
Approach 1: Quadratic regression
Quadratic ဖန်ရှင်တစ်ခုကို အောက်ပါအတိုင်း သတ်မှတ်နိုင်ပါတယ်။
$$f=w_0+w_1 x + w_2 x^2$$
အနည်းဆုံး ဖြစ်အောင် လုပ်မယ့် cost function ကို အောက်ကလို သတ်မှတ်မှာပါ။
$$J(w)=\frac{1}{2}\sum_{i=1}^{n}(y_i-f_i)^2$$
$$J(w)=\frac{1}{2}\sum_{i=1}^{n}(y_i-w_0+w_1 x_i + w_2 x_i^2)^2$$
ဒါဆို Optimal weights တွေကို differentiate လုပ်ပြီးသုည ညီလိုက်ပြီး ရှာနိုင်ပါတယ်။
$$\frac{\partial J(w)}{\partial w_0}=0$$
$$-\sum_{i=1}^{n}(y_i-w_0+w_1 x_i + w_2 x_i^2)=0$$
$$w_0\sum_{i=1}^{n}1+w_1\sum_{i=1}^{n}x_i+w_2\sum_{i=1}^{n}x_i^2=\sum_{i=1}^{n}y_i$$
w1 နဲ့ w2 ကိုလည်း အဲဒီလိုပဲ ရှာလိုက်မယ် ဆိုရင် အောက်အတိုင်း ထပ်ရလာပါမယ်။
$$w_0\sum_{i=1}^{n}x_i+w_1\sum_{i=1}^{n}x_i^2+w_2\sum_{i=1}^{n}x_i^3=\sum_{i=1}^{n}y_i x_i$$
$$w_0\sum_{i=1}^{n}x_i^2+w_1\sum_{i=1}^{n}x_i^3+w_2\sum_{i=1}^{n}x_i^4=\sum_{i=1}^{n}y_i x_i^2$$
အဲဒီ equation သုံးခုကို မေ့ထရစ် ပုံစံ နဲ့ အောက်ပါအတိုင်း ရေးလို့ရပါတယ်။
$$ \begin{bmatrix} \sum_{i=1}^{n}1 & \sum_{i=1}^{n}x_i & \sum_{i=1}^{n}x_i^2 \\ \sum_{i=1}^{n}x_i & \sum_{i=1}^{n}x_i^2 & \sum_{i=1}^{n}x_i^3 \\ \sum_{i=1}^{n}x_i^2 & \sum_{i=1}^{n}x_i^3 & \sum_{i=1}^{n}x_i^4 \end{bmatrix} \begin{bmatrix} w_0 \\ w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} \sum_{i=1}^{n}y_i \\ \sum_{i=1}^{n}y_i x_i \\ \sum_{i=1}^{n}y_i x_i^2 \end{bmatrix} $$
$$\mathbf{A}\mathbf{W}=\mathbf{B}$$
$$\mathbf{W}=\mathbf{A}^{-1}\mathbf{B}$$
Approach 2: Three equations
တကယ်တော့ ဒီကိစ္စမှာ နောက်ဆုံး အမှတ် ၃ ခုကိုပဲ သုံးလိုက်ရင်ရတဲ့ အတွက်၊ ညီမျှခြင်း သုံးကြောင်း ကို အောက်က အတိုင်း တစ်ခါတည်း ချရေးလို့လည်း ရပါတယ်။
$$y_1=w_0+w_1 x_1 + w_2 x_1^2$$
$$y_2=w_0+w_1 x_2 + w_2 x_2^2$$
$$y_3=w_0+w_1 x_3 + w_2 x_3^2$$
$$ \begin{bmatrix} 1 & x_1 & x_1^2 \\ 1 & x_2 & x_2^2 \\ 1 & x_3 & x_3^2 \end{bmatrix} \begin{bmatrix} w_0 \\ w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} y_1 \\ y_2 \\ y_3 \end{bmatrix} $$
$$\mathbf{A}\mathbf{W}=\mathbf{B}$$
$$\mathbf{W}=\mathbf{A}^{-1}\mathbf{B}$$
Approach 3: Two equations အကယ်၍ x1=-1, x2=0, နဲ့ x3=1 လို့ သတ်မှတ်လို့ ရတယ်ဆိုရင် y2 က w0 နဲ့ ညီသွားပါမယ်။ နောက်ကျန်တဲ့ အမှတ် ၂ ခုကနေ ညီမျှခြင်း နှစ်ကြောင်းပဲ ရှင်းဖို့ လိုပါတော့တယ်။
$$y_1=y_2-w_1+ w_2$$
$$y_3=y_2+w_1+ w_2$$
$$ \begin{bmatrix} -1 & 1 \\ 1 & 1 \end{bmatrix} \begin{bmatrix} w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} y_1-y_2 \\ y_3-y2 \end{bmatrix} $$
$$ \begin{bmatrix} w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} -0.5 & 0.5 \\ 0.5 & 0.5 \end{bmatrix} \begin{bmatrix} y_1-y_2 \\ y_3-y2 \end{bmatrix} $$
နောက် အောက်ကအတိုင်းရလာပါမယ်။
$$w_0=y_2$$
$$w_1=-0.5(y_1-y_2)+0.5(y_3-y2)$$
$$w_2=0.5(y_1-y_2)+0.5(y_3-y2)$$
အထက်ကနည်းတွေကို MatLab နဲ့စမ်းကြည့်ထားတာကို အောက်က ကုဒ်တွေမှာ တွေ့နိုင်ပါတယ်။
Approach 1: Quadratic regression
Quadratic ဖန်ရှင်တစ်ခုကို အောက်ပါအတိုင်း သတ်မှတ်နိုင်ပါတယ်။
$$f=w_0+w_1 x + w_2 x^2$$
အနည်းဆုံး ဖြစ်အောင် လုပ်မယ့် cost function ကို အောက်ကလို သတ်မှတ်မှာပါ။
$$J(w)=\frac{1}{2}\sum_{i=1}^{n}(y_i-f_i)^2$$
$$J(w)=\frac{1}{2}\sum_{i=1}^{n}(y_i-w_0+w_1 x_i + w_2 x_i^2)^2$$
ဒါဆို Optimal weights တွေကို differentiate လုပ်ပြီးသုည ညီလိုက်ပြီး ရှာနိုင်ပါတယ်။
$$\frac{\partial J(w)}{\partial w_0}=0$$
$$-\sum_{i=1}^{n}(y_i-w_0+w_1 x_i + w_2 x_i^2)=0$$
$$w_0\sum_{i=1}^{n}1+w_1\sum_{i=1}^{n}x_i+w_2\sum_{i=1}^{n}x_i^2=\sum_{i=1}^{n}y_i$$
w1 နဲ့ w2 ကိုလည်း အဲဒီလိုပဲ ရှာလိုက်မယ် ဆိုရင် အောက်အတိုင်း ထပ်ရလာပါမယ်။
$$w_0\sum_{i=1}^{n}x_i+w_1\sum_{i=1}^{n}x_i^2+w_2\sum_{i=1}^{n}x_i^3=\sum_{i=1}^{n}y_i x_i$$
$$w_0\sum_{i=1}^{n}x_i^2+w_1\sum_{i=1}^{n}x_i^3+w_2\sum_{i=1}^{n}x_i^4=\sum_{i=1}^{n}y_i x_i^2$$
အဲဒီ equation သုံးခုကို မေ့ထရစ် ပုံစံ နဲ့ အောက်ပါအတိုင်း ရေးလို့ရပါတယ်။
$$ \begin{bmatrix} \sum_{i=1}^{n}1 & \sum_{i=1}^{n}x_i & \sum_{i=1}^{n}x_i^2 \\ \sum_{i=1}^{n}x_i & \sum_{i=1}^{n}x_i^2 & \sum_{i=1}^{n}x_i^3 \\ \sum_{i=1}^{n}x_i^2 & \sum_{i=1}^{n}x_i^3 & \sum_{i=1}^{n}x_i^4 \end{bmatrix} \begin{bmatrix} w_0 \\ w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} \sum_{i=1}^{n}y_i \\ \sum_{i=1}^{n}y_i x_i \\ \sum_{i=1}^{n}y_i x_i^2 \end{bmatrix} $$
$$\mathbf{A}\mathbf{W}=\mathbf{B}$$
$$\mathbf{W}=\mathbf{A}^{-1}\mathbf{B}$$
Approach 2: Three equations
တကယ်တော့ ဒီကိစ္စမှာ နောက်ဆုံး အမှတ် ၃ ခုကိုပဲ သုံးလိုက်ရင်ရတဲ့ အတွက်၊ ညီမျှခြင်း သုံးကြောင်း ကို အောက်က အတိုင်း တစ်ခါတည်း ချရေးလို့လည်း ရပါတယ်။
$$y_1=w_0+w_1 x_1 + w_2 x_1^2$$
$$y_2=w_0+w_1 x_2 + w_2 x_2^2$$
$$y_3=w_0+w_1 x_3 + w_2 x_3^2$$
$$ \begin{bmatrix} 1 & x_1 & x_1^2 \\ 1 & x_2 & x_2^2 \\ 1 & x_3 & x_3^2 \end{bmatrix} \begin{bmatrix} w_0 \\ w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} y_1 \\ y_2 \\ y_3 \end{bmatrix} $$
$$\mathbf{A}\mathbf{W}=\mathbf{B}$$
$$\mathbf{W}=\mathbf{A}^{-1}\mathbf{B}$$
Approach 3: Two equations အကယ်၍ x1=-1, x2=0, နဲ့ x3=1 လို့ သတ်မှတ်လို့ ရတယ်ဆိုရင် y2 က w0 နဲ့ ညီသွားပါမယ်။ နောက်ကျန်တဲ့ အမှတ် ၂ ခုကနေ ညီမျှခြင်း နှစ်ကြောင်းပဲ ရှင်းဖို့ လိုပါတော့တယ်။
$$y_1=y_2-w_1+ w_2$$
$$y_3=y_2+w_1+ w_2$$
$$ \begin{bmatrix} -1 & 1 \\ 1 & 1 \end{bmatrix} \begin{bmatrix} w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} y_1-y_2 \\ y_3-y2 \end{bmatrix} $$
$$ \begin{bmatrix} w_1 \\ w_2 \end{bmatrix} = \begin{bmatrix} -0.5 & 0.5 \\ 0.5 & 0.5 \end{bmatrix} \begin{bmatrix} y_1-y_2 \\ y_3-y2 \end{bmatrix} $$
နောက် အောက်ကအတိုင်းရလာပါမယ်။
$$w_0=y_2$$
$$w_1=-0.5(y_1-y_2)+0.5(y_3-y2)$$
$$w_2=0.5(y_1-y_2)+0.5(y_3-y2)$$
အထက်ကနည်းတွေကို MatLab နဲ့စမ်းကြည့်ထားတာကို အောက်က ကုဒ်တွေမှာ တွေ့နိုင်ပါတယ်။
%------------------------------------------------------------------------- clc; close all; clear all; %------------------------------------------------------------------------- % y= w0 + w1*x + w2* x^2; %------------------------------------------------------------------------- %Got x and y x=[-1 0 1]'; Wo=[4 3 2]'; y=Wo(1)+Wo(2)*x+Wo(3).*x.*x; %------------------------------------------------------------------------- %Approach 1 %Polynomial regression of order 2 %For n=3 S1=3; Sx=sum(x); Sx2=sum(x.*x); Sx3=sum(x.*x.*x); Sx4=sum(x.*x.*x.*x); Sy=sum(y); Syx=sum(y.*x); Syx2=sum(y.*x.*x); P=[S1 Sx Sx2; Sx Sx2 Sx3; Sx2 Sx3 Sx4]; B=[Sy Syx Syx2]'; %P1=P^(-1); W1=P\B %------------------------------------------------------------------------- %Approach 2 %Linear equations A=[1 x(1) x(1)*x(1);1 x(2) x(2)*x(2); 1 x(3) x(3)*x(3)]; W2=A\y %------------------------------------------------------------------------- %Approach 3 %Only 2 linear equations w0=y(2); w1=-0.5*( y(1)- y(2))+0.5*( y(3)- y(2)); w2=0.5*( y(1)- y(2))+0.5*(y(3)- y(2)); W3=[w0 w1 w2]' %-------------------------------------------------------------------------အောက်ကပုံမှာ ဒီနည်းကို သုံးလို့ရတဲ့ ရလဒ် (အပြာ) နဲ့ ပုံမှန် zero order hold သုံးရင် ရမယ့် ရလဒ် (အနက်) တို့ကို ယှဉ်ပြထားပါတယ်။ ဒီနည်းက ပိုပြီး ညက်ညော ချောမွေ့တဲ့ ရလဒ်ကို ရပေမယ့် one sample delay ရှိသွားတာကိုတော့ သတိထားဖို့ လိုပါတယ်။ ဒီနည်းလမ်းကို LabVIEW မှာ C code သုံးပြီး လုပ်ထားတာကို အောက်ကပုံမှာ တွေ့နိုင်ပါတယ်။ ပထမ နှစ်ခုမှာ 3x3 matrix ကို inverse ရှာဖို့ လိုတဲ့အတွက် inverse ရှာတဲ့ C program လေးတစ်ခုကို ရေးပြီး စမ်းကြည့်ထားပါတယ်။
#include#include main() { float M[3][3]={{3,0,2},{0,2,0},{2,0,2}}; //initialize a 3x3 matrix float N[3][3]={{0,0,0},{0,0,0},{0,0,0}}; //allocate for inverse int i,j; float d; //------------------------------------------------------------------------- N[0][0]=(M[1][1]*M[2][2]-M[2][1]*M[1][2]); N[1][0]=-(M[1][0]*M[2][2]-M[2][0]*M[1][2]); N[2][0]=(M[1][0]*M[2][1]-M[1][1]*M[2][0]); d=M[0][0]*N[0][0]+M[0][1]*N[1][0]+M[0][2]*N[2][0]; N[0][0]/=d; N[1][0]/=d; N[2][0]/=d; N[0][1]=-(M[0][1]*M[2][2]-M[0][2]*M[2][1])/d; N[1][1]=(M[0][0]*M[2][2]-M[0][2]*M[2][0])/d; N[2][1]=-(M[0][0]*M[2][1]-M[0][1]*M[2][0])/d; N[0][2]=(M[0][1]*M[1][2]-M[0][2]*M[1][1])/d; N[1][2]=-(M[0][0]*M[1][2]-M[0][2]*M[1][0])/d; N[2][2]=(M[0][0]*M[1][1]-M[0][1]*M[1][0])/d; //------------------------------------------------------------------------- //print 3x3 matrix for(i=0;i<3;i++) { for(j=0;j<3;j++) printf("%3.4f ",N[i][j]); printf("\n"); } getch(); return 0; }
Friday, December 16, 2011
Geometric Template Matching in LabVIEW
NI ရဲ့ IMAQ Vision Concepts Manual ထဲမှာ geometric template matching ကို အောက်ပါ အတိုင်း ဖော်ပြထားပါတယ်။
Geometric matching က ကင်မရာ က ဖမ်းယူ ရရှိတဲ့ ပုံမှာ ကိုယ်ရှာ ဖို့ သတ်မှတ်ထားတဲ့ အရာ ဘယ်နားမှာ ရှိနေလဲ ဆိုတာ ရှာပေး ပေး ပါတယ်။ Geometric matching က ဘယ်လို ပုံသဏ္ဍာန် ဆိုတာ သတ်မှတ်ထားတဲ့ အချက်အလက် ပေါ် မူတည်ပြီး ပုံစံပြား ကို ရှာပါတယ်။
Geometric matching ကို သုံးဖို့ အတွက် ရှာလိုတဲ့ ပစ္စည်း ကို ကိုယ်စား ပြုတဲ့ ပုံစံပြား တစ်ခုကို ဖန်တီးရ ပါတယ်။ စက်ရဲ့ အမြင်အနေနဲ့ အသုံးချ တဲ့ အခါ ပုံရိပ် တစ်ခု ချင်းစီမှာ ပုံစံပြား နဲ့ ကိုက်ညီမှု ရှိ တဲ့ နေရာတွေမှာ ဘယ်လောက်ထိ ကိုက်ညီမှု ရှိလဲ ဆိုတာ အမှတ်တွေ ပေးပါတယ်။
Geometric matching က အလင်းအမှောင် ပြောင်းလဲခြင်း၊ ပုံဝါးနေခြင်း၊ ပုံရိပ် မကြည်လင်ခြင်း၊ တဝက်တပြက် ဖုံးကွယ်နေခြင်း၊ အနေအထား နဲ့ အရွယ်အစား မတူခြင်း တွေ ရှိနေရင် တောင် ရှာ လိုတဲ့ ပုံစံပြား ရှိတဲ့ နေရာတွေ ကို ရှာပေးနိုင်ပါတယ်။
LabVIEW ထဲက IMAQ Find CoordSys (Pattern) 2 အစရှိတဲ့ VI တွေက ပုံစံပြား ကို ရှာဖို့ သုံးနိုင်ပါတယ်။ ပုံစံပြား ကို အောက်မှာ ဖော်ပြထားတဲ့ အဆင့်တွေ အတိုင်း ဖန်တီး နိုင်ပါတယ်။
Template Editor ကို Start -> All Programs -> National Instruments -> Vision -> Template Editor မှာဖွင့်ပါ။
File menu->New Template... ကိုနှိပ်ပါ။
Geometric Matching Template (Edge Based) ကိုရွေးပြီး ဖန်တီးမယ့် ပုံစံပြား ပါတဲ့ ပုံရိပ် ကို သတ်မှတ်ပေးပါ။
Select Template Region ဆိုတဲ့ tab မှာ ပုံစံပြား ဖန်တီးမယ့် နေရာကို သတ်မှတ်ပါ။ ဥပမာ အားဖြင့် (200,300) ကနေ (232,332) ထိ mouse ကို ဖိဆွဲ ပြီး သတ်မှတ်နိုင်ပါတယ်။ ပြီးနောက် မှတ်ထားတဲ့ နေရာကို ကိုယ်လိုချင်တဲ့ နေရာ ရောက်အောင် ပြန်ရွေ့နိုင်ပါတယ်။
Define curves ဆိုတဲ့ tab မှာ ပုံစံပြား ရဲ့ အနားသတ် ပုံစံနဲ့ ပတ်သက် တဲ့ အချက်တွေ ကို သတ်မှတ်ပါ။ ဥပမာ အားဖြင့် Extraction mode ကို normal၊ Edge Threshold ကို 32၊ Edge Filter size ကို Fine၊ Minimum Length ကို 5၊ Row Search Step Size ကို 1 နဲ့ Column Search Step size ကို 1 အစရှိသဖြင့် သတ်မှတ် နိုင်ပါတယ်။ Customize Scoring နဲ့ Specify Match Options tab တွေကိုတော့ နဂို အတိုင်း ထားနိုင်ပါတယ်။
File -> Save Template... ကိုနှိပ်ပြီး ပုံစံပြား ကို သိမ်းပါ။
နမူနာ အနေနဲ့ ဖန်တီးထားတဲ့ VI တွေကို
Geometric Template Matching on GitHub
မှာ ကြည့်နိုင်ပါတယ်။ VI အဝင် တွေ အတွက် သတ်မှတ်ခြင်း တွေကို အောက်မှာ ပြထားပါတယ်။
Geometric Template Matching on GitHub
မှာ ကြည့်နိုင်ပါတယ်။ VI အဝင် တွေ အတွက် သတ်မှတ်ခြင်း တွေကို အောက်မှာ ပြထားပါတယ်။
Tuesday, May 3, 2011
Byte Stuffing
ပစ္စည်း တစ်ခု ကနေ တစ်ခု data bytes တွေကို ပို့ဖို့ နဲ့၊ လက်ခံဖို့ အတွက် program တွေကို မကြာခဏ ရေးရပါတယ်။ ဒါနဲ့ပဲ ရိုးရှင်းတဲ့ byte stuffing မူကွဲ တစ်ခု ကို ရွေးပြီး data bytes တွေကို frame ဆောက် ပြီး ပို့ဖို့ နဲ့၊ လက်ခံဖို့ အတွက် လုပ်ရပါတယ်။ ပထမဆုံး အနေနဲ့ Frame ရဲ့ အစ နဲ့ အဆုံးကို သတ်မှတ်ဖို့ အတွက် control characters တွေ အနေနဲ့ 0x02 နဲ့ 0x03 ကို start of text (STX) ရယ်၊ end of text (ETX) ရယ် လို့ ထားလိုက် ပါမယ်။ လက်ခံရရှိတဲ့ ဒေတာ မှာ အမှား ပါမပါ စစ်ဖို့ အတွက် data bytes တွေရဲ့ exclusive-or တန်ဖိုးကို ETX နောက်မှာ အဆုံးသတ် checksum အနေနဲ့ ထည့်လိုက်ပါမယ်။ ပိုကောင်းတဲ့ error detection အတွက်တော့
CRC Calculation in VB and C
မှာဖော်ပြထားသလို CRC ကို သုံးလို့ ရပါတယ်။
ဥပမာ data byte နှစ်လုံး
Byte Stuffing on GitHub
အောက်ကဟာက ပို့ဖို့ အတွက် frame ဆောက်တဲ့ C++ code ဖြစ်ပါတယ်။
CRC Calculation in VB and C
မှာဖော်ပြထားသလို CRC ကို သုံးလို့ ရပါတယ်။
ဥပမာ data byte နှစ်လုံး
0x30 0x31ကို ပို့ဖို့ ဆိုရင်၊ ပို့ရမယ့် frame က
0x02 0x30 0x31 0x03 0x01ဖြစ်ပါတယ်။ အစက 0x02 က STX အနေနဲ့ ထည့်ထားပြီး၊ data bytes တွေကို ပို့ပါမယ်။ ဘိတ်ရှေ့ က 0x03 က ETX အနေနဲ့ ထည့်ထားတာပါ။ data byte တွေရဲ့ exclusive-or (0x02^0x03) ဖြစ်တဲ့ 0x01 ကို checksum အနေနဲ့ နောက်ဆုံးက နေ ထည့်ထားတာပါ။ အကယ်၍ ပို့ရမယ့် ဒေတာမှာ control characters တွေ အနေနဲ့ သုံးထားတဲ့ 0x02 တို့၊ 0x03 တို့ ပါလာရင် ဘယ်လို လုပ်မလဲ လို့ မေးစရာရှိ ပါတယ်။ အဲဒီ အတွက် နောက်ထပ် control character 0x10 ကို Data Link Escape (DLE) အနေနဲ့ သတ်မှတ်ဖို့ လိုပါတယ်။ နောက်ထပ် ဥပမာ အနေနဲ့ data byte ငါးလုံး ဖြစ်တဲ့
0x30 0x02 0x65 0x10 0x03အတွက် frame တစ်ခု ဆောက်ကြည့် ပါမယ်။ ဒေတာထဲမှာ STX တို့၊ ETX တို့၊ DLE တို့ ကိုတွေ့တိုင်း control character မဟုတ်ကြောင်း သိအောင် ရှေ့မှာ DLE တစ်လုံးကို အပို ထည့်ပေး မှာပါ။ ဒါဆို ပို့ရမယ့် frame က
0x02 0x30 0x10 0x02 0x65 0x10 0x10 0x10 0x03 0x03 0x44ဖြစ်ပါတယ်။ C တို့၊ LabVIEW တို့ နဲ့ ပရိုဂရမ် တချို့ ရေးကြည့်ထားပါတယ်။ Example programs တွေကို အောက်က link မှာ တွေ့နိုင်ပါတယ်။
Byte Stuffing on GitHub
အောက်ကဟာက ပို့ဖို့ အတွက် frame ဆောက်တဲ့ C++ code ဖြစ်ပါတယ်။
// Byte stuffing- sending and receiving frames // Author: Yan Naing Aye #ifndef FRAME_H #define FRAME_H #include#define STX 0x02 #define ETX 0x03 #define DLE 0x10 #define TX_BUF_SIZE 128 #define RX_BUF_SIZE 128 enum RX_STATE { IGNORE,RECEIVING,ESCAPE,RXCRC1,RXCRC2 }; //----------------------------------------------------------------------------- class Frame { RX_STATE rState; protected: int TxN;//number of transmitting bytes int RxN;//number of receiving bytes char tb[TX_BUF_SIZE];//transmit buffer char rb[RX_BUF_SIZE];//receiving data public: Frame(); int setTxFrame(char* d,int n); unsigned int CRC16CCITT_Calculate(char* s,unsigned char len,unsigned int crc); int getTxN(); int getRxN(); int receiveRxFrame(char c);//get receiving frame from received char char* getTxBuf(); char* getRxBuf(); }; //----------------------------------------------------------------------------- Frame::Frame():TxN(0),RxN(0),rState(IGNORE){} //----------------------------------------------------------------------------- char* Frame::getTxBuf(){ return tb; } //----------------------------------------------------------------------------- char* Frame::getRxBuf(){ return rb; } //----------------------------------------------------------------------------- //Prepare transmitting frame int Frame::setTxFrame(char* d,int n) { unsigned int txcrc=0xFFFF;//initialize crc char c; int i=0,j=0; tb[i++]=STX;//start of frame for(j=0;j < n;j++) { c=d[j]; if((c==STX)||(c==ETX)||(c==DLE)) tb[i++]=(DLE); tb[i++]=c; } tb[i++]=(ETX);//end of frame txcrc=CRC16CCITT_Calculate(d,n,txcrc);//calculate crc tb[i++]=txcrc & 0xFF; tb[i++]=(txcrc >> 8) & 0xFF; TxN=i; return TxN; } //----------------------------------------------------------------------------- //Inputs //s : pointer to input char string //len: string len (maximum 255) //crc: initial CRC value //Output //Returns calculated CRC unsigned int Frame::CRC16CCITT_Calculate(char* s,unsigned char len,unsigned int crc) { //CRC Order: 16 //CCITT(recommendation) : F(x)= x16 + x12 + x5 + 1 //CRC Poly: 0x1021 //Operational initial value: 0xFFFF //Final xor value: 0 unsigned char i,j; for(i=0;i < len;i++,s++) { crc^=((unsigned int)(*s) & 0xFF) << 8; for(j=0;j<8;j++) { if(crc & 0x8000) crc=(crc << 1)^0x1021; else crc <<=1; } } return (crc & 0xFFFF);//truncate last 16 bit } //----------------------------------------------------------------------------- //get number of transmitting bytes int Frame::getTxN() { return TxN; } //----------------------------------------------------------------------------- //get number of transmitting bytes int Frame::getRxN() { return RxN; } //----------------------------------------------------------------------------- //process receiving char int Frame::receiveRxFrame(char c) { static char b; unsigned int crc; unsigned int rxcrc=0xFFFF;//initialize CRC switch(rState){ case IGNORE: if(c==STX) { rState=RECEIVING;RxN=0;} break; case RECEIVING: if(c==STX) { rState=RECEIVING;RxN=0;} else if(c==ETX){rState=RXCRC1;} else if(c==DLE){ rState=ESCAPE; } else { rb[RxN++]=c; } break; case ESCAPE: rb[RxN++]=c; rState=RECEIVING; break; case RXCRC1: b=c; rState=RXCRC2; break; case RXCRC2: rState=IGNORE; crc=( (int)c << 8 | ((int)b & 0xFF) ) & 0xFFFF;//get received crc rxcrc=CRC16CCITT_Calculate(rb,RxN,rxcrc);//calculate crc //printf("crc: %x rxcrc:%x \n",crc,rxcrc); if(rxcrc==crc){return RxN;}//if crc is correct else {RxN=0;}//discard the frame break; } return 0; } //----------------------------------------------------------------------------- //############################################################################# class Frame2:public Frame { char Dt[20];//transmitting data public: Frame2(); void printTxFrame(); void printRxFrame(); void printRxData(); void setTxData(float x,float y,float z,float b,float t); }; //----------------------------------------------------------------------------- Frame2::Frame2():Frame(),Dt(""){} //----------------------------------------------------------------------------- //Print out frame content void Frame2::printTxFrame() { printf("Tx frame buffer: "); for(int j=0;j < TxN;j++) printf("%02X ",(unsigned char)tb[j]); printf("\n"); } //----------------------------------------------------------------------------- //Print out frame content void Frame2::printRxFrame() { printf("Rx data buffer: "); for(int j=0;j < RxN;j++) printf("%02X ",(unsigned char)rb[j]); printf("\n"); } //----------------------------------------------------------------------------- //Set transmitting data void Frame2::setTxData(float x,float y,float z,float b,float t) { *(float*)(Dt)=x; *(float*)(Dt+4)=y; *(float*)(Dt+8)=z; *(float*)(Dt+12)=b; *(float*)(Dt+16)=t; Frame::setTxFrame(Dt,20); } //----------------------------------------------------------------------------- //Print out received data void Frame2::printRxData() { float x,y,z,b,t; x=*(float*)(Dt); y=*(float*)(Dt+4); z=*(float*)(Dt+8); b=*(float*)(Dt+12); t=*(float*)(Dt+16); printf("Rx data: %f %f %f %f %f \n",x,y,z,b,t); } //----------------------------------------------------------------------------- #endif // FRAME_H
Subscribe to:
Posts (Atom)





