Disable Interrupts

Hi there,

I'm working on controlling several PWM devices and I need to be sure that my widths are accurate to within about hundred milliseconds. Originally I was using this code, which worked OK:

digitalWrite(pin1, HIGH);
delayMicroseconds(pulse);
digitalWrite(pin1, LOW);
digitalWrite(pin2, HIGH);
delayMicroseconds(pulse);
digitalWrite(pin2, LOW);
// etc...

However we have since discovered that this is just too long of a delay as all of the pulses add up together. I'm fully aware that delayMicroseconds() disables interrupts, but our new plan involves something along these lines:

digitalWrite(pin1, HIGH);
digitalWrite(pin2, HIGH);
delayMicroseconds(pulse);
digitalWrite(pin1, LOW);
delayMicroseconds(difference);
digitalWrite(pin2, LOW);

This way we only have to spend some time sorting the timings beforehand. Problem is that these delays are no longer atomic. I am worried that if serial data or something similar comes in at the point in between the two delays, the pulse widths will be extended beyond where they should be.

My hope is that there is a way to disable interrupts so that I can wrap the entire pulse code. I'm not concerned with losing serial data; our protocol has a mechanism to recover from this; however I am concerned if the devices are not operating as they should be. In theory, disabling interrupts should fix this problem.

Any ideas?

Thanks,
-- Matt

To disable interrupts:
cli(); // disable global interrupts

and to enable them:
sei(); // enable interrupts

note that the millis timer will also be affected by disabling interrupts so take that into account if you use it.

Thanks a bunch; I can't say I noticed any major problem with the timing while interrupts were enabled today but I figured I should prepare for a worst-case scenario. I'm used to coding realtime systems and while it isn't likely that an interrupt will occur in the middle of this pulse, it is definitely possible.

Do you think my reasoning is justified here? Or do you see a better way of handling PWM that I am missing? The problem I was facing is that I have 4 analog values coming in which need to be fed serially to a controlling computer. I also have 4 servos hooked up which need to have their signals periodically refreshed. I have determined that I can have all of the analog values interleaved and the signals for the PWM pulsed all at the same time using the code above. Originally I was doing it one servo at a time, then one sensor at a time, then serial. Unfortunately the delay was far too much to maintain accuracy, especially when the sensor values tend to be compared against each other.

So far this has worked well for me, so I think I'll leave interrupts disabled. A lost packet isn't a big deal if it were to ever occur, I can handle that. An incorrect value from a sensor or to a servo, however, could be disasterous.

Thanks for the help,
-- Matt

Turning interrupts off seems a logical approach for your application as long as you don't use the one millisecond timer for your 20 ms frame rate (delay and millis() wont work). Also, according to the documentation serial receive wont work.

I don't think anything else will be affected but I am new to Arduino myself so I hope someone else will comment if there is a problem running with global interrupts off