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!

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.

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.

So what is the equation of the green curve?

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

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

Gemfire:

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.

PaulS:

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.

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.

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

Hello Gemfire,

This code:

```
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.

Thanks, PerryBebbington!

I'll git it a try!

This is really just first-year High School Algebra. The basic formula is: **Output = K1 * e ^{K2 * 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.

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.

Engineering is all about trade-offs. Performance vs Memory vs Processor Cycles vs Power Dissipation vs Cost vs Size vs .......

gfvalvo:

Engineering is all about trade-offs. Performance vs Memory vs Processor Cycles vs Power Dissipation vs Cost vs Size vs .......

Yes, of course. My light dimmer works as desired. I can swap processor time for memory use by using some kind of look up table as you suggest, but it won't make any difference to anything; I'll still be using the same processor, it will still do what I wanted it to do, it will still have unused memory and unused processor time. No amount of optimisation will change this or free up resources for another task as I don't have another task for it to do.