What factors determine efficiency of a lookup table? - c

I've been working on a synthesizer project for the past few weeks, implementing a set of C based numerically controlled oscillators that feed their output to a DAC on an FPGA.
One thing that I tried was to use a lookup table to more efficiently determine the sine values of a given tone. For example, consider the following code:
PhaseArray[NOTE1-1][idx] = ((PhaseArray[NOTE1-1][!idx] + SigmaArray[NOTE1-1]) % (MODULO_CONST) );
....
PhaseDivArray[NOTE1-1][idx] = PhaseArray[NOTE1-1][idx] >> 10;
....
audio = ((iNoteOn[NOTE1-1]) * (SINE_TABLE[PhaseDivArray[NOTE1-1][idx]])) +
....
Now this is the thing that confuses me. I have a fair number of phase accumulators running at the same time without issue. I can get more than a dozen notes to play correctly when I don't bother with the sine lookup and just use an effective square wave signal.
But the second I start using the SINE_TABLE[1024] lookup I have defined (which is a static table full of unsigned 16 bit integer values for the sine curve) the slowdown is immediate to the point where the same micro-controller struggles to produce 3 tones at the right speed for buffered playback.
What is it that causes the lookup table to be so inefficient? Is it something to do with the way the table might be defined in memory?

Related

Implementing PI control for Teensy Atmega 32u4

I am implementing PID control using the standard libraries of the Teensy Atmega32u4. My control variable is PWM signal. My process variable is the current angular position of a DC motor that is interfaced with a 10kohm potentiometer with code that reads position ADC input on a scale of 0 to 270 degrees. The set point is a laser cut joystick whose handle is also attached to a 10kohm potentiometer that reads angular position in the same manner as the process variable.
My question is how to implement the integral portion of the control scheme. The integral term is given by:
Error = Set Point – Process Variable
Integral = Integral + Error
Control Variable = (Kp * Error) + (Ki * Integral)
But I am unsure as to how to calculate the integral portion. Do we need to account for the amount of time that has passed between samples or just the accumulated error and initialize the integral portion to zero, such that it is truly discretized? Since I'm using C, the Integral term can just be a global variable?
Am I on the right track?
Since Sample time (time after which PID is calculated) is always the same it does not matter whether u divide the integral term with sample time as this sample time will just act as a Ki constant but it is better to divide the integral term by sample time so that if u change the sample time the PID change with the sample time but it is not compulsory.
Here is the PID_Calc function I wrote for my Drone Robotics competition in python. Ignore "[index]" that was an array made by me to make my code generic.
def pid_calculator(self, index):
#calculate current residual error, the drone will reach the desired point when this become zero
self.Current_error[index] = self.setpoint[index] - self.drone_position[index]
#calculating values req for finding P,I,D terms. looptime is the time Sample_Time(dt).
self.errors_sum[index] = self.errors_sum[index] + self.Current_error[index] * self.loop_time
self.errDiff = (self.Current_error[index] - self.previous_error[index]) / self.loop_time
#calculating individual controller terms - P, I, D.
self.Proportional_term = self.Kp[index] * self.Current_error[index]
self.Derivative_term = self.Kd[index] * self.errDiff
self.Intergral_term = self.Ki[index] * self.errors_sum[index]
#computing pid by adding all indiviual terms
self.Computed_pid = self.Proportional_term + self.Derivative_term + self.Intergral_term
#storing current error in previous error after calculation so that it become previous error next time
self.previous_error[index] = self.Current_error[index]
#returning Computed pid
return self.Computed_pid
Here if the link to my whole PID script in git hub.
See if that help u.
Press the up button ig=f u like the answer and do star my Github repository i u like the script in github.
Thank you.
To add to previous answer, also consider the case of integral wind up in your code. There should be some mechanism to reset the integral term, if a windup occurs. Also select the largest available datatype to keep the integram(sum) term, to avoid integral overflow (typically long long). Also take care of integral overflow.
If you are selecting a sufficiently high sampling frequency, division can be avoided to reduce the computation involved. However, if you want to experiment with the sampling time, keep the sampling time in multiples of powers of two, so that the division can be accomplished through shift operations. For example, assume the sampling times selected be 100ms, 50ms, 25ms, 12.5ms. Then the dividing factors can be 1, 1<<1, 1<<2, 1<<4.
It is convenient to keep all the associated variables of the PID controller in a single struct, and then use this struct as parameters in functions operating on that PID. This way, the code will be modular, and many PID loops can simultaneously operate on the microcontroller, using the same code and just different instances of the struct. This approach is especially useful in large robotics projects, where you have many loops to control using a single CPU.

