Topic: Need Help With a Logarithmic Function (Page 1 of 1) Pages that link to <a href="https://ozoneasylum.com/backlink?for=31285" title="Pages that link to Topic: Need Help With a Logarithmic Function (Page 1 of 1)" rel="nofollow" >Topic: Need Help With a Logarithmic Function <span class="small">(Page 1 of 1)</span>\

 
Wes
Paranoid (IV) Mad Scientist

From: Inside THE BOX
Insane since: May 2000

posted posted 08-30-2009 01:47

I have an interesting problem I was hoping some of the math/scripting gurus here could help me out with.

I've been building a circuit on top of an Arduino for a project I've been working on. Basically, it's a sophisticated control for controlling a series of lights in programmable patterns (at its simplest, just a series of four lights chasing in sequence). I've got a potentiometer hooked up to it to control the speed of the patterns; using a script I wrote in the Arduino environment, I read the pot, which gives me a value between 0 and 1023, and then I use that to calculate a delay between steps in the pattern.

FYI, here?s the basic function that calculates the speed:

code:
speedDelayMax = 1200;  // Maximum delay in milliseconds

float calcSpeedDelay(int potLevel) {
  speedLevel = speedPotLevel / 1023.0;               // Convert the pot reading to a percentage
  speedDelay = speedLevel * speedDelayMax;        // Determine milliseconds of delay
  return speedDelay;
}


Problem is, when using a liner-taper pot, I don't get enough sensitivity toward the fast end. In other words, turning the pot from slow to fast (1023 to 0), the pattern appears to jump very quickly into the fast range.

I tried using an audio-taper (or logarithmic-taper) pot and the result is much, much better; the pattern doesn't appear to speed up as quickly toward that end of the turn. The problem at this point, though, is that the taper on the audio pot works the wrong way. I want slow (1023) to be to the left and fast (0) to be to the right, which I can control by connecting the leads to the pot the right way round. Unfortunately, this doesn't change the direction of the taper; that's built into the hardware and can't be changed. So, I've decided to go back to using a linear-taper pot and to use a software solution instead. And that's where I need the help.

Basically, what I need is a function that takes the pot reading and recalculates it so that I get a reading that more closely represents the purple line on the following graph:



The 0 pot reading is the fast end, which is where I need more sensitivity. Luckily, the Arduino environment is close enough to PHP that I've been able to figure it out, but I'm still not very good at the whole math deal.

Why not just reverse the leads on the audio pot so it works the opposite way?
Well, as I said, that would reverse the reading I get from the pot, but it wouldn't change the taper. The taper is still at the wrong end. There is such a thing as a reverse-audio-taper (or antilogarithmic) pot, but they are almost impossible to find and would probably be expensive if I could locate one.

Why does fast have to be to the right?
It may sound picky, but to me it's intuitive. Turning a volume knob to the right increases the sound. Turning a dimmer knob (which I also have on my project) to the right increases a light's brightness. So, it only makes sense to me that turning the speed knob to the right should increase the speed.

Why not ask on the Arduino forum?
If it were an Arduino-specific question, I would. But I have more faith in the people here when it comes to scripting and math.

I may not have explained this very well, so let me know if there are any questions.



(Edited by Wes on 08-30-2009 02:12)

helven
Obsessive-Compulsive (I) Inmate

From:
Insane since: Aug 2009

posted posted 08-30-2009 05:36

you might need to check resistors. they're awesome at it.

Wes
Paranoid (IV) Mad Scientist

From: Inside THE BOX
Insane since: May 2000

posted posted 08-30-2009 06:27

Actually, I just came back to stop anyone from putting a lot of effort into this, because I just discovered a technique I believe is called shunting that might make a linear pot do what I want with the addition of the right resistor. It's the kind of alternative I've been looking for, but I didn't know what it was called.

Wes
Paranoid (IV) Mad Scientist

From: Inside THE BOX
Insane since: May 2000

posted posted 08-30-2009 07:27

OK, never mind. The hardware solution does not give me the result I want. It may work OK for an audio application, but not for this. All it does is clip one end of the output, which makes the other end seem more sensitive. But from my point of view, all it does is give me a reading of, for example, 92-0. This means I have to increase speedDelayMax to make up for the lost time and I just end up with the same end effect.

I think I'm still going to need to do this with software.

warjournal
Maniac (V) Mad Scientist

From:
Insane since: Aug 2000

posted posted 08-30-2009 08:26

Lin = Linear
Log = Log
Anti = Anti-Log

Anti = Lin + ( Lin - Log )
Anti = 2 * Lin - Log

??

Personally, I would try a gamma function. Then chuck a bunch of values at it until I got what I wanted.

Lord_Fukutoku
Maniac (V) Inmate

From: San Antonio
Insane since: Jul 2002

