• Forums
• Posts
Latest Posts
Active Posts
Recently Visited
Search Results
• Page Extras
• Forum Themes
• AVR Freaks

Hot!Need help creating quantizer Page: 1234 > Showing page 1 of 4
Author
didierleplae Starting Member • Total Posts : 43
• Reward points : 0
• Joined: 2019/03/31 16:57:50
• Location: 0
• Status: offline 0

Need help creating quantizer

I'm trying to create a voltage quantizer for use in synthesizers. Varying voltages from 0-5v inputted would be converted to specific increments. The standard I'm using is 1V/octave, so a change of one semitone equals 1/12V.
I would like to eventually create a controller that can change between different scales.
To start with, I am trying to write a code that will simply convert inputted voltage to 1/12V increments using PWM1 of CCP1.

Here is what I've come up with so far. My code seems to be exceeding the program memory. I'm using a 16F18313 and PICKIT4.
I'm new to this, so I'm sure the way I wrote this is probably really inefficient, but I haven't thought of a better way. How can I achieve the same result without using all my memory or am I missing something?

Also, what would be the optimal oscillator and clock settings to get the cleanest voltages from the PWM using RC circuit? And best PWM resolution?

Or is there a better way, using DAC? another PIC chip?

uint16_t inputValue;
uint16_t x;

while (1)
{

x=17;

//octave1

if (inputValue < 0.5*x){
}

if (inputValue >= 0.5*x && inputValue < 1.5*x){
}

if (inputValue >= 1.5*x && inputValue < 2.5*x){
}

if (inputValue >= 2.5*x && inputValue < 3.5*x){
}

if (inputValue >= 3.5*x && inputValue < 4.5*x){
}

if (inputValue >= 4.5*x && inputValue < 5.5*x){
}

if (inputValue >= 5.5*x && inputValue < 6.5*x){
}

if (inputValue >= 6.5 * x && inputValue < 7.5 * x) {
}

if (inputValue >= 7.5 * x && inputValue < 8.5 * x) {
}

if (inputValue >= 8.5 * x && inputValue < 9.5 * x) {
}

if (inputValue >= 9.5 * x && inputValue < 10.5 * x) {
}

if (inputValue >= 10.5 * x && inputValue < 11.5 * x) {
}

if (inputValue >= 11.5 * x && inputValue < 12.5 * x) {
}

//octave2

if (inputValue >= 12.5 * x && inputValue < 13.5 * x) {
}

if (inputValue >= 13.5 * x && inputValue < 14.5 * x) {
}

if (inputValue >= 14.5 * x && inputValue < 15.5 * x) {
}

if (inputValue >= 15.5 * x && inputValue < 16.5 * x) {
}

if (inputValue >= 16.5 * x && inputValue < 17.5 * x) {
}

if (inputValue >= 17.5 * x && inputValue < 18.5 * x) {
}

if (inputValue >= 18.5 * x && inputValue < 19.5 * x) {
}

if (inputValue >= 19.5 * x && inputValue < 20.5 * x) {
}

if (inputValue >= 20.5 * x && inputValue < 21.5 * x) {
}

if (inputValue >= 21.5 * x && inputValue < 22.5 * x) {
}

if (inputValue >= 22.5 * x && inputValue < 23.5 * x) {
}

if (inputValue >= 23.5 * x && inputValue < 24.5 * x) {
}

//octave3

if (inputValue >= 24.5 * x && inputValue < 25.5 * x) {
}

if (inputValue >= 25.5 * x && inputValue < 26.5 * x) {
}

if (inputValue >= 26.5 * x && inputValue < 27.5 * x) {
}

if (inputValue >= 27.5 * x && inputValue < 28.5 * x) {
}

if (inputValue >= 28.5 * x && inputValue < 29.5 * x) {
}

if (inputValue >= 29.5 * x && inputValue < 30.5 * x) {
}

if (inputValue >= 30.5 * x && inputValue < 31.5 * x) {
}

if (inputValue >= 31.5 * x && inputValue < 32.5 * x) {
}

if (inputValue >= 32.5 * x && inputValue < 33.5 * x) {
}

if (inputValue >= 33.5 * x && inputValue < 34.5 * x) {
}

if (inputValue >= 34.5 * x && inputValue < 35.5 * x) {
}

if (inputValue >= 35.5 * x && inputValue < 36.5 * x) {
}

//octave4

if (inputValue >= 36.5 * x && inputValue < 37.5 * x) {
}

if (inputValue >= 37.5 * x && inputValue < 38.5 * x) {
}

if (inputValue >= 38.5 * x && inputValue < 39.5 * x) {
}

if (inputValue >= 39.5 * x && inputValue < 40.5 * x) {
}

if (inputValue >= 40.5 * x && inputValue < 41.5 * x) {
}

if (inputValue >= 41.5 * x && inputValue < 42.5 * x) {
}

if (inputValue >= 42.5 * x && inputValue < 43.5 * x) {
}

if (inputValue >= 43.5 * x && inputValue < 44.5 * x) {
}

if (inputValue >= 44.5 * x && inputValue < 45.5 * x) {
}

if (inputValue >= 45.5 * x && inputValue < 46.5 * x) {
}

if (inputValue >= 46.5 * x && inputValue < 47.5 * x) {
}

if (inputValue >= 47.5 * x && inputValue < 48.5 * x) {
}

//octave5

if (inputValue >= 48.5 * x && inputValue < 49.5 * x) {
}

if (inputValue >= 49.5 * x && inputValue < 50.5 * x) {
}

if (inputValue >= 50.5 * x && inputValue < 51.5 * x) {
}

if (inputValue >= 51.5 * x && inputValue < 52.5 * x) {
}

if (inputValue >= 52.5 * x && inputValue < 53.5 * x) {
}

if (inputValue >= 53.5 * x && inputValue < 54.5 * x) {
}

if (inputValue >= 54.5 * x && inputValue < 55.5 * x) {
}

if (inputValue >= 55.5 * x && inputValue < 56.5 * x) {
}

if (inputValue >= 56.5 * x && inputValue < 57.5 * x) {
}

if (inputValue >= 57.5 * x && inputValue < 58.5 * x) {
}

if (inputValue >= 58.5 * x && inputValue < 59.5 * x) {
}

if (inputValue >= 59.5 * x && inputValue < 60.5 * x) {
}

}
}

