0

So I use MPU6050 to get acceleration from stepper motor linear rail movement(steper motor working in thread, I use pigpio for the motor) by make the MPU6050 can work on threading and it can show data on gui graphic (I use pyqt to create GUI dan pyqtgraph for create a graph) with time delay 0,1 . Th problem is I suddently getting an error message when the script is running for the moment OSError: [Errno 121] Remote I/O error when use smbus library so I change it to pigpio but get an error message pigpio.error: 'I2C read failed'

smbus error message:

Traceback (most recent call last):


File "/home/pi/Desktop/mejaGetar/ThreadAccelerator.py", line 33, in run
    self.startAccelerator()
  File "/home/pi/Desktop/mejaGetar/ThreadAccelerator.py", line 22, in startAccelerator
    getData = ThreadAccelerator.accelerator.get_accelerator()
  File "/home/pi/Desktop/mejaGetar/accel.py", line 43, in get_accelerator
    x = self.read_i2c_word(self.ACCEL_XOUT0)
  File "/home/pi/Desktop/mejaGetar/accel.py", line 32, in read_i2c_word
    high = self.bus.read_byte_data(self.address,register)
OSError: [Errno 121] Remote I/O error

pgpio error message:

Traceback (most recent call last):


File "/home/pi/Desktop/mejaGetar/ThreadAccelerator.py", line 33, in run
    self.startAccelerator()
  File "/home/pi/Desktop/mejaGetar/ThreadAccelerator.py", line 22, in startAccelerator
    getData = ThreadAccelerator.accelerator.get_accelerator()
  File "/home/pi/Desktop/mejaGetar/mmpu.py", line 48, in get_accelerator
    z = self.read_i2c_word(self.ACCEL_ZOUT0)
  File "/home/pi/Desktop/mejaGetar/mmpu.py", line 36, in read_i2c_word
    low = self.pi.i2c_read_byte_data(self.h,register + 1)
  File "/usr/local/lib/python3.4/dist-packages/pigpio.py", line 2792, in i2c_read_byte_data
    return _u2i(_pigpio_command(self.sl, _PI_CMD_I2CRB, handle, reg))
  File "/usr/local/lib/python3.4/dist-packages/pigpio.py", line 975, in _u2i
    raise error(error_text(v))
pigpio.error: 'I2C read failed'

and this is my code (using smbus): accel.py

import smbus

class accel:

    ACCEL_SCALE_MODIFIER_2G = 16384.0
    GRAVITIY_CMS2 = 980.665
    address = None
    bus = None

    #register MPU-6050
    PWR_MGMT_1 = 0x6B
    PWR_MGMT_2 = 0x6C

    #register accelerator
    ACCEL_CONFIG = 0x1C
    ACCEL_XOUT0 = 0x3B
    ACCEL_YOUT0 = 0x3D
    ACCEL_ZOUT0 = 0x3F
    CONFIG = 0x1A
    INT_ENABLE = 0x38

    def __init__(self,address,bus = 1):
        self.address = address
        self.bus = smbus.SMBus(bus)


        self.bus.write_byte_data(self.address,self.PWR_MGMT_1,0x00)
        self.bus.write_byte_data(self.address, self.ACCEL_CONFIG, 0x00)

    def read_i2c_word(self,register):

        high = self.bus.read_byte_data(self.address,register)
        low = self.bus.read_byte_data(self.address,register + 1)

        value = (high << 8) + low

        if(value > 32768):
           return -((65535 - value) + 1)
        else:
            return value

    def get_accelerator(self):
        x = self.read_i2c_word(self.ACCEL_XOUT0)
        y = self.read_i2c_word(self.ACCEL_YOUT0)
        z = self.read_i2c_word(self.ACCEL_ZOUT0)

        scale_modifier = self.ACCEL_SCALE_MODIFIER_2G

        x = x/scale_modifier
        y = y/scale_modifier
        z = z/scale_modifier

        x = x * self.GRAVITIY_CMS2
        y = y * self.GRAVITIY_CMS2
        z = z * self.GRAVITIY_CMS2

        return {'x': x, 'y': y, 'z': z}

threading implementation ThreadAccelerator.py

import time
import sys
from accel import accel
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import QTime, QTimer
from write import write
import datetime

class ThreadAccelerator(QtCore.QThread):
    dataAccelerator = QtCore.pyqtSignal(object)
    accelerator = accel()
    time.sleep(1)
    collectData = []
    tulisRecord = write()
    run = False

    def __init__(self,parent=None):
        QtCore.QThread.__init__(self,parent)

    def startAccelerator(self):
        self.accelerator.setup()
        x = 0 
        while self.run == True:

            getData = self.accelerator.get_accelerator()
            self.dataAccelerator.emit({'x': getData['x'],'xx':x})
            print("hasil ",abs(getData['x']))
            x = x + 1

            time.sleep(0.1)


    def run(self):

        self.startAccelerator()

    def start(self):
        self.run = True
        super(ThreadAccelerator,self).start()

    def stop(self):
        self.run = False

and this is pigpio version: mmpu.py

import time
import sys

import pigpio