posted posted 09-02-2009 22:35

Maybe I'm missing something here (it has been awhile since I've taken a class or dealt with anything more complicated than converting degrees to rads), but the purple line looks pretty close to y = log(x). Stretch it, skew it, and translate it some and you should be able to get something close to it I would think.

Edit: Couple of quick tests:


--

Any sufficiently advanced bug is indistinguishable from a feature.

(Edited by Lord_Fukutoku on 09-02-2009 23:03)

Wes
Paranoid (IV) Mad Scientist

From: Inside THE BOX
Insane since: May 2000

posted posted 09-09-2009 09:08

OK, I think maybe the "degrees of rotation" in the graph I posted confused us both.

Let's start again. In Excel, I created a column of numbers 0-1023. In column B, I used the formula LOG(A1+1)*0.3321928095, which gave me a logarithmic result of fractions from 0 to 1.0. (I decided on the 0-1 result so I could use it to multiply against a given value of microseconds to determine amount of delay.)

What I get is the blue line on the following graph:



I think what I actually need (I say "think" because I've confused myself numerous times already) is something like the red line. The x-axis, by the way, actually goes to 1023, despite what it looks like.

Luckily, I discovered a library of math functions I can use in programming the Arduino. The following is what I have available:

http://www.arduino.cc/en/Reference/Mathh
http://www.nongnu.org/avr-libc/user-manual/group__avr__math.html

hyperbole
Paranoid (IV) Inmate

From: Madison, Indiana
Insane since: Aug 2000

posted posted 09-09-2009 18:11

Wes,
If you want to approximate the red line try a function like:

code:
.          x^n
   y = --------------
         (x-max) ^ n



The line you have there looks to me as if n should be about 4 or 6. Since you're only intrested in the first quandrant, you may use even or odd values for n. The larger you make n, the steeper the slope on the right side of the graph will be and the closer the bottom will be to a straight line approaching 0.


<edit...>Trying to align the numerator with the rest of the fraction.</edit>



-- not necessarily stoned... just beautiful.


(Edited by hyperbole on 09-09-2009 18:14)

Wes
Paranoid (IV) Mad Scientist

From: Inside THE BOX
Insane since: May 2000

posted posted 09-11-2009 05:24

OK, I've been working on this for the past hour and I'm still clueless and frustrated, probably because I'm not exactly sure what max is supposed to be.

I'm sure this is all due to something I'm misunderstanding on my end, but please allow me to review my goal to make sure both that I'm being clear and that I understand what I want, myself.

potReading is the reading from my potentiometer, which is from 0 to 1023, depending on where the dial is set.

delayMax is the maximum delay between changes in pattern, which we'll set at 1000 milliseconds (1 second).

I want to take potReading and calculate that to equal between 0.0 and 1.0, but in a nonlinear way (as indicated by the red line on the graph above). I will then multiply that value by delayMax to get the number of milliseconds of delay between steps.

I know I'm asking for what amounts to a complete solution here, but I swear I've worked on this independently for as far as my synapses will take me.

Wes
Paranoid (IV) Mad Scientist

From: Inside THE BOX
Insane since: May 2000

posted posted 09-11-2009 06:16

Haha! Never mind!

I decided to futz around a little more in Excel and came up with a solution!

First, I flipped the leads so I got 1023-0 instead of 0-1023. I also added 1 to the result so I got 1024-1 (0 gave me invalid results later on).

Then, I divided potReading^4 by potReading.

Next, I divided that by 1,073,741,824 (the maximum of the calculation above), which gave me 1.0-9.31323E-10.

Finally, I multiplied that by delayMax, which gave me a high delay to the left (slow) and a low delay to the right (fast). And the nonlinear effect looks terrific!

Thanks for helping me think it through!



(Edited by Wes on 09-11-2009 06:40)

Moon Shadow
Paranoid (IV) Inmate

From: Paris, France
Insane since: Jan 2003

posted posted 09-16-2009 17:43

Now that's some twisted logic

Basically you can just do (potReading/potReadingMax)^Pow

Edit : anyway that's what hyperbole said

----
If wishes were fishes, we'd all cast nets.



(Edited by Moon Shadow on 09-16-2009 18:02)

Wes
Paranoid (IV) Mad Scientist

From: Inside THE BOX
Insane since: May 2000

posted posted 09-17-2009 06:39

Ah -- that's a cleaner way of doing what I did in my 4th and 5th sentences.

I read hyperbole's suggestion, however, as (potReading^4)/(potReading-potReadingMax)^4 which didn't work for me. It's highly likely I misunderstood, though.



Post Reply
 
Your User Name:
Your Password:
Login Options:
 
Your Text:
Loading...
Options:


« BackwardsOnwards »

Show Forum Drop Down Menu