74 Replies Related Threads

1and0 Access is Denied • Total Posts : 9771
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline Re: Need help creating quantizer 2019/09/18 02:39:38 (permalink)
+1 (1)
Floating point math takes a lot of memory and cycles.  Replace all those if() statements with this (untested):
uint16_t half = x >> 1;
uint16_t value = 0;
do {
if (inputValue < (value + half)) {
break;
}
value += x;
} while (value <= 60);

pcbbc Super Member • Total Posts : 1332
• Reward points : 0
• Joined: 2014/03/27 07:04:41
• Location: 0
• Status: offline Re: Need help creating quantizer 2019/09/18 02:41:22 (permalink)
+1 (1)
It is pointless using floating point comparisons when you are only using integer arithmetic:
uint16_t inputValue = ADC_GetConversionResult()/64;

A fundamental rule of 8 bit processors is never use floating point unless you have to.  Instead keep everything as integers and multiple the values you are comparing against by 64 (instead of dividing the value by 64 and then using FP).

Alternatively perhaps the divide by 64 is because your ADC values are 10-bit left aligned?  In which case the decimal is irrelevant and discarded by the integer divide operation.

Your code is way too verbose. You can replace all of those IF statements with a single IF inside a loop if you think about it.

Something like (I don't claim this is 100% correct - up to you to do the thinking):
for (int i = 1; i <= 60; i++)
{
if (inputValue <= i)
{
break;
}
}

Edit: 1and0 beat me too it, but we're both heading in the same direction.
Although note that the compare in his code is with value which increases by x (17) each time round the loop (so 0, 17, 34...).  That's not what your supplied code compares against (1, 2, 3...).
post edited by pcbbc - 2019/09/18 02:49:49
1and0 Access is Denied • Total Posts : 9771
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline Re: Need help creating quantizer 2019/09/18 02:53:36 (permalink)
+1 (1)
pcbbc
1and0 beat me too it, but we're both heading in the same direction.
Although note that the compare in his code is with value which increases by x (17) each time round the loop (so 0, 17, 34...).  That's not what your supplied code compares against (1, 2, 3...).

I did say it's untested. I will leave it for the OP to fix it. ;)

<edit> Hint: The compare value in the while() statement is wrong.  Better yet, replace it with a count-down loop of 60 iterations.

post edited by 1and0 - 2019/09/18 03:07:36
pcbbc Super Member • Total Posts : 1332
• Reward points : 0
• Joined: 2014/03/27 07:04:41
• Location: 0
• Status: offline Re: Need help creating quantizer 2019/09/18 03:00:38 (permalink)
+1 (1)
1and0I did say it's untested. I will leave it for the OP to fix it. ;)

Indeed, as did I.
Didn't test mine either (and I initially got the compare round the wrong way - now fixed).
Agree the OP should be doing a little thinking of their own. Smile: 1and0 Access is Denied • Total Posts : 9771
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline Re: Need help creating quantizer 2019/09/18 03:06:29 (permalink)
0
pcbbc
Indeed, as did I.
Didn't test mine either (and I initially got the compare round the wrong way - now fixed).
Agree the OP should be doing a little thinking of their own. Smile:

The compare values are multiples of x, not just 1 to 60. ;)
NorthGuy Super Member • Total Posts : 5688
• Reward points : 0
• Joined: 2014/02/23 14:23:23
• Location: Northern Canada
• Status: online Re: Need help creating quantizer 2019/09/18 07:54:25 (permalink)
+1 (1)
Assuming you're always in bounds

