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

Thread Starter

snesh

Joined Feb 2, 2016
3
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
 

Thread Starter

snesh

Joined Feb 2, 2016
3
OK here is the code that i have for generating the PWM and increasing/decreasing the duty cycle
Code:
;*****************************************************************
;PROGRAM TO GENERATE PWM VARYING DUTY CYCLE TO CONTROL SPEED OF DC MOTOR
;SPEED++ PUSH BUTTON CONNECTED TO RD5
;SPEED-- PUSH BUTTON CONNECTED TO RD6
;**********************************************************************
;equates
STATUS EQU 3H
PORTC EQU 7H
PORTD EQU 8H
ZEROBIT EQU 4H
CCPR1L EQU 15H
T2CON EQU 12H
PR2 EQU 92H
CCP1CON EQU 17H

LIST P = 16F877
ORG 0
GOTO MAIN

MAIN:
BSF STATUS,5 ;going to bank 1
MOVLW B'11111111'
TRISD ;set port D as input
BCF PORTC,2 ; pin 2 of port c is an output
BCF STATUS,5
movlw B'00000100'
movwf T2CON ; config TMR2 prescale =1 , timer2 is on, post scaler =1:1
movlw B'00001100' ;configuring CCP1 for PWM mode
movwf CCP1CON
movlw B'11111111' ; period = 256ms,PR2=255(full scale range)
movwf PR2

call minDCYCLE ;set min duty cycle

BEGIN:
BTFSS PORTD,5 ;check if speed++ button is pressed
GOTO BEGIN

MOVLW B'00000110' ;incr duty cycle by 10%
ADDWF CCPR1L,F ;increament duty cycle if pressed

BTFSS PORTD,6 ;check if speed-- button is pressed
GOTO BEGIN

MOVLW B'00000110'
SUBWF CCPR1L,F ;decr duty cycle by 10 ;decr if pressed
GOTO BEGIN ;start routine again

;SUBROUTINES

minDCYCLE: 
MOVLW B'00000110'
MOVWF CCPR1L
BCF CCP1CON,5
BCF CCP1CON,4 ;set min duty cycle to be 10%
GOTO BEGIN

END
Mod edit: added code tags
 
Last edited by a moderator:

JohnInTX

Joined Jun 26, 2012
4,787
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:
; pseudocode

MainLoop:
// Wait for a button
if increment_button  ; this must be debounced
   call increment
if decrement_button
  call decrement
goto MainLoop:

// Process increment/decrement
increment:
  W = increment_amount ; adjust PWM value
  addwf CCP1RL,W  ; accumulate sum
  if W > max
    W = max ; clip to max
  CCP1RL = W ; update PWM with valid value
  call WaitSwitchesClear ; wait until no switch
  return

decrement:
  W = decrement_amount
  subwf CCP1RL,W  ;   W = CCP1RL - W
  if NO_CARRY 
      W = 0  ; clip to 0 on underflow, NC means underflow
  movwf CCP1RL ; update PWM with valid value
  call WaitSwitchesClear
  return

// helper routine- waits here until buttons are clear
WaitSwitchesClear:  ; wait until both buttons clear
  if increment_button
    goto WaitSwitchesClear
  if decrement_button
    goto WaitSwitchesClear
  return  ; both are open
Have fun!
 
Last edited:
Top