RC Aircraft idle guard project and some questions.

Hi to all. This is my first post in this forum. For the last four months I have been involved in many projects for RC aircraft. Now this is another one.

I am building a module to prevent a gas engine stopping unexpectedly. The module will continuously monitor the ignition pulses and calculate the RPM. If the RPM falls below a preset level (set by a multiturn potentiometer) it will just add some throttle for three seconds gradually taking it back.
During this process the module will also monitor the throttle signal from the receiver and produce an appropriate PWM signal output to the servo.

The final product will be based on an Attiny85 but the development is going on on an Arduino Uno.

The RPM measurement is being accomplished using INT0. An interrupt is attached to INT0 on the RISING edge. The ISR is very short. It writes the previous value of X1 to X2 (both unsigned long) and the current millis() to X1. It also sets a flag indicating that the values have changed.

In the main loop if the flag is set, the difference of X1 and X2 (transferred to Y1 and Y2 by an atomic read) is used to calculate the RPM.

To prevent jitter there is an array with the last five measurements for the RPM. Everytime the flag is set, the RPM is being calculated and the values in the array are shifted. The last reading is entered into the array. An arithmetical averaging of the last five RPM calculations gives the final result.

For the PWM signal from the receiver I have tried two different approaches. One is pulseIn() function. The other is simply waiting for a pulse and then measuring the HIGH pulse using micros().

For the PWM signal output I have tried two different approaches. One is digitalWrite(throut, HIGH) then delayMicroseconds(required pulse lenght) and then digitalWrite(throut, LOW). The other is replacing the delayMicroseconds() by a while statement checking the micros() until timeout.

To test this module I have used another Arduino Uno which produces pseudo-ignition pulses. The frequency (read RPM) can be set using a potentiometer.

The code in general works fine but there is a strange problem after switching over to Attiny85.

The servo is making continuous small movements. This problem renders the whole project unusable. So I have written a new and very simple code to test the situation. The code reads the PWM signal from the receiver and sends it to the servo without any change.

const int thrin = 1; // Throttle signal pin from the receiver
const int throut = 0; // Servo signal output pin

unsigned int thrinpwm;
unsigned int throutpwm;

void setup()
{
  pinMode(throut, OUTPUT);
}

void loop()
{
  thrinpwm = pulseIn(thrin, HIGH, 25000);
  if ((thrinpwm > 1000) && (thrinpwm < 2000))
  {
    throutpwm = thrinpwm;
    servoout();
  }
}

void servoout()
{
  digitalWrite(throut, HIGH);
  delayMicroseconds(throutpwm);
  digitalWrite(throut, LOW);
}

Unfortunately the servo jitters.

For the servo jitter there may be two explanations.
1- There is a problem with the reading of the throttle PWM signal
2- There is a problem with the output of the PWM signal

So I tried different approaches.

First I tried another algorithm to read the incoming signal. It is waiting first for a LOW then for a HIGH and then measures the time in microseconds until the pin goes to LOW. There is a timeout of 22000 microseconds.

void readthr()
{
  limittimer = micros();
  while (digitalRead(thrin) == 1)
  {
    if((micros() - limittimer) > 22000) return;
  }
  limittimer = micros();
  while (digitalRead(thrin) == 0)
  {
    if((micros() - limittimer) > 22000) return;
  }
  frame = micros();
  while (digitalRead(thrin) == 1)
  {
    if((micros() - limittimer) > 22000) return;
  }
  thrinpwm = micros() - frame;
}

There was no difference.

Then I tried another method for PWM output. It writes a HIGH to the outut and continuously monitors micros() until the required pulse lenght has been reached.

void servoout()
{
  digitalWrite(throut, HIGH);
  frame = micros();
  while ((micros() - frame) < throutpwm)
  {
  }
  digitalWrite(throut, LOW);
}

The jitter continues…

Now I need some advice on reading a PWM pulse (duration between 1000 - 2000 microseconds recurring every 20 milliseconds) and on output a PWM pulse (duration between 1000 - 2000 microseconds) reliably.

For the PWM signal output I have tried two different approaches. One is digitalWrite(throut, HIGH) then delayMicroseconds(required pulse lenght) and then digitalWrite(throut, LOW). The other is replacing the delayMicroseconds() by a while statement checking the micros() until timeout.

Have you tried using the servo library to do the output ?

I have successfully used this code to change the pulse width of an RC signal

const byte yawInPin = 7;
const byte yawOutPin = 8;
unsigned long yawDuration;

const byte thrInPin = 9;
const byte thrOutPin = 10;
unsigned long thrDuration;

void setup()
{
  Serial.begin(115200);
  pinMode(yawInPin, INPUT);
  pinMode(yawOutPin, OUTPUT);

  pinMode(thrInPin, INPUT);
  pinMode(thrOutPin, OUTPUT);
}

void loop()
{
  yawDuration = pulseIn(yawInPin, HIGH);
  yawDuration = map(yawDuration, 1000, 1800, 980, 2020);
  digitalWrite(yawOutPin, HIGH);
  delayMicroseconds(yawDuration);
  digitalWrite(yawOutPin, LOW);  

  thrDuration = pulseIn(thrInPin, HIGH);
  thrDuration = map(thrDuration, 1000, 2000, 980, 2020);
  digitalWrite(thrOutPin, HIGH);
  delayMicroseconds(thrDuration);
  digitalWrite(thrOutPin, LOW);  
}

Thank you very much for the reply.
As a newbie I am always trying to accomplish simple tasks (a PWM pulse output is a simple task isn’t it? :smiley: ) by myself. Using ready made libraries seems to be more difficult to me.
Additionally I am using many interrupts in some projects. I am doing this by directly manipulating the registers of the MCU. As there may be some conflicts with other libraries I am trying to limit their usage to a minimum.

Your example code is a very straightforward piece of code (similar to one of my alternatives) and should work without any problems. But I cannot stop the servo jittering.

I am really sorry. I have found out that the code works fine on Arduino Uno but the servo jitters on an Attiny85 (with the same code). It has something to do with the processor and/or board. I am using a slef made simple board for Attiny85. My next step will be using a Digispark Attiny85 module to see if the servo stays calm or if it will keep jittering. :D

Is it possible that the on chip 8 MHz oscillator of the Attiny85 is not accurate enough leading to erroneous time readings???