Radio readings jitter when .attach -ing a servo

I am trying to read values from a receiver with pulseIn():

  pulseFront = pulseIn(frontPin,HIGH);

Everything works fine until I use .attach() for a servo.
Normally, the readings when the controller is centre wobble from 95 to 94 (the centre is 95).

When I add .attach(), the values wobble from 95 to 88.

This is only when reading the values though, as when I plug a servo directly into the receiver there is no jitter.

What exact receiver? Do you have a PPM output available?

It may be that service to the servo(s) messes with the timing done by pulseIn().

Look for a library that can do a better job of grabbing the r/c data from your receiver.

a7

  • The receiver I'm using is the RadioLink R16F
  • What is a PPM output
  • Do you know any easy to use libraries for reading the data
    Thanks!

The horn is off center of the servo spline.

Sounds like a power and wiring problem. Connect the servo to an external power supply and ensure Arduino, Servo, ?HC-SR04 receiver? and Power Supplies share the same ground.

"PWM"

I don't think so because just having .attach in the code causes the problem, even if there isn't actually a servo attached

Perhaps the servo library uses a timer used by whatever is wobbling.

You need to throw away the first reading of the pulseln() because the beginning point is random because of the servo attach.

Time for you to post some code that is a complete sketch and illustrates the problem so we can try the same thing for ourselves.

Without seeing what you are trying, it's hard to see why it shouldn't just work.

a7

The receiver you are using has both CRSF and SBUS outputs. These are modern serial protocols, for which there are libraries that work with Arduino. Either would be superior to using the PWM outputs, or PPM if that was available.

I'll not deprive you of the fun and joy and experience of using google to advance your progress from this point.

a7

Please post schematics showing all servo connections.

My apologies - my sketch is quite messy.
I also forgot to mention I am using a Gyro module (GY-521 Module / MPU6050) if that makes a difference.

#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
MPU6050 mpu;
#define OUTPUT_READABLE_YAWPITCHROLL

int const INTERRUPT_PIN = 2;  // Define the interruption #0 pin
bool blinkState;

/*---MPU6050 Control/Status Variables---*/
bool DMPReady = false;  // Set true if DMP init was successful
uint8_t MPUIntStatus;   // Holds actual interrupt status byte from MPU
uint8_t devStatus;      // Return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // Expected DMP packet size (default is 42 bytes)
uint8_t FIFOBuffer[64]; // FIFO storage buffer

/*---Orientation/Motion Variables---*/ 
Quaternion q;           // [w, x, y, z]         Quaternion container
VectorInt16 aa;         // [x, y, z]            Accel sensor measurements
VectorInt16 gy;         // [x, y, z]            Gyro sensor measurements
VectorInt16 aaReal;     // [x, y, z]            Gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            World-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            Gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3];           // [yaw, pitch, roll]   Yaw/Pitch/Roll container and gravity vector

/*-Packet structure for InvenSense teapot demo-*/ 
uint8_t teapotPacket[14] = { '$', 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, '\r', '\n' };

/*------Interrupt detection routine------*/
volatile bool MPUInterrupt = false;     // Indicates whether MPU6050 interrupt pin has gone high
void DMPDataReady() {
  MPUInterrupt = true;
}






#include <Servo.h>
Servo ESC;
int Speed;

Servo ruddServo;
Servo elevServo;
Servo frontServo;

//reviever stuff
const int ESCPin = 2;
unsigned long pulseDuration;

const int ruddPin = 3;
unsigned long pulseRudd;

const int elevPin = 4;
unsigned long pulseElev;

const int frontPin = 5;
unsigned long pulseFront;

//stabalisation
int frontAngle;
int frontOffset = 0;    // 0 = no 1 = yes