didierleplae Starting Member • Total Posts : 43
• Reward points : 0
• Joined: 2019/03/31 16:57:50
• Location: 0
• Status: offline Re: Need help creating quantizer 2019/09/19 15:29:54 (permalink)
0
Thank you all for the help.
I tried this here code earlier and it seems to work pretty well.
I can change the values of 'x' and 'i' depending on how small I want the increments.

int inputValue;
int x;

while (1)
{

x = 40;

for (int i = 1; i <= 24; i++)
{
if (inputValue <= i * x)
{
break;
}
}

}
}
/**
End of File
*/

Now the next thing I'm wondering is if I want to skip increments, as in to create other scales, I wonder if using arrays would be the best way?
NorthGuy Super Member • Total Posts : 5688
• Reward points : 0
• Joined: 2014/02/23 14:23:23
• Location: Northern Canada
• Status: online Re: Need help creating quantizer 2019/09/19 16:03:26 (permalink)
+1 (1)
Why didn't you like my suggestion which calculates everything everything in a single operation instead of a loop? If you did, changing the scale would be as easy as assigning different values to the "Increment".
1and0 Access is Denied • Total Posts : 9771
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline Re: Need help creating quantizer 2019/09/19 18:54:15 (permalink)
+1 (1)
didierleplae
I tried this here code earlier and it seems to work pretty well.

...

for (int i = 1; i <= 24; i++)
{
if (inputValue <= i * x)
{
break;
}
}

But that is NOT what the code in your Post #1 is compared against.?!

didierleplae Starting Member • Total Posts : 43
• Reward points : 0
• Joined: 2019/03/31 16:57:50
• Location: 0
• Status: offline Re: Need help creating quantizer 2019/09/19 22:41:01 (permalink)
0
NorthGuy
Why didn't you like my suggestion which calculates everything everything in a single operation instead of a loop? If you did, changing the scale would be as easy as assigning different values to the "Increment".

Sorry, I didn't mean to gloss over your suggestion. Honestly, I don't understand it. I am a novice here, so you'll have to spell it out. I'm guessing "increment" would be the "x" that I had put in my original code? What is "base"?
didierleplae Starting Member • Total Posts : 43
• Reward points : 0
• Joined: 2019/03/31 16:57:50
• Location: 0
• Status: offline Re: Need help creating quantizer 2019/09/19 22:46:15 (permalink)
0
1and0
didierleplae
I tried this here code earlier and it seems to work pretty well.

...

for (int i = 1; i <= 24; i++)
{
if (inputValue <= i * x)
{
break;
}
}

But that is NOT what the code in your Post #1 is compared against.?!

Sorry, but I guess I don't understand what you mean. Not trying to piss anyone off here.
I'm just starting to learn how to code by trial and error.
The code that pcbbc suggested made the most sense to my amateur mind, so that's the first one I tried and it worked.
1and0 Access is Denied • Total Posts : 9771
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline Re: Need help creating quantizer 2019/09/19 23:42:55 (permalink)
0
didierleplae
Sorry, but I guess I don't understand what you mean. Not trying to piss anyone off here.

The code in your Post #1 is equivalent to this
if (inputValue < 0.5 * x){
} else if (inputValue < 1.5 * x){
} else if (inputValue < 2.5 * x){
/*
* snipped
*/
} else if (inputValue < 60.5 * x) {
}

and the code in your Post #8 is equivalent to this
if (inputValue <= x){
} else if (inputValue <= 2 * x){
} else if (inputValue <= 3 * x){
/*
* snipped
*/
} else if (inputValue <= 24 * x) {
}

Now, do you see the difference?

I'm just starting to learn how to code by trial and error.

Get a copy of this:  https://www.amazon.com/Pr...p;s=gateway&sr=8-1
didierleplae Starting Member • Total Posts : 43
• Reward points : 0
• Joined: 2019/03/31 16:57:50
• Location: 0
• Status: offline Re: Need help creating quantizer 2019/09/20 00:26:44 (permalink)
0
1and0
didierleplae
Sorry, but I guess I don't understand what you mean. Not trying to piss anyone off here.

The code in your Post #1 is equivalent to this
if (inputValue < 0.5 * x){
} else if (inputValue < 1.5 * x){
} else if (inputValue < 2.5 * x){
/*
* snipped
*/
} else if (inputValue < 60.5 * x) {
}

and the code in your Post #8 is equivalent to this
if (inputValue <= x){
} else if (inputValue <= 2 * x){
} else if (inputValue <= 3 * x){
/*
* snipped
*/
} else if (inputValue <= 24 * x) {
}

