Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have 8 data points that form the peak of a partial sine wave. I am trying to fit these to get an equation so I discover the point of the true maximum position (which most likely lies between the data points). The coding will be in C. Does anyone have any info on algorithms or ideally code samples?
Since the data points are all near a maximum, the wave y = A*sin(B*x + C) + D can be approximated as a parabola much like the first 2 terms of cos(x) = (1.0 - x*x/2! + ...).
So find the best fit parabola for the 8 data points and calculate the maximum.
C- Peak detection via quadratic fit
Lots of google examples exist. Example
Provided your sample-values form a "hump", i.e. increasing followed by decreasing samples, you could try viewing the samplevalues as "weights" and compute the "center of gravity":
float cog = 0f;
for (i=0; i<num_samples; ii+) {
cog += i * samples[i];
}
cog /= num_samples;
I've used that in similar cases in the past.
NOTE: This scheme only works if the set of samples used contain a single peak, which the question phrasing certainly made me think was the case. Finding locations of interest can easily be done by monitoring, if sample values are increasing or decreasing, selecting an "interesting" range of samples and computing the peak location as described.
Also note, that if the actual goal is to determine the sine wave phase or frequency of an input signal, it would be a lot better to correlate the signal against reference set of sine-waves (in other words, do a Fourier transform).
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm writing a piece of software which is responsible for logging the position of certain machine parts.
Now this is the case:
There is 1 RTK fixed GPS receiver (+/- 2cm accuracy), fixed on the machine. The heading is calculated using 2 different locations
There are 2 arms (left and right arm) on the machine that can rotate independent of each other outwards or inwards
There is 1 arm (mid arm) with a fixed location on the machine
What I Already have:
A piece of software which calculates the location of the outer location of the arms (this works like a charm). This produces a shapefile as logfile in which the location of the arms are visible and this works good for every heading.
The problem is:
The algorithm is calculating the location of the arms using the delta X and delta Y distances in mm.
My assumption was that the longitude 0.00000001 is equal to 1.1 mm on the X axis (source). Boy, what was I wrong...
When the shapefile that is generated is being measured using a shapefile viewer it returnes 2,19 meter instead of the calculated 3,25. Note that this is on the latitude 52.810146939 (Northern Hemisphere).
Thus the question:
Has anybody any idea how a formula can be formed that takes a latitude or longitude as starting point and a distance in [mm] and then returnes the corrected latitude or longitude? Or how I can calcuate the relative delta coordinates values to sum them with the Original coordinates?
I've got a snippet of the code:
Armlocations->leftarm.locationX = ownLocation.locationX + MM_TO_COOR(deltaX);
Armlocations->leftarm.locationY = ownLocation.locationY + MM_TO_COOR(deltaY);
deltaX and deltaY are the distances in mm that should be added to the coordinate. The macro MM_TO_COOR is this:
#define COOR_TO_MM(x) ((x) * 110000000)
#define MM_TO_COOR(x) ((x) / 110000000)
The question is not about programming -> I got that going for me, but more about the math involved to this.
I am sure this is not the right place, it might be a better fit to use https://gis.stackexchange.com.
About the latitude, it is always (about) 111 km per degree, so .00000001° (1E-8°) should indeed be 1.1 mm in y direction.
The relation for the longitude indeed depends on your current latitude: here, the factor per degree is 111 km multiplied by cos(latitude). In your case, that would (on a spherical earth) make a factor of 0.60445804192912, resulting in 67.1 km per degree or .671 mm per 1E-8°. On our earch, being flattened at the poles, the value is slightly different, but should be about the same (I cannot, however, tell how big the error is.)
Are you sure that your GPS device has this high resolution of several mm?
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I have designed a board that samples audio input using a 16 bit DAC at 48kHz. It stores the data as signed 16-bit integers. I have also implemented a 16 bit ADC on the board and I am able to pass audio through the board successfully.
I would like to design a low pass filter using MATLAB and implement it on this board. I understand how to create basic filters using MATLAB but I cant quite grasp how to bridge the gap between creating the filter in MATLAB and implementing this filter using C code on my board. I would like to be able to pass the signal into the board and observe the filtered signal on the output in 'real-time'.
How can this be achieved?
ok, you said that you get your coefficients from a [B,A]= butter(..) likewise filter (try getting them in Z domain AKA digital filter), those A,B coefficients correspond to a simple transfer function you know
H(z) = B(z)/A(z) = (b(1)+b(2) z^−1+⋯+b(n+1) z^−n)/(a(1)+a(2) z^−1+⋯+a(n+1) z^−n)
right?
you just need to remember that the output y = H(z)*x or in other words
y = B(z)/A(z) * x and finally A(z)*y = b(z)*x
and what was x(t) * z^-1 equals? yep x(t-1)
that means that you'll end with an ecuation similar to:
y(t)*a(1)+y(t-1)*a(2)+⋯+y(t-n)a(n+1) = x(t)*b(1)+x(t-1)*b(2)+⋯+x(t-n)b(n+1)
and what we need is the actual value of y(t) with the known values of actual x(t) and past x(t-1) etc, and also with known and stored values of past y(t-1) etc...
y(t) = 1/a(1) * (x(t)*b(1)+x(t-1)*b(2)+⋯+x(t-n)b(n+1) - y(t-1)*a(2)-⋯-y(t-n)a(n+1))
that means you need two arrays for x and y, and apply the equation with the B and A arrays you got from matlab...
sadly, this assumes you ALREADY took in consideration the sampling time in the butter() (hence Wn should be normalized) and make sure you take your samples at that exact sampling time (and ideally calculate your output at the exact time too)
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 7 years ago.
Improve this question
I am trying to classify the events above as 1 or 0. 1 would be the lower values and 0 would be the higher values. Usually the data is does not look as clean as this. Currently the approach I am taking is to have two different thresholds so that in order to go from 0 to 1 it has to go past the 1 to 0 threshold and it has to be above for 20 sensor values. This threshold is set to the highest value I receive minus ten percent of that value. I dont think a machine learning approach will work because I have too few features to work with and also the implementation has to take up minimal code space. I am hoping someone may be able to point me in the direction of a known algorithm that would apply well to this sort of problem, googling it and checking my other sources isnt producing great results. The current implementation is very effective and the hardware inst going to change.
Currently the approach I am taking is to have two different thresholds so that in order to go from 0 to 1 it has to go past the 1 to 0 threshold and it has to be above for 20 sensor values
Calculate the area on your graph of those 20 sensor values. If the area is greater than a threshold (perhaps half the peak value) assign it as 1, else assign it as 0.
Since your measurements are one unit wide (pixels, or sensor readings) the area ends up being the sum of the 20 sensor values.
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I just need some guidance as to how to detect the frequency from a sine wave. I generated the sinewave via a DtoA converter. Now, I'm putting that signal back through an AtoD to monitor and verify the output.
I don't know how to detect the frequency of the sine wave. Apparently, I'm supposed to get the period from the sine wave and apply hysteresis to compensate for noise.
Any hint is much appreciated. thanks.
If this is about sine waves only, I'd check for zero crossings, and calculate the average time between zero crossings for a couple of hundred cycles, that would give an accurate half period length, and from that, you can calculate the frequency.
("zero" might not be trivial, as most uC have 0-Vdd range ADC inputs only, so zero in that case might happen to be Vdd/2...)
(very simple) pseudocode could be
const zero = 0; //or vdd/2 if that's the case
while(cyclesSoFar<enoughCycles) {
currentSample=adcRead();
//detect zero crossing (needs hysteresis added)
if((lastSample>zero&¤tSample<=zero) || (lastSample<zero&¤tSample>=zero) ) {
period = getTicks()-ticksAtLastCrossing; //might have to check for over/underflow to get correct value
avgPeriod = avgPeriod * (cyclesSoFar)/(cyclesSoFar+1) + period/(cyclesSoFar+1);
cyclesSoFar++;
}
lastSample = currentSample;
}
freq = ticksFreq/(avgPeriod*2);
Where: enoughCycles is the number of cycles to measure, zero is the DC offset of the sine wave, and ticksFreq is the frequency of the CPU, the most precise time available. Of course, this is very-very simplified, lots of fluff and checks need to be added.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
Can you tell me any ways to generate non-uniform random numbers?
I am using Java but the code examples can be in whatever you want.
One way is to create a skewed distribution by adding two uniform random numbers together (i.e. rolling 2 dice).
Try generating uniformly distributed random numbers, then applying your inverted non-uniform cumulative distribution function to each of them.
What distribution of deviates do you want?
Here is a technique which always works, but isn't always the most efficient. The cumulative distrubtion function P(x) gives the fraction of the time that values fall below x. Thus P(x)=0 at the lowest possible value of x and P(x)=1 at the highest possible value of x. Every distribution has a unique CDF, which encodes all the properties of the distrubtion in the way that P(x) rises from 0 to 1. If y is a uniform deviate on the interval [0,1], then x satisfying P(x)=y will be disributed according to your distribution. To make this work comuptationally, you just need a way computing the inverse of P(x) for your distribution.
The Meta.Numerics library defines a large number of commonly used distrubtions (e.g. normal, lognormal, exponential, chi squared, etc.) and has functions for computing the CDF (Distribution.LeftProbability) and the inverse CDF (Distribution.InverseLeftProbability) of each.
For specialized techniques that are fast for particular distrubtions, e.g. the Box-Muller technique for normaly distributed deviates, see the book Numerical Recipies.
If you are using Java then my Uncommons Maths library may be of interest. It includes classes for generating random numbers for Uniform, Gaussian, Poisson, Binomial and Exponential distributions. This article shows how you might use these distributions.