Fast IO

27 Feb 2010

Hi,

I need faster output switching than offered by using DigitalOut(), I also need to change the state of up to 3 outputs at exactly the same time (BusOut() wont do this).

After some searching I found the FIOSET fast port output set register, But I have had no luck finding any examples of how to assign pins to a given port and then how to set all the bits at once.

Hope some one will be able to help.

Thanks,

Mike.

 

 

 

05 Mar 2010 . Edited: 05 Mar 2010

Anyone? Pretty please!

#include "mbed.h"

#define LED_2 (1 << 21)
#define LED_3 (1 << 23)

// All Leds
#define LED_ALL (LED_2 | LED_3)

int main() {
   
        LPC_GPIO1->FIODIR |= LED_ALL;
    while (1) {
        LPC_GPIO1->FIOSET = LED_ALL;
        wait(1);
        LPC_GPIO1->FIOCLR = LED_ALL;

    }
}

The above code turns on 2 Led's on the mbed at the same time but fails to turn them off again, Can any one tell me why?

Thanks.

Mike.

 

 

05 Mar 2010

 

Michael Duffin wrote:

Anyone? Pretty please!

#include "mbed.h"

#define LED_2 (1 << 21)
#define LED_3 (1 << 23)

// All Leds
#define LED_ALL (LED_2 | LED_3)

int main() {
   
        LPC_GPIO1->FIODIR |= LED_ALL;
    while (1) {
        LPC_GPIO1->FIOSET = LED_ALL;
        wait(1);
        LPC_GPIO1->FIOCLR = LED_ALL;

    }
}

The above code turns on 2 Led's on the mbed at the same time but fails to turn them off again, Can any one tell me why?

Thanks.

Mike.

 

 

     LPC_GPIO1->FIODIR |= LED_ALL;
    while (1) {
        LPC_GPIO1->FIOSET = LED_ALL;
        wait(1);
        LPC_GPIO1->FIOCLR = LED_ALL;
        wait(1);
    }

    The loop re-enables them before they have chance to go off

 

05 Mar 2010

Thanks for that Andrew,

Instead of a delay I assume several lines of code before the loop starts again will be sufficient?

Mike.

06 Mar 2010

Michael Duffin wrote:

Thanks for that Andrew,

Instead of a delay I assume several lines of code before the loop starts again will be sufficient?

Mike.

It goes back to while 1 not main.

The processor is running at 100Mhz, you would need approximately 100million operations to see a 1 second delay, humans typically cannot observe faster than around 50ms, so IRO 5mil operations

06 Mar 2010

Hi Andrew,

I didn't explane things very well and I misunderstood "the loop re-enables them before they have chance to go off", what actually happended is the output did go high and then low but then went high again at the begining of the loop it just just did it so fast as It could not be seen by eye.

I actually want to use the above to step several stepper motors quite fast, the code will be ran in an ISR and I only need a pulse width of 1us (per motor) to step the motor drivers I am using, I hope that a bit of math between setting them high and then low will be enough to give me the 1us period.

Another reason for wanting to do things this way is in hope that I can spend a little less time in my ISR than using several DigitalOut()'s , allowing non timing related activities to take place outside of the ISR.

Thanks.

Mike.

15 Mar 2010

What is the equivalent way to read a pin? I tried  val = LPC_GPIO0->FIOPIN(X_MIN); but that got thrown out by the compiler

15 Mar 2010

If X_MIN is the bitmask for your pin (1<<n), then something like this:

val = (LPC_GPIO0->FIOPIN & X_MIN) != 0;

15 Mar 2010 . Edited: 15 Mar 2010

 

Michael Duffin wrote:

Hi Andrew,

I didn't explane things very well and I misunderstood "the loop re-enables them before they have chance to go off", what actually happended is the output did go high and then low but then went high again at the begining of the loop it just just did it so fast as It could not be seen by eye.

I actually want to use the above to step several stepper motors quite fast, the code will be ran in an ISR and I only need a pulse width of 1us (per motor) to step the motor drivers I am using, I hope that a bit of math between setting them high and then low will be enough to give me the 1us period.

