My Pot Position LED patterns not quite right ????

OLDmarty

Senior Member
Hi All,

I created this small code to read a pot position and generate a pattern of LEDs attached to the Port.B pins.
It works fine "as is", but when i try to change my pot range to more than 16 patterns on the LEDs, it never seems to go beyond my 16 pot ranges assigned.

The Pot_Position value is read from a pot attached to the ADC input on Pin C.0
The Pot_Position value is then divided by 16 to create 16 evenly spaced "zones" around the entire pot travel, it seems to work perfectly.

When i try to increase my range of 16 to say 20 and include 20 data values in my lookup table, the code doesn't seem to display the LED patterns for 20 different positions of the pot rotation.
The data values of $00 to $0F were just for my initial tests to prove it works, but the final values will not be in that order.

I feel i'm overlooking something, but there's not much in the code to go wrong, arghh!


Code:
#picaxe 14m2
#no_data

symbol Pot_Position = b0    'Store a variable of the Pot_Position ADC input into an 8bit number.
symbol LED_Loader = pinsB    'assign LED_loader to the entire PortB pins (B.0 to B.5)
dirsb = %11111111        'set PortB to all OUTPUTS.

do
if Pot_Position=0 then        'if pot value is 0 (the "off" position)
    LED_Loader=0        'then turn the LED_loader Leds OFF.
        else                'otherwise load pot value onto loader LEDs.
                    Pot_Position=Pot_Position/16    'divide pot into ranges of "16" (256/16=16 zones/patterns to display) to evenly create zones in the pot where each value will change.
                    lookup Pot_Position,($00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0A,$0B,$0C,$0D,$0E,$0F),LED_Loader    'Load value onto Loader LEDs!
endif
    readadc C.0,Pot_Position             'read pot value on pin C.0 (ADC) to set the "pattern" value for the LED_loader.
loop
 
Last edited:
Is the pot a linear pot - as in used for voltage control - or a logarithmic pot - as used for volume control?
Log pots have a non-linear change across the pot's rotation and that might be a problem when interpreting the ADC values.
 
Is the pot a linear pot - as in used for voltage control - or a logarithmic pot - as used for volume control?
Log pots have a non-linear change across the pot's rotation and that might be a problem when interpreting the ADC values.

Yes, it's a 50k (B) Linear Pot and currently it works perfectly that all 16 zones are spread evenly from one end of the pot (all LEDs off) to the other end of travel where all LEDs are ON.
 
The Pot_Position value is then divided by 16 to create 16 evenly spaced "zones" around the entire pot travel, it seems to work perfectly.

When i try to increase my range of 16 to say 20 and include 20 data values in my lookup table, the code doesn't seem to display the LED patterns for 20 different positions of the pot rotation.

So to get 20 discrete points, you're dividing by 13, rather than 16 ❓ (given that you can't divide by 12.8)
 
Hi,
Code:
       Pot_Position=Pot_Position/16    'divide pot into ranges of "16" (256/16=16 zones/patterns to display) ...
You haven't listed the code which doesn't work, but my guess is that you've overlooked that each sector/zone for 20 is only 12.8 units wide. So you need to divide the ADC value (strictly maximum 255) by 13 or 12. If you divide by 13, the last sector will be slightly small (247 - 255) or if you use 12, there will be 21 zones. So the lookup would need 21 values, but you can easily repeat one of the values in the list.

In either case, one of the zones will be slightly the wrong size, which could be improved by using READADC10 that gives a maximum value of 1023, so for 20 zones needs to be divided by 51.15, then 51 will give 20 almost equal sectors/zones.

Cheers, Alan.
 
Hi,

You haven't listed the code which doesn't work, but my guess is that you've overlooked that each sector/zone for 20 is only 12.8 units wide. So you need to divide the ADC value (strictly maximum 255) by 13 or 12. If you divide by 13, the last sector will be slightly small (247 - 255) or if you use 12, there will be 21 zones. So the lookup would need 21 values, but you can easily repeat one of the values in the list.

