dmadison / ServoInput

Interrupt-driven servo decoder library for Arduino
GNU Lesser General Public License v3.0
22 stars 10 forks source link

wrong angle values #13

Closed AdrianTschannen closed 3 years ago

AdrianTschannen commented 3 years ago

Hi Using ServoInput in combination with other functions, from time to time the function "servo1.getAngle()" delivers wrong values in a row: 0's or 180's. One possible reason could be, that the extreme values come due to other interrupt routines, that interferes with ServoInput. I bypassed this problem by simply not using the values 0 or 180. These extreme values are not relevant for my application.

Here is my simple code example:

include

include

ServoInputPin<0> servo1; ServoInputPin<1> servo2;

Servo myservo1; // create servo object to control a servo Servo myservo2; // create servo object to control a servo

void setup() { Serial.begin(115200); myservo1.attach(4); // attaches the servo on pin 9 to the servo object myservo2.attach(5); // attaches the servo on pin 10 to the servo object
}

void loop() { int angle1 = servo1.getAngle(); // get angle of servo (0 - 180) int angle2 = servo2.getAngle(); // get angle of servo (0 - 180)
if (!((angle1==180)or(angle1==0))){myservo1.write(angle1);} else {Serial.println(angle1);} // sets the servo position according to the scaled value if (!((angle2==180)or(angle2==0))){myservo2.write(angle2);} else {Serial.println(angle2);} // sets the servo position according to the scaled value
}

dmadison commented 3 years ago

Hi Adrian. A few questions:

In general extreme values that are well outside of the angle range are caught by the library and ignored. Only values that are within the 'legitimate' pulse window (500 - 2500 µs) will be reported, so it's possible that this is an issue with the command signal and not the library.

I don't understand what you're trying to demonstrate with the example you've shared. Testing with an Uno and 3" jumpers I just get '0' in the serial console constantly, as expected.

Maybe try something like this:

#include <ServoInput.h>
#include <Servo.h>

ServoInputPin<2> servoIn;
Servo servo;

const unsigned long ReportFreq = 5000;
unsigned long lastReport = 0;

int lastAngle = 90;

void setup() {
  Serial.begin(115200);
  servo.attach(4);
  servo.write(lastAngle);
  delay(100);  // wait for initial angle read
}

void loop() {
  int angle = servoIn.getAngle(); // get angle of servo (0 - 180)

  if((angle == 0 || angle == 180) && angle != lastAngle) {
    Serial.print("!!! Angle irregularity: ");
    Serial.print(angle);
    Serial.print(" @ t");
    Serial.print(millis());
    Serial.println();
    lastReport = millis();
  }
  else if(millis() - lastReport >= ReportFreq) {
    unsigned long t = millis();
    Serial.print("No issues: t");
    Serial.print(t - ReportFreq);
    Serial.print(" - t");
    Serial.print(t);
    Serial.print(" (");
    Serial.print(angle);
    Serial.print(")");
    Serial.println();
    lastReport = t;
  }

  lastAngle = angle;
}

With a loopback wire that should return 90 or close to it, and will report an issue if the angle is read at either 0 or 180.

AdrianTschannen commented 3 years ago

Hi Dave What a cool testing program and procedure! so cool... The test shows, that there must be some issues inside the library in combination with MKR boards. From time to time, wrong values (180) are delivered. What suprises me: Feeding the Servo with 90 angle value, the detected value delivers 85. Is this what should be expected? Best, Adrian

Results: Board: ARDUINO MKR WIFI 1010 Adapter: none ServoInputPin: 1 (I changed from 2 to 1, as the MKR boards don't support interrupts on No 2)

No issues: t3403 - t8403 (85) !!! Angle irregularity: 180 @ t12245 No issues: t12245 - t17245 (85) No issues: t17245 - t22245 (85) No issues: t22245 - t27245 (85) No issues: t27245 - t32245 (85) No issues: t32245 - t37245 (85) No issues: t37245 - t42245 (85) No issues: t42245 - t47245 (85) No issues: t47245 - t52245 (85) No issues: t52245 - t57245 (85) No issues: t57245 - t62245 (85) No issues: t62245 - t67245 (85) !!! Angle irregularity: 180 @ t71210 No issues: t71211 - t76211 (85) No issues: t76211 - t81211 (85) No issues: t81211 - t86211 (85) No issues: t86211 - t91211 (85) No issues: t91211 - t96211 (85) No issues: t96211 - t101211 (85) No issues: t101211 - t106211 (85) !!! Angle irregularity: 180 @ t106774 No issues: t106774 - t111774 (85) No issues: t111774 - t116774 (85) No issues: t116774 - t121774 (85) No issues: t121774 - t126774 (85) !!! Angle irregularity: 180 @ t130435 No issues: t130435 - t135435 (85) No issues: t135435 - t140435 (85) No issues: t140435 - t145435 (85) No issues: t145435 - t150435 (85) No issues: t150435 - t155435 (85) No issues: t155435 - t160435 (85) No issues: t160435 - t165435 (85) No issues: t165435 - t170435 (85) No issues: t170435 - t175435 (85) No issues: t175435 - t180435 (85) No issues: t180435 - t185435 (85) No issues: t185435 - t190435 (85) No issues: t190435 - t195435 (85) No issues: t195435 - t200435 (85) No issues: t200435 - t205435 (85) No issues: t205435 - t210435 (85) No issues: t210435 - t215435 (85) No issues: t215435 - t220435 (85) !!! Angle irregularity: 180 @ t224904 No issues: t224904 - t229904 (85) No issues: t229904 - t234904 (85) !!! Angle irregularity: 180 @ t236484 No issues: t236484 - t241484 (85)

dmadison commented 3 years ago

The test shows, that there must be some issues inside the library in combination with MKR boards.

That's possible, as you know the current MKR support is tentative at best and seems to have some issues with other pins.

Have you look at the signal with an oscilloscope, or tested with an externally generated servo signal? It's also possible that this is an issue with the Servo library creating a single pulse which is outside of the normal period, as mechanical servos will only jitter slightly if a single pulse is out of alignment.

What suprises me: Feeding the Servo with 90 angle value, the detected value delivers 85. Is this what should be expected?

Yup, that's what I receive as well on the Uno. The Servo library for whatever reason outputs a pulse duration that's skewed lower than typical control signals. Best practice is to run the Calibration example beforehand so you know the min/max pulse values, then use those to calibrate the range.

AdrianTschannen commented 3 years ago

I don't have an oscilloscope. But I have used an external servo signal: JETI Receiver. With the same "problem". I suggest we close this issue due to the fact, that there is an easy workaround: I simply filter the 180 values and have a stable and reliable signal. Thanks a lot! Adrian

dmadison commented 3 years ago

Fair enough. We should probably revisit this once the MKR support is solid.

dmadison commented 3 years ago

This looks to be an unresolved issue with the Arduino SAMD core and the micros() implementation within interrupts, and not an issue with the library itself: https://github.com/arduino/ArduinoCore-samd/issues/463

AdrianTschannen commented 3 years ago

Thank you for this information. It is good to know the reason of this issue. The workaround (filter 180 values) is therefore needed and an appropriate way to handle this.