How to compress/archive a temperature curve effectively?

Summary: The industrial thermometer is used to sample temperature at the technology device. For few months, the samples are simply stored in the SQL database. Are there any well-known ways to compress the temperature curve so that much longer history could be stored effectively (say for the audit purpose)?
More details: Actually, there are much more thermometers, and possibly other sensors related to the technology. And there are well known time intervals where the curve belongs to a batch processed on the machine. The temperature curves should be added to the batch documentation.
My idea was that the temperature is a smooth function that could be interpolated somehow -- say the way a sound is compressed using MP3 format. The compression need not to be looseless. However, it must be possible to reconstruct the temperature curve (not necessarily the identical sample values, and the identical sampling interval) -- say, to be able to plot the curve or to tell what was the temperature in certain time.
The raw sample values from the SQL table would be processed, the compressed version would be stored elsewhere (possibly also in SQL database, as a blob), and later the raw samples can be deleted to save the database space.
Is there any well-known and widely used approach to the problem?
A simple approach would be code the temperature into a byte or two bytes, depending on the range and precision you need, and then to write the first temperature to your output, followed by the difference between temperatures for all the rest. For two-byte temperatures you can restrict the range some and write one or two bytes depending on the difference with a variable-length integer. E.g. if the high bit of the first byte is set, then the next byte contains 8 more bits of difference, allowing for 15 bits of difference. Most of the time it will be one byte, based on your description.
Then take that stream and feed it to a standard lossless compressor, e.g. zlib.
Any lossiness should be introduced at the sampling step, encoding only the number of bits you really need to encode the required range and precision. The rest of the process should then be lossless to avoid systematic drift in the decompressed values.
Subtracting successive values is the simplest predictor. In that case the prediction of the next value is the value before it. It may also be the most effective, depending on the noisiness of your data. If your data is really smooth, then you could try a higher-order predictor to see if you get better performance. E.g. a predictor for the next point using the last two points is 2a - b, where a is the previous point and b is the point before that, or using the last three points 3a - 3b + c, where c is the point before b. (These assume equal time steps between each.)

Matlab Fast Fourier Transform / fft for time and speed