class mmpu:

    #default accell adalah 2G
    ACCEL_SCALE_MODIFIER_2G = 16384.0
    GRAVITIY_CMS2 = 980.665
    address = 0x68
    bus = None

    #register MPU-6050
    PWR_MGMT_1 = 0x6B
    PWR_MGMT_2 = 0x6C

    #register accelerator
    ACCEL_CONFIG = 0x1C
    ACCEL_XOUT0 = 0x3B
    ACCEL_YOUT0 = 0x3D
    ACCEL_ZOUT0 = 0x3F

    h = None

    pi=None

    def __init__(self):
        self.pi = pigpio.pi()

    def setup(self):
        self.h = self.pi.i2c_open(1, self.address)
        self.pi.i2c_write_byte_data(self.h,self.PWR_MGMT_1,0x00)
        self.pi.i2c_write_byte_data(self.h,self.ACCEL_CONFIG, 0x00)
        time.sleep(1)

    def read_i2c_word(self,register):
        high = self.pi.i2c_read_byte_data(self.h,register)
        low = self.pi.i2c_read_byte_data(self.h,register + 1)

        value = (high << 8) + low

        if(value > 32768):
           return -((65535 - value) + 1)
        else:
            return value

    def get_accelerator(self):
        x = self.read_i2c_word(self.ACCEL_XOUT0)
        y = self.read_i2c_word(self.ACCEL_YOUT0)
        z = self.read_i2c_word(self.ACCEL_ZOUT0)

        scale_modifier = self.ACCEL_SCALE_MODIFIER_2G

        x = x/scale_modifier
        y = y/scale_modifier
        z = z/scale_modifier

        x = x * self.GRAVITIY_CMS2
        y = y * self.GRAVITIY_CMS2
        z = z * self.GRAVITIY_CMS2

        return {'x': x, 'y': y, 'z': z}

    def close(self):
        self.pi.i2c_close(self.h)
        time.sleep(1)

threading implementation ThreadAccelerator.py

import time
import sys
from mmpu import mmpu
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import QTime, QTimer
from write import write
import datetime

class ThreadAccelerator(QtCore.QThread):
    dataAccelerator = QtCore.pyqtSignal(object)
    accelerator = mmpu()
    time.sleep(1)
    collectData = []
    tulisRecord = write()
    run = False

    def __init__(self,parent=None):
        QtCore.QThread.__init__(self,parent)

    def startAccelerator(self):
        self.accelerator.setup()
        x = 0 
        while self.run == True:

            getData = self.accelerator.get_accelerator()
            self.dataAccelerator.emit({'x': getData['x'],'xx':x})
            print("hasil ",abs(getData['x']))
            x = x + 1

            time.sleep(0.1)


        self.accelerator.close()

    def run(self):

        self.startAccelerator()

    def start(self):
        self.run = True
        super(ThreadAccelerator,self).start()

    def stop(self):
        self.run = False

and this is the picture of my sensor connected with raspberry pi (it has been connected correcly)

using jumper cable

imlementation

implementation 2

So, what the error cause? Is that cause by too much using threading (there're around 3 thread: one for stepper motor,one for accelerometer mpu6050,and the last for some program)? Or by the bad quality of cable? Or the delay on threading accelerator MPU6050 is too fast? If the elay on threading accelerator MPU6050 is too fast then what should I do? I need it to fast generate data to grapic. That's all of my question, thank you. (I run it on raspbian jessie,pigpio library is already up to date)

2
  • Remote I/O error is pretty much always a poor connection to the I2C device. Loose ground, loose power supply, loose SDA, loose SCL, or pins not being soldered to the device. I'd double check all those before looking at a timing problem.
    – joan
    Dec 14, 2018 at 22:01
  • @joan Idon't know if it cause by bad quality of wire jumper or simmilar. but I already check the cable condition is fine, it didn't broke inside (I already check it using multimeter). I still get OSError: [Errno 121] Remote I/O error when use smbus or pigpio.error: 'I2C read failed' when use pigpio even I implement it without python thread (using ordinary python loop, no other thread running in that time) Dec 15, 2018 at 5:02

2 Answers 2

1

I don't have a MPU6050 so I can't really test this.

However I suggest you look at this ADXL345 example and try similar code to read registers X, Y, Z as a block.

  import sys

  if sys.version > '3':
     buffer = memoryview

  # removed code

  # 0x32 = X LSB, 0x33 = X MSB
  # 0x34 = Y LSB, 0x35 = Y MSB
  # 0x36 = Z LSB, 0x37 = Z MSB

  # < = little endian

  (s, b) = pi.i2c_read_i2c_block_data(h, 0x32, 6)

  if s >= 0:
     (x, y, z) = struct.unpack('<3h', buffer(b))
     print("{} {} {}".format(x, y, z))
     read += 1
2
  • Ah, it's ok no problem. But why ADXL345? Dec 15, 2018 at 10:19
  • @Jansebastian Because it's probably pretty similar in operation to the MPU6050.
    – joan
    Dec 15, 2018 at 10:37
0

Ah, it's ok no problem. But why ADXL345? – Jan sebastian

In my case that ADXL345 works pretty much perfectly. But I got the same phenomenon as same error message, OSError: [Errno 121] Remote I/O error. I assumed that the SCL1 signal may cause overshoot or undershoot issue on the site of MPU6050, and the clock is count to many cycles and in wrong mapping on MPU6050. In my opinion, it can be resolved using a damping resistor to vanish the overshoot/undershoot phenomenon. just like this , SCL1(Pi)--/\/\/\/-SCL(MPU6050). Unfortunately, I don't have different resistors to match such experience. It also can be treated using low-pass filter as well.

Dec 15, 2018 at 10:19 @Jansebastian Because it's probably pretty similar in operation to the MPU6050. – joan Dec 15, 2018 at 10:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.