Another reason for wanting to do things this way is in hope that I can spend a little less time in my ISR than using several DigitalOut()'s , allowing non timing related activities to take place outside of the ISR.

Thanks.

Mike.

1us would be be approximately 100 instructions running at 100Mhz, not including interrupts.

 

How fast is the interrupt running?

 

ETA: Thought, You could dynamically change the speed of the interrupt if you're running a timer interrupt at say 250us, change the next step to 1us and just clear the step pin states and reset back to 249us

 

volatile bool ISR_state = false;

void ISRFunction()
{
    if(ISR_state)
    {
        // TODO: Insert step pin clear ops

        // TODO: Change ISR Timeout to 249us
        ISR_State = false;
    } 
    else
    {
        // TODO: Insert normal ops

        // TODO: Change ISR timeout to 1us
        ISR_state = true;
    }
}

16 Mar 2010

Hi Andrew,

The ISR is called at a varying rate depending on the speed I want the motors to run, The shortest period of time between interupts is about 60us.

I now know how to set multipul pins at once using,

#define LED_ALL (LED_2 | LED_3) 
LPC_GPIO1->FIOSET = LED_ALL;

But.... Say I don't know until somewhere within the ISR what pins need to be set high? (at this point how do I allow only the chosen outputs to be effected?) Is this where the bitmask comes in?

I'm using an algorithm that dictates if an axis (3 total) is able to step in order to interpolate a move, So in one case I may only want to turn on 1 output and in another case 2 or 3 outputs all at the same time. Once they have been set high I need to make sure all of the 3 outputs are set low again. The 1us is the minimum period the stepper motor drives i'm using require. (I'm not too worried about this now as their is more than enough going on in my ISR between them going high and low to cause a 1us delay).

Thanks.

16 Mar 2010

Sounds like you're running from a GCode interpretter with commands dictating when the motors should move, is the interrupt the message received interrupt?

RepRap or CNC?

You could also have a single interrupt for just clearing the pins, turn it on when you activate the pins and then get the interrupt to disable itself.

I would suggest increasing the duration for a number of reasons but mainly because the input, circuit line impedance etc will impact the rise time of the signal, as you stated yourself, you're not driving the motor at 1MHz (I think the motor would probably not work at this frequency anyway)

I would suggest looking at 5-10us, this allows for some impedances in the circuitry.

Does the driver in question operate on the rising or falling edge of the input? if rising then the off time is irrelevant as long as it's off before it steps again. Falling is a seperate problem and possibly justifies your question.

16 Mar 2010
Andrew Harpin wrote:

Sounds like you're running from a GCode interpretter with commands dictating when the motors should move, is the interrupt the message received interrupt?

RepRap or CNC?

You could also have a single interrupt for just clearing the pins, turn it on when you activate the pins and then get the interrupt to disable itself.

I would suggest increasing the duration for a number of reasons but mainly because the input, circuit line impedance etc will impact the rise time of the signal, as you stated yourself, you're not driving the motor at 1MHz (I think the motor would probably not work at this frequency anyway)

I would suggest looking at 5-10us, this allows for some impedances in the circuitry.

Does the driver in question operate on the rising or falling edge of the input? if rising then the off time is irrelevant as long as it's off before it steps again. Falling is a seperate problem and possibly justifies your question.

Hi,

The code i'm writing is a GCODE interpretter, similar to Chris Meighans re-write of the RepRap Arduino firmware, I'm using micro-stepping upto 16X so 1Mhz is quite possible (although i'm currently only at 8x). The driver i'm currently using steps on the rising edge. Its for a CNC Mill.

Like I said I'm no longer concerned about the 1us delay between the outputs going from high to low.

I'm more in need of an explanation of how to use LPC_GPIO1->FIOSET = LED_ALL where LED_ALL could consist of 1, 2 or 3 outputs. I need to be able to change this for each step. I'm currently doing this using 3 DigitalOut statements (one for each axis), which as we know is slow and more to the point I want to get back out of my ISR as soon as possible so other code has time to execute before the next interupt.

The interupt to interupt time changes depending on acel /decel and the feedrate required at that time.

Thanks.

Mike.