PI control algorithm manually implemented in matlab - pid

I'm trying to implement a simple script performing a PI control for a cruise control application, but I'm founding some problems with the integral part. Here is my code:
function [] = PI_cruisecontrol()
clc; close all;
t0 = 0; tfinal = 50; dt = 0.001; % time parameters
r = 10; % reference of 10 m/s
m = 1000; % mass
b = 50; % friction coeff. (depends on v)
yp = zeros(tfinal/dt,1); t = yp; % initialize speed and time array
Ki = 40; % integrarl constant
Kp = 800; % proportional constant
int = 0; % itinialize int error
% CONTROL LOOP (Forward-Euler integrator is used to solve the ODE)
for i=t0+2:tfinal/dt
err = r-yp(i-1); % update error
int = int+err; % integral term
u = (Kp*err)+(Ki*int*dt); % action of control
yp(i) = yp(i-1)+((-b*yp(i)/m) + (u/m))*dt; % solve ode for speed
t(i) = t(i)+dt*i; % log the time
end
% Results
figure(1)
plot(t,yp)
title ('Step Response')
xlabel('Time (seconds)')
ylabel('Amplitud')
axis([0 20 0 12])
hold on
reference = ones(tfinal/dt,1)*10;
plot(t,reference,':')
end
And this is how it should be, using predefinided matlab functions:
function [] = PI_cruisecontrol2()
m = 1000;
b = 50;
r = 10;
s = tf('s');
P_cruise = 1/(m*s + b);
Kp = 800;
Ki = 40;
C = pid(Kp,Ki);
T = feedback(C*P_cruise,1);
t = 0:0.1:20;
step(r*T,t)
axis([0 20 0 12])
end
What am I doing wrong in my code?
Thanks!

I managed to fix the problem, working with float variables instead of arrays. Moreover, I added the derivative term (although for this first order problem was not necessary)
Here I left the code:
function [] = aFortran_PI()
clc; close all;
r = 10; % reference of 10 m/s
m = 1000; % mass
b = 50; % friction coeff. (depends on v)
yp = 0; % init response
Kp = 800; % proportional constant
Ki = 40; % proportional constant
Kd = 0; % derivative term is not necessary in this problem
previous_error = 0;
integral = 0;
dt = 0.001;
% CONTROL LOOP
for i=1:20000
error = r-yp; % update error
integral = integral + error*dt; % integral term
derivative = (error-previous_error)/dt; % derivative term
u = Kp*error+Ki*integral+Kd*derivative; % action of control
yp = yp+(-b*yp/m + u/m)*dt % solve ode for velocity
end
end

Related

compressed sparse row and Jacobi iterative method

I've tried implementing Jacobi method for compressed sparse row format. But i couldnt obtain the output correctly. Below is the coding i tried. I'm trying with a 4 by 4 sparse matrix which is a tridiagonal matrix stored in compressed form before implementing Jacobi iterative method. Please help.
clear all;
close all;
clc;
H=4;
a=2;
b=-1;
c=-1;
A = diag(a*ones(1,H)) + diag(b*ones(1,H-1),1) + diag(c*ones(1,H-1),-1);%Matrix A
n = size(A,1); % no of rows
m = size(A,2); % no of columns
V = [];
C = [];
R = [];
counter=1;
R= [counter];
for i=1:n
for j=1:m
if (A(i,j) ~= 0)
V = [V A(i,j)];
C = [C j];
counter=counter+1;
end
R(i+1)=counter;
end
end
b = [9,18,24,3];
x_new = [1 ; 1 ; 1 ; 1];
eps = 1e-5; % 1 x 10^(-10).
error = 1000; % use any large value greater than eps to make sure that the loop can work
counter2=1;
while (error > eps)
x_old = x_new;
for i=1:length(R)-1 %modified
t = 0;
for j=R(i):R(i+1)-1 %modified
if (C(j)~=i) %not equal
t = t + x_old(C(j))*A(i,C(j)); %modified
end
end
x_new(i,1) = (b(i) - t)/A(i,C(j)); % is a row vector
end
error = norm(x_new-x_old);
counter2=counter2+1;
end
x_new % print x
Expected output is
[28.1987 47.3978 48.5979 25.7986]
this is the coding i tried and the expected output is above. Thank you for your time and consideration.

