setting values and percentages


Closed Thread
Results 1 to 38 of 38
  1. #1
    Join Date
    Oct 2009
    Posts
    583

    Default setting values and percentages

    Hi,

    I'm in the process of developing my LED Aquarium light controller a stage further and smoothing out the pulse width modulation by using 0 - 4095 steps rather than the current 255 setps. I have the leds fading nicely when using preset hard coded values, but I want to be able to program the maximum setting for brightness via the LCD as a percentage between 0 and 100 %. When I used 255 steps the following code worked

    Code:
    brightness:
     
    Lcdout $FE,2
    LCDOUT $FE,$80,"Set Max Brightness"
    IF H_butt = 0 THEN GOSUB up
    IF M_butt = 0 THEN GOSUB down
    If (maxbright * 100)/255 = 100 then
    LCDOUT $FE,$C0,"Channel 1 "
    LCDOut $FE,$D4,dec3 (maxbright *100)/255,"%"
    endif
    
    If (maxbright * 100)/255 =0 or (maxbright * 100)/255 <10 then
    LCDOUT$FE,$C0,"Channel 1 "
    LCDOut $FE,$D4,dec1 (maxbright *100)/255,"% "
    endif
    
    if (maxbright * 100)/255 >=10 and (maxbright * 100)/255 <100 then
    LCDOUT$FE,$C0,"Channel 1 "
    LCDOut $FE,$D4,dec2 (maxbright *100)/255,"%   "
    endif
        B_max = maxbright 
    write 8,b_max      
        
    If S_butt = 0 then
        pause 200 
        goto brightness2
    endif 
    goto brightness
    But I'm stumped trying to convert this to use 4095 steps. Replacing the 255 with 4095 seemed the logical answer, but that didn't work. Changing the < = or > values (ie 10% would be 409.5) didn't work either.

    Any suggestions ?

  2. #2
    Join Date
    May 2013
    Location
    australia
    Posts
    2,397


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    you will find that the led 'brightness' will not be a linear progression over the full 4096 steps anyway . its probably easier to have a finite number of brightness levels in a lookup table (how many brightness levels do you think the average person could differentiate between?)
    try starting with 20 levels [ 0=off ,( and 18 between ) , 4095=full on] , those in between levels could be established by observation

  3. #3
    Join Date
    Jan 2005
    Location
    Montreal, Quebec, Canada
    Posts
    2,661


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Wouldn't he be better just staying with 255? Or am I missing something obvious?

    Robert

  4. #4
    Join Date
    May 2013
    Location
    australia
    Posts
    2,397


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    maybe malcom could refresh us on the issue , but as I understand it
    1.the external pwm chip has 4096 steps
    2.the loop update time is in 1 sec intervals
    3. the desired fade in /out period divided by the loop time yields too few "pwm" steps for a smooth looking transition if you simply divide 4096 by the number of available steps

    my theory is that if the steps are chosen well the effect may be smoother

  5. #5
    Join Date
    Jun 2009
    Location
    Sc*nthorpe, UK
    Posts
    333


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Quote Originally Posted by Scampy View Post
    Hi,

    I'm in the process of developing my LED Aquarium light controller a stage further and smoothing out the pulse width modulation by using 0 - 4095 steps rather than the current 255 setps. I have the leds fading nicely when using preset hard coded values, but I want to be able to program the maximum setting for brightness via the LCD as a percentage between 0 and 100 %. When I used 255 steps the following code worked

    Code:
    brightness:
     
    Lcdout $FE,2
    LCDOUT $FE,$80,"Set Max Brightness"
    IF H_butt = 0 THEN GOSUB up
    IF M_butt = 0 THEN GOSUB down
    If (maxbright * 100)/255 = 100 then
    LCDOUT $FE,$C0,"Channel 1 "
    LCDOut $FE,$D4,dec3 (maxbright *100)/255,"%"
    endif
    
    If (maxbright * 100)/255 =0 or (maxbright * 100)/255 <10 then
    LCDOUT$FE,$C0,"Channel 1 "
    LCDOut $FE,$D4,dec1 (maxbright *100)/255,"% "
    endif
    
    if (maxbright * 100)/255 >=10 and (maxbright * 100)/255 <100 then
    LCDOUT$FE,$C0,"Channel 1 "
    LCDOut $FE,$D4,dec2 (maxbright *100)/255,"%   "
    endif
        B_max = maxbright 
    write 8,b_max      
        
    If S_butt = 0 then
        pause 200 
        goto brightness2
    endif 
    goto brightness
    But I'm stumped trying to convert this to use 4095 steps. Replacing the 255 with 4095 seemed the logical answer, but that didn't work. Changing the < = or > values (ie 10% would be 409.5) didn't work either.

    Any suggestions ?
    This code displays the maxbright value which comes from the up/down routines could you post these? Also obviously maxbright has to be a word?

  6. #6
    Join Date
    May 2013
    Location
    australia
    Posts
    2,397


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    just notice your brackets are still incorrect too . if you use multiple logical conditions in if statements they must be parenthesized
    eg
    If (maxbright * 100)/255 =0 or (maxbright * 100)/255 <10 then

    should be

    If ((maxbright * 100/255 =0 ) or ( (maxbright * 100/255 <10 ) then

  7. #7
    Join Date
    Jun 2009
    Location
    Sc*nthorpe, UK
    Posts
    333


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Quote Originally Posted by Scampy View Post
    When I used 255 steps the following code worked
    Richard,

    I am puzzled because like you I believe the parenthesis are required but in this case apparently not. Certainly they are for other software and therefore I use them as you do as "good practice".

  8. #8
    Join Date
    May 2013
    Location
    australia
    Posts
    2,397


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    with out the brackets you rely on the "operator precedence" order that the compiler will use , its often not what you really want . best bet is to always use brackets it eliminates the doubt

    ps I typed reply #6 wrong left the closing brackets after 100's out
    should be
    If ((maxbright * 100)/255 =0 ) or ( (maxbright * 100)/255 <10 ) then
    Last edited by richard; - 29th June 2014 at 11:34.

  9. #9
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Hi Guys and thanks for the input.

    As requested here is the complete brightness routine that works when using Darrels software PWM.

    Code:
    brightness:
     
    Lcdout $FE,2
    LCDOUT $FE,$80,"Set Max Brightness"
    IF H_butt = 0 THEN GOSUB up
    IF M_butt = 0 THEN GOSUB down
    If (maxbright * 100)/255 = 100 then
    LCDOUT $FE,$C0,"Channel 1 "
    LCDOut $FE,$D4,dec3 (maxbright *100)/255,"%"
    endif
    
    If (maxbright * 100)/255 =0 or (maxbright * 100)/255 <10 then
    LCDOUT$FE,$C0,"Channel 1 "
    LCDOut $FE,$D4,dec1 (maxbright *100)/255,"% "
    endif
    
    if (maxbright * 100)/255 >=10 and (maxbright * 100)/255 <100 then
    LCDOUT$FE,$C0,"Channel 1 "
    LCDOut $FE,$D4,dec2 (maxbright *100)/255,"%   "
    endif
        B_max = maxbright 
    write 8,b_max      
        
    If S_butt = 0 then
        pause 200 
        goto brightness2
    endif 
    goto brightness
    
    brightness2: 
     
    Lcdout $FE,2
    LCDOUT $FE,$80,"Set Max Brightness"
    IF H_butt = 0 THEN GOSUB up
    IF M_butt = 0 THEN GOSUB down
    If (maxbright * 100)/255 = 100 then
    LCDOUT $FE,$C0,"Channel 2 "
    LCDOut $FE,$D4,dec3 (maxbright *100)/255,"%"
    endif
    
    If (maxbright * 100)/255 =0 or (maxbright * 100)/255 <10 then
    LCDOUT$FE,$C0,"Channel 2 "
    LCDOut $FE,$D4,dec1 (maxbright *100)/255,"% "
    endif
    
    if (maxbright * 100)/255 >=10 and (maxbright * 100)/255 <100 then
    LCDOUT$FE,$C0,"Channel 2 "
    LCDOut $FE,$D4,dec2 (maxbright *100)/255,"%   "
    endif
        
        W_max = maxbright
    write 9,W_max 
    pause 200
    If S_butt = 0 then
        pause 200 
        LCDOUT $FE,1   
        goto mainmenu
    endif
    goto brightness2
    
    up:
        maxbright = maxbright + 1
        IF maxbright > 255 THEN maxbright = 0
        pause 50
    RETURN
    down:
        maxbright = maxbright - 1
        IF maxbright = 0 THEN maxbright = 255
        pause 50
    RETURN
    I can't argue with the brackets - all I know when I enter that menu option I can press the up and down buttons and the LCD displays 0% - 100%, and when checked using a diagnostics section which displays the variable value it correctly shows 0 - 255 and 127 for a 50% value - However I'm now using a PCA 9685 chip, which has a resolution of 4095 steps, so the progression is nice and smooth, and all I need is to repeat this but with 4095 steps, ie so 100% = 4095, 1%=40.95 (or 41 as it would need to be an integer) and 50% would equal 2047, but just can't seem to get my head round the calculation (never was any good at percentages at school all those years ago !

    Malcolm

  10. #10
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Quote Originally Posted by richard View Post
    maybe malcom could refresh us on the issue , but as I understand it
    1.the external pwm chip has 4096 steps
    2.the loop update time is in 1 sec intervals
    3. the desired fade in /out period divided by the loop time yields too few "pwm" steps for a smooth looking transition if you simply divide 4096 by the number of available steps

    my theory is that if the steps are chosen well the effect may be smoother
    Close

    With a friends help I've implemented a routine using the internal timers to get timings under a second.

    Code:
    ASM
    INT_LIST  macro   ;  IntSource,   Label,        Type, ResetFlag?
            INT_Handler   TMR1_INT,  _ToggleLED1,   ASM,  yes        
        endm
        INT_CREATE                                  ; Creates the interrupt processor
    ENDASM
    
    T1CON = %00000001                               ; free-running, 1:1 prescaler
    TMR1H = %11111111
    TMR1L = %11111011
    @   INT_ENABLE   TMR1_INT                       ; enable Timer1 interrupts
    And

    Code:
    ToggleLED1:
    TMR1H = %11111111
    TMR1L = %11111011
    pcaPwmValue0=pcaPwmValue0+1 
    pcaPwmValue1=pcaPwmValue1+1 
    @ INT_RETURN
    I can go from 0 - 4095 in less than two minutes, which helps in test runs.

    The ramp up is controlled by the case statement

    Code:
    case DAWN
    lcdout $FE,$80+15,"DAWN "  
    if pcaPwmValue0 => blue_delay_in then 
    B_PWM=B_PWM+1
    pcaPwmValue0 = 0 
    endif
    if B_PWM => B_MAX then   
    Blue_Day_Cycle = DAY
    endif
    The value for the pulse width is then written to the PCA chip in the main loop

    Code:
    pcaChannel = 0                                              ;Set a PWM channel
    lcdout $FE,$80,"CH1"
    i2cControl = $6 + 4*pcaChannel                              ;LED0_ON_L $6
    I2CWRITE SDApin,SCLpin,i2cWriteAddress,i2cControl,[0,0,0,B_PWM ]
    I have everything working fine, when using pre-set values for the fade in times and brightness and can do a full dawn, day, dusk, night cycle in five minutes, I just need to be able to sort out the manual settings for adjusting the the brightness so I can enter 0-100% rather than 0 - 4095 on the LCD

    Hope this additional information helps

  11. #11
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,531


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    How about
    Code:
    PWMValue = Percentage */ 10483
    ?

  12. #12
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Bit of a fudge, but it works well enough

    Code:
    '*******************************************************************************
    ' Set Brightness levels for each channel
    
    
    brightness:
    
    B_max = (4095/100)*maxbright
    
    Lcdout $FE,2
    LCDOUT $FE,$80,"Set Max Brightness"
    IF H_butt = 0 THEN GOSUB up
    IF M_butt = 0 THEN GOSUB down
    
    If maxbright  = 100 then
    LCDOUT $FE,$C0,"Channel 1 "
    LCDOut $FE,$D4,#maxbright,"%"
    endif
    
    If maxbright  =0 or maxbright <10 then
    LCDOUT$FE,$C0,"Channel 1 "
    LCDOut $FE,$D4,dec1 maxbright,"% "
    endif
    
    if maxbright >=10 and maxbright <100 then
    LCDOUT$FE,$C0,"Channel 1 "
    LCDOut $FE,$D4,dec2 maxbright,"%   "
    endif
         
    If S_butt = 0 then
        pause 100 
        goto brightness2
    endif 
    goto brightness
    
    
    
    brightness2: 
     
    W_max = (4095/100)*maxbright
    
    Lcdout $FE,2
    LCDOUT $FE,$80,"Set Max Brightness"
    IF H_butt = 0 THEN GOSUB up
    IF M_butt = 0 THEN GOSUB down
    
    If maxbright  = 100 then
    LCDOUT $FE,$C0,"Channel 2 "
    LCDOut $FE,$D4,#maxbright,"%"
    endif
    
    If maxbright  =0 or maxbright <10 then
    LCDOUT$FE,$C0,"Channel 2 "
    LCDOut $FE,$D4,dec1 maxbright,"% "
    endif
    
    if maxbright >=10 and maxbright <100 then
    LCDOUT$FE,$C0,"Channel 2 "
    LCDOut $FE,$D4,dec2 maxbright,"%   "
    endif
    
    pause 200
    If S_butt = 0 then
        pause 100 
        LCDOUT $FE,1   
        goto mainmenu
    endif
    goto brightness2
    
    up:
        maxbright = maxbright + 1
        IF maxbright >= 100 THEN maxbright = 100
        pause 250
    RETURN
    down:
        maxbright = maxbright - 1
        IF maxbright <= 0 THEN maxbright = 0
        pause 250
    RETURN
    Again, the lack of floating point maths in PBP means the calculations are not exact, but this way every 1% increment equals a block of 41 steps on the PCA chip, so 50% brightness = 2050 but that's close enough to the 2047 is should be and to be honest I doubt if the human eye could distinguish the difference

  13. #13
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,531


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Hi,
    If it works it works.
    If you want it a little better PWMValue = Percentage */ 10483 will give you 2047 at 50%.

    /Henrik.

  14. #14
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    So using my variables B_max = (4095/100)*maxbright would that be

    Code:
    B_max = maxbright */10483
    Nope - that don't work
    Last edited by Scampy; - 29th June 2014 at 19:21.

  15. #15
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,531


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    If B_Max is the value you send to the PWM controller (0-4095) and maxbright is the percentage value (0-100) as entered by the user then yes.
    Actually, at 100% it'll give you 4094 so make that B_max = maxbright */10484 instead.

    /Henrik.

  16. #16
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Quote Originally Posted by HenrikOlsson View Post
    If B_Max is the value you send to the PWM controller (0-4095) and maxbright is the percentage value (0-100) as entered by the user then yes.
    Actually, at 100% it'll give you 4094 so make that B_max = maxbright */10484 instead.

    /Henrik.
    Yes - B_max and W_max are the values that are sent to the PCA chip (0 - 4095). And maxbright has a value between 0 and 100 as you assumed. But using that line of code the values for B_max and W_max do not change from the pre-programmed default of 4095 after the menu option is used to change the max brightness level

  17. #17
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,531


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Hi,
    Strange..... I tested the following code
    Code:
    HSEROUT["Program start",13]
    For i = 0 to 5
        Lookup2 i,[1, 10, 25, 50, 75, 100], maxbright
        B_max = maxbright */ 10484
        HSEROUT ["Maxbright: ", DEC3 maxbright, "     B_Max: ", DEC4 B_max, 13]
    NEXT
    And got the following results:
    Code:
    Program start
    Maxbright: 001     B_Max: 0040
    Maxbright: 010     B_Max: 0409
    Maxbright: 025     B_Max: 1023
    Maxbright: 050     B_Max: 2047
    Maxbright: 075     B_Max: 3071
    Maxbright: 100     B_Max: 4095
    Seems to work fine here....

    /Henrik.

  18. #18
    Join Date
    Jun 2009
    Location
    Sc*nthorpe, UK
    Posts
    333


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Quote Originally Posted by Scampy View Post
    the values for B_max and W_max do not change from the pre-programmed default of 4095 after the menu option is used to change the max brightness level
    Is the default of 4095 inside the main loop and resetting B_max and W_max after the menu option returns to the main loop.

  19. #19
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Don't know what happened to my post last night, but I found out why it was doing that - It was one of those oversights caused through hours of programming without a break. The menu option saved all the changes when exiting from the menu to the main program, so unless this action was performed all the changes were lost if you remained in the menu section as the diagnostics option reads the values stored in memory and thus read the defaults and over wrote them. This was changed so each section of the menu now writes the new values to memory when exiting the option and reverting back to the menu screen, so switching between menu options and then the diagnostics means that the changes made in any of the other menu sections are read back in.

    One thing I would like to know is what the */ function means

  20. #20
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,531


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    It's been covered multiple times on the forum and it's covered in the manual.
    In short, think of it as multiplying by units of 1/256. 10484/256=40.95.

    /Henrik.

  21. #21
    Join Date
    Jun 2009
    Location
    Sc*nthorpe, UK
    Posts
    333


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    One thing I would like to know is what the */ function means
    This is what I understand or misunderstand possibly.

    Internally the maths can have a 32 bit result because the PIC has a 32 bit register. But if your maths calculation will fit in a word then using word=byte*byte will work and you do not need ** or */.

    If you have wordH=word**word and wordL=word*word then you have all 32 bits stored in two words.

    */ is less obvious but gives the middle word of the 32 bits. Which is the same as word=word*word/256 losing the top and bottom 8 bits.

    If as in your case and as you know 4095/100 gives a result of 40 therefore B_max = (4095/100)*maxbright will give 2000 when maxbright is 50.

    Whereas 4095*256/100 gives result of 10483 and 50*/10483 gives 2047 because by multiplying by 256 and using the */ to remove the 8 lower bits (or divide by 256 which is the same) increased accuracy is achieved. So where is the precision lost? The division /100 is the source of lost precision so as a rule multiply first and divide last which is exactly what */ does in that your program multiplies by 256 and */ divides by 256 last. As an aside working this way reduces the calculations within the program, there is only a division

    A question then. What is the result of 50*4095/100 2000 or 2047? and (4095/100)*50?

  22. #22
    Join Date
    May 2013
    Location
    australia
    Posts
    2,397


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    result 50*4095/100 is 2047
    result (4095/100)*50 is 2000

    the calc follows typical bodmas rules (brackets, of , divide .....) see precedence in manual

    the only 'suprising' bit is that the indermediate result (50*4095) is 204750 way too big for a word var. the pbp compiler code does indeed use 32 bit intermediate results.
    the */ and ** operators allow you access these 32 bit results (providing you follow the rules of course)

  23. #23
    Join Date
    May 2013
    Location
    australia
    Posts
    2,397


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    however
    if you have a word var say numx
    and x =4095
    then 50*numx/100 the result is 81
    the word var causes a intermediate stage overflow (bits 0-15 of 204750 =8142)
    I still say integer math is tricky and results need to be double checked

  24. #24
    Join Date
    Jun 2009
    Location
    Sc*nthorpe, UK
    Posts
    333


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Quote Originally Posted by richard View Post
    however
    if you have a word var say numx
    and x =4095
    then 50*numx/100 the result is 81
    the word var causes a intermediate stage overflow (bits 0-15 of 204750 =8142)
    I do not understand this.
    What is the relationship between numx and x?
    Why does an intermediate stage overflow occur and what is an intermediate stage overflow?

  25. #25
    Join Date
    May 2013
    Location
    australia
    Posts
    2,397


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    What is the relationship between numx and x?
    poor typing
    if you have a word var say numx
    and numx =4095
    then 50*numx/100 the result is 81
    the word var causes a intermediate stage overflow (bits 0-15 of 204750 =8142)
    I still say integer math is tricky and results need to be double checked

    intermediate overflow
    50*4095 =204750 max value for word 65535 therefore an overflow occurs and the result becomes 8142
    Last edited by richard; - 3rd July 2014 at 10:44. Reason: more info

  26. #26
    Join Date
    Jun 2009
    Location
    Sc*nthorpe, UK
    Posts
    333


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Quote Originally Posted by EarlyBird2 View Post
    I do not understand this.

    Why does an intermediate stage overflow occur and what is an intermediate stage overflow?
    Could you explain please?

  27. #27
    Join Date
    Jun 2009
    Location
    Sc*nthorpe, UK
    Posts
    333


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Quote Originally Posted by richard View Post
    intermediate overflow
    50*4095 =204750 max value for word 65535 therefore an overflow occurs and the result becomes 8142
    But the result is not stored in numx it is stored in another word variable called result?

  28. #28
    Join Date
    May 2013
    Location
    australia
    Posts
    2,397


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    simply stated
    if there is a var in a multilstage calculation then any intermediate results must be able to be stored in that var , its just the way it works.
    try it yourself
    the */ ,** ops are the only workaround

  29. #29
    Join Date
    May 2013
    Location
    australia
    Posts
    2,397


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    you might have missed the point

    50*4095/100 is 2047 this works (all constants)

    numx=4095
    50*numx/100 is 81 this does not

    numy=50
    numy*4095/100 is 81 this does not

    numz=100
    50*4095/numz is 81 this does not

  30. #30
    Join Date
    Jun 2009
    Location
    Sc*nthorpe, UK
    Posts
    333


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Now I understand what you are saying. It does seem odd to me that there is a 32 bit register for maths calculation which can not be used if there is a word or byte variable in the calculation because the word/byte variable could overflow. A bit more thinking is required on my part, I think.

    Does this mean that using ** and */ uses 32 bit and * only 16 bit?
    Last edited by EarlyBird2; - 3rd July 2014 at 11:48. Reason: more thinking

  31. #31
    Join Date
    Mar 2003
    Location
    Commerce Michigan USA
    Posts
    1,166


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Look at the Statement keyword "DIV32". It is possible to compute all of these statements:
    numx=4095
    50*numx/100

    numy=50
    numy*4095/100

    numz=100
    50*4095/numz
    Dave Purola,
    N8NTA
    EN82fn

  32. #32
    Join Date
    Jun 2009
    Location
    Sc*nthorpe, UK
    Posts
    333


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Quote Originally Posted by EarlyBird2 View Post
    Now I understand what you are saying. It does seem odd to me that there is a 32 bit register for maths calculation which can not be used if there is a word or byte variable in the calculation because the word/byte variable could overflow. A bit more thinking is required on my part, I think.

    Does this mean that using ** and */ uses 32 bit and * only 16 bit?
    After more thought and a bit of direction to look at DIV32 by Dave.

    Multiplication stores a 32 bit result internally but the normal divide only works on the lower 16 bits which causes the 'overflow' problem highlighted by Richard. DIV32 was created specifically to overcome the 16 bit division limitation and as Dave says is a solution here.

    Scampy asked about */ and how that works. It works by removing the division in the calculation so there is no 16 bit divide, there is an 8 bit shift or a divide by 256 of the 32 bits whichever way one wishes to visualise the process. Knowing that */ will apply a division by 256 one has to take account of this in the program.

    In this case

    B_max = (4095/100)*maxbright

    take 4095/100 and multiply by 256 giving 10483.2 which is rounded up to 10484. Resulting in this

    B_max = maxbright*/10484 which results in an integer value of 2047 when maxbright is 50.
    Last edited by EarlyBird2; - 4th July 2014 at 07:44.

  33. #33
    Join Date
    May 2013
    Location
    australia
    Posts
    2,397


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    I wrote this little bit of code to experiment with this thread its interesting to note that to */ method fails when your percentage goes past 1600 in lieu of 50
    but the div32 method is quit sound up until the result exceeds 2^16 (65535 )
    you need to remember that */ is the middle 16 bits and if you overflow that your still in trouble
    Code:
    ****************************************************************
    '*  Name    : UNTITLED.BAS                                      *
    '*  Author  : [select VIEW...EDITOR OPTIONS]                    *
    '*  Notice  : Copyright (c) 2014 [select VIEW...EDITOR OPTIONS] *
    '*          : All Rights Reserved                               *
    '*  Date    : 7/2/2014                                          *
    '*  Version : 1.0                                               *
    '*  Notes   : 16f684                                                  *
    '*          :                                                   *
    '****************************************************************
      
    #CONFIG
         __config _INTRC_OSC_NOCLKOUT & _CP_OFF & _WDT_ON  &  _PWRTE_ON  &  _MCLRE_OFF 
    #ENDCONFIG
     include "alldigital.pbp"
     
     
     
     
     
     
                  OPTION_REG.7=0
                  trisa = %11111110
                 
                  DEFINE OSC 4
                  so var porta.0
                  dq var portc.1
                  Nposn var word
                  ss var word
                  s2 var word    
                  s1 var word
                  
                   
        high so         
        ss=4095 
        s1=1600
        s2=100      
             
        pause 4000       
        serout2 so,84,[ "ready ",13,10] 
        lop: 
        pause 2000
        nposn=s1*ss
        nposn = div32 s2          
        serout2 so,84,["1 " ,#Nposn,13,10   ]   
        nposn=1600*4095/100          ; you need to adjust this line too
        serout2 so,84,["2 " ,#Nposn,13,10   ]
        nposn =  s1  */ 10484
        serout2 so,84,["3 ", #Nposn,13,10   ]
        nposn=s1*ss/100
        serout2 so,84,["4 ", #Nposn,13,10   ] 
        
        goto lop

  34. #34
    Join Date
    Jun 2009
    Location
    Sc*nthorpe, UK
    Posts
    333


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Quote Originally Posted by richard View Post
    the div32 method is quit sound up until the result exceeds 2^16 (65535 )
    you need to remember that */ is the middle 16 bits and if you overflow that your still in trouble
    Is this because of the word variable being used?
    Is this different in PBPL?

  35. #35
    Join Date
    May 2013
    Location
    australia
    Posts
    2,397


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    yes only because the result needs to fit a word var


    all of this only applies to pbpw only , pbpl is another story
    Last edited by richard; - 4th July 2014 at 08:49. Reason: misunderstood question

  36. #36
    Join Date
    Jun 2009
    Location
    Sc*nthorpe, UK
    Posts
    333


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Quote Originally Posted by richard View Post
    no its not because of the word var its just the way */ works .

    all of this only applies to pbpw only , pbpl is another story
    Yes */ can only result in a word the same applies to DIV32 in PBP2.xx as LONGs are not supported.

    PBP3 supports LONG variables and */ returns the top 32 bits of a 48 bits internal result, ignoring the lower 16 bits or dividing by 65536 which ever you prefer.

  37. #37
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,531


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Hi,

    With PBPW a multiplication results in an internal 32bit result. The */ operator returns the middle 16 bits (inherent division by 256) while the ** operator returns the top 16bits (inherent division by 65536) of this 32bit intermediate result. You need a WORD variable to accommodate the "full" result.

    With PBPL a multiplication results in an internal 48bit result. The */ operator returns the middle 32 bits (inherent division by 256) while the ** operator returns the top 32bits (inherent division by 65536) of this 48bit intermediate result. You need a LONG variable to accommodate the full result.

    Yes */ can only result in a word the same applies to DIV32 in PBP2.xx as LONGs are not supported.
    You don't need PBP3 to use LONGs. Support for that was introduced in PBP2.50, 7 years ago. But you DO need to use an 18F part.

    And, finally, DIV32 isn't supported (not needed) with PBPL since it uses a 32bit division routine by default.

    All this according to the manual.

    EDIT: Both the */ and ** operators supports variables on both sides of the operator while DIV32 requires a constant on the right side. You can't do
    Code:
    Dummy = 1000*1000
    Result = DIV32 myVAR   ' Won't work, DIV32 requires division by a constant.
    EDIT again, about that DIV32 requiring a constant.....I'm not sure any more. Must try it on actual hardware so you may want to disregard that for the moment :-)

    /Henrik.
    Last edited by HenrikOlsson; - 4th July 2014 at 10:21.

  38. #38
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,531


    Did you find this post helpful? Yes | No

    Default Re: setting values and percentages

    Aargh, not allowed to edit my post....
    Regarding the DIV32 - I was wrong, it's more the other way around. Doing Dummy = 1000*1000 won't work because both are constants. At least one of the vaules must be a variable or the compiler will replace the multiplication with a constant resulting in the internal system variables not containing the value for DIV32 to operate on. See here and here for more details.

    Sorry for the mixup in my previous reply.

    /Henrik.

Similar Threads

  1. POT part values
    By Michael in forum mel PIC BASIC Pro
    Replies: 7
    Last Post: - 24th January 2009, 10:41
  2. Port Values
    By Pesticida in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 2nd January 2007, 20:44
  3. t in POT, c's values
    By selbstdual in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 24th August 2006, 23:30
  4. Numeric Values
    By Armando Herjim in forum General
    Replies: 8
    Last Post: - 28th June 2006, 01:54
  5. Wrong values with COSINE!
    By Eng4444 in forum mel PIC BASIC Pro
    Replies: 24
    Last Post: - 8th May 2006, 16:59

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts