Inconsistency between I2C (imu) and SerialUSB.read()

I am working on quadcopter project with DUE communicate with Ubuntu on NUC i3 via serialUSB port. It work fine when arduino DUE send out protocal data to NUC. I was plot acceleretion graph imu is still ok as shown in attached file until i send data from NUC back to DUE around 25 Hz, then i plot acceleration graph again. It seem more agressive but still work normally when in action (moving up and down) by added some noise.

I tried many way, for example, to reduce frequency data that sending from NUC. It seem reduce noise just when the data is not send (in delay of frequency).

Or i try to comment out the serial receieve function. Imu have seem working fine so i notice it's not a TX RX voltage level disturb to I2C problem (I guess).

So i think it maybe a inconsistency between 1000hz imu read data and 25 hz serial.read ? :confused:
Any idea will be welcome.

PS . srry for my english skill :smiley:

I'm not sure what your problem is. I'm not sure what a NUC is. Please try again to explain what you want it to do and what it actually does. If you have different configurations or you are commenting out different lines, please say what you expected that to do and what it actually does.

The problem is certainly somewhere in the code you didn't post.

Thank u for suggestion :slight_smile:
My purpose is to hovering a quadcopter indoor with combine image processing information and IMU data.

Due to image processing can do only in minicomputer (in my case is NUC i3). I must exchange some kind of data between arduinoDUE and my minicomputer.

And a diagram will be placed a thousand word. :slight_smile:

arduinoDUE ------ IMU data ---> minicomputer (NUC i3)

if(position_is_ready_to_send) {
minicomputer------position,velocity---->arduinoDUE
}

Everything work fine when i send IMU from arduinoDUE to minicomputer without send back following the graph have been shown acceleration z is still at around 9.8 m/s^2. But when the position data that ready to use, i clicked allow it to send the data to arduinoDUE that have been pack with python code below.
I got a problem that IMU are going crazy, in spite of position not affect to IMU.

(NUC send image processing data to arduinoDUE with this function)

def send_vision_data(self,datav) : #(3 float 1 uint)
         dlen = 14
         head = struct.pack('ccc',chr(181),chr(dlen),chr(VISION_DATA))
         data = struct.pack('fffH',datav[0],datav[1],datav[2],datav[3])
         summ= 181+dlen+VISION_DATA
         for d in str(data):
             summ+=ord(d)
         chk = struct.pack('h',summ)
         tatal = len(head)+len(data)+len(chk)
         self.s.write( head )
         self.s.write( data )
         self.s.write( chk )
         print 'p x:', datav[0] ,'p y:' , datav[1]
         return tatal

