Interrupts and timing of a PPM signal

To use with my RC aircraft I have modified a Saitek joystick / throttle set and connected the potentiometers to an Arduino Nano board. I also added a few buttons for trims and wrote a sketch to handle all this stuff. Arduino Nano is planned to produce a standart PPM pulse train which will be sent to the trainer port of my RC transmitter.
This is not a very complicated task. But I have experienced an interesting problem.
First let me explain the code...
To achieve 1 microsecond resolution I planned to use Timer1 with a prescaler of 8. This gives me a 0.5 microsecond resolution for pulse production.
As you know, a PPM signal consists of a long (around 4 - 5 mS) HIGH pulse as sync pulse and then channel pulses of 1 - 2 mS separated by 300 microseconds LOW pulses. Pulse period of a single channel consists of it's corresponding HIGH pulse plus 300 microseconds.
My sketch collects the necessary information (read the pots, read the buttons, calculate trims etc.) during the sync pulse and then starts the PPM pulse train.
The PPM pulse train is being generated like this: (aileron is an unsigned integer which contains the pulse length for Channel 1, x is a temporary variable). Upon entry the output is already HIGH.

  digitalWrite(PPMout, HIGH);
  ...
  unsigned int x;
  x = aileron * 2 - 600; // 600 is for 300 microseconds LOW pulse
  while (TCNT1 < x);
  digitalWrite(PPMout, LOW);
  TCNT1 = 0;
  while (TCNT1 < 600);
  TCNT1 = 0;
  digitalWrite(PPMout, HIGH);

This is only part of the PPMOut function. Other channel pulses are generated similarly.

Now the problem:

As this signal generation is very time sensitive, I decided to disable interrupts during this period. That means, the PPMOut function begins with "cli();" and ends with "sei();".
If I do this, the servos do not move smoothly but they move in steps. A very annoying problem. But if I remove these lines (cli() and sei()) the code works perfectly.

Now I want to find out whether the Arduino IDE uses interrupts during reading of the Timer Counter 1 or are there other fine details?

Now I want to find out whether the Arduino IDE uses interrupts during reading of the Timer Counter 1 or are there other fine details?

What do you think makes the clock tick? If you said "an interrupt", you were correct.

Thanks for the reply.
As far as I know, the clock(s) ticking and interrupts are different worlds. :slight_smile:
If the Timer1 is enabled but global interrupts are disabled the timer counter should keep on counting. Or?

The micros() function has a resolution of 4µsecs. The shortest RC pulse is about 1000µsecs so any error introduced by micros() would be about 0.4%. Would that matter?

If not, why not use micros() for the timing in the same way that you would use millis() for slower timing (see Several Things at a Time )? Then you could build your stream of output pulses without any interrupts.

...R

"Shortest pulse of 4 µsecs" and "a resolution of 4 µsecs" are different terms. Which one is valid for delayMicroseconds()?
If the first is valid, you are 100 % right. But if the second one is right, the RC resolution will drop to 256 from 1024 steps and this is not acceptable.
Btw I normally do not use any interrupts for the generation of the PPM pulse train. At least not intentionally. :slight_smile:

As I am now at work I do not have access to a "real" Arduino board. So I decided to use the online simulator at "123d.circuits.io".

This is a simpe sketch:

void setup()
{
  Serial.begin(9600);
  TCCR1A = 0;
  TCCR1B = 2;
  TIMSK1 = 0;
  TCNT1 = 0;
}

void loop()
{
  Serial.println(TCNT1);
}

It starts nicely at 0 and counts up until around 60000 and then it stays there like this:
63394
53105
63389
53125
63376
53139
63373
53130
63386
53129
63372

Enabling or disabling interrupts does not have any effect.

My expectation was that the Timer1 would overflow at 65535 and continue from 0. Any explanation is welcome...

sumeryamaner:
"Shortest pulse of 4 µsecs"

I did not use that phrase. I can't imagine why you would need such a short pulse.

...R

I do not need a 4 microseconds pulse but I definitely need 1 microsecond resolution. If I get the same pulse for a pwm value of say 1510 and 1512 I cannot fly a real RC aircraft with it.

sumeryamaner:
My expectation was that the Timer1 would overflow at 65535 and continue from 0. Any explanation is welcome...

It should overflow about thirty times per second. It's like looking at a wheel spinning with a video, you're probably getting a beat frequency. Try a different baud rate. Or use more intelligent code to see that it is, in fact, overflowing.

sumeryamaner:
I do not need a 4 microseconds pulse but I definitely need 1 microsecond resolution. If I get the same pulse for a pwm value of say 1510 and 1512 I cannot fly a real RC aircraft with it.

I am amazed that an accuracy of 1 in 1000 is necessary and that 1 in 256 is not sufficient, however I am not an expert.

If micros() updated more than once every 4 µsecs the Arduino would not have enough spare MCU cycles to do anything useful.

If you want to use a hardware Timer to give you more accurate time intervals you will need to use it to generate the pulse directly rather than using it to generate an alternative "clock" to micros().

...R

As you know, a PPM signal consists of a long (around 4 - 5 mS) HIGH pulse as sync

That's news to me.
Are you sure?

Groove:
That's news to me.
Are you sure?

It sounds plausible. Remember the OP is talking about the collection of signals for several servos - not the signal for a single servo.

...R

RC PPM frame sync is a long low.
Has been for donkeys years.

Robin2:
I am amazed that an accuracy of 1 in 1000 is necessary and that 1 in 256 is not sufficient, however I am not an expert.

1024 resolution is very important. Some of the resolution will be lost due to endpoint adjustments. We always try to use the full range but it is not always possible.
Newer equipment has 4096 resolution.

Groove:
RC PPM frame sync is a long low.
Has been for donkeys years.

Unfortunately not... Yes there are some manufacturers with an inverted signal pattern but the classical PPM pulse train is like the one on the attached drawing.

Now try feeding those servo PWM pulse directly to your servos. :wink:

With respect to the servo pulses, the sync pulse is long and low.

Groove:
Now try feeding those servo PWM pulse directly to your servos. :wink:

It would make no sense to do that. Each pulses in that train is for a different servo.

...R

The point I was making is that the pulses are inverted for transmission.
If you isolate the PWM pulses whilst inverted, you cannot drive a servo with them, so they are not (pun intended) servo pulses.

With respect to the servo pulses, the sync pulse is, and always has been (well, at least since the 1970s, long and low.

I think it is technically not appropriate to define the LOW state on the servo lines as "sync pulses". And... PPM and PWM are two different entities. :slight_smile:

The PPM stream is just a collection (serial multiplex) of PWM pulses.

If you're uncomfortable with "sync pulses", think " reset timeout", because that's what they are - a pause long enough to allow a simple CR circuit to reset the decade counter that formed the demultiplexer. The normal inter-pulse gap is too short to allow the counter to reset.

OK. I do not want to discuss this topic further.
Back to the original question:

Does anyone have an idea why disabling interrupts corrupts pulse lengths based on Timer1?
Thank you...