Go Down

### Topic: Linear to exponential voltage (Read 325 times)previous topic - next topic

#### Gemfire

##### Jun 25, 2019, 09:23 am
Hi! I'm trying to use an attiny85 to convert linear input voltage to exponential output, using it with a voltage controlled oscillator to achieve musical 1 Volt/octave tracking. I understand it's a fairly simple task, but I can't wrap my hand around the main equation to get 0-5v pwm output from 0-5v input, as I'm not that good at math. If someone could at least point me in the right direction, I'd be very grateful. Thanks!

#### PaulS

#1
##### Jun 25, 2019, 10:08 am
We have no clue what your input voltage (source) is, or what you output equation is, so you can't expect us to help you with the math.

#### Gemfire

#2
##### Jun 25, 2019, 10:54 am
My input voltage source would be a control voltage keyboard or a sequencer that produces CV in the range of 0 to 5 volts and the output should also produce 0 to 5 volts but in an exponential curve. The graph of the function should look like this if this helps (found the pic on the internet, from an article describing a transistor-based linear to expo converter) where pink is the linear voltage input and green is the expo output, except in the picture the input voltage goes all the way up to 8 volts.

#### PaulS

#3
##### Jun 25, 2019, 11:26 am
So what is the equation of the green curve?

#### Gemfire

#4
##### Jun 25, 2019, 11:38 am
Yes, exactly. I'd really like to know that.

#### Gemfire

#5
##### Jun 25, 2019, 11:45 am
Or at least where should I look to find it out for myself

#### PaulS

#6
##### Jun 25, 2019, 11:49 am
Yes, exactly. I'd really like to know that.
You have to tell us that.

You can't output a true variable voltage (at least not on most Arduinos). You can output a signal that a appears to some devices, like LEDs and motors, as a variable voltage, but all you are really doing is changing the duty cycle of a pin.

So it is not clear what your output is supposed to be or whether whatever you are outputting it to will be happy with what you output.

#### Gemfire

#7
##### Jun 25, 2019, 12:11 pmLast Edit: Jun 25, 2019, 12:26 pm by Gemfire
You can't output a true variable voltage
Yes I know that. As I said in the OP I'll be using a PWM signal for the output. If I'm not happy with that I'll use a DAC (I have a bunch of MCP4822 laying around). For the moment I just need to find a way to convert the input voltage to an exponential curve.

#### PaulS

#8
##### Jun 25, 2019, 12:27 pm
Quote
For the moment I just need to find a way to convert the voltage output to an exponential curve.
No, you want to convert the linear input to a specific exponential curve, but you don't seem to be able to say what exponential curve you want.

#### Gemfire

#9
##### Jun 25, 2019, 12:54 pm
Well, if I knew I wouldn't be asking, right?

#### PerryBebbington

#10
##### Jun 25, 2019, 01:19 pm
Hello Gemfire,
This code:

Code: [Select]
`unsigned char white_scale (unsigned char set) {    return (unsigned char)round((1 - log10(10 - (double)set * 9 / 254)) * 255);}`
Is from my light dimmer project and converts a linear input to a log output for the purpose of making the brightness of my white lights appear to change linearly even though human eyes respond logarithmically to changes in brightness. It is probably not quite what you want but I offer it as a starting point for you to experiment with.

#### Gemfire

#11
##### Jun 25, 2019, 01:33 pm
Thanks, PerryBebbington!
I'll git it a try!

#### gfvalvo

#12
##### Jun 25, 2019, 06:17 pmLast Edit: Jun 25, 2019, 06:17 pm by gfvalvo
This is really just first-year High School Algebra. The basic formula is:  Output = K1 * eK2 * Input

Assuming you be reading the Input using 'analogRead' (returns 0-1023) and writing the Output using 'analogWrite' (takes 0-255), then you just need to choose the proper values for K1 and K2. Start with an Input of 0 and set K1 so that Output is sufficiently small (technically it can never be 0). Then use that K1 with an Input of 1023 to set K2 to give 255. Since digitalWrite only takes whole values, you'd round the Output from the formula to the nearest integer.

I would not do the computation in your code on the fly since exp() and floating point math is computationally expensive on an 8-bit AVR. Rather, I'd make a lookup table using Excel, Matlab, etc. Store these values in an array (in PROGMEM if you like) and index them by the value from analogRead. You could probably divide the input value by 2 and make the table half as big without appreciable degradation.

Here's a plot (rounded to integers) of Output vs Input for K1 = 0.4 and K2 = 0.0063124.
No technical questions via PM. They will be ignored. Post your questions in the forum so that all may learn.

#### PerryBebbington

#13
##### Jun 25, 2019, 06:32 pm

Quote
I would not do the computation in your code on the fly since exp() and floating point math is computationally expensive
Side discussion....
When I was designing my lighting controller I had this debate with the person who taught me C. I consider him to be something of a software expert, I am not. I wanted to use a table as you suggest, he said calculate on the fly, so that's what I did. The function I use is partly derived mathematically and partly derived by seeing how linearly the light level appeared to change (as judged by my eyes) with respect to the control input and modifying the function accordingly.

#### gfvalvo

#14
##### Jun 25, 2019, 06:43 pm
Engineering is all about trade-offs. Performance vs Memory vs Processor Cycles vs Power Dissipation vs Cost vs Size vs .......
No technical questions via PM. They will be ignored. Post your questions in the forum so that all may learn.

Go Up