Now, do you see the difference?

I'm just starting to learn how to code by trial and error.

Get a copy of this:  https://www.amazon.com/Pr...p;s=gateway&sr=8-1

Yes, I do see the difference. I'm not sure that the distinction will make a difference for my application, though. I'll probably need to do some experimenting to figure that out.

Thanks for the book recommendation, also. I think I'll get that!

NorthGuy Super Member • Total Posts : 5688
• Reward points : 0
• Joined: 2014/02/23 14:23:23
• Location: Northern Canada
• Status: online Re: Need help creating quantizer 2019/09/20 06:32:06 (permalink)
+1 (1)
didierleplae
Sorry, I didn't mean to gloss over your suggestion. Honestly, I don't understand it. I am a novice here, so you'll have to spell it out. I'm guessing "increment" would be the "x" that I had put in my original code? What is "base"?

Base is the smallest value. It will produce 0 PWM. All your values are higher than the base. You subtract the "base" from the value. Then the value is zero-based. In your case the base is 0, but if you decide to calibrate your ADC, you can set base to counteract the ADC offset.

"increment" is the difference in input values between consecutive PWM points, it is the same as "x" in your code.

Given these two values you can calculate the PWM. It is only one line of code and it only takes one subtraction and one division. It is both simpler (less bugs) and more efficient.
post edited by NorthGuy - 2019/09/20 06:52:38
didierleplae Starting Member • Total Posts : 43
• Reward points : 0
• Joined: 2019/03/31 16:57:50
• Location: 0
• Status: offline Re: Need help creating quantizer 2019/09/20 11:27:42 (permalink)
0
NorthGuy
didierleplaeBase is the smallest value. It will produce 0 PWM. All your values are higher than the base. You subtract the "base" from the value. Then the value is zero-based. In your case the base is 0, but if you decide to calibrate your ADC, you can set base to counteract the ADC offset. "increment" is the difference in input values between consecutive PWM points, it is the same as "x" in your code. Given these two values you can calculate the PWM. It is only one line of code and it only takes one subtraction and one division. It is both simpler (less bugs) and more efficient.

I still don’t understand. The inputValue could be any number between 0 and 1023. Say if the base is zero, then the result would always be inputValue/Increment. It wouldn’t result in a multiple of the increment.
1and0 Access is Denied • Total Posts : 9771
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline Re: Need help creating quantizer 2019/09/20 11:59:55 (permalink)
0
This

PWM1_LoadDutyValue((inputValue / x + 1) * x);

is equivalent to this

if (inputValue < x) {
} else if (inputValue < 2 * x) {
} else if (inputValue < 3 * x) {
/*
* snipped
*/

but it takes a division and a multiplication, which is time consuming.
post edited by 1and0 - 2019/09/20 12:01:02
didierleplae Starting Member • Total Posts : 43
• Reward points : 0
• Joined: 2019/03/31 16:57:50
• Location: 0
• Status: offline Re: Need help creating quantizer 2019/09/20 12:19:45 (permalink)
0
1and0
This

PWM1_LoadDutyValue((inputValue / x + 1) * x);

Am I doing this correctly?
If for example:
inputValue = 500
x=17

(inputValue / x + 1) * x
(500/17+1)*17
(500/18)*17
(27.777)*17

Or would the 27.7777 get rounded up to 28?

post edited by didierleplae - 2019/09/20 12:21:02
NorthGuy Super Member • Total Posts : 5688
• Reward points : 0
• Joined: 2014/02/23 14:23:23
• Location: Northern Canada
• Status: online Re: Need help creating quantizer 2019/09/20 12:31:10 (permalink)
0
didierleplae
I still don’t understand. The inputValue could be any number between 0 and 1023. Say if the base is zero, then the result would always be inputValue/Increment. It wouldn’t result in a multiple of the increment.

Multiply in back by the increment then:

TheResult = (InputValue/Increment)*Increment;

which is the same as

TheResult = InputValue - (InputValue%Increment);

As 1and0 says, this involves slow division, but it's still faster than doing it in the loop.

If you're not very picky about the Increment and make it a multiple of 2, then you can eliminate the division.

1and0 Access is Denied • Total Posts : 9771
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline Re: Need help creating quantizer 2019/09/20 12:38:35 (permalink)
+1 (1)
didierleplae
Am I doing this correctly?
If for example:
inputValue = 500
x=17

(inputValue / x + 1) * x
(500/17+1)*17
(500/18)*17
(27.777)*17

Or would the 27.7777 get rounded up to 28?

You really need to go back to elementary school. ;)  Division comes before addition!!!

As inputValue and x are integer, the result is integer; so

500 / 17 = 29
29 + 1 = 30
30 * 17 = 510

Page: 1234 > Showing page 1 of 4 Jump to:
© 2019 APG vNext Commercial Version 4.5