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.