arduinoDUE receieve the position with this function (placed top of void loop():wink:

#define Serial_ulink SerialUSB
void loop()
{
  SerialUSBEvent();


  currentTime = micros();
  
    if (currentTime - sensorPreviousTime >= 1000)   {
      imu_read();
    }
    if (frameCounter % TASK_50HZ == 0) {
    ....
    }
    .....
    
}

uint8_t st = 0,_lenp,_msgid,_pay[512],_idp,_c[2];

uint16_t _sum_pay,_csum;

static void SerialUSBEvent() {
     while (Serial_ulink.available()) {
        uint8_t dd = Serial_ulink.read();
        switch (st) {
          case 0:
            _sum_pay=0;
            if (dd == HEADER) {
              _sum_pay+=dd;
              st++;
            }
            break;
          case 1 :
            _lenp = dd;
            _sum_pay+=dd;
            st++;
            break;
          case 2 :
            _msgid = dd;
            _sum_pay+=dd;
            _idp = 0;
            st++;
            break;
          case 3 :
            _pay[_idp++] = dd;
            _sum_pay+=dd;
            if (_idp >=_lenp) st++;
            break;
          case 4 :
            _c[0] = dd;
            st++;
            break;
          case 5 :
            _c[1] = dd;
            _csum = toUint(_c);
            st = 0;
            if (_sum_pay == _csum) {
              if (_msgid == CMD_TAKEOFF) {
                   uint8_t h;
                   h = _pay[0];
              }else if(_msgid == VISION_DATA) {  //float x,float y,float z uint vision_is_good?
                uint8_t vision_tracking_quality = toUint(_pay[12]);
                vision_is_good= (vision_tracking_quality > 1 ? 1:0);
                vision_time_stamp=millis();
                vision_bx[0]=toFlt(_pay[0]);
                vision_by[0]=toFlt(_pay[4]);
                vision_bz[0]=toFlt(_pay[8]);
                
              }
            }
            break;
        }
     }
}

Is the Due talking to the NUC on its USB native serial port? Isn't lag aproblem?

Since you seem to be using a checksum there is probably no corruption of the data there.

What does toFlt() do? Why are you only giving it one single byte to work with?

This video is one of my tested.

It seem a little lag, i didn't measure (i mean not more than 100ms i guess).

and

#define toFlt(X)    *(float*)(&X)

I tried to comment part of usage incomming value (vision x y z) , and left following code

static void SerialUSBEvent() {
     while (Serial_ulink.available()) {
        uint8_t dd = Serial_ulink.read();
        switch (st) {
          case 0:
            _sum_pay=0;
            if (dd == HEADER) {
              _sum_pay+=dd;
              st++;
            }
            break;
          case 1 :
            _lenp = dd;
            _sum_pay+=dd;
            st++;
            break;
          case 2 :
            _msgid = dd;
            _sum_pay+=dd;
            _idp = 0;
            st++;
            break;
          case 3 :
            _pay[_idp++] = dd;
            _sum_pay+=dd;
            if (_idp >=_lenp) st++;
            break;
          case 4 :
            _c[0] = dd;
            st++;
            break;
          case 5 :
            _c[1] = dd;
            _csum = toUint(_c);
            st = 0;
            if (_sum_pay == _csum) {
            }
        }
     }
}

It still have a crazy IMU output. :confused:

You do realise that a floating-point number isn't stored in 1 byte? When the struct is coerced into the message, you will get 6 bytes for each float.

Casting the 6 bytes into a float doesn't work, even if you did use all 6 in the process.

Unpacking the struct on the receiving end should be done with an identical struct definition. You have a struct which is a series of bytes, send those bytes, then interpret them at the other end as the same type of structure.

This conversion is also HIGHLY dependent on the exact floating-point representation used on both ends. It is quite possible that the Arduino uses a different floating-point format to what Java does. It will almost certainly be different on different operating systems.

This is why most serial communication systems convert floating point numbers into a human-readable format. That way the receiver can read that into its own internal format without you having to know exactly how many bytes it uses. None of my programs ever need to know how many bytes make up a float, on any platform that they run on.

Thank you for reply. For my understand, this structure made less weight of data for less latency compare to using char by a degit of float (is a human readable that you just mention?).

And in this case,i know exactly how many byte i need to receive. I don't think the type of structure affect to IMU because position that received from NUC is correct (since i get those values and send to NUC for visualization monitering for many time are looking fine as shown in my video)

arduinoDUE ------ IMU data ---> minicomputer (NUC i3)

if(position_is_ready_to_send) {
minicomputer------position,velocity---->arduinoDUE
}

arduinoDUE ------ position (that receive from NUC) data ---> minicomputer (NUC i3) (for visualization what arduinoDUE get from NUC)

I really don't know what's next point i must test. :frowning:

Recently, I tried to remove protocal part and change "while" loop to "if" loop with and without serialUSB.read() function.

result

With read function i found crazy imu value.
Without read function not found that issue.

So why read function can disturb imu?

i also try to measure latency of read function epproximately around 3-4us with this function

while (Serial_ulink.available()>=6) {
        long time_start=micros();
        const uint8_t dd = Serial_ulink.read();
        Serial.println(micros()-time_start);
}

that imply the latency from this function isn't effect to algorithm.

So, how about i2c that connected directly (without levelshifter) to gy-86 sensor can corrupt when communicate with other device?

Update ..
I tried to communicate with

2 serial, 1 for send , another for receive
the result is still have the same issue.

and

2 serial , 1 for send (via wire) , 1 for receieve (via telemetry)
the result is no issue.

This prove there isn't a serial.read function issue. Maybe is a noise from the wire issue?

I'm lost and I'm not sure you've asked a question in a way that the forum can answer.

Are you still having problems?

What did you expect it to do?

What does it actually do?

Can you post the code you're using now?