0

Hello i am in making quadcopter(drone) using arduino uno.

I have problem about pulseIn function.

I found dmp filter open source. and I add 4 lines pulseIn function in loop function in order to receive value from transmitter receiver.

When i add this 4 lines code in loop function, value of ypr[2] become very unstable like picture.

ypr[2] is angle value made by dmp code frome mpu6050 sensor.

when i delete that 4 lines (channel1 = pulseIn(7, HIGH); .... ), this problem do not appear. and value of ypr[2] is stable.

and i try to change input time parameter of pulseIn function (channel1 = pulseIn(7, HIGH, 10) or channel1 = pulseIn(7, HIGH, 100) or channel1 = pulseIn(7, HIGH, 1000)), but this problem don't disappear.

in case (channel1 = pulseIn(7, HIGH, 10)), value of ypr[2] is stable. but can not receive transmitter receiver value.......

how do i solve this problem?? please help me T.T

and i confirmed increasing code update time when i add 4 lines of pulsein function. (0.014s > 0.018s) but i don't know whether there is relation or not.

#include <Servo.h>
#include <Wire.h>
#include <I2Cdev.h>
#include <SPI.h>
#include <MPU6050_6Axis_MotionApps20.h>

MPU6050 mpu;                           // mpu interface object

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)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

double channel1 ;
double channel2 ;
double channel3 ;
double channel4 ;

Quaternion q;
VectorFloat gravity;

float ypr[3];
float yprLast[3];
int16_t gyro[3];

volatile bool mpuInterrupt = false;
void dmpDataReady() {
  mpuInterrupt = true;
}



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void dmpsetup() {
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  Wire.begin();
  TWBR = 12; // 400kHz I2C clock (200kHz if CPU is 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
  Fastwire::setup(400, true);
#endif
  Serial.begin(115200);
  while (!Serial);
  Serial.println(F("Initializing I2C devices..."));
  mpu.initialize();
  Serial.println(F("Testing device connections..."));
  Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
  Serial.println(F("Initializing DMP..."));
  devStatus = mpu.dmpInitialize();
  mpu.setXGyroOffset(33);
  mpu.setYGyroOffset(-13);
  mpu.setZGyroOffset(8);
  mpu.setZAccelOffset(1416);



  if (devStatus == 0) {
    Serial.println(F("Enabling DMP..."));
    mpu.setDMPEnabled(true);
    Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
    attachInterrupt(0, dmpDataReady, RISING);
    mpuIntStatus = mpu.getIntStatus();
    Serial.println(F("DMP ready! Waiting for first interrupt..."));
    dmpReady = true;
    packetSize = mpu.dmpGetFIFOPacketSize();
  }
  else {
    Serial.print(F("DMP Initialization failed (code "));
    Serial.print(devStatus);
    Serial.println(F(")"));
  }
}

void setup() {

  Serial.begin(115200);

  pinMode(7, INPUT);
  pinMode(8, INPUT);
  pinMode(12, INPUT);
  pinMode(13, INPUT);

  dmpsetup();

}

void dmploop() {
  if (!dmpReady) return;
  while (!mpuInterrupt && fifoCount < packetSize) {
  }
  mpuInterrupt = false;
  mpuIntStatus = mpu.getIntStatus();
  fifoCount = mpu.getFIFOCount();
  if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
    mpu.resetFIFO();
    // Serial.println(F("FIFO overflow!"));
  } else if (mpuIntStatus & 0x02) {
    while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
    mpu.getFIFOBytes(fifoBuffer, packetSize);
    fifoCount -= packetSize;
    mpu.dmpGetGyro(gyro, fifoBuffer);
    mpu.dmpGetQuaternion(&q, fifoBuffer);
    mpu.dmpGetGravity(&gravity, &q);
    mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
    ypr[1] = (ypr[1] * 180 / M_PI); //x
    ypr[2] = (ypr[2] * 180 / M_PI); //y
    ypr[0] = (ypr[0] * 180 / M_PI); //z
    //gyro[0],gyro[1],gyro[2]//x,y,z 각속도값
  }
}



void loop() {
  dmploop(); //refresh new angle datas from MPU6050

  channel1 = pulseIn(7, HIGH);
  channel2 = pulseIn(8, HIGH);
  channel3 = pulseIn(12, HIGH);
  channel4 = pulseIn(13, HIGH);

  Serial.print(-30);
  Serial.print(" ");
  Serial.print(30);
  Serial.print(" ");
  Serial.print(0);
  Serial.print(" ");
  Serial.println(ypr[2]);

}

just 4 line

enter image description here

gre_gor
  • 6,669
  • 9
  • 47
  • 52
ILWOO KIM
  • 51
  • 1
  • 3

1 Answers1

1

PulseIn(pin,HIGH) is blocking call, it waits for LO->HI transition and then HI->LO to measure it. I suppose it mess with code timing.

If you wan't to do it non blocking, you have to use pin change interrupts (AVR stuff, it might not be implemented in arduino framework). But it seems to be implemented in some libraries like PinChangeInt.

KIIV
  • 3,534
  • 2
  • 18
  • 23
  • Thanks for your reply. Then i can not solve this problem in arduino ? or is there another method about receiving value from transmitter receive? – ILWOO KIM Aug 18 '16 at 07:03
  • You can do it directly (without libraries) or look for some library like PinChangeInt (answer eddited). And use for example micros() to find out how long pulse was. Capture mode in timer is even better, but it's not with 4 channels. – KIIV Aug 18 '16 at 07:15