SparkFun Forums 

Where electronics enthusiasts find answers.

Everything ARM and LPC
By KidE
#65206
I'm trying to get my servo moving using a interupt steered pulstrain.

The servo is not moving but if i connect a LED to it i see the led light up (very low) for a few sec and then on full power.

Could anyone assist to see where i fail?

Solution in last post
Code: Select all
#include "LPC214x.h"
#include "VIClowlevel.h"
#define PLOCK 0x400
void init(void);
void IRQ_Routine (void)   __attribute__ ((interrupt("IRQ")));


int main(void)
{
    int i;
    IODIR0 = 0x00200000;                    //Output
    IOCLR0 = 0x00200000;                    //LEDs off
    init();
    T0TCR = 0x02;                           //reset counter
    T0IR = 0xff;
    T0MCR = 0x0003;                         //interrupt and reset on MR0
    T0MR0 = 0x00124F80;                     //compare-hit count 20ms
    VICVectCntl0 = 0x00000024;              //use it for Timer 0 Interrupt:
    VICVectAddr0 = (unsigned)IRQ_Routine;   //set interrupt vector in 0
    VICIntEnable = 0x00000010;              //enable TIMER0 interrupt
    T0TCR = 0x01;                           //enable Timer0
    enableIRQ();
    
    while(1){
        i=0;
        i=1;
    }
}

void IRQ_Routine(void)
{
    int i;
    IOSET0 = 0x00200000;        
    for(i=0;i<6000;i++);
    IOCLR0 = 0x00200000;
    T0IR = 0x01;                //clear interrupt
    VICVectAddr = 0;            //end of interrupt - dummy write
}

void init(void)
{
    PLLCFG=0x24;                //set multiplier/divider values
    PLLFEED=0xaa;
    PLLFEED=0x55;
    PLLCON=0x01;                //enable PLL
    PLLFEED=0xaa;
    PLLFEED=0x55;
    while(!(PLLSTAT & PLOCK));  //wait for the PLL to lock to set frequency
    PLLCON=0x3;                 //connect the PLL as the clock source
    PLLFEED=0xaa;
    PLLFEED=0x55;
    MAMCR=0x02;                 //enable MAM
    MAMTIM=0x04;                //set number of clocks for flash memory fetch
    VPBDIV=0x01;                //set peripheral clock(pclk) to system clock(cclk)
}

Thanks
Last edited by KidE on Mon Feb 23, 2009 12:02 pm, edited 5 times in total.
By nbl1268
#65451
What type of servo are you trying to drive?? is it a thre wire PWM type or a multiquadrant type?

Roughly how long is the LED dim and full during each interrupt?
By KidE
#65458
It's a 3 wire servo i use a normal analoge one.
I used the servo with PWM and it worked fine but i'm trying it now with a puls train to use it in combi with interrupts.

The led is dimm for 3 sec and after that it fires up fully.

Ernst
By nbl1268
#65615
KidE wrote:The led is dimm for 3 sec and after that it fires up fully.

Ernst
Hmm, does the LED turn off and repeat this cycle or is that it it just stays fully lit??
By nbl1268
#65620
I'm not seeing any immediate coding issues but i am curious whether the issues is that the interrupt routine you have developed probably doesnt provide a 50/50 square wave pulse train.

Actually wondering if you'd be better off changing the interrupt routine so that it just complimented the state of the GPIO pin that you have the servo attached to each time.

This would give a nice 50/50 cycle and then you can just change the timer values to get the servo to move from min to max.
By KidE
#65621
It stays LIT for the rest of the times and i'm wondering if it crashed.
Actually wondering if you'd be better off changing the interrupt routine so that it just complimented the state of the GPIO pin that you have the servo attached to each time.

This would give a nice 50/50 cycle and then you can just change the timer values to get the servo to move from min to max.
Could you supply me with a hint in the right direction? i'm quite new at this so.

Thanks up front.
[/code]
By nbl1268
#65702
KidE wrote: Could you supply me with a hint in the right direction? i'm quite new at this so.

Thanks up front.
[/code]
I'll see what i can do. To help would you mind posting the content of your 'VIClowlevel.h' file?
By KidE
#65705
Both pieces of code ore from http://ghmicro.com/index.php/lpc2000/1- ... rd?start=6
Code: Select all
VIClowlevel.h

unsigned enableIRQ(void);
unsigned disableIRQ(void);
unsigned restoreIRQ(unsigned oldCPSR);
#define IRQ_MASK 0x00000080
Code: Select all
VIClowlevel.c

This piece of code must be used to enable and disable interrupts.

#include "VIClowlevel.h"

static inline unsigned asm_get_cpsr(void)
{
  unsigned long retval;
  asm volatile (" mrs  %0, cpsr" : "=r" (retval) : /* no inputs */  );
  return retval;
}

static inline void asm_set_cpsr(unsigned val)
{
  asm volatile (" msr  cpsr, %0" : /* no outputs */ : "r" (val)  );
}

