Unstable result when passing servo pulse through Arduino

Arduino projects on the go
Post Reply
MaxZ
Posts: 330
Joined: 31 Jan 2019, 11:48
Location: Boskoop, Netherlands

Unstable result when passing servo pulse through Arduino

Post by MaxZ »

Hi all,

Some time ago a clubmate asked me if I could develop something in Arduino to avoid a clash between his retracting landing gear and the closing L/G doors. He had installed a pneumatic retract gear operated by a valve system, in turn operated by a servo. The system also operated the gear doors, but these moved much faster than the gear itself, risking a collision on retracting. The servo operating the valve needed to be operated in stages, low PWM to extend gear and open doors, mid PWM to retract gear, wait for 4 seconds, high PWM to close doors.

Now, I do not remember exactly how the gear doors were operated, but my clubmate preferred to maintain the possibility to trim the end positions of the valve servo from his Tx to finetune the doors. He operated the system with a 3-position switch which worked ok, but his fear was that someday he might skip the mid position by mistake and have the doors being damaged by the retracting gear legs.

So I set about to write some code to detect a sudden change in PWM value, coming from the low PWM position, and add a 4 seconds delay in the mid position irrespective from the PWM value coming from the Rx. This worked as intended. Outside the delay time, I just "passed through" the incoming PWM.

That is where a problem surfaced, the output to the servo showed a noticeable jitter (outside the delay period, where the PWM value output was a constant). Looking at the results from the serial monitor I could see a frequent drop in the incoming PWM of about 10-15 microseconds. I used the pulseIn() to read the PWM, but I have also tried another way by timing interrupts on the rising and falling edges of the pulse. Not much difference there. I ended up in putting out fixed PWM values for all stages, foregoing the request for trimmable end points.

The whole setup works fine and my clubmate is happy. But I would like to know if anyone has an idea as to the cause of this instability, and how to avoid it. I am attaching the code as it was initially. I am using the Servo.h library to generate the PWM output (sorry Phil :P ).

Cheers,
Max.
LG_DelayMiddle_old.ino
(522 Bytes) Downloaded 190 times
Sorry for the long story, which is a bit outside the main topics of this forum, but I figured you might be interested in the background. It boils down to the question why the PWM from a stable input source is not read as a stable number.
MaxZ
Posts: 330
Joined: 31 Jan 2019, 11:48
Location: Boskoop, Netherlands

Re: Unstable result when passing servo pulse through Arduino

Post by MaxZ »

Hi all,

I must correct myself after redoing some testing.

The interrupt timing method does give improved results, showing a regular PWM drop of only 4 microseconds. The only disadvantage is that you can only use, as far as I know, the two dedicated interrupt pins, so you can only monitor 2 Rx channels simultaneously.

Cheers,
Max.

Code: Select all

#include <Servo.h>

Servo Test;

int servopin=10;
volatile int Rxpulse = 0;
volatile int prev_time = 0;
int Pos; 


void setup() {
  Test.attach(servopin);
  Serial.begin(9600);
  // when pin D3 goes high, call the pulse_up function
  attachInterrupt(1, pulse_up, RISING);
}

void loop() {

  Serial.println (Rxpulse);
  Test.writeMicroseconds(Rxpulse);
}
void pulse_up() {
  attachInterrupt(1, pulse_down, FALLING);
  prev_time = micros();
}
 
void pulse_down() {
  attachInterrupt(1, pulse_up, RISING);
  Rxpulse = micros()-prev_time;
}
Last edited by MaxZ on 20 May 2019, 16:12, edited 1 time in total.
User avatar
Mike_K
Posts: 669
Joined: 16 Feb 2018, 06:35
Location: Hertfordshire

Re: Unstable result when passing servo pulse through Arduino

Post by Mike_K »

Hi Max

You can use "pin change" on any of the inputs, but pins 0 to 7 share a common interrupt vector, 8 to 13 share another interrupt vector and A0 to A5 a third interrupt vector. See:

https://playground.arduino.cc/Main/PinChangeInterrupt/

So you can easily monitor to 2 or more receiver channels, but you would need to check which input caused the interrupt within the ISR if the inputs are sharing an interrupt or connect two incoming channels to inputs with different interrupt vectors.

Also D2 and D3 (with ATmega328P based Arduinos) can be used individually as "digitalPinToInterrupt" which is probably the easy way to monitor just 2 channels.

Also using the serial monitor can in some cases affect the interrupts used to measure the servo pwm. When serial.print is used, the uart is interrupt driven and when in use it disable other interrupts, so if a pwm pulse arrives while serial is communicating you will miss the start of the pulse because as its interrupt will be temporarily disabled. Try using a faster serial speed like 115200 baud to see if that makes a difference.

Cheers

MIke
MaxZ
Posts: 330
Joined: 31 Jan 2019, 11:48
Location: Boskoop, Netherlands

Re: Unstable result when passing servo pulse through Arduino

Post by MaxZ »

Hi Mike,

Thanks for the info, I have saved the link with my bookmarks, I hope I can remember I did when needed. :D
Mike_K wrote: 20 May 2019, 15:38Also D2 and D3 (with ATmega328P based Arduinos) can be used individually as "digitalPinToInterrupt" which is probably the easy way to monitor just 2 channels.
Do you mean more or less in the way I posted above?

Cheers,
Max.
User avatar
Phil_G
Posts: 596
Joined: 15 Feb 2018, 23:32
Contact:

Re: Unstable result when passing servo pulse through Arduino

Post by Phil_G »

I wouldnt change the interupt vector twice on every pulse, I'd set it once and use pin change.
Changing a vector takes time Image
I dont believe "digitalPinToInterrupt" has any extra overhead as its resolved to a constant at compile time, so as Mike says, its better etiquette to use it rather than hard-coded interrupt numbers.
Cheers
Phil
Post Reply