how to create a simple iir low pass filter with not round errors? (16 bit pcm data)

i have an array of n length fullfilled by 16 bit (int16) pcm raw data,the data is in 44100 sample_rate
and stereo,so i have in my array first 2 bytes left channel then right channel etc...i tried to implement a simple low pass converting my array into floating points -1 1,the low pass works but there are round errors that cause little pops in the sound
now i do simply this :
INT32 left_id = 0;
INT32 right_id = 1;
DOUBLE filtered_l_db = 0.0;
DOUBLE filtered_r_db = 0.0;
DOUBLE last_filtered_left = 0;
DOUBLE last_filtered_right = 0;
DOUBLE l_db = 0.0;
DOUBLE r_db = 0.0;
DOUBLE low_filter = filter_freq(core->audio->low_pass_cut);
for(UINT32 a = 0; a < (buffer_size/2);++a)
{
l_db = ((DOUBLE)input_buffer[left_id]) / (DOUBLE)32768;
r_db = ((DOUBLE)input_buffer[right_id]) / (DOUBLE)32768;
///////////////LOW PASS
filtered_l_db = last_filtered_left +
(low_filter * (l_db -last_filtered_left ));
filtered_r_db = last_filtered_right +
(low_filter * (r_db - last_filtered_right));
last_filtered_left = filtered_l_db;
last_filtered_right = filtered_r_db;
INT16 l = (INT16)(filtered_l_db * (DOUBLE)32768);
INT16 r = (INT16)(filtered_r_db * (DOUBLE)32768);
output_buffer[left_id] = (output_buffer[left_id] + l);
output_buffer[right_id] = (output_buffer[right_id] + r);
left_id +=2;
right_id +=2;
}
PS: the input buffer is an int16 array with the pcm data from -32767 to 32767;
i found this function here
Low Pass filter in C
and was the only one that i could understand xd
DOUBLE filter_freq(DOUBLE cut_freq)
{
DOUBLE a = 1.0/(cut_freq * 2 * PI);
DOUBLE b = 1.0/SAMPLE_RATE;
return b/(a+b);
}
my aim is instead to have absolute precision on the wave,and to directly low pass using only integers
with the cost to lose resolution on the filter(and i'm ok with it)..i saw a lot of examples but i really didnt understand anything...someone of you would be so gentle to explain how this is done like you would explain to a little baby?(in code or pseudo code rapresentation) thank you
Assuming the result of function filter_freq can be written as a fraction m/n your filter calculation basically is
y_new = y_old + (m/n) * (x - y_old);
which can be transformed to
y_new = ((n * y_old) + m * (x - y_old)) / n;
The integer division / n truncates the result towards 0. If you want rounding instead of truncation you can implement it as
y_tmp = ((n * y_old) + m * (x - y_old));
if(y_tmp < 0) y_tmp -= (n / 2);
else y_tmp += (n / 2);
y_new = y_tmp / n
In order to avoid losing precision from dividing the result by n in one step and multiplying it by n in the next step you can save the value y_tmp before the division and use it in the next cycle.
y_tmp = (y_tmp + m * (x - y_old));
if(y_tmp < 0) y_new = y_tmp - (n / 2);
else y_new = y_tmp + (n / 2);
y_new /= n;
If your input data is int16_t I suggest to implement the calculation using int32_t to avoid overflows.
I tried to convert the filter in your code without checking other parts for possible problems.
INT32 left_id = 0;
INT32 right_id = 1;
int32_t filtered_l_out = 0; // output value after division
int32_t filtered_r_out = 0;
int32_t filtered_l_tmp = 0; // used to keep the output value before division
int32_t filtered_r_tmp = 0;
int32_t l_in = 0; // input value
int32_t r_in = 0;
DOUBLE low_filter = filter_freq(core->audio->low_pass_cut);
// define denominator and calculate numerator
// use power of 2 to allow bit-shift instead of division
const uint32_t filter_shift = 16U;
const int32_t filter_n = 1U << filter_shift;
int32_t filter_m = (int32_t)(low_filter * filter_n)
for(UINT32 a = 0; a < (buffer_size/2);++a)
{
l_in = input_buffer[left_id]);
r_in = input_buffer[right_id];
///////////////LOW PASS
filtered_l_tmp = filtered_l_tmp + filter_m * (l_in - filtered_l_out);
if(last_filtered_left < 0) {
filtered_l_out = last_filtered_left - filter_n/2;
} else {
filtered_l_out = last_filtered_left + filter_n/2;
}
//filtered_l_out /= filter_n;
filtered_l_out >>= filter_shift;
/* same calculation for right */
INT16 l = (INT16)(filtered_l_out);
INT16 r = (INT16)(filtered_r_out);
output_buffer[left_id] = (output_buffer[left_id] + l);
output_buffer[right_id] = (output_buffer[right_id] + r);
left_id +=2;
right_id +=2;
}
As your filter is initialized with 0 it may need several samples to follow a possible step to the first input value. Depending on your data it might be better to initialize the filter based on the first input value.

