VERY short bit bang with a long code loop

Hello,

I've run into a problem where I need to flip a pin for an extremely short duration using micros().

However, each loop of the code takes longer than I need the pin flipped for.

Currently a loop is taking between 1200us and 3000us, but the pin flip needs to happen within 800-1100.

Using a delayMicroseconds() of the appropriate range does the job, but I'd rather not interrupt the program even for a small period of time.

I'm running a very finely-tuned air valve which polls a pressure transducer each loop (which takes 100us in and of itself each loop!). If the valve is open for too long, it moves too much air.

Suggestions?

Share your code (after reading this post so that you know how to do it properly) so that we can make informed suggestions.

When your code turns the air on, also set a global state variable and set a global variable to current micros time.

Make a function that checks for that state variable being set and if stored micros is sufficiently smaller than current micros then turn off the pin and flip the state variable.

Insert calls to that function in multiple spots in your code.

squarebit:
but the pin flip needs to happen within 800-1100.

If there is other work to be done it will be almost impossible to get loop() to repeat reliably within 1 millisec.

I suggest you use one of the Hardware Timers to manage the state of your I/O pin. There are various options but you have not told us much about your project.

For example is each "pulse" a one-off at long intervals?

Or is it something that repeats regularly? If so, at what frequency?

...R

Slumpert:
When your code turns the air on, also set a global state variable and set a global variable to current micros time.

Make a function that checks for that state variable being set and if stored micros is sufficiently smaller than current micros then turn off the pin and flip the state variable.

Insert calls to that function in multiple spots in your code.

Basically you want to slow down the code execution so I can handle the flip in a single loop? I've thought about that too, but... then I might as well use a delay, no?

Robin2:
If there is other work to be done it will be almost impossible to get loop() to repeat reliably within 1 millisec.

I suggest you use one of the Hardware Timers to manage the state of your I/O pin. There are various options but you have not told us much about your project.

For example is each "pulse" a one-off at long intervals?

Or is it something that repeats regularly? If so, at what frequency?

...R

Ideally, I'd like to just keep the air valve on for a small duration - the recheck to see if it needs to fire again. I've tried PWMing these valves, and even using tone() at frequency of 500-2000hz but I'm reluctant to pulse the valve simply because of the time it takes to air to move, combined with the 100us polling of the transducer. It would call to fire more often if I give it "permission" so to speak by turing it on/off with a frequency..

I've had the best accuracy with on - delay - off, recheck.

With a high enough frequency from tone() or pwming it, I was able to walk backwards from 2000hz on each loop until the frequency was low enough to actually let air through. It worked, but gave less than timely results.

squarebit:
3
Ideally, I'd like to just keep the air valve on for a small duration - the recheck to see if it needs to fire again.

That, and the rest of your Reply is a very fuzzy response to what I thought were simple questions in Reply #3

From the piece I have quoted I infer that you would prefer single air pulses with an opportunity to test the effect between each. In that case I suggest you program one of the HardwareTimers so that it generates an interrupt when the duration of the pulse has expired, and in the Interrupt Service Routine (ISR) your code can close the valve. In other words the sequence would be something like

start the Hardware Timer
open the valve

leave it to the ISR to close the valve.

...R

Don't know how hard it would be to do in the Arduino environment, but there is a way to configure an AVR timer to output a one-shot pulse as described in the links from here: AVR Hardware Timer Tricked Into One-Shot | Hackaday

So as I understand your problem, you could calculate a desired pulse width, configure the timer to generate a single pulse of that width, and your code could move on to other things while the timer does its thing.

MrMark:
Don't know how hard it would be to do in the Arduino environment, but there is a way to configure an AVR timer to output a one-shot pulse as described in the links from here: AVR Hardware Timer Tricked Into One-Shot | Hackaday

So as I understand your problem, you could calculate a desired pulse width, configure the timer to generate a single pulse of that width, and your code could move on to other things while the timer does its thing.

Yessir, that's the crux of it.

I've looked into the one-shot pulse generator listed above and that seems like exactly what I need. I attempted to modify the pin it uses (from pin 3 to pin 9) but couldn't get it to pulse. I'm going to try getting that idea to work on another breadboard.

Failing that, the only other thing I can think of is a separate Arduino to run the valves triggered by output from the first with really short code.

squarebit:
I attempted to modify the pin it uses (from pin 3 to pin 9) but couldn't get it to pulse

Each HardwareTimer is associated with two specific pins.

Pin 3 is on Timer2 and pin 9 is on Timer1. Timer2 is an 8 bit timer and Timer1 is a 16 bit timer (all assuming you are using an Uno)

...R

Yeah need timer1 stuff. Looking at Josh's code, switching it is beyond me aside from the actual output pin line.