Servo, small & quick fonts ?

7 views
Skip to first unread message

El Tom

unread,
Mar 14, 2017, 5:43:21 AM3/14/17
to Developers
Hello,

I made a special font code for my Arduino project, it is using a outline en/decoder to make fonts much smaller (similar to LZW results), any interest ?
And I found Arduino unreliable - I am using Servo, but it works random when more interrupts are used as Atmel cannot process more than one interrupt at a time, it is delayed sometimes and result are upredictable random servo ticks - yes, another interrupts should be very short, but anyway servo is not well done and each time unreliable when another interrupt come in "bad time".
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.

What do you think about or is anyone interested doing that ?

BR,
El Tom
P.S. I have these fonts/conversions implemented on PC (VS Express & Arduino 1.6.3 cage) including PC simulator of TFT ILI9340 (C++/.Net) and as adjusted Arduino/TFT libraries (also speed is improved a lot - points are sent in a stream similar to fill not one by one where was huge overhead on SPI so very slow print speed).

William Westfield

unread,
Mar 17, 2017, 4:18:53 AM3/17/17
to devel...@arduino.cc, El Tom

On Mar 10, 2017, at 1:31 AM, El Tom <elzein...@gmail.com> wrote:

> using a outline en/decoder to make fonts much smaller (similar to LZW results), any interest ?

You mean for LCD displays and similar? I didn’t think those libraries were using any outline-based fonts, but using less space for fonts would be a great idea; I’ve had to suggest several times that people manually prune their font tables. (OTOH, come other LCD libraries already do a better job at permitting that.)


> 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.

> 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’m prepared to believe that there are bugs in the Servo library, or (even more likely) bugs in other code that uses interrupts, and I know that various interrupts are slower than they could be. But I’d need a lot more convincing that your solution would help any, and it would certainly cause any number of problems. Do you have a more detailed analysis of exactly what goes wrong?

BillW/WestfW

Paul Stoffregen

unread,
Mar 17, 2017, 7:53:31 AM3/17/17
to devel...@arduino.cc
>
>> 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.

William Westfield

unread,
Mar 17, 2017, 8:04:10 AM3/17/17
to devel...@arduino.cc
> 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.

But isn’t the error on the order of 10us out of a 1ms pulse - 1% or so? It sounds like El Tom had found something considerably more serious… (and, rewriting the servo code wouldn’t help; it’s the other ISRs running for too long, and being “exclusive”, that causes the problem, right?)

BillW

Thomas Roell

unread,
Mar 17, 2017, 8:16:47 AM3/17/17
to devel...@arduino.cc
You cannot solve the "other ISRs running for too long" without having multiple ISR priorities. Actually the user-callback feature (attachInterrupt() / detachInterrupt()) is a big issue there, as most users simply do not understand the effects their code has on the whole system.

For STM32L4 the Servo code ended up with the highest priority, so that the jitter for Servo could be avoided. The user-level callbacks with the exception of the pin changing callbacks are religated to the lowest priority to avoid adverse effects ...

Long, long time ago I implemented a virtual nested scheme for Z80 and some old ARMV4T architectures. The problem there (besides complexity) is that you add a lot of latency.

- Thomas


--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@arduino.cc.

Reply all
Reply to author
Forward
0 new messages