SINGLE SERVO TESTER WITH 2 BUTTON CONTROL For PIC12/16

General discussion on mikroBasic.
Post Reply
Author
Message
xor
Posts: 5465
Joined: 18 May 2005 00:59
Location: NYC
Contact:

SINGLE SERVO TESTER WITH 2 BUTTON CONTROL For PIC12/16

#1 Post by xor » 01 Jan 2009 01:33

Amazing what you can do with only 190 Bytes of Code. It has been tested on a 16F628A using the internal osc.

The following code provides a full-featured single servo controller with up to 1 microsecond resolution and controlled using only 2 buttons.

Using the buttons the servo increments or decrements by a user declared step value until the minimum or maximum timing values, also declared by the user, are reached.

It has another button feature that allows auto-repeat-incrementing and auto-repeat-decrementing the position until it reaches the max or min value by simply holding a button down for an extended period.

The final button feature is auto-center of the servo by holding both buttons at the same time. The center timing is declared by the user.

Also, this is a nice project to make using an 8-Pin 12F683... only 3 GPIO pins needed!

Enjoy the program and have a great new year.

Code: Select all

program PB_SERVO

'**************************************************************************'
'*****                                                                *****'
'*****          50Hz SINGLE SERVO TESTER USING 2 BUTTONS              *****'
'*****              16F628A @ 4MHz INTOSC_NoClkout                    *****'
'*****          Written By Warren Schroeder on 12.31.08               *****'
'*****                 Using MikroBASIC v.7.2                         *****'
'*****           Tested and Programmed Using EasyPIC5                 *****'
'*****     Code Is Easily Adapted For Any PIC With CCP Module         *****'
'*****                                                                *****'
'*****              1 microsecond position accuracy                   *****'
'*****                 Range of 1us to 19,999us                       *****'
'*****   User can setup Min, Max, & Center Sweep Range as needed      *****'
'*****                                                                *****'
'*****      Features 2 Button Control For 3 Main Functions:           *****'
'*****                                                                *****'
'*****   Button1 = move to min position by user declared Step Value   *****'
'*****   Button2 = move to max position by user declared Step Value   *****'
'*****   Button1+Button2 = move to center position                    *****'
'*****                                                                *****'
'*****   HOLDING a BUTTON WILL AUTO INCREMENT/DECREMENT Till MAX/MIN  *****'
'*****                                                                *****'
'**************************************************************************'

  Symbol SPIN    = PORTB.0            ' Servo Output Pin
  
  Const StepVal  = 5                  ' in microseconds
        MinPos   = 500                ' in microseconds
        MaxPos   = 2500               ' in microseconds
        Center   = 1500               ' in microseconds
        
  Dim   CCPR     as Word Absolute $15 ' CCPR1L:CCPR1H pair
        ServoPos as Word
        Temp     as Byte

  sub procedure Interrupt()
        If (PORTB And 1) = 1 Then
           SPIN = 0                   ' turn servo off
           CCPR = 20000 - CCPR        ' off time to finish 20ms
        Else
           SPIN = 1                   ' turn servo on
           CCPR = ServoPos            ' on time in microseconds
        End If
        PIR1.CCP1IF = 0               ' clear int flag
  End sub
  
  sub procedure delay30()
        Delay_ms(30)
  end sub

  sub procedure INIT()
        CMCON    = 7                  ' turn off comparators
        PORTA    = 0
        PORTB    = 0
        TRISA    = 3
        TRISB    = 0
        ServoPos = 0
  end sub

  Sub procedure CCP_SETUP()
        INTCON  = 192                 ' GIE, PEIE enabled
        T1CON   = 0                   ' no prescale; off;  1us ticks
        TMR1H   = 0                   ' clear timer1
        TMR1L   = 0
        CCP1CON = 11                  ' reset timer1 on compare-match
        CCPR    = MinPos              ' match int value; 0 deg position
        PIR1.CCP1IF  = 0              ' clear int flag
        PIE1.CCP1IE  = 1              ' enable int
        T1CON.TMR1ON = 1              ' timer1 run
   end sub

   '***** Buttons Inputs are Pulled Low on RA0 and RA1  *****'
   '*********************************************************'
   sub procedure BUTTONS()

        If (PORTA And 3) <> 0 Then    ' check for active buttons
           delay30                    ' debounce delay
           Temp = PORTA And 3         ' save button value
           
           While Temp <> 0            ' while a button is active do
           
              If Temp = 3 Then        ' both buttons active
                ServoPos = Center     ' goto center position
              Else
              
                 If Temp = 1 Then     ' dec position by stepval
                    ServoPos = ServoPos - StepVal
                    If ServoPos < MinPos Then ServoPos = MinPos End If
                    
                 Else                 ' inc position by stepval
                    ServoPos = ServoPos + StepVal
                    If ServoPos > MaxPos Then ServoPos = MaxPos End If
                 End If
                 
              End If
              delay30                 ' button release delay
              Temp = PORTA And 3      ' check again for release
              
           Wend                       ' if not released will inc or dec more
        End If
        
   end sub
   
   main:
   
         INIT()
         CCP_SETUP()
         
         While 1=1
            BUTTONS()
         Wend
         
   end.