void setup() {



  

  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    Wire.begin();
    Wire.setClock(400000); // 400kHz I2C clock. Comment on this line if having compilation difficulties
  #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
    Fastwire::setup(400, true);
  #endif
  
  Serial.begin(115200); //115200 is required for Teapot Demo output
  while (!Serial);

  /*Initialize device*/
  Serial.println(F("Initializing I2C devices..."));
  mpu.initialize();
  pinMode(INTERRUPT_PIN, INPUT);

  /*Verify connection*/
  Serial.println(F("Testing MPU6050 connection..."));
  if(mpu.testConnection() == false){
    Serial.println("MPU6050 connection failed");
    while(true);
  }
  else {
    Serial.println("MPU6050 connection successful");
  }

  /*Wait for Serial input*/
  //Serial.println(F("\nSend any character to begin: "));
  //while (Serial.available() && Serial.read()); // Empty buffer
  //while (!Serial.available());                 // Wait for data
  //while (Serial.available() && Serial.read()); // Empty buffer again

  /* Initializate and configure the DMP*/
  Serial.println(F("Initializing DMP..."));
  devStatus = mpu.dmpInitialize();

  /* Supply your gyro offsets here, scaled for min sensitivity */
  mpu.setXGyroOffset(0);
  mpu.setYGyroOffset(0);
  mpu.setZGyroOffset(0);
  mpu.setXAccelOffset(0);
  mpu.setYAccelOffset(0);
  mpu.setZAccelOffset(0);

  /* Making sure it worked (returns 0 if so) */ 
  if (devStatus == 0) {
    mpu.CalibrateAccel(6);  // Calibration Time: generate offsets and calibrate our MPU6050
    mpu.CalibrateGyro(6);
    Serial.println("These are the Active offsets: ");
    mpu.PrintActiveOffsets();
    Serial.println(F("Enabling DMP..."));   //Turning ON DMP
    mpu.setDMPEnabled(true);

    /*Enable Arduino interrupt detection*/
    Serial.print(F("Enabling interrupt detection (Arduino external interrupt "));
    Serial.print(digitalPinToInterrupt(INTERRUPT_PIN));
    Serial.println(F(")..."));
    attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), DMPDataReady, RISING);
    MPUIntStatus = mpu.getIntStatus();

    /* Set the DMP Ready flag so the main loop() function knows it is okay to use it */
    Serial.println(F("DMP ready! Waiting for first interrupt..."));
    DMPReady = true;
    packetSize = mpu.dmpGetFIFOPacketSize(); //Get expected DMP packet size for later comparison
  } 
  else {
    Serial.print(F("DMP Initialization failed (code ")); //Print the error code
    Serial.print(devStatus);
    Serial.println(F(")"));
    // 1 = initial memory load failed
    // 2 = DMP configuration updates failed
  }
  pinMode(LED_BUILTIN, OUTPUT);



  //ESC.attach(9,1000,2000);
  //ESC.write(5);
  //ruddServo.attach(10);
  //elevServo.attach(11);
  //frontServo.attach(12);
  

}


void loop() {

  if (!DMPReady) return; // Stop the program if DMP programming fails.
    
  /* Read a packet from FIFO */
  if (mpu.dmpGetCurrentFIFOPacket(FIFOBuffer)) { // Get the Latest packet 
    #ifdef OUTPUT_READABLE_YAWPITCHROLL
      /* Display Euler angles in degrees */
      mpu.dmpGetQuaternion(&q, FIFOBuffer);
      mpu.dmpGetGravity(&gravity, &q);
      mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
      /*Serial.print("ypr\t");
      Serial.print(ypr[0] * 180/M_PI);
      Serial.print("\t");
      Serial.print(ypr[1] * 180/M_PI);
      Serial.print("\t");
      Serial.println(ypr[2] * 180/M_PI);*/
    #endif
  }




  pulseFront = pulseIn(frontPin,HIGH);

  pulseFront = map(pulseFront, 1070, 1890, 45, 145);


  Serial.println(pulseFront);

}

The part that when I add makes the radio readings jitter is any of:

  //ESC.attach(9,1000,2000);
  //ESC.write(5);
  //ruddServo.attach(10);
  //elevServo.attach(11);
  //frontServo.attach(12);

Here's a diagram of what I have setup right now. If I get this working, I will add more recover inputs and servos.


I will look into how to use the serial bus.

I ended up using the sBus and it is working fine.