3D / 4D Matrix manipulation

I often struggle with slow Matlab processing due to high numbers of for loops.
Maybe you can help me with this example, which would help me in other cases as well: Is it possible to completely transfer it to matrices?
R = [1 2 3; 1 2 3; 1 2 3];
u1 = 200; u2 = 300; v1 = 100; v2 = 222; w1 = 123; w2 = 312;
px = 20; py = 30; pz = 25;
a = 20; b = 30; c = 25;
Ellipse = zeros(500,600,500)
for i=u1:u2
for j=v1:v2
for k=w1:w2
x=[i-px;j-py;k-pz];
x=R*x;
if (x(1)/a)^2+(x(2)/b)^2+(x(3)/c)^2<1
Ellipse(i,j,k)=1;
end
end
end
end
Here's one approach that runs about 2 orders of magnitude faster
R = [1 2 3; 1 2 3; 1 2 3];
u1 = 200; u2 = 300; v1 = 100; v2 = 222; w1 = 123; w2 = 312;
px = 20; py = 30; pz = 25;
a = 20; b = 30; c = 25;
Ellipse = zeros(500,600,500);
% Create mesh of points to process
vx = (u1:u2) - px;
vy = (v1:v2) - py;
vz = (w1:w2) - pz;
[X,Y,Z] = meshgrid(vx, vy, vz);
% Compute R*x
V = [X(:)'; Y(:)'; Z(:)'];
V = R * V;
% Divide by ellipse axes
M = diag([1/a, 1/b, 1/c]);
V = M * V;
% Determine if norm criteria is met
index = norm(V') < 1;
Ellipse(X(index), Y(index), Z(index)) = 1;
Agree with #Dan, a smaller working example would make it easier to test.
If you are doing more than simple mathematical operations matrices can be tricky.
Here you can (should) reduce the size of Ellipse because you are not using most of its entries.
All you need is (101,123,190) and things will be much faster, especially the way you are accessing the matrix entries, remember MATLAB will eventually store the matrix as just an array.
#dpmcmlxxvi Thank you very much for the answer. At first, sorry for the large example. I used your answer with some modification as norm(XY) did not work for me.(smaller example and valueas adapted to run properly)
R = [1 2 3; 1 2 3; 1 2 3];
u1 = 50; u2 = 90; v1 = 20; v2 = 50; w1 = 30; w2 = 60;
px = 60; py = 25; pz = 50;
a = 10; b = 20; c = 15;
Ellipse = zeros(100,200,100);
% Create mesh of points to process
vx = (u1:u2) - px;
vy = (v1:v2) - py;
vz = (w1:w2) - pz;
[X,Y,Z] = meshgrid(vx, vy, vz);
% Compute R*x
V = [X(:)'; Y(:)'; Z(:)'];
V = R * V;
% Divide by ellipse axes
M = diag([1/a, 1/b, 1/c]);
V = M * V;
% Apply criteria
Vsq = V.*V;
crit = Vsq(1,:)+Vsq(2,:)+Vsq(3,:);
% Look for indices in the meshgrid fullfilling criteria
xe = X(find(crit<1));
ye = Y(find(crit<1));
ze = Z(find(crit<1));
xi = ceil(abs(xe+px));
yi = ceil(abs(ye+py));
zi = ceil(abs(ze+pz));
% Set values at correpsonding indices to 1
linind = sub2ind(size(Ellipse),xi,yi,zi);
Ellipse(linind) = 1;
It works fine and all for loops have been removed.

FFT algorithm in MATLAB [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I'm looking to implement an FFT algorithm on microcontrollers so I want to simulate the codes before actually using it
I got 2 examples which I converted to matlab codes but the result just isn't what I'm expected
Here are the codes:
function [ H ] = fft_2( g )
%FFT2 Summary of this function goes here
% Detailed explanation goes here
NUMDATA = length(g);
NUMPOINTS = NUMDATA/2;
N = NUMPOINTS;
% for(k=0; k<N; k++)
% {
% IA[k].imag = -(short)(16383.0*(-cos(2*pi/(double)(2*N)*(double)k)));
% IA[k].real = (short)(16383.0*(1.0 - sin(2*pi/(double)(2*N)*(double)k)));
% IB[k].imag = -(short)(16383.0*(cos(2*pi/(double)(2*N)*(double)k)));
% IB[k].real = (short)(16383.0*(1.0 + sin(2*pi/(double)(2*N)*(double)k)));
% }
for k=0:(N-1)
IA(k+1,2) = -floor(16383.0*(-cos(2*pi/(2*N)*k)));
IA(k+1,1) = floor(16383.0*(1.0 - sin(2*pi/(2*N)*k)));
IB(k+1,2) = -floor(16383.0*(cos(2*pi/(2*N)*k)));
IB(k+1,1) = floor(16383.0*(1.0 + sin(2*pi/(2*N)*k)));
end
% Note, IA(k) is the complex conjugate of A(k) and IB(k) is the complex conjugate of
% B(k).
% *********************************************************************************/
% #include <math.h>
% #include ”params1.h”
% #include ”params.h”
% extern short g[];
% void dft(int, COMPLEX *);
% void split(int, COMPLEX *, COMPLEX *, COMPLEX *, COMPLEX *);
% main()
% {
% int n, k;
% COMPLEX x[NUMPOINTS+1]; /* array of complex DFT data */
% COMPLEX A[NUMPOINTS]; /* array of complex A coefficients */
% COMPLEX B[NUMPOINTS]; /* array of complex B coefficients */
% COMPLEX IA[NUMPOINTS]; /* array of complex A* coefficients */
% COMPLEX IB[NUMPOINTS]; /* array of complex B* coefficients */
% COMPLEX G[2*NUMPOINTS]; /* array of complex DFT result */
% for(k=0; k<NUMPOINTS; k++)
for k=0:(NUMPOINTS-1)
% {
% A[k].imag = (short)(16383.0*(-cos(2*pi/(double)(2*NUMPOINTS)*(double)k)));
% A[k].real = (short)(16383.0*(1.0 - sin(2*pi/(double)(2*NUMPOINTS)*(double)k)));
% B[k].imag = (short)(16383.0*(cos(2*pi/(double)(2*NUMPOINTS)*(double)k)));
% B[k].real = (short)(16383.0*(1.0 + sin(2*pi/(double)(2*NUMPOINTS)*(double)k)));
% IA[k].imag = -A[k].imag;
% IA[k].real = A[k].real;
% IB[k].imag = -B[k].imag;
% IB[k].real = B[k].real;
% }
A(k+1, 2) = floor(16383.0*(-cos(2*pi/(2*NUMPOINTS)*k)));
A(k+1, 1) = floor(16383.0*(1.0 - sin(2*pi/(2*NUMPOINTS)*k)));
B(k+1, 2) = floor(16383.0*(cos(2*pi/(2*NUMPOINTS)*k)));
B(k+1, 1) = floor(16383.0*(1.0 + sin(2*pi/(2*NUMPOINTS)*k)));
IA(k+1, 2) = -A(k+1, 2);
IA(k+1, 1) = A(k+1, 1);
IB(k+1, 2) = -B(k+1, 2);
IB(k+1, 1) = B(k+1, 1);
end
% /* Forward DFT */
% /* From the 2N point real sequence, g(n), for the N-point complex sequence, x(n) */
% for (n=0; n<NUMPOINTS; n++)
% {
for n=0:(NUMPOINTS-1)
% x[n].imag = g[2*n + 1]; /* x2(n) = g(2n + 1) */
% x[n].real = g[2*n]; /* x1(n) = g(2n) */
% }
x(n+1,2)=g(2*n + 1+1);
x(n+1,1)=g(2*n +1);
end
% /* Compute the DFT of x(n) to get X(k) -> X(k) = DFT{x(n)} */
% dft(NUMPOINTS, x);
% void dft(int N, COMPLEX *X)
% {
% int n, k;
% double arg;
% int Xr[1024];
% int Xi[1024];
% short Wr, Wi;
% for(k=0; k<N; k++)
% {
N=NUMPOINTS;
for k=0:(N-1)
% Xr[k] = 0;
% Xi[k] = 0;
Xr(k+1)=0;
Xi(k+1)=0;
% for(n=0; n<N; n++)
% {
for n=0:(N-1)
% arg =(2*PI*k*n)/N;
% Wr = (short)((double)32767.0 * cos(arg));
% Wi = (short)((double)32767.0 * sin(arg));
% Xr[k] = Xr[k] + X[n].real * Wr + X[n].imag * Wi;
% Xi[k] = Xi[k] + X[n].imag * Wr – X[n].real * Wi;
arg = (2*pi*k*n)/N;
Wr = floor(32767*cos(arg));
Wi = floor(32767*sin(arg));
Xr(k+1) = Xr(k+1)+x(n+1,1)*Wr+x(n+1,2)*Wi;
Xi(k+1) = Xr(k+1)+x(n+1,2)*Wr-x(n+1,1)*Wi;
% }
% }
end
end
% for (k=0;k<N;k++)
% {
for k=0:(N-1)
% X[k].real = (short)(Xr[k]>>15);
% X[k].imag = (short)(Xi[k]>>15);
x(k+1,1)=floor(Xr(k+1)/pow2(15));
x(k+1,2)=floor(Xi(k+1)/pow2(15));
% }
% }
end
% /* Because of the periodicity property of the DFT, we know that X(N+k)=X(k). */
% x[NUMPOINTS].real = x[0].real;
% x[NUMPOINTS].imag = x[0].imag;
x(NUMPOINTS+1,1)=x(1,1);
x(NUMPOINTS+1,2)=x(1,2);
% /* The split function performs the additional computations required to get
% G(k) from X(k). */
% split(NUMPOINTS, x, A, B, G);
% void split(int N, COMPLEX *X, COMPLEX *A, COMPLEX *B, COMPLEX *G)
% {
% int k;
% int Tr, Ti;
% for (k=0; k<N; k++)
% {
for k=0:(NUMPOINTS-1)
% Tr = (int)X[k].real * (int)A[k].real – (int)X[k].imag * (int)A[k].imag +
% (int)X[N–k].real * (int)B[k].real + (int)X[N–k].imag * (int)B[k].imag;
Tr = x(k+1,1)*A(k+1,1)-x(k+1,2)*A(k+1,2)+x(NUMPOINTS-k+1,1)*B(k+1,1)+x(NUMPOINTS-k+1,2)*B(k+1,2);
% G[k].real = (short)(Tr>>15);
G(k+1,1)=floor(Tr/pow2(15));
% Ti = (int)X[k].imag * (int)A[k].real + (int)X[k].real * (int)A[k].imag +
% (int)X[N–k].real * (int)B[k].imag – (int)X[N–k].imag * (int)B[k].real;
Ti = x(k+1,2)*A(k+1,1)+x(k+1,1)*A(k+1,2)+x(NUMPOINTS-k+1,1)*B(k+1,2)-x(NUMPOINTS-k+1,2)*B(k+1,1);
% G[k].imag = (short)(Ti>>15);
G(k+1,2)=floor(Ti/pow2(15));
% }
end
% }
% /* Use complex conjugate symmetry properties to get the rest of G(k) */
% G[NUMPOINTS].real = x[0].real - x[0].imag;
% G[NUMPOINTS].imag = 0;
% for (k=1; k<NUMPOINTS; k++)
% {
% G[2*NUMPOINTS-k].real = G[k].real;
% G[2*NUMPOINTS-k].imag = -G[k].imag;
% }
G(NUMPOINTS+1,1) = x(1,1) - x(1,2);
G(NUMPOINTS+1,2) = 0;
for k=1:(NUMPOINTS-1)
G(2*NUMPOINTS-k+1,1) = G(k+1,1);
G(2*NUMPOINTS-k+1,2) = -G(k+1,2);
end
for k=1:(NUMDATA)
H(k)=sqrt(G(k,1)*G(k,1)+G(k,2)*G(k,2));
end
end
Another one:
function [ fr, fi ] = fix_fft( fr, fi )
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
N_WAVE = 1024; % full length of Sinewave[]
LOG2_N_WAVE = 10; % log2(N_WAVE)
m = nextpow2(length(fr));
% void fix_fft(short fr[], short fi[], short m)
% {
% long int mr = 0, nn, i, j, l, k, istep, n, shift;
mr=0;
% short qr, qi, tr, ti, wr, wi;
%
% n = 1 << m;
n = pow2(m);
% nn = n - 1;
nn = n-1;
%
% /* max FFT size = N_WAVE */
% //if (n > N_WAVE) return -1;
%
% /* decimation in time - re-order data */
% for (m=1; m<=nn; ++m)
for m=1:nn
% {
% l = n;
l=n;
% do
% {
% l >>= 1;
% } while (mr+l > nn);
not_done = true;
while(mr+l>nn || not_done)
l=floor(l/2);
not_done=false;
end
%
% mr = (mr & (l-1)) + l;
mr = (mr & (l-1)) + l;
% if (mr <= m) continue;
if (mr <= m)
continue
end
%
% tr = fr[m];
% fr[m] = fr[mr];
% fr[mr] = tr;
% ti = fi[m];
% fi[m] = fi[mr];
% fi[mr] = ti;
tr = fr(m+1);
fr(m+1) = fr(mr+1);
fr(mr+1) = tr;
ti = fi(m+1);
fi(m+1) = fi(mr+1);
fi(mr+1) = ti;
% }
end
%
% l = 1;
% k = LOG2_N_WAVE-1;
l=1;
k = LOG2_N_WAVE-1;
%
% while (l < n)
% {
while (l < n)
% /*
% fixed scaling, for proper normalization --
% there will be log2(n) passes, so this results
% in an overall factor of 1/n, distributed to
% maximize arithmetic accuracy.
%
% It may not be obvious, but the shift will be
% performed on each data point exactly once,
% during this pass.
% */
%
% // Variables for multiplication code
% long int c;
% short b;
%
% istep = l << 1;
istep = l*2;
% for (m=0; m<l; ++m)
% {
for m=0:(l-1)
% j = m << k;
% /* 0 <= j < N_WAVE/2 */
% wr = Sinewave[j+N_WAVE/4];
% wi = -Sinewave[j];
j = m*(pow2( k));
wr = sin((j+N_WAVE/4)*2*pi/N_WAVE)*32768;
wi = -sin(j*2*pi/1024)*32768;
%
% wr >>= 1;
% wi >>= 1;
wr = floor(wr/2);
wi = floor(wi/2);
%
% for (i=m; i<n; i+=istep)
% {
i=m;
while(i<n)
% j = i + l;
j = i+l;
%
% // Here I unrolled the multiplications to prevent overhead
% // for procedural calls (we don't need to be clever about
% // the actual multiplications since the pic has an onboard
% // 8x8 multiplier in the ALU):
%
% // tr = FIX_MPY(wr,fr[j]) - FIX_MPY(wi,fi[j]);
% c = ((long int)wr * (long int)fr[j]);
% c = c >> 14;
% b = c & 0x01;
% tr = (c >> 1) + b;
c = wr * fr(j+1);
c = floor(c / pow2(14));
b = c & 1;
tr = floor(c /2) + b;
%
% c = ((long int)wi * (long int)fi[j]);
% c = c >> 14;
% b = c & 0x01;
% tr = tr - ((c >> 1) + b);
c = wi * fi(j+1);
c = floor(c / pow2(14));
b = c & 1;
tr = tr - (floor((c/2)) + b);
%
% // ti = FIX_MPY(wr,fi[j]) + FIX_MPY(wi,fr[j]);
% c = ((long int)wr * (long int)fi[j]);
% c = c >> 14;
% b = c & 0x01;
% ti = (c >> 1) + b;
c = wr*fi(j+1);
c = floor(c / pow2(14));
b = c & 1;
ti = floor((c /2)) + b;
%
% c = ((long int)wi * (long int)fr[j]);
% c = c >> 14;
% b = c & 0x01;
% ti = ti + ((c >> 1) + b);
c = wi * fr(j+1);
c = floor(c / pow2(14));
b = c & 1;
ti = ti + (floor((c/2)) + b);
%
% qr = fr[i];
% qi = fi[i];
% qr >>= 1;
% qi >>= 1;
%
% fr[j] = qr - tr;
% fi[j] = qi - ti;
% fr[i] = qr + tr;
% fi[i] = qi + ti;
qr = fr(i+1);
qi = fi(i+1);
qr = floor(qr/2);
qi = floor(qi/2);
fr(j+1) = qr - tr;
fi(j+1) = qi - ti;
fr(i+1) = qr + tr;
fi(i+1) = qi + ti;
% }
i = i+istep;
end
% }
end
%
% --k;
% l = istep;
% }
k=k-1;
l=istep;
end
% }
end
Those in comments are the original, those aren't are the translated code
Then I simulated with this
function [ r ] = mfft( f )
%MFFT Summary of this function goes here
% Detailed explanation goes here
Fs = 2048;
T = 1/Fs;
L = 2048;
t = (0:L-1)*T;
NFFT = 2^nextpow2(L);
l = length(f);
y = 0;
for k=1:l
y = y + sin(2*pi*f(k)*t);
end
%sound(y, Fs);
Y = fft(y,NFFT)/L;
YY = fft_2(y)/L;
[Y1 Y2] = fix_fft(y, zeros(1, L));
YYY = Y1+j()*Y2;
f = Fs/2*linspace(0,1,NFFT/2+1);
plot(f, 2*abs(Y(1:NFFT/2+1)), ':+b');
hold on
plot(f, 2*abs(YY(1:NFFT/2+1)), '-or');
plot(f, abs(YYY(1:NFFT/2+1)), '--*g');
hold off
r=0;
end
Basically create a simple sine wave with a specific frequency (say 400Hz)
The expected output of the FFT should be a spike at 400 only, which the builtin FFT function agrees but the other codes didn't
Here's the output graph
The blue line is from builtin function and is what expected
The red line is the above code which, well, looks pretty good except there is a spike elsewhere with higher amplitude
The green line is absolute mess
I tried checking the program several times but to no avail
Did I ported them wrong or somehow I can fix them?
There are several ways to approach this problem, and a programmer should try all of them. First, an FFT is an optimization of a Fourier Transform, so as a first step code a Fourier Transform. That is, don't do an FFT, just do a FT directly.
These days an FT is not as slow as you might think. Unless the project needs to transform something like 10,000 data points in less than a few milliseconds. Also, an FT, compared to an FFT, is simple and easy to debug.
Doing this for a problem provides a baseline, that is, the correct answer. This is important because when you work on the FFT how do you know if the problem is in the code for the FFT or that the data is correct and just giving you an unexpected, but correct, answer.
Next, use a pre-written package to do an FFT. Scan the web, I know there are packages written in C that do FFTs.
Third, if you just have to write your own FFT then do so. But only if tasks (1) or (2) don't meet your requirements. It will be difficult to out-do any pre-written FFT packages.
You will learn much along this path.

value of natural logarithm

I want to find value of In(x) without using math.h function
I am following this formula which I found in my math book:
log(m) base e = 2[ (m-1/m+1) + (1/3) * (m-1/m+1)^3 + (1/5) * (m-1/m+1)^5 + ... ]
Here is my code:
i = 3;
logx = 0 ;
ty = (x-1)/(x+1) ;
do
{
logx = logx + ty ;
tty = ty ;
ty = (ty * ((x-1)/(x+1)) * ((x-1)/(x+1))) / i ;
i = i + 2 ;
} while(tty - ty > 0.0000005 );
logx = 2*logx ;
printf("\n ln (%g) = %g \n", x, logx);
but this shows ln(2) = 0.691916 instead of 0.693147 and ln(3) = 1.08765 instead of 1.098612 etc. What is wrong?
You should not divide by i and then assign to ty, devide by i after the addition, i.e. logx = logx + ty / i.
Edit this should work:
i=1; // (i.e. not 3)
logx = 0 ;
ty = (x-1)/(x+1) ;
do
{
logx = logx + ty / i;
tty = ty ;
ty = (ty * ((x-1)/(x+1)) * ((x-1)/(x+1)));
i = i + 2 ;
} while(tty - ty > 0.0000005 );
Actually what OP's computing is
$2\sum_{n=1,n\text{ odd}}^\infty\frac1{n!!}\left(\frac{m-1}{m+1}\right)^n = \sqrt{2\pi} \exp\left(\frac12\left(\frac{m-1}{m+1}\right)^2\right)\operatorname{erf}\left(\frac1{\sqrt2}\frac{m-1}{m+1}\right)$ http://mathcache.appspot.com/?tex=%5cpng%5c%5b2%5Csum_%7Bn%3D1%2Cn%5Ctext%7B%20odd%7D%7D%5E%5Cinfty%5Cfrac1%7Bn%21%21%7D%5Cleft%28%5Cfrac%7Bm-1%7D%7Bm%2b1%7D%5Cright%29%5En%20%3D%20%5Csqrt%7B2%5Cpi%7D%20%5Cexp%5Cleft%28%5Cfrac12%5Cleft%28%5Cfrac%7Bm-1%7D%7Bm%2b1%7D%5Cright%29%5E2%5Cright%29%5Coperatorname%7Berf%7D%5Cleft%28%5Cfrac1%7B%5Csqrt2%7D%5Cfrac%7Bm-1%7D%7Bm%2b1%7D%5Cright%29%5c%5d
instead of
$2\sum_{n=1,n\text{ odd}}^\infty\frac1{n}\left(\frac{m-1}{m+1}\right)^n = 2\tanh^{-1}\frac{m-1}{m+1} = \ln m$ http://mathcache.appspot.com/?tex=%5cpng%5c%5b2%5Csum_%7Bn%3D1%2Cn%5Ctext%7B%20odd%7D%7D%5E%5Cinfty%5Cfrac1%7Bn%7D%5Cleft%28%5Cfrac%7Bm-1%7D%7Bm%2b1%7D%5Cright%29%5En%20%3D%202%5Ctanh%5E%7B-1%7D%5Cfrac%7Bm-1%7D%7Bm%2b1%7D%20%3D%20%5Cln%20m%5c%5d
BTW, it's better to factor out the ((x-1)/(x+1)) * ((x-1)/(x+1)) to avoid recomputing it. (The compiler may or may not treat this as a loop invariant and take it out.)
double ty = (x-1)/(x+1);
double p = ty * ty;
int i = 1;
double logx = 0;
do {
logx += ty / i;
tty = ty;
ty *= p;
i += 2;
} while (tty/(i-2) - ty/i > 5e-6);
Your C implementation is not correct for the algorithm.
log(m) base e = 2[ (m-1/m+1) + (1/3) * (m-1/m+1)^3 + (1/5) * (m-1/m+1)^5 + ... ]
^^^ what is this ^^^ and this
Your algorithm:
i = 3;
logx = 0 ;
ty = (x-1)/(x+1) ;
do
{
logx = logx + ty ;
tty = ty ;
ty = (ty * ((x-1)/(x+1)) * ((x-1)/(x+1))) / i ;
// ^^ when i = 3 ty after this line = ((x-1)/(x+1) * ((x-1)/(x+1))^2) / 3
// when i = 5 ty after this line = ((((x-1)/(x+1)^3) / 3) * ((x-1)/(x+1))^2) / 5
// = ((x-1)/(x+1)^5) / 15 <<< wrong divisor (see above, should be 5)
// and it gets worse for each iteration of the loop
i = i + 2 ;
} while(tty - ty > 0.0000005 );
logx = 2*logx ;
printf("\n ln (%g) = %g \n", x, logx);
you're approximating a function with a finite number of iterations (the stop condition is tty-ty > ...); decrease the 0.00000005 and you should obtain better precision
then you might run into numerical precision problems, so try using double instead of float if you're not already doing so
finally remember that generally logarithms are irrational numbers so they just can't be represented with a finite number of digits
ISTR that the rate of convergence of log series are notoriously slow.

Resources