[color=darkred][b]xor[/b][/color]
[url=http://circuit-ed.com]CircuitED -[/url]

Copy'nPaste
Posts: 573
Joined: 25 Apr 2006 15:39
Location: Cape Town, South Africa

#2 Post by Copy'nPaste » 01 Jan 2009 09:40

Thanks Warren,
Just what I need to get my head around using interrupts :D
All of the best for you too in this new year.
"Copy'nPaste"

neske
Posts: 45
Joined: 04 Sep 2007 10:34

#3 Post by neske » 01 Jan 2009 16:36

As always, master of simplicity! Thank you, Warren!

Philtkp
Posts: 307
Joined: 26 Apr 2006 00:58
Location: Tucson Arizona

#4 Post by Philtkp » 01 Jan 2009 17:02

Warren,

Happy New Year!
You never fail to amaze me. I was going to try (from your previous code) this when if finally figured out how to use Timer1.

Thanks
Phil

chipbreaker
Posts: 67
Joined: 01 May 2008 18:23
Location: Germany

Re: SINGLE SERVO TESTER WITH 2 BUTTON CONTROL For PIC12/16

#5 Post by chipbreaker » 14 Mar 2009 11:26

xor wrote:Amazing what you can do with only 190 Bytes of Code. It has been tested on a 16F628A using the internal osc.

The following code provides a full-featured single servo controller with up to 1 microsecond resolution and controlled using only 2 buttons.

Using the buttons the servo increments or decrements by a user declared step value until the minimum or maximum timing values, also declared by the user, are reached.

It has another button feature that allows auto-repeat-incrementing and auto-repeat-decrementing the position until it reaches the max or min value by simply holding a button down for an extended period.

The final button feature is auto-center of the servo by holding both buttons at the same time. The center timing is declared by the user.

Also, this is a nice project to make using an 8-Pin 12F683... only 3 GPIO pins needed!

Enjoy the program and have a great new year.

Code: Select all

program PB_SERVO

'**************************************************************************'
'*****                                                                *****'
'*****          50Hz SINGLE SERVO TESTER USING 2 BUTTONS              *****'
'*****              16F628A @ 4MHz INTOSC_NoClkout                    *****'
'*****          Written By Warren Schroeder on 12.31.08               *****'
'*****                 Using MikroBASIC v.7.2                         *****'
'*****           Tested and Programmed Using EasyPIC5                 *****'
'*****     Code Is Easily Adapted For Any PIC With CCP Module         *****'
'*****                                                                *****'
'*****              1 microsecond position accuracy                   *****'
'*****                 Range of 1us to 19,999us                       *****'
'*****   User can setup Min, Max, & Center Sweep Range as needed      *****'
'*****                                                                *****'
'*****      Features 2 Button Control For 3 Main Functions:           *****'
'*****                                                                *****'
'*****   Button1 = move to min position by user declared Step Value   *****'
'*****   Button2 = move to max position by user declared Step Value   *****'
'*****   Button1+Button2 = move to center position                    *****'
'*****                                                                *****'
'*****   HOLDING a BUTTON WILL AUTO INCREMENT/DECREMENT Till MAX/MIN  *****'
'*****                                                                *****'
'**************************************************************************'

  Symbol SPIN    = PORTB.0            ' Servo Output Pin
  
  Const StepVal  = 5                  ' in microseconds
        MinPos   = 500                ' in microseconds
        MaxPos   = 2500               ' in microseconds
        Center   = 1500               ' in microseconds
        
  Dim   CCPR     as Word Absolute $15 ' CCPR1L:CCPR1H pair
        ServoPos as Word
        Temp     as Byte

  sub procedure Interrupt()
        If (PORTB And 1) = 1 Then
           SPIN = 0                   ' turn servo off
           CCPR = 20000 - CCPR        ' off time to finish 20ms
        Else
           SPIN = 1                   ' turn servo on
           CCPR = ServoPos            ' on time in microseconds
        End If
        PIR1.CCP1IF = 0               ' clear int flag
  End sub
  
  sub procedure delay30()
        Delay_ms(30)
  end sub

  sub procedure INIT()
        CMCON    = 7                  ' turn off comparators
        PORTA    = 0
        PORTB    = 0
        TRISA    = 3
        TRISB    = 0
        ServoPos = 0
  end sub

  Sub procedure CCP_SETUP()
        INTCON  = 192                 ' GIE, PEIE enabled
        T1CON   = 0                   ' no prescale; off;  1us ticks
        TMR1H   = 0                   ' clear timer1
        TMR1L   = 0
        CCP1CON = 11                  ' reset timer1 on compare-match
        CCPR    = MinPos              ' match int value; 0 deg position
        PIR1.CCP1IF  = 0              ' clear int flag
        PIE1.CCP1IE  = 1              ' enable int
        T1CON.TMR1ON = 1              ' timer1 run
   end sub

   '***** Buttons Inputs are Pulled Low on RA0 and RA1  *****'
   '*********************************************************'
   sub procedure BUTTONS()

        If (PORTA And 3) <> 0 Then    ' check for active buttons
           delay30                    ' debounce delay
           Temp = PORTA And 3         ' save button value
           
           While Temp <> 0            ' while a button is active do
           
              If Temp = 3 Then        ' both buttons active
                ServoPos = Center     ' goto center position
              Else
              
                 If Temp = 1 Then     ' dec position by stepval
                    ServoPos = ServoPos - StepVal
                    If ServoPos < MinPos Then ServoPos = MinPos End If
                    
                 Else                 ' inc position by stepval
                    ServoPos = ServoPos + StepVal
                    If ServoPos > MaxPos Then ServoPos = MaxPos End If
                 End If
                 
              End If
              delay30                 ' button release delay
              Temp = PORTA And 3      ' check again for release
              
           Wend                       ' if not released will inc or dec more
        End If
        
   end sub
   
   main:
   
         INIT()
         CCP_SETUP()
         
         While 1=1
            BUTTONS()
         Wend
         
   end.
Very impressed with your coding, thank you. I decided to try this with a PIC16F684 that has the second port register as port "C". I guessed it should also operate without problem with the C port used as the output to the servo, however I can get no digital output at all from the port c.0 pin, as checked with a Cmos probe and a known good servo.
I have spent some time trying to ascertain why the routine does not work with this 16f684 chip, without success.
Any Ideas what the problem might be please?
P.S. the only code changes I made were changing port B to port C !
Thanks in advance, Brian

chipbreaker
Posts: 67
Joined: 01 May 2008 18:23
Location: Germany

servo routine

#6 Post by chipbreaker » 14 Mar 2009 12:33

HI all, I found my errors, and for the benefit of others here they are;
1. For the 16F684 the CCPR1L and CCPR1H register is at $13 not $15 as in the example
2. The ports must be digital for the PB to work ie. ANSEL =0

Hope this helps someone else, regards Brian

Kalain
Posts: 1093
Joined: 11 Mar 2005 18:26
Location: Aubenas, France

Re: SINGLE SERVO TESTER WITH 2 BUTTON CONTROL For PIC12/16

#7 Post by Kalain » 27 Mar 2009 21:58

Hi,

Tried this code on 16F628A 4MHz INTOSC
There is a small error to correct (shown in red below).

Great code xor.
xor wrote:
program PB_SERVO

'**************************************************************************'
'***** *****'
'***** 50Hz SINGLE SERVO TESTER USING 2 BUTTONS *****'
'***** 16F628A @ 4MHz INTOSC_NoClkout *****'
'***** Written By Warren Schroeder on 12.31.08 *****'
'***** Using MikroBASIC v.7.2 *****'
'***** Tested and Programmed Using EasyPIC5 *****'
'***** Code Is Easily Adapted For Any PIC With CCP Module *****'
'***** *****'
'***** 1 microsecond position accuracy *****'
'***** Range of 1us to 19,999us *****'
'***** User can setup Min, Max, & Center Sweep Range as needed *****'
'***** *****'
'***** Features 2 Button Control For 3 Main Functions: *****'
'***** *****'
'***** Button1 = move to min position by user declared Step Value *****'
'***** Button2 = move to max position by user declared Step Value *****'
'***** Button1+Button2 = move to center position *****'
'***** *****'
'***** HOLDING a BUTTON WILL AUTO INCREMENT/DECREMENT Till MAX/MIN *****'
'***** *****'
'**************************************************************************'

Symbol SPIN = PORTB.0 ' Servo Output Pin

Const StepVal = 5 ' in microseconds
MinPos = 500 ' in microseconds
MaxPos = 2500 ' in microseconds
Center = 1500 ' in microseconds

Dim CCPR as Word Absolute $15 ' CCPR1L:CCPR1H pair
ServoPos as Word
Temp as Byte

sub procedure Interrupt()
If (PORTB And 1) = 1 Then
SPIN = 0 ' turn servo off
CCPR = 20000 - CCPR ' off time to finish 20ms
Else
SPIN = 1 ' turn servo on
CCPR = ServoPos ' on time in microseconds
End If
PIR1.CCP1IF = 0 ' clear int flag
End sub

sub procedure delay30()
Delay_ms(30)
end sub

sub procedure INIT()
CMCON = 7 ' turn off comparators
PORTA = 0
PORTB = 0
TRISA = 3
TRISB = 0
Servopos= center 'was ServoPos = 0
end sub

Sub procedure CCP_SETUP()
INTCON = 192 ' GIE, PEIE enabled
T1CON = 0 ' no prescale; off; 1us ticks
TMR1H = 0 ' clear timer1
TMR1L = 0
CCP1CON = 11 ' reset timer1 on compare-match
CCPR = MinPos ' match int value; 0 deg position
PIR1.CCP1IF = 0 ' clear int flag
PIE1.CCP1IE = 1 ' enable int
T1CON.TMR1ON = 1 ' timer1 run
end sub

'***** Buttons Inputs are Pulled Low on RA0 and RA1 *****'
'*********************************************************'
sub procedure BUTTONS()

If (PORTA And 3) <> 0 Then ' check for active buttons
delay30 ' debounce delay
Temp = PORTA And 3 ' save button value

While Temp <> 0 ' while a button is active do

If Temp = 3 Then ' both buttons active
ServoPos = Center ' goto center position
Else

If Temp = 1 Then ' dec position by stepval
ServoPos = ServoPos - StepVal
If ServoPos < MinPos Then ServoPos = MinPos End If

Else ' inc position by stepval
ServoPos = ServoPos + StepVal
If ServoPos > MaxPos Then ServoPos = MaxPos End If
End If

End If
delay30 ' button release delay
Temp = PORTA And 3 ' check again for release

Wend ' if not released will inc or dec more
End If

end sub

main:

INIT()
CCP_SETUP()

While 1=1
BUTTONS()
Wend

end.
Alain

cymb
Posts: 464
Joined: 30 Nov 2008 01:19
Location: indiana usa

wow i missed this b4

#8 Post by cymb » 28 Mar 2009 02:19

and i agree on the interrupt info, but i am using this as a tutorial on procedures , uses, as i am very weak there

am i correct that some compilers require a "on interrupt goto,,," and a disable b4 the int label? the difference??

thanks to all
not an appliance operator

xor
Posts: 5465
Joined: 18 May 2005 00:59
Location: NYC
Contact:

Re: SINGLE SERVO TESTER WITH 2 BUTTON CONTROL For PIC12/16

#9 Post by xor » 28 Mar 2009 04:38

Kalain wrote:Hi,

Tried this code on 16F628A 4MHz INTOSC
There is a small error to correct (shown in red below).

Great code xor.
xor wrote: Servopos= center 'was ServoPos = 0
end sub
0 is a tough one to start with... eh? .... thanks.
[color=darkred][b]xor[/b][/color]
[url=http://circuit-ed.com]CircuitED -[/url]

GrunF
Posts: 13
Joined: 05 Dec 2010 17:01

Re: SINGLE SERVO TESTER WITH 2 BUTTON CONTROL For PIC12/16

#10 Post by GrunF » 09 Aug 2011 14:49

Hello here is code in mikoC for 16F887 and ext osc on 12 MHz, there is no error while compiling but the cod does not work???? any idea

Code: Select all

const stepVal=5;
const minpos =500;
const maxpos=2500;
const centar =1500;
unsigned int CCPR absolute 0x15; //CCPR1L:CCPR1H pair
unsigned int servopos;
unsigned int Temp absolute 0x0E;

void interrupt(void)
{
if ((PORTC & 1)=1)
{
  PORTC.F0=0;
  CCPR=20000-ccpr;
}
else
{      
PORTC.F0=1;
CCPR = servopos;
}
    PIR1.CCP1IF = 0; // clear interrupt flag
}

 void delay30()
{
delay_ms(30);
}
void Init() {
  //C1ON_bit = 0;                                  // Disable comparators
  //C2ON_bit = 0;
    PORTC  = 0;
    PORTA  = 0;
    TRISA  = 3;
    TRISC  = 0;
    servopos = 0;
}

void CCPInit(){

    INTCON = 0xC0;         // GIE & PEIE are enabled
    T1CON = 0;            // timer1 off and no prescaler
    TMR1H   = 0;                //   ' clear timer1
    TMR1L   = 0;
    CCP1CON = 11;         // interrupt on compare and auto-reset Timer1
    CCPR=minpos;
    PIR1.CCP1IF = 0;      // clear interrupt flag
    PIE1.CCP1IE = 1;      // enable interrupt
    T1CON.TMR1ON = 1;     // start timer1 running
}


 void buttons()
 {
     if ((PORTA & 3) != 0)
     {
      delay30();
     Temp = (PORTA & 3);

           while (Temp != 0)
              {
               if (Temp = 3)
              {
              ServoPos = centar;
               }
              else
              {
              if(Temp = 1)
                 {
                    ServoPos = (ServoPos - StepVal);
                    if (ServoPos < MinPos) {ServoPos = MinPos;}
                    }


                 else
                    {ServoPos = (ServoPos + StepVal);
                    
                    if (ServoPos > MaxPos){ ServoPos = MaxPos;}
                    }

              delay30();
              Temp = (PORTA & 3);
               }


              }
 }
 }

void main() 
{
     Init();
     CCPInit();
     while(1)
     {
     buttons();
     }
}

shoaib392
Posts: 4
Joined: 04 Jun 2015 18:07

Re: SINGLE SERVO TESTER WITH 2 BUTTON CONTROL For PIC12/16

#11 Post by shoaib392 » 04 Jun 2015 18:19

can anybody write the same code in mikroC??

Post Reply

Return to “mikroBasic General”