In either case, one of the zones will be slightly the wrong size, which could be improved by using READADC10 that gives a maximum value of 1023, so for 20 zones needs to be divided by 51.15, then 51 will give 20 almost equal sectors/zones.

Cheers, Alan.

Thank You Alan,

I do (now) see my error with dividing by a larger number instead of a smaller number to get more zones on my pot.
Yes, depending on the division there will always be a few values missing(or extra) at the end of range of the pot, but that's ok.
 
Hi OLDmarty
position 0 plus position 20 = 21
so (21 x 65536 / 255 ) = 5397
so try
Pot_Position=Pot_Position **5397
 
I do (now) see my error with dividing by a larger number instead of a smaller number to get more zones on my pot.
Using the wrong divisor does seem to have been the issue. If you want 20 LED steps it's -
Code:
          0 to 255
0 to 19 = --------
             N
So your 'N' to divide by will be 255/19, or 1023/19 if using READADC10.

Yes, depending on the division there will always be a few values missing(or extra) at the end of range of the pot, but that's ok.
Because 'N' has to be an integer for a PICAXE it does mean that you can end up with more pot values for the highest LED section than others. And you may sometimes have to limit the divided value so you doesn't exceed the number of LED you have ...
Code:
Symbol LEDS         = 20

Symbol LEDS_MINUS_1 = LEDS - 1
Symbol DIVISOR      = 255 / LEDS_MINUS_1

Do
  ReadAdc POT_PIN, b0
  b1 = b0 / DIVISOR Max LEDS_MINUS_1
  SerTxd("Pot=", #b0, TAB, "LED=", #b1, CR, LF)
Loop
You can spread things more evenly if you have a means of specifying 'this LED has this pot value range', but division will often be good enough,

You can also scale values so, if 'N' were ideally 5.1, you can multiply that by 10 and divide by 51, providing the number you are dividing has also been scaled by 10, but watch out for overflow, the pot value multiplied becoming greater than 65535 ($FFFF).

There's also the '**' trick described by 'marks' above.
 
Last edited:
Hi All,

Well, i've tried a few different coding options and they all seem to work much better than my original code snippet.

I have also increased the pot divisions to 40 and 80 zones instead of my initial 20 pot zones for the ADC to decode.
However, i am seeing some jitter between any 2 adjacent pot positions all across the pot rotation.
(i see some slight jitter on the 20 position code too, but the jitter seems to (obviously) become more common as i increased my pot zones to 40 or 80 positions).

I think this is because the (50k) pot divisions are now too small for the ADC to accurately decode between adjacent values and maybe raising the pot to 100k might reduce or eliminate the jitter between any 2 positions.

My test project has 100uF on the 5v rail to offer stability in the power supply as well as a 0.1uf decoupling cap on the power pin of the Picaxe chip.
I'm now thinking about putting a 0.1uf to 1uF cap from the pot wiper to ground to help stabilize any slight pot drift.

All input welcomed, but i also have a feeling the better way to do this would be to use a rotary encoder instead of a pot, but that's a different chapter ;-)
 
Hi,
.... maybe raising the pot to 100k might reduce or eliminate the jitter between any 2 positions.
Unlikely, and if anything you should be reducing the pot value to 40k or less. The PIC(axe) data sheet recommends that the source resistance of the signal driving the ADC should be less than 10k, which is equivalent to a 40k pot at its middle position (i.e. 20k to ground in parallel with 20k to the supply rail). Alternatively, it recommends connecting a capacitor directly from the ADC input pin to ground (as you are proposing), probably 100nF or perhaps less (not an electrolytic type).

Cheers, Alan.
 
There will always be potential for jitter; if a pot is sitting on the boundary of being say 9 and 10 just a single bit change from noise will have it switching between the two. Other than at the boundaries there shouldn't be any jitter.

Adding a capacitor on the input will help reduce jitter but it's still possible that the smoothed voltage is right on the boundary so it's not eliminated.

The best way to handle jitter is to have some hysteresis, so if it's moving up it won't go down until there's more than noise movement in the reverse direction. For example, if it is above 10 it won't go back to 9 until the input producing those numbers is less than 9.8, and it won't go to 10 until it's above 10.2
 
Back
Top