unsigned enableIRQ(void)
{
  unsigned _cpsr;

  _cpsr = asm_get_cpsr();
  asm_set_cpsr(_cpsr & ~IRQ_MASK);
  return _cpsr;
}

unsigned disableIRQ(void)
{
  unsigned _cpsr;

  _cpsr = asm_get_cpsr();
  asm_set_cpsr(_cpsr | IRQ_MASK);
  return _cpsr;
}

unsigned restoreIRQ(unsigned oldCPSR)
{
  unsigned _cpsr;

  _cpsr = asm_get_cpsr();
  asm_set_cpsr((_cpsr & ~IRQ_MASK) | (oldCPSR & IRQ_MASK));
  return _cpsr;
}
By KidE
#65823
OK i forgot to mention that i use crossworks.

In another piece of code i ran into the same problem so it seems that crossworks is handeling interrupts in a different way and they bite with the current "gcc for ARM" way.

I have some sample code how it should be done and i have to look into this.

I found some interesting links and i'm going to dig into this somewhere this week.

http://tech.groups.yahoo.com/group/lpc2 ... sage/31140

http://ccgi.rowley.co.uk/support/faq.ph ... ticleid=28

http://ccgi.rowley.co.uk/support/faq.ph ... ticleid=25
By KidE
#66028
If i look in the examples from Rowley's this is how it
should look i think.
Only downside..... its not working
Reading the manual part of ctl_api this should be working.

In the startup file i've also enabled: VECTORED_IRQ_INTERRUPTS

Anyone smart idea's?
Code: Select all
#include <ctl_api.h>
#define PLOCK 0x400
void init(void);
void delay_ms(int);

volatile int servo;

int main(void)
{
    init();
    PINSEL1 = 0x10000000;               //p0.30 = AD0.3
    IODIR0 = 0x00200000;                //p0.21 = output
    AD0CR = 0x00210e08;                 //start burst A/D on AD0.3
    T0TCR = 0x02;                       //reset counter
    T0IR = 0xff;
    T0MCR = 0x0003;                     //interrupt and reset on MR0
    T0MR0 = 0x00124f80;                 //compare-hit count
//    VICVectCntl0 = 0x00000024;          //use it for Timer 0 Interrupt:
//    VICVectAddr0 = (unsigned)isr;       //set interrupt vector in 0
//    VICIntEnable = 0x00000010;          //enable TIMER0 interrupt
    T0TCR = 0x01;                       //enable Timer0
    ctl_global_interrupts_enable();
   
    while(1){
    }
}

void isr(void)
{
    // let burn some LED's
    T0IR = 0x01;                //clear interrupt
    VICVectAddr = 0;            //end of interrupt - dummy write
}

void init_isr(void)
{
    ctl_set_isr(1, 0, CTL_ISR_TRIGGER_FIXED, isr, 0);
    ctl_unmask_isr( 1);
}


Gr,

Ernst
By KidE
#66089
Ok almost solved

The code is working now and interrupts are fired :D
Code: Select all
#include <ctl_api.h>
#define PLOCK 0x400
void init(void);
void delay_ms(int);

volatile int servo;

int main(void)
{
    init();
    init_isr();
    PINSEL1 = 0x10000000;                //p0.30 = AD0.3
    IODIR0 = 0x00200000;                 //p0.21 = output
    AD0CR = 0x00210e08;                 //start burst A/D on AD0.3
    T0TCR = 0x02;                            //reset counter
    T0IR = 0xff;
    T0MCR = 0x0003;                        //interrupt and reset on MR0
    T0MR0 = 0x00124f80;                 //compare-hit count
    T0TCR = 0x01;                           //enable Timer0
    ctl_global_interrupts_enable();
   
    while(1){
    }
}

void isr(void)
{
    // let burn some LED's
    T0IR = 0x01;                //clear interrupt
    VICVectAddr = 0;            //end of interrupt - dummy write
}

void init_isr(void)
{
    ctl_set_isr(1, 0, CTL_ISR_TRIGGER_FIXED, isr, 0);
    ctl_unmask_isr( 1);
} 
Using crossworks in the ISR the following should be replaced by something else. Only what?
Code: Select all
    T0IR = 0x01;                //clear interrupt
    VICVectAddr = 0;            //end of interrupt - dummy write
By nbl1268
#66232
Hi, great to hear you almost got it working.
Spent some time doing the same and come up with this.
Code: Select all
#include "LPC214x.h"
//#include "VIClowlevel.h"

#define PLOCK 0x400
#define TIMER0_INT	(1<<4)

#define LED		(1<<17)				// PIN address of output
#define LEDON()		IOSET0 = LED
#define LEDOFF()	IOCLR0 = LED

void init(void);
//void ISR_Timer0 (void)   __attribute__ ((interrupt("IRQ")));
void ISR_Timer0 (void);
//void delay_ms(int count);

int main(void){
	int i;
	
	// Initialise uC
    init();									// Setup PPL

    //IOCLR0 = 0x00200000;					//LEDs off
	LEDOFF();
	
	//enableIRQ();							// use if using VIClowlevel.h
	VICIntEnable |= TIMER0_INT;				//Turn on Timer0 interrupts
   
    while(1){
        // Wait here for interrupt
		i=0;
		i=1;
	}
}

