Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Interrupt-based servo control not working

Status
Not open for further replies.

Sodrohu

New Member
Hi there. This is a servo code originally from ermicro's blog. I modified it so that the pulse values can be increased and decreased for a max of 25(2.5ms) and min of 5(.5ms). I'm using push buttons to as the two increase/decrease inputs. I can see the interrupt and main loop working as the LEDs got toggled all the time, but when I pressed the buttons the servo didn't run at all. Here's the code:
Code:
//__CONFIG(INTIO & WDTDIS & PWRTEN & MCLREN & UNPROTECT \
//  & UNPROTECT & BORDIS & IESODIS & FCMDIS);

// Using Internal Clock of 8 Mhz
#define FOSC 20000000L
#define _XTAL_FREQ 20000000

#define    SW1            RB0            
#define    SW2            RB1            
#define    SERVO        RC2    
#define    LED1        RB6            
#define    LED2        RB7    

// Servo definition and variables
#define MAX_VALUE 200
#define CCW_ROTATION 180//MAX_VALUE - 23
#define CW_ROTATION 193 //MAX_VALUE - 5
#define STOP_ROTATION 185 //MAX_VALUE - 15
#define THRESHOLD_VALUE 50

unsigned char pulse_max=0;
unsigned char pulse_top=0;
unsigned char top_value = 0;
int VALVE = 25;

static void interrupt isr(void)
{
  if(T0IF) {                // TIMER0 Interrupt Flag
    pulse_max++;            // Pulse Max Increment
    pulse_top++;            // Pulse Top Increment

    /* MAX_VALUE=200 turn off the pulse */
    if (pulse_max >= MAX_VALUE)
     {
      pulse_max=0;
      pulse_top=0;
      SERVO=0;                // Turn off RC2
    //RB2=0;
    LED1^ = 1;
    }

    /* top_value = MAX_VALUE - n, n=10: 10 x 0.1ms = 1.0ms, n=20: 20 x 0.1ms = 2.0ms */
    /* 2ms -> CCW Rotation, 1ms -> CW Rotation */
    if (pulse_top == VALVE)//top_value) 
    {
      SERVO=1;                // Turn On RC2
    //RB2=1;
    }

    //TMR0 = 131;             // Initial Value for 0.1ms Interrupt
    TMR0 = 6;
    T0IF = 0;            // Clear TIMER0 interrupt flag
  }
}

void main(void)
{

 // OSCCON=0x70;         // Select 8 Mhz internal clock
    TRISB = 0b00000011;                //configure PORTB I/O direction
    TRISD = 0b00000000;                //configure PORTD I/O direction
    TRISA = 0b00000111;                //configure PORTA I/O direction
    PORTB = 0b00000000;            
    
  /* Initial Port Used */
  TRISC = 0x00;        // Set RC0 and RC1 as input others as Output
  PORTC = 0x00;        // Turn Off all PORTC

  /* Init Servo Pulse */
  pulse_max=0;
  pulse_top=0;
  top_value = MAX_VALUE; // top_value = MAX_VALUE: Servo Motor Stop

PEIE=1;
T0CS=0; 
PSA = 0;   // bit 3  Prescaler Assignment bit...0 = Prescaler is assigned to the Timer0
PS2 = 0;   // bits 2-0  PS2:PS0: Prescaler Rate Select bits
PS1 = 0;
PS0 = 0;
TMR0 = 6;             // preset for timer register

 // OPTION = 0b00000000; // 1:2 Prescaller
  //TMR0=156;            // Interupt every 0.1 ms
  T0IE = 1;               // Enable interrupt on TMR0 overflow
  GIE = 1;               // Global interrupt enable

    while(1)                            //Infinite loop
    {
        if(!SW1)                        //check if SW1 is pressed
        {
                VALVE++;
                if(VALVE>=26) 
                {    VALVE=25;
                }
        }
         if(!SW2)                    //check if SW2 is pressed
        {
                VALVE--;
                if(VALVE<=4) 
                {    VALVE=5;
                }
        }
        
        LED2^ = 1;    
        __delay_ms(250);                    
    }
}
 
When you 'pressed the buttons' was this for real or a simulation?
 
Sodrohu! Take care when modifying a PWM generator when simulating this in ISIS your on time is dominant!! Instead of 2ms out of 10ms on you have 2ms out of 10ms off..
Was this the desired affect? The pulse varies from around 200Us to about 2ms when operating the buttons..
 
Sodrohu! Take care when modifying a PWM generator when simulating this in ISIS your on time is dominant!! Instead of 2ms out of 10ms on you have 2ms out of 10ms off..
Was this the desired affect? The pulse varies from around 200Us to about 2ms when operating the buttons..

Nope. I'm not simulating this one on the ISIS; I'm writing down the code and testing it the non-simulation method. The idea for the buttons is that they control the length of how long the servo is on.

Instead of 2ms out of 10ms on you have 2ms out of 10ms off..
Was this the desired affect?
You're absolutely correct. I just realised that I got the values wrong. Instead of
time servo off = (MAX_VALUE - VALVE)
time servo on = (VALVE)
I got it backwards:
time servo on = (MAX_VALUE - VALVE)
time servo off = (VALVE)

that means the on pulse is (200-25)*100us = 17.5 ms. Too long for a servo pulse!

Darnit. I'll have to try rectify this once I got back.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top