简体   繁体   English

使用 pigpio 从传感器获取数据时 I2C 读取错误

[英]I2C read error while getting data from sensor with pigpio

i have a Tkinter GUI and the acceleration sensor MMA8452Q.我有一个 Tkinter GUI 和加速度传感器 MMA8452Q。 I set up the sensor that if a threshold is reached, a interrupt flag gets set and data for a specific period of time gets collected and plotted through the GUI.我设置了传感器,如果达到阈值,则会设置中断标志,并通过 GUI 收集和绘制特定时间段的数据。

Sometimes when I read the data or at any other point of using an I2C read function to read a register i get the error "I2C read failed" (when the error happens in the check_flags() method) and sometimes I get something like this:有时,当我读取数据或在使用 I2C 读取 function 读取寄存器的任何其他点时,我会收到错误“I2C 读取失败”(当错误发生在 check_flags() 方法中时),有时我会得到如下信息:

interrupt 1 True
4 0 1810275105
Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.7/threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "/home/pi/.../tkinter/mix/mix_interrupt.py", line 307, in check_flags
    pi.i2c_read_byte_data(acc_sensor, FF_MT_SRC)
  File "/usr/lib/python3/dist-packages/pigpio.py", line 2874, in i2c_read_byte_data
    return _u2i(_pigpio_command(self.sl, _PI_CMD_I2CRB, handle, reg))
  File "/usr/lib/python3/dist-packages/pigpio.py", line 1011, in _u2i
    raise error(error_text(v))
pigpio.error: 'I2C read failed'

Is there maybe something wrong with my code or should i could the baudrate be the fault of this problem?我的代码可能有问题还是我的波特率可能是这个问题的错? It doesn't happen all the time, but seemingly at random times.它不会一直发生,但似乎是随机的。 Just to clarify, if the error happens in the try-except-block, my data still gets plotted, but some data gets missing and the plot looks sometimes incomplete澄清一下,如果错误发生在 try-except-block 中,我的数据仍然会被绘制,但有些数据会丢失,并且 plot 有时看起来不完整

My important code parts:我的重要代码部分:

This is the thread:这是线程:

threading.Thread(target=self.check_flags).start() #This is in the init method

This function runs in a thread like this and checks if self.interrupt_flag is set这个 function 在这样的线程中运行并检查是否设置了 self.interrupt_flag

def check_flags(self):
        while(True):
            #print("check the flags")
            if (self.interrupt_flag == True):
                pi.i2c_read_byte_data(acc_sensor, FF_MT_SRC)
                global scale_variable
                self.x_graph = []
                self.y1_graph = []
                self.y2_graph = []
                self.y3_graph = []
                
                a = datetime.datetime.now()
                one_time = True 
                start_time = time.time()*1000
                while(time.time()*1000-start_time) < self.timeframe:
                    try:
                        b = datetime.datetime.now()
                        delta = b-a
                        y1 = self.readACCx()
                        y2 = self.readACCy()
                        y3 = self.readACCz()
                        self.y1_graph.append(y1)
                        self.y2_graph.append(y2)
                        self.y3_graph.append(y3)
                        self.x_graph.append(delta.total_seconds()*1000)
                        if (y1 > self.threshold or y2 > self.threshold): # this is for catching the whole movement if its longer than the set timeframe
                            self.timeframe += 5          
                    except pigpio.error as e:
                        print("error:", e)
                self.save_data()
                self.plot_data()
                self.interrupt_flag = False

This is one of the functions i use to read sensor data.这是我用来读取传感器数据的功能之一。 The other two are almost identical其他两个几乎一样

def readACCx(self): #reads x axis value 12 bit
        global scale_variable
        comp_acc_x2 = pi.i2c_read_byte_data(acc_sensor, OUT_X_MSB)
        comp_acc_x1 = pi.i2c_read_byte_data(acc_sensor, OUT_X_LSB)
        acc_combined = ((comp_acc_x2 << 8) | comp_acc_x1) >>4
        if acc_combined < 2048:
            acc_combined = acc_combined*scale_variable
            return acc_combined
        else:
            acc_combined = acc_combined - 4096
            acc_combined = acc_combined*scale_variable
            return acc_combined

This is my interrupt routine:这是我的中断程序:

def my_callback1(self, gpio, level, tick): #first interrupt function
        self.interrupt_flag = True
        print("interrupt 1", self.interrupt_flag)
        
        print(gpio, level, tick)

Your traceback doesn't match your code.您的回溯与您的代码不匹配。 The traceback shows the i2c_read_byte_data result not being saved anywhere.回溯显示i2c_read_byte_data结果未保存在任何地方。 The I2C clock must be right, otherwise you'd get nothing at all. I2C 时钟必须正确,否则您将一无所获。

The problem is probably synchronization.问题可能是同步。 When you said "interrupt", that raised a red flag.当你说“中断”时,这引发了一个危险信号。 If your interrupt handler tries to do an I2C operation while your mainline code is also doing one, the two will clash, especially since you have to do MSB and LSB separately.如果您的中断处理程序尝试执行 I2C 操作,而您的主线代码也在执行一项操作,则两者将发生冲突,特别是因为您必须分别执行 MSB 和 LSB。 I suggest you use a threading.Lock to make sure your sequences aren't interrupted.我建议你使用threading.Lock来确保你的序列不会被打断。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM