Go Down

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

Gemfire

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

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.
The art of getting good answers lies in asking good questions.

Gemfire

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

So what is the equation of the green curve?
The art of getting good answers lies in asking good questions.

Gemfire

Yes, exactly. I'd really like to know that.

Gemfire

Or at least where should I look to find it out for myself  :)

PaulS

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.
The art of getting good answers lies in asking good questions.

Gemfire

#7
Jun 25, 2019, 12:11 pm Last 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

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.
The art of getting good answers lies in asking good questions.

Gemfire

Well, if I knew I wouldn't be asking, right?

PerryBebbington

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

Thanks, PerryBebbington!
I'll git it a try!

gfvalvo

#12
Jun 25, 2019, 06:17 pm Last 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


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

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