We have several 3-axis accelerometers attached to a rigid body at arbitrary positions.
The rigid body is moving at arbitrary linear and angular movements, but the accelerometers can only sense linear accelerations.
Consequently, the information about angular movements of the rigid body is not available.
A question is whether it is possible to integrate them to get an equivalent accelerometer without using angular movement information.
After consideration, I think the answer for that question is 'YES'.
Showing posts with label Signal Processing. Show all posts
Showing posts with label Signal Processing. Show all posts
Tuesday, February 21, 2017
Sunday, April 17, 2016
Adaptive Filter: BMFLC
In this article, I will discuss about adaptive noise canceling techniques such as
FLC estimates the quasiperiodic signal of known frequency by using least mean square (LMS) algorithm to adapt the amplitude and phase of a reference signal. WFLC is an extension of FLC which can adapt to a periodic signal of unknown frequency and amplitude. Consequently, WFLC also adapts to time-varying reference signal frequencies while FLC can only estimate a signal with fixed and known frequency. To eliminate the time lag which is not desirable in real-time application, a method using combination of WFLC-FLC has been proposed. One limitation of WFLC is its inability to extract a periodic or quasi-periodic signal containing more than one dominant frequency. To overcome that, BMFLC approach tracks a predetermined band of multiple dominant frequencies based on the prior knowledge of the desired signal. The adaption process is achieved using LMS optimization similar to WFLC and FLC. As the frequency components in BMFLC are constant, analytical ouble integration can be employed to obtain the displacement from acceleration. Due to this reason, it becomes an ideal choice for applications where data is sensed with accelerometers.
- Fourier Linear Combiner (FLC)
- Weighted-frequency Fourier Linear Combiner (WFLC)
- Bandlimited Multiple Fourier Linear Combiner (BMFLC)
FLC estimates the quasiperiodic signal of known frequency by using least mean square (LMS) algorithm to adapt the amplitude and phase of a reference signal. WFLC is an extension of FLC which can adapt to a periodic signal of unknown frequency and amplitude. Consequently, WFLC also adapts to time-varying reference signal frequencies while FLC can only estimate a signal with fixed and known frequency. To eliminate the time lag which is not desirable in real-time application, a method using combination of WFLC-FLC has been proposed. One limitation of WFLC is its inability to extract a periodic or quasi-periodic signal containing more than one dominant frequency. To overcome that, BMFLC approach tracks a predetermined band of multiple dominant frequencies based on the prior knowledge of the desired signal. The adaption process is achieved using LMS optimization similar to WFLC and FLC. As the frequency components in BMFLC are constant, analytical ouble integration can be employed to obtain the displacement from acceleration. Due to this reason, it becomes an ideal choice for applications where data is sensed with accelerometers.
Setup
Arduino zero pro is used for the experiment. The code are written in C so that it can be ported to other platforms easily. Firstly, a reference signal is generated which is superimposed with noise. The generated signal is filtered with adaptive filter. The filtered output is compared with the reference signal by plotting them on serial plotter. The latest version Arduino IDE has not only Serial Monitor but it also has Serial Plotter. Therefore, it is easy and convenient to plot and see them serial plotter how an adaptive filter adapts to its input signal.Monday, November 16, 2015
Fitting a curve to a function
An example MatLab code to fit a curve to a piecewise linear function with the fixed end points.
LineSeg.m
%Fitting a curve to a piecewise linear function using least square method
%with the fixed start and end points
%clear command windows
clc;
%clear workspace
clear all;
%--------------------------------------------------------------------------
%Read curves
load Curve.dat;
%find lower left and upper right corners
xD=Curve(1,:);
yD=Curve(2,:);
x0=min(xD); x1=max(xD);
y0=min(yD); y1=max(yD);
n=5;%order n i.e, the number of segments
FS=x1-x0;
global xs;
global yB;
global yE;
xs=(0:FS/n:FS);
yB=y0;
yE=y1;
%initialize coefficients (y values) to find
%excluding the first and the last one
ys_initial=xs(2:n);
% options = optimset('MaxFunEvals',1000,'MaxIter',1000);
% LowerBoundC=y0;
% UpperBoundC=y1;
% ys =lsqcurvefit(@LineSeg,ys_initial,xD,yD,LowerBoundC,UpperBoundC,options);
ys =lsqcurvefit(@LineSeg,ys_initial,xD,yD);
%fixed start and end points
ys=[y0 ys y1];
%--------------------------------------------------------------------------
%Plot
hFig1 = figure(1);
set(hFig1, 'Position', [600 100 500 300])
plot(xD,yD,':g','LineWidth',3,...
'MarkerEdgeColor','b',...
'MarkerFaceColor','b',...
'MarkerSize',2)
hold on;
plot(xs,ys,'-rs','LineWidth',1,...
'MarkerEdgeColor','r',...
'MarkerFaceColor','r',...
'MarkerSize',4)
hold off;
grid on;
%--------------------------------------------------------------------------
LineSeg.m
function [y] = LineSeg(ys,x)
global xs
global yB
global yE
L=length(x);
y=zeros(1,L);
ys=[yB ys yE];
LS=length(ys);
for i=1:L
xt=x(i);
%--------------------------
%find segment
for j=2:LS
if(xs(j)>=xt)
break;
end
end
%interpolate
x2=xs(j);
y2=ys(j);
y1=ys(j-1);
x1=xs(j-1);
y(i)=y1+(y2-y1)/(x2-x1)*(xt-x1);
%--------------------------
end
Saturday, September 19, 2015
Controlling Your Hardware from the Web Using Arduino
Using Arduino Ethernet shield 2 to control a hardware from the web is discussed.
Arduino Ethernet 2 Library is used to implement in an Arduino Uno board as a server in an example as well as a client in an another example.
The latest version Arduino IDE ( 1.7.6 in our case ) is used in the following examples. An Arduino Uno board with Ethernet shield 2 is shown below.
Labels:
Arduino,
Circuit,
Code,
Electronics,
Embedded System,
Ethernet,
firmware,
Interface,
internet,
MCU,
Mechatronics,
Microcontroller,
Robotics,
Sensor,
Signal Processing,
Web
Thursday, September 10, 2015
Accelerometer LIS3DSH
LIS3DSH is an 3-axis MEMS accelerometer made by STMicroelectronics. Its full scale range is selectable from ±2g to ±16g. The size is small and it is only 3mm x 3mm. Either SPI or I2C can be used to interface with it. Supply voltage is from 1.71 V to 3.6 V. In this article, testing and evaluation of STEVAL-MKI134V1 adapter board is discussed.
Labels:
8051,
Accelerometer,
Arduino,
ARM,
AT89C51CC03,
Circuit,
Code,
Electronics,
Embedded System,
firmware,
I2C,
Interface,
LPC54102,
MCU,
Mechatronics,
Microcontroller,
Robotics,
Sensor,
Signal Processing,
SPI
Monday, January 21, 2013
Amplitude spectrum of a signal using Fourier transform
I have developed a MATLAB function to calculate amplitude spectrum of a signal using Fourier transform. Example usage of the function and implementation is shown below. Another example MATLAB program using built in function fft is also demonstrated. I hope they will be helpful for those who want to find amplitude spectrum or power spectrum of a signal.
%Example MATLAB code to test function FX Fs=100; t=(0:1/Fs:1-1/Fs)'; x=2*cos(2*pi*5*t)+sin(2*pi*10*t); [f a]=FX(x,Fs); plot(f,a);
function [f a]=FX(x,fs)
%Calculates amplitude spectrum of a signal x using Fourier transform
%[f a]=FX(x,fs)
%Input: x=signal, fs = sampling rate
%Output: f = frequency axis, a = amplitude spectrum
%File name: FX.m
%Author: Yan Naing Aye
%Website: http://cool-emerald.blogspot.sg/
dT = 1/fs;
N=length(x);
dF=1/(N*dT);
NF=fs/2;%Nyquist Freq
%You can always limit freq range for faster performance
%NF=20;
t=(0:dT:(N-1)*dT)';
f=(0:dF:NF)';
a=f;%initialize a
a(1)=mean(x);
for i=2 : length(a)
b=(2*mean(x.*cos(2*pi*dF*(i-1)*t)));
c=(2*mean(x.*sin(2*pi*dF*(i-1)*t)));
a(i)=sqrt(b^2+c^2);
end
%MATLAB program to calculates amplitude spectrum of a signal x using fft %Author: Yan Naing Aye %Website: http://cool-emerald.blogspot.sg/ Fs=100; t=(0:1/Fs:1-1/Fs)'; x=2*cos(2*pi*5*t)+sin(2*pi*10*t); L=length(x); A=2*abs(fft(x)/L); A=A(1:Fs/2+1); f = Fs/2*linspace(0,1,Fs/2+1); plot(f,A);
Sunday, January 13, 2013
Changing sampling rate using quadratic regression
I want to change sampling rate of a signal from 333Hz to 5000Hz. To get a smoother result, I have implemented second order hold system instead of popular zero order hold (ZOH) system. This approach can also be used for down sampling. Another possible application is to filter out noise without introducing phase delay. And it can be useful for real-time application.
Approach 1: Quadratic regression
Quadratic function is defined as
$$f=w_0+w_1 x + w_2 x^2$$
Then, cost function to be minimized is defined as
$$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 can be found by differentiating the cost function and setting them to zero.
$$\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$$
Similarly, differentiating with w1 and w2 gives,
$$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$$
When these three equations are written in matrix form.
$$ \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
In our case, we can use only the last three points and we can get three equations from these three points.
$$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
If we define x1=-1, x2=0, and x3=1, y2 is equal to w0. And,
$$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} $$
Then, we have
$$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)$$
I have tested the above three approaches using MatLab and it is shown below.
Approach 1: Quadratic regression
Quadratic function is defined as
$$f=w_0+w_1 x + w_2 x^2$$
Then, cost function to be minimized is defined as
$$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 can be found by differentiating the cost function and setting them to zero.
$$\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$$
Similarly, differentiating with w1 and w2 gives,
$$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$$
When these three equations are written in matrix form.
$$ \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
In our case, we can use only the last three points and we can get three equations from these three points.
$$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
If we define x1=-1, x2=0, and x3=1, y2 is equal to w0. And,
$$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} $$
Then, we have
$$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)$$
I have tested the above three approaches using MatLab and it is shown below.
%------------------------------------------------------------------------- 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]' %-------------------------------------------------------------------------The following figure shows the result of using this method (blue color plot) compare to ordinary zero order hold (black color plot). This method gives much more smoother result but it should be noted that it introduces one sample delay. The implementation of this method in LabVIEW using C code is shown in the following figure. The first two approaches involve finding inverse of a 3x3 matrix and I have developed a C program as shown below.
#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, June 3, 2011
Curve Fitting in Matlab
One of my friends was doing analysis of some sampled data. He wanted to fit them into a curve to derive the equation. He said Excel could fit up to polynomial of order 6 and he wanted a higher order one. So, he asked my help to write a Matlab program. He also wanted the plotted curve besides the calculated coefficients. The program and sample data are shown below. That is good for me because I also need to fit data occasionally and I can reuse it later :)
See d.txt and cf.m.
See d.txt and cf.m.
%--------------------------------------
%Curve fitting
%2011-Jun-03
%Programmer: Yan Naing Aye
%--------------------------------------
clc;
close all;
clear all;
%--------------------------------------
%get data from file that can be edited
load('d.txt');
X=d(:,1);
Y=d(:,2);
%--------------------------------------
%define order
N=2;
%--------------------------------------
%curve fitting
p=polyfit(X,Y,N);
%generate curve fitted data
[nr nc]=size(X);
YA=zeros(nr,1);
for i=0:N
YA=YA+p(i+1)*X.^(N-i);
end
%--------------------------------------
%Plot Y vs X
figure;
plot(X,Y,' rd','LineWidth',2,...
'MarkerEdgeColor','k',...
'MarkerFaceColor','g',...
'MarkerSize',6)
hold on;
plot(X,YA,'b','LineWidth',2,...
'MarkerEdgeColor','k',...
'MarkerFaceColor','g',...
'MarkerSize',6)
hold off;
grid on;
Title('Y vs X')
xlabel('X');
ylabel('Y');
legend('Sampled data','Fitted curve',...
'Location','NW')
%--------------------------------------
Tuesday, May 3, 2011
Byte Stuffing
I occasionally need to write programs to send and receive data bytes from one device to another. That is why I arbitrarily choose a simple variant of byte stuffing methods to build frames to send and receive data. To delimit the frame, control characters - 0x02 and 0x03- are defined as start of text (STX) and end of text (ETX) respectively. For error detection, exclusive-or of data bytes is appended after the ETX as a checksum. If you need better error detection, CRC as described at
CRC Calculation in VB and C
can also be used.
For example, if we want to send two bytes of data -
Byte Stuffing on GitHub
The following is the C++ code to build, send and receive a frame.
CRC Calculation in VB and C
can also be used.
For example, if we want to send two bytes of data -
0x30 0x31,the resulting frame will be
0x02 0x30 0x31 0x03 0x01,where 0x02 at the start is added as STX, followed by data bytes and the byte before the last one, 0x03, is added as ETX. Since the exclusive-or of data bytes, 0x02^0x03, is 0x01, it is appended at the end as checksum. How can we send data that contains 0x02 or 0x03 which were already used as control characters? We need to define another control character 0x10 as Data Link Escape (DLE) to mark data that are not control characters. As an another example, let us build a frame for five data bytes -
0x30 0x02 0x65 0x10 0x03.We will do byte stuffing by putting DLE in front of every data byte that conflicts with STX, ETX, or DLE. And
0x02 0x30 0x10 0x02 0x65 0x10 0x10 0x10 0x03 0x03 0x44will be the resulting frame. I have developed a few programs in C and LabVIEW. Example programs can be downloaded at the following links.
Byte Stuffing on GitHub
The following is the C++ code to build, send and receive a frame.
// 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
Friday, September 25, 2009
CRC Calculation in VB and C
Just to share a few software modules that were written in Visual Basic 2005 and C for the calculation of CRC -Cyclic Redundancy Check.
CRC Calculation - GitHub
An example usage for calculation of CRC16 CCITT is shown below.
Initial value for CRC16 CCITT is 0xFFFF. The following example calculate CRC for Str1 and use that CRC value as initial value to calculate Str2.
CRC Calculation - GitHub
An example usage for calculation of CRC16 CCITT is shown below.
Online checksum calculator such as the following one may be useful to debug the code.
Online Checksum Calculator
CRC Calculation in VB2005
The followings are the source code for various CRC calculations in VB2005. To make the calculation faster, they use CRC tables.CRC Calculation - GitHub
An example usage for calculation of CRC16 CCITT is shown below.
Dim StrIn as String= "String to calculate CRC" Dim CRCVal16 As UInt16 = 0 Dim crc As String CRCVal16 = CRC16_CCITT.Calculate(StrIn) crc = CRC16_CCITT.ToString(CRCVal16)
Initial value for CRC16 CCITT is 0xFFFF. The following example calculate CRC for Str1 and use that CRC value as initial value to calculate Str2.
CRCVal16 = CRC16_CCITT.Calculate(Str1) CRCVal16 = CRC16_CCITT.Calculate(Str2, CRCVal16) crc = CRC16_CCITT.ToString(CRCVal16)
CRC Calculation in C
The followings are the source code for various CRC calculations in C. To save storage, they do not use CRC tables .CRC Calculation - GitHub
An example usage for calculation of CRC16 CCITT is shown below.
#define STRLEN 4
char str[STRLEN]={0x01,0x01,0x00,0x0B};
unsigned char c[2];
unsigned int crc;
//Calculate CRC16 CCITT
crc=CRC16CCITT_InitialValue();
crc=CRC16CCITT_Calculate(str,STRLEN,crc);
CRC16CCITT_ToString(crc,c);
printf("CRC16 CCITT = %02X %02X \n",c[0],c[1]);
Online checksum calculator such as the following one may be useful to debug the code.
Online Checksum Calculator
Subscribe to:
Posts (Atom)




