# How to Read 2 Packets of Data at Once - MPU6050

**URL:** <https://discourse.processing.org/t/how-to-read-2-packets-of-data-at-once-mpu6050/5793>\
**Category:** Electronics (Arduino, etc.)\
**Created:** [November 21, 2018, 1:04pm UTC](https://discourse.processing.org/t/how-to-read-2-packets-of-data-at-once-mpu6050/5793 "2018-11-21T13:04:06Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![yodayoshi](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/yodayoshi/32/2451_2.png) [@yodayoshi](https://discourse.processing.org/u/yodayoshi)\
**Post date:** [November 21, 2018, 1:04pm UTC](https://discourse.processing.org/t/how-to-read-2-packets-of-data-at-once-mpu6050/5793/1 "2018-11-21T13:04:06Z")

</div>

Hello, I am trying to extend the teapot demo from Jeff Rowberg to be able to show a graphical representation of 2 MPU 6050 sensors instead of just the one. I have modified the Arduino sketch to be able to take in values from both of the sensors and that part works fine as can be seen from the output of the OUTPUT\_READABLE portions of the Arduino code. The problem arises when I have to differentiate between the two packets in the teapot demo in processing. Can someone help me in figuring out how to differentiate between the two packets that are sent from the Arduino sketch?

Here is the Arduino Sketch:

> **Arduino Sketch**
>
> // I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files  
> // for both classes must be in the include path of your project  
> #include “I2Cdev.h”
> 
> #include “MPU6050\_6Axis\_MotionApps20.h”  
> //#include “MPU6050.h” // not necessary if using MotionApps include file
> 
> // Arduino Wire library is required if I2Cdev I2CDEV\_ARDUINO\_WIRE implementation  
> // is used in I2Cdev.h  
> #if I2CDEV\_IMPLEMENTATION == I2CDEV\_ARDUINO\_WIRE  
> #include “Wire.h”  
> #endif
> 
> // class default I2C address is 0x68  
> // specific I2C addresses may be passed as a parameter here  
> // AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)  
> // AD0 high = 0x69  
> MPU6050 mpu(0x68); // set up one of the sensors to use the AD0 ground set sensor  
> MPU6050 mpu2(0x69); // \<-- use sensor with AD0 set high
> 
> //#define OUTPUT\_READABLE\_QUATERNION
> 
> //#define OUTPUT\_READABLE\_EULER
> 
> //#define OUTPUT\_READABLE\_YAWPITCHROLL
> 
> //#define OUTPUT\_READABLE\_REALACCEL
> 
> //#define OUTPUT\_READABLE\_WORLDACCEL
> 
> // uncomment “OUTPUT\_TEAPOT” if you want output that matches the  
> // format used for the InvenSense teapot demo  
> #define OUTPUT\_TEAPOT
> 
> #define INTERRUPT\_PIN 2 // use pin 2 on Arduino Uno & most boards  
> #define INTERRUPT\_PIN\_2 3 //use pin D3 of Arduino for the interrupt pin of the second sensor  
> #define LED\_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)  
> bool blinkState = false;
> 
> // MPU control/status vars  
> bool dmpReady = false; // set true if DMP init was successful  
> bool dmp2Ready = false;  
> uint8\_t mpuIntStatus; // holds actual interrupt status byte from MPU  
> uint8\_t mpu2IntStatus;  
> uint8\_t devStatus; // return status after each device operation (0 = success, !0 = error)  
> uint8\_t dev2Status;  
> uint16\_t packetSize; // expected DMP packet size (default is 42 bytes)  
> uint16\_t packet2Size;  
> uint16\_t fifoCount; // count of all bytes currently in FIFO  
> uint16\_t fifo2Count;  
> uint8\_t fifoBuffer[64]; // FIFO storage buffer  
> uint8\_t fifo2Buffer[64];
> 
> // orientation/motion vars  
> Quaternion q; // [w, x, y, z] quaternion container  
> Quaternion q2;  
> VectorInt16 aa; // [x, y, z] accel sensor measurements  
> VectorInt16 aa2;  
> VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements  
> VectorInt16 aaReal2;  
> VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements  
> VectorInt16 aaWorld2;  
> VectorFloat gravity; // [x, y, z] gravity vector  
> VectorFloat gravity2;  
> float euler[3]; // [psi, theta, phi] Euler angle container  
> float euler2[3];  
> float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector  
> float ypr2[3];
> 
> // packet structure for InvenSense teapot demo  
> uint8\_t teapotPacket[14] = { ‘', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' }; uint8\_t teapotPacket2[14] = { '’, 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, ‘\r’, ‘\n’ };
> 
> // ================================================================  
> // === INTERRUPT DETECTION ROUTINE ===  
> // ================================================================
> 
> volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high  
> volatile bool mpu2Interrupt = false;  
> void dmpDataReady() {  
> mpuInterrupt = true;  
> }
> 
> void dmp2DataReady(){  
> mpu2Interrupt = true;  
> }
> 
> // ================================================================  
> // === INITIAL SETUP ===  
> // ================================================================
> 
> void setup() {  
> // join I2C bus (I2Cdev library doesn’t do this automatically)  
> #if I2CDEV\_IMPLEMENTATION == I2CDEV\_ARDUINO\_WIRE  
> Wire.begin();  
> Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties  
> #elif I2CDEV\_IMPLEMENTATION == I2CDEV\_BUILTIN\_FASTWIRE  
> Fastwire::setup(400, true);  
> #endif
> 
> ```
> // initialize serial communication
> // (115200 chosen because it is required for Teapot Demo output, but it's
> // really up to you depending on your project)
> Serial.begin(115200);
> while (!Serial); // wait for Leonardo enumeration, others continue immediately
> 
> // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3V or Arduino
> // Pro Mini running at 3.3V, cannot handle this baud rate reliably due to
> // the baud timing being too misaligned with processor ticks. You must use
> // 38400 or slower in these cases, or use some kind of external separate
> // crystal solution for the UART timer.
> 
> // initialize device
> Serial.println(F("Initializing I2C devices..."));
> mpu.initialize();
> mpu2.initialize();
> pinMode(INTERRUPT_PIN, INPUT);
> pinMode(INTERRUPT_PIN_2, INPUT);
> 
> // verify connection
> Serial.println(F("Testing device connections..."));
> Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
> Serial.println(mpu2.testConnection() ? F("MPU6050 2 connection successful") : F("MPU6050 2 connection failed"));
> 
> // wait for ready
> Serial.println(F("\nSend any character to begin DMP programming and demo: "));
> while (Serial.available() && Serial.read()); // empty buffer
> while (!Serial.available()); // wait for data
> while (Serial.available() && Serial.read()); // empty buffer again
> 
> // load and configure the DMP
> Serial.println(F("Initializing DMP..."));
> devStatus = mpu.dmpInitialize();
> dev2Status = mpu2.dmpInitialize();
> 
> // supply your own gyro offsets here, scaled for min sensitivity
> /*mpu.setXGyroOffset(220);
> mpu.setYGyroOffset(76);
> mpu.setZGyroOffset(-85);
> mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
> */
> mpu.setXGyroOffset(117);
> mpu.setYGyroOffset(-26);
> mpu.setZGyroOffset(17);
> mpu.setXAccelOffset(-1891);
> mpu.setYAccelOffset(-2829);
> mpu.setZAccelOffset(653);
> 
> mpu2.setXGyroOffset(117);
> mpu2.setYGyroOffset(-26);
> mpu2.setZGyroOffset(17);
> mpu2.setXAccelOffset(-1891);
> mpu2.setYAccelOffset(-2829);
> mpu2.setZAccelOffset(653);
> 
> // make sure it worked (returns 0 if so)
> if (devStatus == 0) {
> // turn on the DMP, now that it's ready
> Serial.println(F("Enabling DMP..."));
> mpu.setDMPEnabled(true);
> mpu2.setDMPEnabled(true);
> 
> // enable Arduino interrupt detection
> Serial.print(F("Enabling interrupt detection (Arduino external interrupt "));
> Serial.print(digitalPinToInterrupt(INTERRUPT_PIN));
> Serial.println(F(")..."));
> Serial.print(digitalPinToInterrupt(INTERRUPT_PIN_2));
> Serial.println(F(")..."));
> attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
> attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN_2), dmp2DataReady, RISING);
> mpuIntStatus = mpu.getIntStatus();
> mpu2IntStatus = mpu2.getIntStatus();
> 
> // set our DMP Ready flag so the main loop() function knows it's okay to use it
> Serial.println(F("DMP ready! Waiting for first interrupt..."));
> dmpReady = true;
> dmp2Ready = true;
> 
> // get expected DMP packet size for later comparison
> packetSize = mpu.dmpGetFIFOPacketSize();
> packet2Size = mpu2.dmpGetFIFOPacketSize();
> } else {
> // ERROR!
> // 1 = initial memory load failed
> // 2 = DMP configuration updates failed
> // (if it's going to break, usually the code will be 1)
> Serial.print(F("DMP Initialization failed (code "));
> Serial.print(devStatus);
> Serial.println(F(")"));
> 
> Serial.print(F("DMP2 Initialization failed (code "));
> Serial.print(dev2Status);
> Serial.println(F(")"));
> }
> 
> // configure LED for output
> pinMode(LED_PIN, OUTPUT);
> 
> ```
> 
> }
> 
> // ================================================================  
> // === MAIN PROGRAM LOOP ===  
> // ================================================================
> 
> void loop() {  
> // if programming failed, don’t try to do anything  
> if (!dmpReady) return;  
> if (!dmp2Ready) return;
> 
> ```
> // wait for MPU interrupt or extra packet(s) available
> while (!mpuInterrupt && fifoCount < packetSize) {
> if (mpuInterrupt && fifoCount < packetSize) {
> // try to get out of the infinite loop 
> fifoCount = mpu.getFIFOCount();
> }  
> // other program behavior stuff here
> // .
> // .
> // .
> // if you are really paranoid you can frequently test in between other
> // stuff to see if mpuInterrupt is true, and if so, "break;" from the
> // while() loop to immediately process the MPU data
> // .
> // .
> // .
> }
> while (!mpu2Interrupt && fifo2Count < packet2Size) {
> if (mpu2Interrupt && fifo2Count < packet2Size) {
> // try to get out of the infinite loop 
> fifo2Count = mpu2.getFIFOCount();
> }  
> // other program behavior stuff here
> // .
> // .
> // .
> // if you are really paranoid you can frequently test in between other
> // stuff to see if mpuInterrupt is true, and if so, "break;" from the
> // while() loop to immediately process the MPU data
> // .
> // .
> // .
> }
> 
> // reset interrupt flag and get INT_STATUS byte
> mpuInterrupt = false;
> mpu2Interrupt = false;
> mpuIntStatus = mpu.getIntStatus();
> mpu2IntStatus = mpu2.getIntStatus();
> 
> // get current FIFO count
> fifoCount = mpu.getFIFOCount();
> fifo2Count = mpu2.getFIFOCount();
> 
> // check for overflow (this should never happen unless our code is too inefficient)
> if ((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024) {
> // reset so we can continue cleanly
> mpu.resetFIFO();
> fifoCount = mpu.getFIFOCount();
> Serial.println(F("FIFO overflow!"));
> 
> // otherwise, check for DMP data ready interrupt (this should happen frequently)
> } else if (mpuIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT)) {
> // wait for correct available data length, should be a VERY short wait
> while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
> while (fifo2Count < packet2Size) fifo2Count = mpu2.getFIFOCount();
> 
> // read a packet from FIFO
> mpu.getFIFOBytes(fifoBuffer, packetSize);
> mpu2.getFIFOBytes(fifo2Buffer, packet2Size);
>     
> // track FIFO count here in case there is > 1 packet available
> // (this lets us immediately read more without waiting for an interrupt)
> fifoCount -= packetSize;
> fifo2Count -= packet2Size;
> 
> #ifdef OUTPUT_READABLE_QUATERNION
> // display quaternion values in easy matrix form: w x y z
> mpu.dmpGetQuaternion(&q, fifoBuffer);
> mpu2.dmpGetQuaternion(&q2, fifo2Buffer);
> Serial.print("quat\t");
> Serial.print(q.w);
> Serial.print("\t");
> Serial.print(q.x);
> Serial.print("\t");
> Serial.print(q.y);
> Serial.print("\t");
> Serial.print(q.z);
> Serial.print("\t\t");
> Serial.print("quat2\t");
> Serial.print(q2.w);
> Serial.print("\t");
> Serial.print(q2.x);
> Serial.print("\t");
> Serial.print(q2.y);
> Serial.print("\t");
> Serial.println(q2.z);
> #endif
> 
> #ifdef OUTPUT_READABLE_EULER
> // display Euler angles in degrees
> mpu.dmpGetQuaternion(&q, fifoBuffer);
> mpu2.dmpGetQuaternion(&q2, fifo2Buffer);
> mpu.dmpGetEuler(euler, &q);
> mpu2.dmpGetEuler(euler2, &q2);
> Serial.print("euler\t");
> Serial.print(euler[0] * 180/M_PI);
> Serial.print("\t");
> Serial.print(euler[1] * 180/M_PI);
> Serial.print("\t");
> Serial.print(euler[2] * 180/M_PI);
> Serial.print("\t\t");
> Serial.print("euler2\t");
> Serial.print(euler2[0] * 180/M_PI);
> Serial.print("\t");
> Serial.print(euler2[1] * 180/M_PI);
> Serial.print("\t");
> Serial.println(euler2[2] * 180/M_PI);
> #endif
> 
> #ifdef OUTPUT_READABLE_YAWPITCHROLL
> // display Euler angles in degrees
> mpu.dmpGetQuaternion(&q, fifoBuffer);
> mpu.dmpGetGravity(&gravity, &q);
> mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
> mpu2.dmpGetQuaternion(&q2, fifo2Buffer);
> mpu2.dmpGetGravity(&gravity2, &q2);
> mpu2.dmpGetYawPitchRoll(ypr2, &q2, &gravity2);
> 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.print(ypr[2] * 180/M_PI);
> Serial.print("\t");
> Serial.print("ypr2\t");
> Serial.print(ypr2[0] * 180/M_PI);
> Serial.print("\t");
> Serial.print(ypr2[1] * 180/M_PI);
> Serial.print("\t");
> Serial.println(ypr2[2] * 180/M_PI);
> #endif
> 
> #ifdef OUTPUT_READABLE_REALACCEL
> // display real acceleration, adjusted to remove gravity
> mpu.dmpGetQuaternion(&q, fifoBuffer);
> mpu.dmpGetAccel(&aa, fifoBuffer);
> mpu.dmpGetGravity(&gravity, &q);
> mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
> mpu2.dmpGetQuaternion(&q2, fifo2Buffer);
> mpu2.dmpGetAccel(&aa2, fifo2Buffer);
> mpu2.dmpGetGravity(&gravity2, &q2);
> mpu2.dmpGetLinearAccel(&aaReal2, &aa2, &gravity2);
> Serial.print("areal\t");
> Serial.print(aaReal.x);
> Serial.print("\t");
> Serial.print(aaReal.y);
> Serial.print("\t");
> Serial.print(aaReal.z);
> Serial.print("\t");
> Serial.print("areal2\t");
> Serial.print(aaReal2.x);
> Serial.print("\t");
> Serial.print(aaReal2.y);
> Serial.print("\t");
> Serial.println(aaReal2.z);
> #endif
> 
> #ifdef OUTPUT_READABLE_WORLDACCEL
> // display initial world-frame acceleration, adjusted to remove gravity
> // and rotated based on known orientation from quaternion
> mpu.dmpGetQuaternion(&q, fifoBuffer);
> mpu.dmpGetAccel(&aa, fifoBuffer);
> mpu.dmpGetGravity(&gravity, &q);
> mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
> mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);
> mpu2.dmpGetQuaternion(&q2, fifo2Buffer);
> mpu2.dmpGetAccel(&aa2, fifo2Buffer);
> mpu2.dmpGetGravity(&gravity2, &q2);
> mpu2.dmpGetLinearAccel(&aaReal2, &aa2, &gravity2);
> mpu2.dmpGetLinearAccelInWorld(&aaWorld2, &aaReal2, &q2);
> Serial.print("aworld\t");
> Serial.print(aaWorld.x);
> Serial.print("\t");
> Serial.print(aaWorld.y);
> Serial.print("\t");
> Serial.print(aaWorld.z);
> Serial.print("\t");
> Serial.print("aworld2\t");
> Serial.print(aaWorld2.x);
> Serial.print("\t");
> Serial.print(aaWorld2.y);
> Serial.print("\t");
> Serial.println(aaWorld2.z);
> #endif
> 
> #ifdef OUTPUT_TEAPOT
> // display quaternion values in InvenSense Teapot demo format:
> teapotPacket[2] = fifoBuffer[0];
> teapotPacket[3] = fifoBuffer[1];
> teapotPacket[4] = fifoBuffer[4];
> teapotPacket[5] = fifoBuffer[5];
> teapotPacket[6] = fifoBuffer[8];
> teapotPacket[7] = fifoBuffer[9];
> teapotPacket[8] = fifoBuffer[12];
> teapotPacket[9] = fifoBuffer[13];
> teapotPacket2[2] = fifo2Buffer[0];
> teapotPacket2[3] = fifo2Buffer[1];
> teapotPacket2[4] = fifo2Buffer[4];
> teapotPacket2[5] = fifo2Buffer[5];
> teapotPacket2[6] = fifo2Buffer[8];
> teapotPacket2[7] = fifo2Buffer[9];
> teapotPacket2[8] = fifo2Buffer[12];
> teapotPacket2[9] = fifo2Buffer[13];
> //Serial.print("Q");
> Serial.write(teapotPacket, 14);
> //Serial.write("P");
> //Serial.write(teapotPacket2, 14);
> teapotPacket[11]++; // packetCount, loops at 0xFF on purpose
> teapotPacket2[11]++;
> #endif
> 
> // blink LED to indicate activity
> blinkState = !blinkState;
> digitalWrite(LED_PIN, blinkState);
> }
> 
> ```
> 
> }

Here is the Processing Sketch from the MPU6050 teapot demo that I altered a bit. I really need help starting with the serialEvent() method. I need to be able to assign ch2 to the values from teapotPacket2 from the Arduino sketch. Right now, I have the Arduino sketch only sending out the packet for the first sensor and I have ch2 being set to the same value as ch, which are the values from teapotPacket from the Arduino sketch. Please let me know if you can help me in any way, I can clarify anything else you need me to.

> **Modified Teapot Demo (not working as intended yet)**
>
> import processing.serial._;  
> import processing.opengl._;  
> import toxi.geom._;  
> import toxi.processing._;
> 
> // NOTE: requires ToxicLibs to be installed in order to run properly.  
> // 1. Download from [http://toxiclibs.org/downloads](http://toxiclibs.org/downloads)  
> // 2. Extract into [userdir]/Processing/libraries  
> // (location may be different on Mac/Linux)  
> // 3. Run and bask in awesomeness
> 
> ToxiclibsSupport gfx;
> 
> Serial port; // The serial port  
> char[] teapotPacket = new char[14]; // InvenSense Teapot packet  
> char[] teapotPacket2 = new char[14];  
> int serialCount = 0; // current packet byte position  
> int serialCount2 = 0;  
> int synced = 0;  
> int synced2 = 0;  
> int interval = 0;  
> int interval2 = 0;
> 
> float[] q = new float[4];  
> float[] q2 = new float[4];  
> Quaternion quat = new Quaternion(1, 0, 0, 0);  
> Quaternion quat2 = new Quaternion(1, 0, 0, 0);
> 
> float[] gravity = new float[3];  
> float[] gravity2 = new float[3];  
> float[] euler = new float[3];  
> float[] euler2 = new float[3];  
> float[] ypr = new float[3];  
> float[] ypr2 = new float[3];
> 
> void setup() {  
> size(1200, 600, OPENGL);  
> gfx = new ToxiclibsSupport(this);
> 
> ```
> // setup lights and antialiasing
> lights();
> smooth();
> 
> // display serial port list for debugging/clarity
> println(Serial.list());
> 
> // get the first available port (use EITHER this OR the specific port code below)
> String portName = Serial.list()[0];
> 
> // open the serial port
> port = new Serial(this, portName, 115200);
> 
> // send single character to trigger DMP init/start
> // (expected by MPU6050_DMP6 example Arduino sketch)
> port.write('r');
> port.write('r');
> port.write('r');
> port.write('r');
> 
> ```
> 
> }
> 
> void draw() {  
> if (millis() - interval \> 1000) {  
> // resend single character to trigger DMP init/start  
> // in case the MPU is halted/reset while applet is running  
> port.write(‘r’);  
> interval = millis();  
> }
> 
> ```
> // black background
> background(0);
> 
> // translate everything to the middle of the viewport
> pushMatrix();
> translate(width / 4, height / 2);
> 
> // 3-step rotation from yaw/pitch/roll angles (gimbal lock!)
> // ...and other weirdness I haven't figured out yet
> //rotateY(-ypr[0]);
> //rotateZ(-ypr[1]);
> //rotateX(-ypr[2]);
> 
> // toxiclibs direct angle/axis rotation from quaternion (NO gimbal lock!)
> // (axis order [1, 3, 2] and inversion [-1, +1, +1] is a consequence of
> // different coordinate system orientation assumptions between Processing
> // and InvenSense DMP)
> float[] axis = quat.toAxisAngle();
> rotate(axis[0], -axis[1], axis[3], axis[2]);
> 
> // draw main body in red
> fill(255, 0, 0, 200);
> box(10, 10, 200);
> 
> // draw front-facing tip in blue
> fill(0, 0, 255, 200);
> pushMatrix();
> translate(0, 0, -120);
> rotateX(PI/2);
> drawCylinder(0, 20, 20, 8);
> popMatrix();
> 
> // draw wings and tail fin in green
> fill(0, 255, 0, 200);
> beginShape(TRIANGLES);
> vertex(-100, 2, 30); vertex(0, 2, -80); vertex(100, 2, 30); // wing top layer
> vertex(-100, -2, 30); vertex(0, -2, -80); vertex(100, -2, 30); // wing bottom layer
> vertex(-2, 0, 98); vertex(-2, -30, 98); vertex(-2, 0, 70); // tail left layer
> vertex( 2, 0, 98); vertex( 2, -30, 98); vertex( 2, 0, 70); // tail right layer
> endShape();
> beginShape(QUADS);
> vertex(-100, 2, 30); vertex(-100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80);
> vertex( 100, 2, 30); vertex( 100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80);
> vertex(-100, 2, 30); vertex(-100, -2, 30); vertex(100, -2, 30); vertex(100, 2, 30);
> vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, -30, 98); vertex(-2, -30, 98);
> vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, 0, 70); vertex(-2, 0, 70);
> vertex(-2, -30, 98); vertex(2, -30, 98); vertex(2, 0, 70); vertex(-2, 0, 70);
> endShape();
> 
> popMatrix();
> 
> pushMatrix();
> translate((width*3)/4, height / 2);
> float[] axis2 = quat2.toAxisAngle();
> rotate(axis2[0], -axis2[1], axis2[3], axis2[2]);
> 
> // draw main body in red
> fill(255, 0, 0, 200);
> box(10, 10, 200);
> 
> // draw front-facing tip in blue
> fill(0, 0, 255, 200);
> pushMatrix();
> translate(0, 0, -120);
> rotateX(PI/2);
> drawCylinder(0, 20, 20, 8);
> popMatrix();
> 
> // draw wings and tail fin in green
> fill(0, 255, 0, 200);
> beginShape(TRIANGLES);
> vertex(-100, 2, 30); vertex(0, 2, -80); vertex(100, 2, 30); // wing top layer
> vertex(-100, -2, 30); vertex(0, -2, -80); vertex(100, -2, 30); // wing bottom layer
> vertex(-2, 0, 98); vertex(-2, -30, 98); vertex(-2, 0, 70); // tail left layer
> vertex( 2, 0, 98); vertex( 2, -30, 98); vertex( 2, 0, 70); // tail right layer
> endShape();
> beginShape(QUADS);
> vertex(-100, 2, 30); vertex(-100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80);
> vertex( 100, 2, 30); vertex( 100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80);
> vertex(-100, 2, 30); vertex(-100, -2, 30); vertex(100, -2, 30); vertex(100, 2, 30);
> vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, -30, 98); vertex(-2, -30, 98);
> vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, 0, 70); vertex(-2, 0, 70);
> vertex(-2, -30, 98); vertex(2, -30, 98); vertex(2, 0, 70); vertex(-2, 0, 70);
> endShape();
> 
> popMatrix();
> 
> ```
> 
> }
> 
> void serialEvent(Serial port) {  
> interval = millis();  
> while (port.available() \> 0) {  
> int ch = port.read();  
> int ch2 = ch;
> 
> ```
> if (synced == 0 && ch != '$') return; // initial synchronization - also used to resync/realign if needed
> synced = 1;
> print ((char)ch);
>     
> if (synced2 == 0 && ch2 != 'k') return; // initial synchronization - also used to resync/realign if needed
> synced2 = 1;
> print ((char)ch2);
> 
> if ((serialCount == 1 && ch != 2)
> || (serialCount == 12 && ch != '\r')
> || (serialCount == 13 && ch != '\n')) {
> serialCount = 0;
> synced = 0;
> return;
> }
>     
> if ((serialCount2 == 1 && ch2 != 2)
> || (serialCount2 == 12 && ch2 != '\r')
> || (serialCount2 == 13 && ch2 != '\n')) {
> serialCount2 = 0;
> synced2 = 0;
> return;
> }
> 
> if (serialCount > 0 || ch == '$') {
> teapotPacket[serialCount++] = (char)ch;
> if (serialCount == 14) {
> serialCount = 0; // restart packet byte position
>             
> // get quaternion from data packet
> q[0] = ((teapotPacket[2] << 8) | teapotPacket[3]) / 16384.0f;
> q[1] = ((teapotPacket[4] << 8) | teapotPacket[5]) / 16384.0f;
> q[2] = ((teapotPacket[6] << 8) | teapotPacket[7]) / 16384.0f;
> q[3] = ((teapotPacket[8] << 8) | teapotPacket[9]) / 16384.0f;
> for (int i = 0; i < 4; i++) if (q[i] >= 2) q[i] = -4 + q[i];
>             
> // set our toxilibs quaternion to new data
> quat.set(q[0], q[1], q[2], q[3]);
> }
> }
>     
> if (serialCount2 > 0 || ch2 == 'k') {
> teapotPacket2[serialCount2++] = (char)ch2;
> if (serialCount2 == 14) {
> serialCount2 = 0; // restart packet byte position
>             
> // get quaternion from data packet
> q2[0] = ((teapotPacket2[2] << 8) | teapotPacket2[3]) / 16384.0f;
> q2[1] = ((teapotPacket2[4] << 8) | teapotPacket2[5]) / 16384.0f;
> q2[2] = ((teapotPacket2[6] << 8) | teapotPacket2[7]) / 16384.0f;
> q2[3] = ((teapotPacket2[8] << 8) | teapotPacket2[9]) / 16384.0f;
> for (int i = 0; i < 4; i++) if (q2[i] >= 2) q2[i] = -4 + q2[i];
>             
> // set our toxilibs quaternion to new data
> quat2.set(q2[0], q2[1], q2[2], q2[3]);
> }
> }
> }
> 
> ```
> 
> }
> 
> void drawCylinder(float topRadius, float bottomRadius, float tall, int sides) {  
> float angle = 0;  
> float angleIncrement = TWO\_PI / sides;  
> beginShape(QUAD\_STRIP);  
> for (int i = 0; i \< sides + 1; ++i) {  
> vertex(topRadius_cos(angle), 0, topRadius_sin(angle));  
> vertex(bottomRadius_cos(angle), tall, bottomRadius_sin(angle));  
> angle += angleIncrement;  
> }  
> endShape();
> 
> ```
> // If it is not a cone, draw the circular top cap
> if (topRadius != 0) {
> angle = 0;
> beginShape(TRIANGLE_FAN);
>     
> // Center point
> vertex(0, 0, 0);
> for (int i = 0; i < sides + 1; i++) {
> vertex(topRadius * cos(angle), 0, topRadius * sin(angle));
> angle += angleIncrement;
> }
> endShape();
> }
> 
> // If it is not a cone, draw the circular bottom cap
> if (bottomRadius != 0) {
> angle = 0;
> beginShape(TRIANGLE_FAN);
> 
> // Center point
> vertex(0, tall, 0);
> for (int i = 0; i < sides + 1; i++) {
> vertex(bottomRadius * cos(angle), tall, bottomRadius * sin(angle));
> angle += angleIncrement;
> }
> endShape();
> }
> 
> ```
> 
> }

---

<div class="post-metadata">

**Author:** ![rodrigogamboa](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/rodrigogamboa/32/2642_2.png) [@rodrigogamboa](https://discourse.processing.org/u/rodrigogamboa)\
**Post date:** [December 3, 2018, 4:52am UTC](https://discourse.processing.org/t/how-to-read-2-packets-of-data-at-once-mpu6050/5793/2 "2018-12-03T04:52:22Z")

</div>

Hi @yodayoshi! Usually when I want to send data from Arduino to Processing or visceversa, and have multiple sensors, I use this simple solution: Add values to each sensor. For example:  
If you have 2 sensors (analog), each sensor would send data from 0 to 1023. So you can add 1024 to each other sensor in Arduino to differentiate them. So the first sensor would be from 0-1023, the second from 1024-2047, third from 2048-3071… So in Processing you could know which data belongs to which sensor and substract 1024 to have the original value. I hope this helps you!

---

<div class="post-metadata">

**Author:** ![ishan25dav](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/ishan25dav/32/8052_2.png) [@ishan25dav](https://discourse.processing.org/u/ishan25dav)\
**Post date:** [February 11, 2020, 11:28am UTC](https://discourse.processing.org/t/how-to-read-2-packets-of-data-at-once-mpu6050/5793/3 "2020-02-11T11:28:29Z")

</div>

please explain how can I do it in my code what parameter I have to change

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [February 12, 2020, 11:36am UTC](https://discourse.processing.org/t/how-to-read-2-packets-of-data-at-once-mpu6050/5793/4 "2020-02-12T11:36:48Z")

</div>

Hello,

Welcome to the forum.

You should start a separate topic.

> [@ishan25dav](#):
>
> please explain how can I do it in my code what parameter I have to change

Please post your code; a minimal version of it that you require assistance with.

’ 🙂 ’

---

<div class="post-metadata">

**Author:** ![ishan25dav](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/ishan25dav/32/8052_2.png) [@ishan25dav](https://discourse.processing.org/u/ishan25dav)\
**Post date:** [February 13, 2020, 4:54am UTC](https://discourse.processing.org/t/how-to-read-2-packets-of-data-at-once-mpu6050/5793/5 "2020-02-13T04:54:28Z")

</div>

```auto
import processing.serial.*;
import java.awt.event.KeyEvent;
import java.io.IOException;
Serial myPort;
String data="";
float roll, pitch,yaw;
void setup() {
  size (800, 400, P3D);
  myPort = new Serial(this, "COM4", 19200); // starts the serial communication
  myPort.bufferUntil('\n');
  delay(1000);
}
void draw() {
  translate(width/2, height/2, 0);
  translate(width/2, height/2, 0);
  background(232);
  textSize(22);
  text("Roll: " + int(roll) + " Pitch: " + int(pitch), -100, 265);
  // Rotate the object
  rotateX(radians(-pitch));
  rotateZ(radians(roll));
  rotateY(radians(yaw));
  
  
//line(30, 20, 0, 85, 20, 15);
//stroke(255);
//line(85, 20, 15, 85, 75, 0);
//stroke(255);
//line(85, 75, 0, 30, 75, -50);

  // 3D 0bject
  //textSize(30);  
  //fill(0, 76, 153);
  //box (386, 40, 200); // Draw box
  ////box (100, 10, 100);
  //textSize(25);
  //fill(255, 255, 255);
  //text("HUMAN ARM ", -183, 10, 101);
  //delay(10);
  //println("ypr:\t" + angleX + "\t" + angleY); // Print the values to check whether we are getting proper values
}
// Read data from the Serial Port
void serialEvent (Serial myPort) { 
  // reads the data from the Serial Port up to the character '.' and puts it into the String variable "data".
  data = myPort.readStringUntil('\n');
  // if you got any bytes other than the linefeed:
  if (data != null) {
    data = trim(data);
    // split the string at "/"
    String items[] = split(data, '/');
    if (items.length > 1) {
      //--- Roll,Pitch in degrees
      roll = float(items[0]);
      pitch = float(items[1]);
      yaw = float(items[2]);
    }
  }
}

```

where and what should I change to get the animation of two MPU6050 at the same time

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [February 13, 2020, 10:38am UTC](https://discourse.processing.org/t/how-to-read-2-packets-of-data-at-once-mpu6050/5793/6 "2020-02-13T10:38:43Z")

</div>

Hello,

Please format your code:  
[https://discourse.processing.org/faq#format-your-code](https://discourse.processing.org/faq#format-your-code)

The Processing website has lots of resources that will help display two animations:  
[https://processing.org/](https://processing.org/)

Are you sending data from 2 Arduinos each with a sensor?  
You can use more than one serial port:  
[https://processing.org/reference/libraries/serial/serialEvent\_.html](https://processing.org/reference/libraries/serial/serialEvent_.html)

Are you sending data from 1 Arduino with 2 sensors?  
You can double the data you send with yaw, pitch, roll for each sensor.

’ 🙂 ’
