I am designing a small circuit for use in twin engine RC aircraft. Let me explain it a little bit first.
As you may already know, in twin engine RC aircraft we must use two separate receiver channels to be able to fine tune each engine and to prevent thrust difference during flight.
Sometimes we run out of available receiver channels and look for solutions to combine similar channels in one channel.
Now my module is a simple servo sync module. It gets the receiver signal from CH.3 (usually the throttle channel) and lets you adjust the high and low end positions of the throttle servo using two multiturn potentiometers. Every engine will have it's own controller and this way only one channel of the receiver will be occupied.
Now, this is the PCB (sorry, I do not have a schematic). The signal from the receiver (consisting of 1000 - 2000 microsecond pulses repeating every 20 mS) go to the base of a 2N2222 and the collector of the 2N2222 is connected to the Attiny85 input. The emitter is of course connected to ground and the internal pullup resistor of the Attiny85 will be activated by the code. This setup guarantees that even puses of 2.5V are recognized by the microcontroller (some modern RC receivers work on very low voltages). This setup also leads to an inverted signal at the microcontroller input.
The microcontroller reads the pulse lenght, reads the two potentiometers and computes the necessary output signal. It then outputs a PWM pulse to the servo.
Attiny85 has been programmed to work on the internal oscillator at 8MHz.
I have planned subroutines to do the individual tasks.
This is the beginning of the code and there is nothing special.
Now the main loop...
That means there are three subroutines...
The first is to read the incoming signal:
The second is to calculate the output signal according to the readings of the two potentiometers.
And finally the third is to produce the servo signal
The cli() and sei() instruction are there to prevent servo jitter.
Now, this is a very straightforward code. Of course it can be optimized but I don't think that for such a simple task one should try to optimize it further.
Now my problem...
This code didn't work as expected. I have been getting only 160 microsecond pulses at the output.
Then I erased almost everything and tried to output the input signal without modification. That means I used;
"servoout(inpwm);" instead of "servoout(outpwm);". Interestingly I kept getting only about 160 microsecond pulses at the output.
Later I decided to cancel all subroutines and put everything into the "loop".
Now it works without any problems!
Summary:
If I put the servo signal output routine in a subroutine, there is a serious timing problem of the output signal. If I write the exact same code into the main loop, there are no problems.
Any idea about what I did wrong?
Thank you for your help...
As you may already know, in twin engine RC aircraft we must use two separate receiver channels to be able to fine tune each engine and to prevent thrust difference during flight.
Sometimes we run out of available receiver channels and look for solutions to combine similar channels in one channel.
Now my module is a simple servo sync module. It gets the receiver signal from CH.3 (usually the throttle channel) and lets you adjust the high and low end positions of the throttle servo using two multiturn potentiometers. Every engine will have it's own controller and this way only one channel of the receiver will be occupied.
Now, this is the PCB (sorry, I do not have a schematic). The signal from the receiver (consisting of 1000 - 2000 microsecond pulses repeating every 20 mS) go to the base of a 2N2222 and the collector of the 2N2222 is connected to the Attiny85 input. The emitter is of course connected to ground and the internal pullup resistor of the Attiny85 will be activated by the code. This setup guarantees that even puses of 2.5V are recognized by the microcontroller (some modern RC receivers work on very low voltages). This setup also leads to an inverted signal at the microcontroller input.
The microcontroller reads the pulse lenght, reads the two potentiometers and computes the necessary output signal. It then outputs a PWM pulse to the servo.
Attiny85 has been programmed to work on the internal oscillator at 8MHz.
I have planned subroutines to do the individual tasks.
This is the beginning of the code and there is nothing special.
Code:
#define high_end_read A2
#define low_end_read A3
#define pwm_pin PB0
#define servo_pin PB1
int inpwm;
int outpwm;
int high_value;
int low_value;
int temp;
int tmph;
int tmpl;
void setup()
{
pinMode(pwm_pin, INPUT_PULLUP);
pinMode(servo_pin, OUTPUT);
}
Code:
void loop()
{
inpwm = readPWM(pwm_pin);
outpwm = calcPWM();
servoout(outpwm);
}
The first is to read the incoming signal:
Code:
int readPWM(int q)
{
temp = pulseIn(q, LOW);
if(temp < 800) return 0;
if(temp > 2200) return 0;
return temp;
}
Code:
int calcPWM()
{
high_value = analogRead(high_end_read);
low_value = analogRead(low_end_read);
tmpl = map(low_value, 0, 1023, 1000, 1500);
tmph = map(high_value, 0, 1023, 1500, 2000);
int x = map(inpwm, 1000, 2000, tmpl, tmph);
return x;
}
Code:
void servoout(int z)
{
cli();
digitalWrite(servo_pin, HIGH);
delayMicroseconds(z);
digitalWrite(servo_pin, LOW);
sei();
}
Now, this is a very straightforward code. Of course it can be optimized but I don't think that for such a simple task one should try to optimize it further.
Now my problem...
This code didn't work as expected. I have been getting only 160 microsecond pulses at the output.
Then I erased almost everything and tried to output the input signal without modification. That means I used;
"servoout(inpwm);" instead of "servoout(outpwm);". Interestingly I kept getting only about 160 microsecond pulses at the output.
Later I decided to cancel all subroutines and put everything into the "loop".
Code:
void loop()
{
high_value = analogRead(high_end_read);
low_value = analogRead(low_end_read);
cli();
inpwm = pulseIn(pwm_pin, LOW);
if (inpwm > 0)
{
tmpl = map(low_value, 0, 1023, 1000, 1500);
tmph = map(high_value, 0, 1023, 1500, 2000);
outpwm = map(inpwm, 1000, 2000, tmpl, tmph);
digitalWrite(servo_pin, HIGH);
delayMicroseconds(outpwm);
digitalWrite(servo_pin, LOW);
}
sei();
}
Summary:
If I put the servo signal output routine in a subroutine, there is a serious timing problem of the output signal. If I write the exact same code into the main loop, there are no problems.
Any idea about what I did wrong?
Thank you for your help...