how to increase/decrease a duty cycle of PWM in PIC16f877 using push buttons

Discussion in 'Embedded Systems and Microcontrollers' started by snesh, Feb 22, 2016.

  1. snesh

    Thread Starter New Member

    Feb 2, 2016
    3
    0
    I am working on a project of a DC motor car which have the following features:
    1. operating in 4 quadrants
    2. varying speed using PWM
    3. automatic lighting system (will turn on lights based on the environment light intensity)
    4. crash avoiding system (the car will automatically stop when there is an obstacle)

    i have been able to achieve the 4 quadrants operation.
    my problem is with the speed varying using PWM. i want to increase the speed in rate of 10% when the SPPED++ is pressed. the dc motor i am using runs at 6v max. i am able to set min duty cycle and run the motor at 10%.

    But when i press the increase button the speed does not go to 20% but runs at a random value. and when the speed is at maximum it should ignore the pressing the SPEED++ button

    please help
     
  2. snesh

    Thread Starter New Member

    Feb 2, 2016
    3
    0
    OK here is the code that i have for generating the PWM and increasing/decreasing the duty cycle
    Code (Microchip Assembler):
    1.  
    2. ;*****************************************************************
    3. ;PROGRAM TO GENERATE PWM VARYING DUTY CYCLE TO CONTROL SPEED OF DC MOTOR
    4. ;SPEED++ PUSH BUTTON CONNECTED TO RD5
    5. ;SPEED-- PUSH BUTTON CONNECTED TO RD6
    6. ;**********************************************************************
    7. ;equates
    8. STATUS EQU 3H
    9. PORTC EQU 7H
    10. PORTD EQU 8H
    11. ZEROBIT EQU 4H
    12. CCPR1L EQU 15H
    13. T2CON EQU 12H
    14. PR2 EQU 92H
    15. CCP1CON EQU 17H
    16.  
    17. LIST P = 16F877
    18. ORG 0
    19. GOTO MAIN
    20.  
    21. MAIN:
    22. BSF STATUS,5 ;going to bank 1
    23. MOVLW B'11111111'
    24. TRISD ;set port D as input
    25. BCF PORTC,2 ; pin 2 of port c is an output
    26. BCF STATUS,5
    27. movlw B'00000100'
    28. movwf T2CON ; config TMR2 prescale =1 , timer2 is on, post scaler =1:1
    29. movlw B'00001100' ;configuring CCP1 for PWM mode
    30. movwf CCP1CON
    31. movlw B'11111111' ; period = 256ms,PR2=255(full scale range)
    32. movwf PR2
    33.  
    34. call minDCYCLE ;set min duty cycle
    35.  
    36. BEGIN:
    37. BTFSS PORTD,5 ;check if speed++ button is pressed
    38. GOTO BEGIN
    39.  
    40. MOVLW B'00000110' ;incr duty cycle by 10%
    41. ADDWF CCPR1L,F ;increament duty cycle if pressed
    42.  
    43. BTFSS PORTD,6 ;check if speed-- button is pressed
    44. GOTO BEGIN
    45.  
    46. MOVLW B'00000110'
    47. SUBWF CCPR1L,F ;decr duty cycle by 10 ;decr if pressed
    48. GOTO BEGIN ;start routine again
    49.  
    50. ;SUBROUTINES
    51.  
    52. minDCYCLE:
    53. MOVLW B'00000110'
    54. MOVWF CCPR1L
    55. BCF CCP1CON,5
    56. BCF CCP1CON,4 ;set min duty cycle to be 10%
    57. GOTO BEGIN
    58.  
    59. END
    60.  
    Mod edit: added code tags
     
    Last edited by a moderator: Feb 22, 2016
  3. JohnInTX

    Moderator

    Jun 26, 2012
    2,341
    1,022
    Welcome to AAC!
    You might need to debounce your buttons. Mechanical switches do not make clean transitions - the contacts 'bounce' when they close making multiple inputs to your fast PIC. Search debounce and debouncing here on AAC for threads that discuss how to debounce buttons.

    Also, your code should inspect the buttons separately and call one of the increment / decrement routines as required. The increment routine should add to WREG first, check for max PWM before writing to CCPR1L clipping WREG to max if the result is too big. The decrement routine should look for underflow after the subtraction and clip to 0 (or minimum duty cycle) before writing to CCP1RL.

    Finally, after a button press is processed you must wait until the button is released before looping back and looking at the buttons again. Otherwise, your finger on the button will cause multiple increments/decrements. Remember, the PIC is much faster than you are.
    Here is one possibility - note that it is pseudocode i.e. something to give the general idea without the burden of exact syntax.
    Code (Text):
    1.  
    2. ; pseudocode
    3.  
    4. MainLoop:
    5. // Wait for a button
    6. if increment_button  ; this must be debounced
    7.    call increment
    8. if decrement_button
    9.   call decrement
    10. goto MainLoop:
    11.  
    12. // Process increment/decrement
    13. increment:
    14.   W = increment_amount ; adjust PWM value
    15.   addwf CCP1RL,W  ; accumulate sum
    16.   if W > max
    17.     W = max ; clip to max
    18.   CCP1RL = W ; update PWM with valid value
    19.   call WaitSwitchesClear ; wait until no switch
    20.   return
    21.  
    22. decrement:
    23.   W = decrement_amount
    24.   subwf CCP1RL,W  ;   W = CCP1RL - W
    25.   if NO_CARRY
    26.       W = 0  ; clip to 0 on underflow, NC means underflow
    27.   movwf CCP1RL ; update PWM with valid value
    28.   call WaitSwitchesClear
    29.   return
    30.  
    31. // helper routine- waits here until buttons are clear
    32. WaitSwitchesClear:  ; wait until both buttons clear
    33.   if increment_button
    34.     goto WaitSwitchesClear
    35.   if decrement_button
    36.     goto WaitSwitchesClear
    37.   return  ; both are open
    Have fun!
     
    Last edited: Feb 22, 2016
  4. snesh

    Thread Starter New Member

    Feb 2, 2016
    3
    0
    tank you very much. this was very helpfull
     
Loading...