>
>> I am using Servo, but it works random when more interrupts are used as Atmel cannot process more than one interrupt at a time
> Which Servo library? I think I’d need stronger proof that problems are due to the inherent interrupt structure of the the AVR.
Since Arduino version 0017 (a long time ago), the Servo lib uses a timer
interrupt and software to synthesize waveforms for up to 12 servos.
That's a huge improvement over only supporting 2 motors as the old
version did using PWM pins. But Servo is sensitive to interrupt
latency. If other libraries or code have interrupts disabled, either by
running their own interrupt code or by disabling interrupts for
exclusive access to data, Servo's interrupt routine runs later than it
should, causing one or two of the pulses it generates to be slightly off.
This really is a combination of latency-sensitive waveform synthesis and
latency "due to the inherent interrupt structure of the the AVR". Some
other architectures like ARM and even Atmel's X-Mega AVR have priority
nested interrupts, which can be used to allow timing-critical interrupts
to interrupt other less sensitive ones. Classic AVR doesn't. It has
only a single interrupt enable/disable bit. When any interrupt runs,
unless code within that interrupt takes the very risky action of
re-enabling more interrupts, all others are blocked. But even with
architectures that support priority nesting, when other code implements
a critical section for data access by disabling all interrupts, even the
highest priority ones have to wait.
Usually the solution is PWMServo, which is merely the original PWM-based
Servo library, updated and renamed by Mikal Hart several years ago, to
solve this very problem for people needing servo motors together with
other code that creates interrupt latency.
>> I am thinking about rewrite it to assembler and create a second level context switch - call another interrupts from servo routine (after finishing) and when that another interrupt finishes return to point where servo interrupt started.
> That sounds awful.
I agree, it does sound terrible. Priority nesting of interrupts really
needs to be implemented in hardware. Any attempt to do this by software
is likely to be error prone (where the failure mode is a recursive
interrupt that overwrites all RAM as it repeatedly saves content onto
the stack), and even if it can be done, the overhead involved is likely
to be far too high. Even if the overhead is acceptable, there's still
the problem of critical sections disabling all interrupts.
PWMServo is the answer.
Ideally, the Servo library reference page could make some (novice
friendly) mention of possible interference from other libraries and
provide a suggestion to try PWMServo for people encounter this well
known problem.