void ISR_Timer0(void){
    // Interrupt from Timer0

	// Toggles state of the output; effectively halves the freq of Timer0
	if((IOPIN0 & LED) == 0)
	{
		//IOSET0 = 0x00200000;
		LEDON();
	}
	else
	{
		//IOCLR0 = 0x00200000;
		LEDOFF();
	}

    T0IR = 0x01;							//clear interrupt
    VICVectAddr = 0;						//end of interrupt - dummy write
}

void init(void){
	// Setup IO
    //IODIR0 = 0x00200000;					//Output
	IODIR0 = LED;							// Set as GPIO as output


	// Setup PLL
    PLLCFG=0x24;                //set multiplier/divider values
    PLLFEED=0xaa;
    PLLFEED=0x55;
    PLLCON=0x01;                //enable PLL
    PLLFEED=0xaa;
    PLLFEED=0x55;
    while(!(PLLSTAT & PLOCK));  //wait for the PLL to lock to set frequency
    PLLCON=0x3;                 //connect the PLL as the clock source
    PLLFEED=0xaa;
    PLLFEED=0x55;
    MAMCR=0x02;                 //enable MAM
    MAMTIM=0x04;                //set number of clocks for flash memory fetch


    //Setup the Interrupts
	VPBDIV=0x01;							//set peripheral clock(pclk) to system clock(cclk)
	VICIntSelect = ~(TIMER0_INT);
    //VICVectCntl0 = 0x00000024;            //use it for Timer 0 Interrupt:
	VICVectCntl0 = 0x20 | 4;				// Timer 0 Interrupt
    VICVectAddr0 = (unsigned int)ISR_Timer0;  	// set interrupt vector in 0
    //VICIntEnable = 0x00000010;			//enable TIMER0 interrupt


	//Setup Timer0 to interrupt on count value
	T0PR = 0;								// increment every PCLK
//	T0TCR = 0x02;							// reset counter
	T0TCR |= 0X01;							// enable Timer0
	T0CTCR = 0x00;							// Timer Mode
	T0MCR = 0x0003;							// Interrupt and Reset Timer on Match
	T0MR0 = 0x00124F80;						// compare-hit count 20ms
											// 0x00124F80 = 1,200,000
											// 60MHz / 1200000 = 50Hz or 20ms


/*	//Setup Timer0 to Interrupt on timer value
	// alternate way of setting up timer 0
	T0PR = 1200;							// Divide Clock(60MHz) by 1200 for 50kHz PS
	T0TCR |= 0X01;							// Enable the clock
	T0CTCR = 0;								// Timer Mode
	T0MCR = 0x0003;							// Interrupt and Reset Timer on Match
	T0MR0 = 1000;							// Divide Timer Clock (50KHz) by 1000 for 50Hz or 20ms
*/
}
I havent used the VIClowlevel.h file
The output toggles every timer match and provides a nice 50% duty cycle for controlling the servo.

Neil
By KidE
#66975
Ok somebody from lpc2000 group helped me good and my problem (at least teh IRQ thing) is solved now.
Code: Select all
#include "LPC214x.h"
#include <ctl_api.h>
#define PLOCK 0x400
void init(void);
void delay_ms(int);
void isr_servo_out(void);

volatile int servo;

void init_isr(void)
{
    ctl_global_interrupts_enable(); // interrupts enabled
    ctl_set_isr(4, 0, CTL_ISR_TRIGGER_FIXED, isr_servo_out, 0); //interrupt set
    ctl_unmask_isr( 4); //interrupt unmasked
}

void isr_servo_out(void)
{
    IOSET0 = 0x00200000;  // and there was light 
    T0IR = 0x01;                //clear interrupt
}

int main(void)
{
    init();
    init_isr();
    PINSEL1 = 0x00002000;               //p0.22 = capture 0.1 (timer0)
    IODIR0 = 0x00200C00;                //p0.10, p0.11, p0.21 = GPIO output
    IOSET0 = 0x00000C00;                // LED1+2 off
    T0TCR = 0x02;                           //reset counter
    T0IR = 0xff;
    T0CCR = 0x00000005; //capture on rising edge
    T0TCR = 0x00000001; //enable timer
    
    while(1){
    }
}


void init(void)
{
    PLLCFG=0x24;                //set multiplier/divider values
    PLLFEED=0xaa;
    PLLFEED=0x55;
    PLLCON=0x01;                //enable PLL
    PLLFEED=0xaa;
    PLLFEED=0x55;
    while(!(PLLSTAT & PLOCK));  //wait for the PLL to lock to set frequency
    PLLCON=0x3;                 //connect the PLL as the clock source
    PLLFEED=0xaa;
    PLLFEED=0x55;
    MAMCR=0x02;                 //enable MAM
    MAMTIM=0x04;                //set number of clocks for flash memory fetch
    VPBDIV=0x01;                //set peripheral clock(pclk) to system clock(cclk)
}


:D :D :D