Altering a variable in a loop.


Closed Thread
Results 1 to 27 of 27
  1. #1
    Join Date
    Feb 2004
    Location
    Michigan, USA
    Posts
    305

    Default Altering a variable in a loop.

    I'm stuck!

    I have a program that increments or decreases a variable from 0 to 5, or from 5 to 0 depending on button presses. Each push of the buttons alters the value up or down by one.

    Each of the numbers 0 to 5 corresponds to a current output. For simplicity, lets say 0 is off, 1 = 100mA, 2 = 200mA etc etc.

    Now, at each current level there is a pwm output. It is altered by a basic feedback loop and can do limited current control by increasing or decreasing the duty cycle.
    What I need to do is have a set duty cycle that gives close to 100mA or 200mA etc as soon as the loop is entered, and than is able to control its self by feedback. Basically this is to speed up initial on time or speed up the output when going from say 100mA to 200mA. Otherwise the program has to loop and increase duty cycle from 0 each time or from the level at the previous set current until target is met. I need it to start at closer to target. Obviously if I put that start number in the loop, it will never self regulate.

    So how do I get it to start at a number, read it once then enter the regulation loop?

  2. #2
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    Hi,
    Several ways to do it, as usual. Here's one:
    Code:
    ' Setting is your variable that step or down between 0-5
    Lookup Setting, [12, 30, 55, 76, 98, 120], BaseDutyCycle
    Another way would be to not step the Setting variable between 0 and 5 but to actually step it directly between dutycycle values
    Code:
    Select Case Step
      Case 12
        IF DOWN THEN
           Setting = 12 ' We're at the bottom setting
        ELSE
           Setting = 30
     
      Case 30
         IF DOWN THEN
            Setting = 12
        ELSE
           Setting = 55
        ENDIF
    
    'And so on
      END SELECT
    
    PWMDuty = Setting
    /Henrik.
    Last edited by HenrikOlsson; - 12th September 2012 at 20:43.

  3. #3
    Join Date
    Feb 2004
    Location
    Michigan, USA
    Posts
    305


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    Ok, but these 2 examples run into the same problem. You've set the pwm duty cycle using CASE and now the program must go into a loop to change the pwm duty according to feedback from a current sense resistor. In that loop the the program needs to start the pwm at the number in the correct CASE and then ignore it every time it loops through as the CASE number could be incorrect. Within that loop it will be monitoring for a change of SETTINGS so it can jump to the next loop for that particular current output. How would the CASE work to exclude the current CASE number in each loop after it has looped once?

  4. #4
    Join Date
    Aug 2012
    Location
    Comodoro Rivadavia - Patagonia Argentina
    Posts
    51


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    not quite understand the idea if you're needing, but I work with a MAP for a car, what I did was to implement a hardware PWM (in the background) and a TMR0 interrupt.
    Within the interrupt, which is to read the ADC and modified the pwm ...
    With all this, I required no implementing a LOOP and my program was much more efficient

    Note: (do not know if the translation is fine >> background = the 2nd plane?)

  5. #5
    Join Date
    Aug 2012
    Location
    Comodoro Rivadavia - Patagonia Argentina
    Posts
    51


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    would fail to correct the fuses and setup the interruption, but more or less the idea was so (I have to find where I have the complete original program that works well) ... ¨ I understood correctly?

    Code:
    'OPTION_REG =%00111111
    PORTA=0:TRISA=%00000001
    PORTB=0:TRISB=%00000000
    PORTC=0:TRISC=%00000000
    PORTD=0:TRISD=%00000000
    ADCON1= %10001110 '
    T2CON = %00000101
    PR2=249
    '-----------------------------------------------------------------
    @ DEVICE PIC16F877
    @ DEVICE PIC16F877, WDT_OFF
    @ DEVICE PIC16F877, PWRT_OFF
    @ DEVICE PIC16F877, PROTECT_OFF
    @ DEVICE PIC16F877, XT_OSC
    
    DEFINE OSC 4
    '**** configuracion canal ADC (ADC chanel setting) ***********
    DEFINE ADC_BITS 10 
    DEFINE ADC_CLOCK 1 
    DEFINE ADC_SAMPLEUS 3 
    '*********** Configuracion HPWM (HPWM PRESETING) *************
    DEFINE CCP1_REG PORTC 
    DEFINE CCP1_BIT 2 
    DEFINE CCP2_REG PORTC 
    DEFINE CCP2_BIT 1 
    
    HAM var word
    X VAR WORD
    DUTY VAR BYTE
    CCP1CON.2=1
    CCP1CON.3=1
    
       On Interrupt Goto int_TIMER0
       INTCON = %10100000
    
    
    Menu:
    DUTY=50
    GOSUB salida
    GOTO Menu
    
    salida:
    PR2=((1024-HAM)*/5625)/100+24
    X=(PR2+1)* DUTY /25
    CCP1CON.4=X.0
    CCP1CON.5=X.1
    CCPR1L=x>>2
    RETURN
    
    Disable
    
    
    int_TIMER0:
    ADCIN 0,HAM
    INTCON = %10100000
    Resume 
    Enable
    regards

  6. #6
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    jmgelba,
    The key is to only execute the lookup (or other) code once each time you actually CHANGE the setting - not all the time. If you insist on having it inside a big loop you need a flag to indicate that the setting has changed and that the dutycycle needs to be reset to a new base value.

  7. #7
    Join Date
    Feb 2004
    Location
    Michigan, USA
    Posts
    305


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    That's exactly it. New current level gets set, pwm is set to a beginning level at the start of the loop. After one loop the pwm is set by the feedback, ignoring the initial start level.

  8. #8
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    Here's the basic principle of using the flag method:
    Code:
    UpButton VAR PortB.0   			' Active high button
    DnButton VAR PortB.1   			' Active high button
    
    Setting VAR BYTE
    SettingChanged VAR BIT
    DutyCycle VAR BYTE
    
    Main:
    
      If UpButton THEN
        Setting = Setting + 1              ' Increment setting
        If Setting = 6 THEN Setting = 5    ' Make sure it doesn't go beyond 5
        SettingChanged = 1                 ' Set flag indicating new setting
      EndIf
    
    
      If DnButton THEN
        Setting = Setting - 1
        If Setting = 255 THEN Setting = 0  ' Make sure it doesn't go below 0
        SettingChanged = 1                 ' Set flag indicating new setting
      EndIf
    
      If SettingChanged THEN
        LOOKUP Setting, [12,23,34,45,56], DutyCycle
        SettingChanged = 0                 ' Clear flag
      EndIf
    
    
      
      ' Your regulator code here...
      ' Your regulator code here...
      ' Your regulator code here...
    
    Goto Main
    /Henrik.

  9. #9
    Join Date
    Aug 2012
    Location
    Comodoro Rivadavia - Patagonia Argentina
    Posts
    51


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    very good your contribution! I find it very helpful to see the logic with other people who program to learn more every day... Thanks Henrik

  10. #10
    Join Date
    Feb 2012
    Location
    PERTH AUSTRALIA
    Posts
    838


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    thank Hendrik , i need a somthing like this and did not know of the lookup , lookup2 commands , before i read this , cheers

  11. #11
    Join Date
    Feb 2012
    Location
    PERTH AUSTRALIA
    Posts
    838


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    allocating a varable as a bit rather than a byte save memory space in the pic ??? , i have several varables which required as flags only !!!

  12. #12
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    From the manual....
    When BIT variables are created, PBP must reserve full BYTEs of RAM and then
    assign variable names to each bit within the BYTE containers. This is fine in most
    cases, but you may wish to control this yourself. To create a bit variable and
    control the BYTE it's assigned to, you can use aliasing to do it manually:
    my_flags VAR BYTE 'Create a container for bits
    flag0 VAR my_flags.0 'Assign an alias to bit-0
    flag1 VAR my_flags.1 'Assign an alias to bit-1
    This is exactly what PBP would do in the background, but it will assign its own
    name to the "container" BYTE variable. It's useful to take control and assign this
    name manually, especially when debugging in an environment that won't show
    individual bits in a watch window.
    Dave
    Always wear safety glasses while programming.

  13. #13
    Join Date
    Aug 2012
    Location
    Comodoro Rivadavia - Patagonia Argentina
    Posts
    51


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    Just like that mackrackit!!
    I, for example, in a project to implement a 10-bit ADC and the output of the pic, I had to generate a 10-bit DAC to simulate approximately the incoming analog signal, so I wrote this (similar to the example):

    Adc VAR WORD
    D0 VAR Adc.0
    D1 VAR Adc.1
    D2 VAR Adc.2
    D3 VAR Adc.3
    D4 VAR Adc.4
    D5 VAR Adc.5
    D6 VAR Adc.6
    D7 VAR Adc.7
    D8 VAR Adc.8
    D9 VAR Adc.9

    TRISA = %11111111
    TRISB = %00000000
    TRISD = %00000000

    ADCON1.7 = 1

    Inicio:
    ADCIN 0,Adc

    PORTD.0 = D0
    PORTD.1 = D1
    PORTD.2 = D2
    PORTD.3 = D3
    PORTD.4 = D4
    PORTD.5 = D5
    PORTD.6 = D6
    PORTD.7 = D7
    PORTB.0 = D8
    PORTB.1 = D9
    GoTo Inicio

    regards friends!!!
    Last edited by martintorres; - 15th September 2012 at 08:04.

  14. #14
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    Or
    Code:
    PortD = ADC.LowByte   ' Or ADC.Byte0
    PortB.0 = ADC.8
    PortB.1 = ADC.9
    Or perhaps even
    Code:
    PortD= ADC.LowByte
    PortB = ADC.HighByte
    But the later will write "fill" the upper 6 bits of PortB with zeros (or whatever is in the upper 6 bits of the ADC variable) which may or may not be an actual problem.

    Neither of this has anything to do with the original question of course, sorry about that.

    /Henrik.

  15. #15
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    Dave
    Always wear safety glasses while programming.

  16. #16
    Join Date
    Feb 2012
    Location
    PERTH AUSTRALIA
    Posts
    838


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    its funny i have always done this for port pins and register assignments but never thought to do it for flags within the program

  17. #17
    Join Date
    Feb 2004
    Location
    Michigan, USA
    Posts
    305


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    Henrik,

    Thank you very much for your example. I will give this a try today and post results. Sorry I did not respond earlier. I spent the last few days helping out with a charity walk to raise money for a little girl with type 1 diabetes. Sure was nice to be out in the open air walking by a river instead of being stuck in the dungeon working

  18. #18
    Join Date
    Feb 2004
    Location
    Michigan, USA
    Posts
    305


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    Ok, so this combines the working crude regulator code with Henriks example code. I havent programmed the pic yet but it does compile.

    Code:
    Define OSC 20
    DEFINE ADC_BITS 10
    DEFINE ADC_CLOCK 3
    DEFINE ADC_SAMPLEUS 50
    DEFINE CCP1_REG PORTB
    DEFINE CCP1_BIT 3
    
    
    PORTA = %00000000       ' Turn off all PORTA 
    PORTB = %00000000       ' Turn off all PORTB
    ADCON0 = %00000001
    ADCON1 = %01111000
    ADCON2 = %10000111
    
    TRISA = %11100111
    TRISB = %11000011
    
    
    UpButton VAR PortB.0   			' Active high button
    DnButton VAR PortB.1   			' Active high button
    
    Setting VAR BYTE
    SettingChanged VAR BIT
    DutyCycle VAR BYTE
    SETPOINT var byte  'Output current level in 0.1A increments)100 = 1A)
    
    CURRENT VAR WORD
    LEDCURRENT VAR WORD
    LEDCURRENT1 VAR WORD
    high_duty var word
    low_duty var word
    
    
    
    Main:
    
      If UpButton THEN
        Setting = Setting + 1              ' Increment setting
        If Setting = 6 THEN Setting = 5    ' Make sure it doesn't go beyond 5
        SettingChanged = 1                 ' Set flag indicating new setting
      EndIf
    
    
      If DnButton THEN
        Setting = Setting - 1
        If Setting = 255 THEN Setting = 0  ' Make sure it doesn't go below 0
        SettingChanged = 1                 ' Set flag indicating new setting
      EndIf
    
      If SettingChanged THEN
        LOOKUP Setting, [12,23,34,45,56], DutyCycle
        SettingChanged = 0                 ' Clear flag
      EndIf
    
      If Setting = 0 THEN 
      SETPOINT = 0
      endif
      
      If SETTING = 1 then
      Setpoint = 2
      endif
      
      If Setting = 2 then
      SETPOINT = 5
      endif
      
      IF setting = 3 then
      SETPOINT = 9
      endif
      
      IF Setting = 4 then
      SETPOINT = 14
      endif
      
      If Setting = 5 then
      Setpoint = 17
      endif
      
    ADCIN 0, CURRENT
    LEDCURRENT = CURRENT * 49 /100 *2
    LEDCURRENT1 = LEDCURRENT/10
    
    CCP1CON = %00111100
    PR2 = 99
    high_duty=(dutycycle>>2)        'high 6 bits in CCPR1L
          low_duty=(dutycycle<<6)         'low two bits for CCP1CON
          'low_duty=(low_duty>>2)           'shift back to CCP1CON<5:4>
          low_duty.4=0                     'PWM configuration bit
          low_duty.5=1                     'PWM configuration bit
    CCPR1L=high_duty
    CCP1CON = $0C
    T2CON = 4
    
    IF LEDCURRENT1 < setpoint then
        dutycycle=dutycycle+1
        if dutycycle => 300 then
        dutycycle = 300
    ENDIF
    ENDIF
    IF LEDCURRENT1 > setpoint then
        dutycycle=dutycycle-1
        IF dutycycle > 301 then
        dutycycle = 0
        
    ENDIF
    ENDIF
    
    Goto Main

  19. #19
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    Hi,
    I think that should work. However, since Setpoint doesn change if Setting doesn't change there's no need to assign a value to SetPoint each time thru the loop.
    You can move it into the If SettingChanged section, something like:
    Code:
    If SettingChanged THEN
        LOOKUP Setting, [12,23,34,45,56], DutyCycle            ' Assign inital value to DutyCycle variable
        LOOKUP Setting, [0, 2, 5, 9, 14, 17], SetPoint         ' Assign value to setpoint variable    
        SettingChanged = 0                 ' Clear flag
    EndIf
    Or you could do something like:
    Code:
    IF SettingChanged THEN
      Select Case Setting
        Case 1
           DutyCycle = 12   'Initial dutycycle for setting 1
           SetPoint = 0
       Case 2
           DutyCycle = 23
           SetPoint = 2
       Case 3
           '.......
           '.......
    End Select
    Try it, see which works best, compiles to the smallest code, is easiest to maintain and understand etc etc.

    Good luck!
    /Henrik.

  20. #20
    Join Date
    Feb 2004
    Location
    Michigan, USA
    Posts
    305


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    Good idea! I like your first example because there are less lines to scroll through, and it looks cleaner.

  21. #21
    Join Date
    Feb 2004
    Location
    Michigan, USA
    Posts
    305


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    Ok I programmed and there are a couple of issues.

    There needs to be a time delay between each step up or down that the button is pressed. Right now, pressing either button and it is too fast to set a desired level. This delay cant be put into the loop though as the response of the regulator will be to slow.

    Also it doesnt fully turn off and seems to settle at a very low duty cycle when it should be zero.

    Code:
    IF but_0 then
    pause 75
    eNDIF
    if !but_0 then
             if SETPOINT>0 then
                SETPOINT=SETPOINT-1
               endif
               
        endif
        
    IF but_1 then
    PAUSE 75
    ENDIF    
        if !but_1 then
                if SETPOINT<19 then
                SETPOINT=SETPOINT+1
            endif
            
        endif
    This button code used before worked well.

  22. #22
    Join Date
    Feb 2004
    Location
    Michigan, USA
    Posts
    305


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    Code:
     If UpButton THEN
        PAUSE 75
        Setting = Setting + 1              ' Increment setting
        If Setting = 6 THEN Setting = 5    ' Make sure it doesn't go beyond 5
        SettingChanged = 1                 ' Set flag indicating new setting
      EndIf
    
    
      If DnButton THEN
        PAUSE 75
        Setting = Setting - 1
        If Setting = 255 THEN Setting = 0  ' Make sure it doesn't go below 0
        SettingChanged = 1                 ' Set flag indicating new setting
      EndIf
    Adding the PAUSE 75 fixed the run away issue and gives a quick response to a button press while still being easy to use.

    Still havent figured out why at DutyCycle=0 there is still a very low pwm signal that lasts for just a few uS. Or while at setting 5 it rolls over to setting 1.

  23. #23
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    There's a mistake in my code.
    The Setting variable can go from 0 to 5 (6 settings) but there's only five entries in the first LOOKUP statement, the one that sets the initial dutycycle.

  24. #24
    Join Date
    Feb 2004
    Location
    Michigan, USA
    Posts
    305


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    I did actually catch that And yes, it does work. Or it did. Now I think I either messed it up or there is a hardware issue

  25. #25
    Join Date
    Feb 2004
    Location
    Michigan, USA
    Posts
    305


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    Code:
    Define OSC 20
    DEFINE ADC_BITS 10
    DEFINE ADC_CLOCK 3
    DEFINE ADC_SAMPLEUS 50
    DEFINE CCP1_REG PORTB
    DEFINE CCP1_BIT 3
    
    
    PORTA = %00000000       ' Turn off all PORTA 
    PORTB = %00000000       ' Turn off all PORTB
    ADCON0 = %00000001
    ADCON1 = %01111000
    ADCON2 = %10000111
    
    TRISA = %11100111
    TRISB = %11000011
    
    
    UpButton VAR PortB.0   			' Active high button
    DnButton VAR PortB.1   			' Active high button
    
    Setting VAR BYTE
    SettingChanged VAR BIT
    DutyCycle VAR WORD
    SETPOINT var byte  'Output current level in 0.1A increments)100 = 1A)
    
    CURRENT VAR WORD
    LEDCURRENT VAR WORD
    LEDCURRENT1 VAR WORD
    high_duty var word
    low_duty var word
    
    
    
    Main:
    
      If UpButton THEN
      pause 75
        Setting = Setting + 1              ' Increment setting
        If Setting = 6 THEN Setting = 5    ' Make sure it doesn't go beyond 5
        SettingChanged = 1                 ' Set flag indicating new setting
      EndIf
    
    
      If DnButton THEN
      pause 75
        Setting = Setting - 1
        If Setting = 255 THEN Setting = 0  ' Make sure it doesn't go below 0
        SettingChanged = 1                 ' Set flag indicating new setting
      EndIf
    
      If SettingChanged THEN
        LOOKUP Setting, [0,100,150,200,240,254], DutyCycle
        LOOKUP Setting, [0, 2, 5, 9, 14, 17], SetPoint ' Assign value to setpoint variable 
        SettingChanged = 0                 ' Clear flag
      EndIf
      
    ADCIN 0, CURRENT
    LEDCURRENT = CURRENT * 49 /100 *2
    LEDCURRENT1 = LEDCURRENT/10
    
    CCP1CON = %00111100
    PR2 = 99
    high_duty=(dutycycle>>2)        'high 6 bits in CCPR1L
          low_duty=(dutycycle<<6)         'low two bits for CCP1CON
          'low_duty=(low_duty>>2)           'shift back to CCP1CON<5:4>
          low_duty.4=0                     'PWM configuration bit
          low_duty.5=1                     'PWM configuration bit
    CCPR1L=high_duty
    CCP1CON = $0C
    T2CON = 4
    
    if LEDCURRENT1 < setpoint then
        dutycycle=dutycycle+1
        if dutycycle => 300 then
        dutycycle = 300
    endif
    ENDIF
    if LEDCURRENT1 > setpoint then
        dutycycle=dutycycle-1
        IF dutycycle > 301 then
        dutycycle = 0
        
    ENDIF
    endif
    pause 100
    Goto Main
    Ok seem to be stuck. It no longer responds to button presses, turns off the LED if I raise the input voltage to 22V - should operate from 19 - 42V, and the pwm output is a constant low %. I have no idea what is causing this.

    The pause 100 at the end is just to slow things down so I can see whats happening on the scope.

  26. #26
    Join Date
    Feb 2004
    Location
    Michigan, USA
    Posts
    305


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    At the start of the program before the loop, I made sure Setting = 0. Works very well now. Still a minor issue of the pwm signal never turning off though, even on a setting of 0.

  27. #27
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: Altering a variable in a loop.

    Hi,
    I think the problem is here:
    Code:
    CCP1CON = %00111100            '<-- Here you actually set the two LSB's of the dutycycle register.
    PR2 = 99                                  ' <--There's no need to set PR2 every time thru the loop.
    high_duty=(dutycycle>>2)        'high 6 bits in CCPR1L
          low_duty=(dutycycle<<6)         'low two bits for CCP1CON 
          'low_duty=(low_duty>>2)           'shift back to CCP1CON<5:4>  
          low_duty.4=0                     'PWM configuration bit 
          low_duty.5=1                     'PWM configuration bit
    CCPR1L=high_duty
    CCP1CON = $0C                       '<- Then you reset the two LSB's of the dutycycle register.
    T2CON = 4                               '<- No need to set this every time
    So, the glitch probably comes from the fact that even when your dutycycle variable is 0 you actually set the dutycycle to 4 (the two LSBs in CCP1CON being set by CCP1CON = %00111100) and then back to 0 again by CCP1CON = $0C.

    Set up the module (ie CCP1CON and PR2) at the beginning of the program. If you need to use the lower two LSBs of the dutycycle then assign those bits in CCP1CON individually each time thru the loop. Don't mess with PR2 or T2CON every time thru the loop.

    Finally, you do a lot of bit shifting an dflippin on the Low_Duty variable but you never actually USE it to set the dutycycle, you're only using the 8 high bits in CCPR1L.

    /Henrik.

Members who have read this thread : 1

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