I have a 2 column vector with times and speeds of a subset of data, like so:
5 40
10 37
15 34
20 39
And so on. I want to get the fourier transform of speeds to get a frequency. How would I go about doing this with a fast fourier transform (fft)?
If my vector name is sampleData, I have tried
fft(sampleData);
but that gives me a vector of real and imaginary numbers. To be able to get sensible data to plot, how would I go about doing this?
Fourier Transform will yield a complex vector, when you fft you get a vector of frequencies, each has a spectral phase. These phases can be extremely important! (they contain most of the information of the time-domain signal, you won't see interference effects without them etc...). If you want to plot the power spectrum, you can
plot(abs(fft(sampleData)));
To complete the story, you'll probably need to fftshift, and also produce a frequency vector. Here's a more elaborate code:
% Assuming 'time' is the 1st col, and 'sampleData' is the 2nd col:
N=length(sampleData);
f=window(#hamming,N)';
dt=mean(diff(time));
df=1/(N*dt); % the frequency resolution (df=1/max_T)
if mod(N,2)==0
f_vec= df*((1:N)-1-N/2); % frequency vector for EVEN length vector
else
f_vec= df*((1:N)-0.5-N/2);
end
fft_data= fftshift(fft(fftshift(sampleData.*f))) ;
plot(f_vec,abs(fft_data))
I would recommend that you back up and think about what you are trying to accomplish, and whether an FFT is an appropriate tool for your situation. You say that you "want to ... get a frequency", but what exactly do you mean by that? Do you know that this data has exactly one frequency component, and want to know what the frequency is? Do you want to know both the frequency and phase of the component? Do you just want to get a rough idea of how many discrete frequency components are present? Are you interested in the spectrum of the noise in your measurement? There are many questions you can ask about "frequencies" in a data set, and whether or not an FFT and/or power spectrum is the best approach to getting an answer depends on the question.
In a comment above you asked "Is there some way to correlate the power spectrum to the time values?" This strikes me as a confused question, but also makes me think that maybe the question you are really trying to answer is "I have a signal whose frequency varies with time, and I want to get an estimate of the frequency vs time". I'm sure I've seen a question along those lines within the past few months here on SO, so I would search for that.

Testing a low pass filter

What is a simple way to see if my low-pass filter is working? I'm in the process of designing a low-pass filter and would like to run tests on it in a relatively straight forward manner.
Presently I open up a WAV file and stick all the samples in a array of ints. I then run the array through the low-pass filter to create a new array. What would an easy way to check if the low-pass filter worked?
All of this is done in C.
You can use a broadband signal such as white noise to measure the frequency response:
generate white noise input signal
pass white noise signal through filter
take FFT of output from filter
compute log magnitude of FFT
plot log magnitude
Rather than coding this all up you can just dump the output from the filter to a text file and then do the analysis in e.g. MATLAB or Octave (hint: use periodogram).
Depends on what you want to test. I'm not a DSP expert, but I know there are different things one could measure about your filter (if that's what you mean by testing).
If the filter is linear then all information of the filter can be found in the impulse response. Read about it here: http://en.wikipedia.org/wiki/Linear_filter
E.g. if you take the Fourier transform of the impulse response, you'll get the frequency response. The frequency response easily tells you if the low-pass filter is worth it's name.
Maybe I underestimate your knowledge about DSP, but I recommend you to read the book on this website: http://www.dspguide.com. It's a very accessible book without difficult math. It's available as a real book, but you can also read it online for free.
EDIT: After reading it I'm convinced that every programmer that ever touches an ADC should definitely have read this book first. I discovered that I did a lot of things the difficult way in past projects that I could have done a thousand times better when I had a little bit more knowledge about DSP. Most of the times an unexperienced programmer is doing DSP without knowing it.
Create two monotone signals, one of a low frequency and one of a high frequency. Then run your filter on the two. If it works, then the low frequency signal should be unmodified whereas the high frequency signal will be filtered out.
Like Bart above mentioned.
If it's LTI system, I would insert impulse and record the samples and perform FFT using matlab and plot magnitude.
You ask why?
In time domain, you have to convolute the input x(t) with the impulse response d(t) to get the transfer function which is tedious.
y(t) = x(t) * d(t)
In frequency domain, convolution becomes simple multiplication.
y(s) = x(s) x d(s)
So, transfer function is y(s)/x(s) = d(s).
That's the reason you take FFT of impulse response to see the behavior of the filter.
You should be able to programmatically generate tones (sine waves) of various frequencies, stuff them into the input array, and then compare the signal energy by summing the squared values of the arrays (and dividing by the length, though that's mathematically not necessary here because the signals should be the same length). The ratio of the output energy to the input energy gives you the filter gain. If your LPF is working correctly, the gain should be close to 1 for low frequencies, close to 0.5 at the bandwidth frequency, and close to zero for high frequencies.
A note: There are various (but essentially the same in spirit) definitions of "bandwidth" and "gain". The method I've suggested should be relatively insensitive to the transient response of the filter because it's essentially averaging the intensity of the signal, though you could improve it by ignoring the first T samples of the input, where T is related to the filter bandwidth. Either way, make sure that the signals are long compared to the inverse of the filter bandwidth.
When I check a digital filter, I compute the magnitude response graph for the filter and plot it. I then generate a linear sweeping sine wave in code or using Audacity, and pass the sweeping sine wave through the filter (taking into account that things might get louder, so the sine wave is quiet enough not to clip) . A visual check is usually enough to assert that the filter is doing what I think it should. If you don't know how to compute the magnitude response I suspect there are tools out there that will compute it for you.
Depending on how certain you want to be, you don't even have to do that. You can just process the linear sweep and see that it attenuated the higher frequencies.

A simple wavetable oscillator in C

I have to program a digital synth for a school graduation project, and while I know most of the theory regarding synthesizers in general, I must confess to be a programming novice.
I have to do it in C, as stated in the title.
The simplest way to do it seems to be with wavetable oscillators, also so I can use a ramp wave as a basis for an ADSR envelope.
However, I have no idea how to make sure it is in the correct pitch. It is easy to change the relative pitch of the oscillator by changing the increment counter, but how do I determine the absolute pitch of the oscillator?
J.Midtgaard
You need to know the sample rate of the audio stream that you're producing. If your sample rate is fs, and you're trying to produce a tone with a frequency of f, then you need to produce a complete cycle (period) every fs / f samples. Alternatively, during every audio sample, you must advance by f / fs of one cycle. So if your wavetable has n entries to represent a complete cycle, then you need to advance by n * f / fs entries per audio sample.
For example, for fs = 44.1kHz, f = 1kHz, n = 1024, your increment must be 1024 * 1000 / 44100 = 23.22 entries per sample.
Note that you will typically obtain a non-integer increment value. In order to obtain the correct pitch, you should not round this value whilst incrementing. Instead, you should round only when converting your accumulator value to the table index value. (A more complicated approach is some sort of interpolation between entries.)

Resources