Dear all I have sampled some data using a 16bit ADC the data is in short(16-bit int) format, now I want to use the Cortex CMSIS DSP library to do some calculations like calculating rms values.I have used the arm_rms_q15 function, but the input to this function is in q15 format. How can I convert the short and other int types to the data that has been used in this library? Any ideas are welcome.
How many places have you posted to?
forums.arm.com/index.php
Have you read up on the Q15 (sometimes written Q1.15) format?
Have you considered how you can take your ADC value and normalize it so that the maximum ADC value would represent 1.0 (or actually 0.99xx something) and how that can be converted into Q1.15? What would the fractional part be for the min ADC value? What would the fractional part be for the maximum ADC value. For an ADC that measures +/- - what would the fractional part be for the maximum negative value?
So - do you now get an idea what to do?
What references to Q15 did you got when you googled?
Thanks for your reply. By using this way (normalizing) we actually force an overhead. I need to do a lot of calculations and it should be real time (I have 20ms and a ton of calculations). Is there a simpler way?
I have used the functions in this way. But I get wrong results. Do you have any idea? float d[8]={1,2,3,4,5,6,7,8}; q15_t dd[8]; q15_t res; float res; arm_float_to_q15(d,dd,8); arm_rms_q15(dd,8,&res); arm_q15_to_float(&res,&first,1);
But I get wrong results. Do you have any idea?
Here's one idea: how about you actually tell us what result you got, and why you think that's the wrong one?
Where does float get into this?
Your ADC is most probably not producing a float result. And the Q15 data type is not a floating point, but a fixed point data type.
Being fixed point, with a limited range, you have to figure out how you take an integer with a much larger range, and represent as a fixed-point number within the valid range, while at the same time you keep track of how many times you needed to rescale the full-range original integer to get into a full-range fixed-point integer.
Then you can use the fixed-point integer for lots of calculations, and finally readjust for the scaling performed, when you want to present your output result.
Here is the test code that I’m using. Suppose I the ADC has filled the buffer data with these values.
float data[8]={1,2,3,4,5,6,7,8}; q15_t qdata[8]; q15_t qres; float res; arm_float_to_q15(data, qdata,8); arm_rms_q15(qdata,8,& qres); arm_q15_to_float(&qres,& res,1);
The answer should be 5.049752469 But I’m getting 0.353485
"Suppose I the ADC has filled the buffer data with these values."
What are "these values"?
You have posted the exact same code again, with the only difference that you have renamed some of your variables.
I asked you where "float" got into the picture, since your ADC most probably did not produce any float. Why did you ignore that question but reposted your source code a second time?
Exactly how do you think any reader of your posts could relate to your figures? What information have you given, that would allow us to reproduce the same calculations?
Have you spent as little time trying to figure out what Q15 numbers are, as you have spent figuring out what information you must supply when asking a question on this forum?
Suppose I the ADC has filled the buffer data with these values.
I'd rather suppose it didn't. Because it really didn't.
arm_float_to_q15(data, qdata,8);
Aha. So how exactly did you expect a 1.15 fixed point datatype to hold values between 3.0 and 8.0?
This is what really happens.
Some ADC code fills this buffer. Fill_adc_buffer(); Short adc[8];
Now I cast the buffer to float so I can use the float functions.(like arm_float_to_q15)
for(int i=0;i<8;i++) {
data[i]= adc[i]; }
Now I try to cast the data to q15 using this function.
arm_float_to_q15(data, qdata,8); now I should calculate the rms value using arm_rms_q15(qdata,8,& qres); and I should translate the response back to float! arm_q15_to_float(&qres,& res,1);
the answer is in res! You do not have my adc so I just filled the data buffer with arbitrary data. but the answer is wrong!?
What should I do? I can use the arm_rms_f32 and its answer is correct, but I wanted to use q15 version. How should I do that? Do you have any idea?
Thanks in advance.
Now I cast the buffer to float so I can use the float functions.
And by doing that, you demonstrate that you really didn't heed any of the advice you've been given. You also cast significant doubt on whether you even tried to understand what you're doing.
but the answer is wrong!?
No, it's not. The problem is that you didn't ask the question you thought you were.
I wanted to use q15 version.
Then you better learn what q15 is, so you'll have a chance to use it correctly.
Your Q15 number is 16 bits large. 15 of these bits are used to store the fractional part.
There is then only one bit left. That bit must then store both integer part and sign.
Now, how large integers do you feel you can store in a 1-bit signed integer? If you think the answer is -1 ..0, you are on the way of understanding your problem.
Now, how would you be able to store the integer value 8 into a Q15 number, where the integer part must be less than 1, and the the fractional part should be stored in the remaining bits?
What would happen if you first scaled your integer value 8 by making it 16 times smaller? Now, it would be a value 0.5. So the integer part would be less than 1. And the fractional part would be 0.5. Such a valud would fit, and would be 0x04000, since fractional 0.5 is 0x4000, fractional 0.25 is 0x2000, fractional 0.125 is 0x1000, ...
Isn't it time you do spend own time thinking?
Much time have passed - have you still not managed to find this reference? en.wikipedia.org/.../Q_(number_format)
Well after the first post I read the wiki, but I did not get their point on type conversion. You mean I should divide all the adc data by 32768? Would you answer one simple question to me? Suppose I have one short variable(min=-32768 max=32767). Now I want to convert it to q15 and after some calculations convert it back to int again. Would you write a simple demo code.I’m totally confused!
You mean I should divide all the adc data by 32768?
No.
Suppose I have one short variable(min=-32768 max=32767)
I'm reasonably certain your ADC doesn't actually produce values in that range, now does it?
So what's the actual data range? How do you think that should be mapped into the actual range of the q15_t type?
The ADC is AD7606 and it can produce data in that range!
Haven't it hit you yet, that you could see the ADC as a magic device that returns measurements within the range [-1 to 1) but with lots of fractional data?