首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用pigpio从传感器获取数据时I2C读取错误

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

Stack Overflow用户
提问于 2022-08-08 17:08:25
回答 1查看 50关注 0票数 0

我有一个Tkinter和加速度传感器MMA8452Q。我设置了传感器,如果达到阈值,则设置中断标志,并通过GUI收集和绘制特定时间段的数据。

有时,当我读取数据或在使用I2C read函数读取寄存器的任何其他点时,都会得到"I2C读取失败“(当错误发生在check_flags()方法中),有时会得到这样的错误:

代码语言:javascript
复制
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'

我的代码可能有什么问题,还是应该是这个问题的错误呢?这种情况并不总是发生,但似乎是随机发生的。为了澄清的是,如果这个错误发生在try-除了-块中,我的数据仍然会被绘制,但是有些数据会丢失,而这个图有时看起来不完整。

我的重要代码部分:

这是一条主线:

代码语言:javascript
复制
threading.Thread(target=self.check_flags).start() #This is in the init method

此函数在这样的线程中运行,并检查是否设置了self.interrupt_flag。

代码语言:javascript
复制
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

这是我用来读取传感器数据的功能之一。另外两个几乎是一样的

代码语言:javascript
复制
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

这是我的中断程序:

代码语言:javascript
复制
def my_callback1(self, gpio, level, tick): #first interrupt function
        self.interrupt_flag = True
        print("interrupt 1", self.interrupt_flag)
        
        print(gpio, level, tick)

编辑(几乎完美)工作代码:

代码语言:javascript
复制
protect = threading.Lock() # this is outside of any class at the top

def check_flags(self): # new data capture method
        while(True):
            #print("check the flags")
            if (self.interrupt_flag == True):
                protect.acquire()
                ff_flag = pi.i2c_read_byte_data(acc_sensor, FF_MT_SRC)
                print("interrupt cleared", ff_flag)
                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):
                            self.timeframe += 5
                    except pigpio.error as e:
                        print("error:", e)
                self.save_data()
                self.plot_data()
                self.interrupt_flag = False
                self.timeframe = self.config.getint('setting', 'timeframe')
                print("scale_variable: ", scale_variable)
                protect.release()
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-08 17:15:52

你的回溯不符合你的代码。回溯显示i2c_read_byte_data结果没有保存在任何地方。I2C时钟一定是正确的,否则你就什么都得不到了。

问题可能是同步。当你说“中断”的时候,就发出了危险的信号。如果您的中断处理程序尝试执行一个I2C操作,而您的主线代码也在执行一个中断处理程序,那么这两个操作将发生冲突,特别是因为您必须分别执行MSB和LSB。我建议你使用一个threading.Lock来确保你的序列不会被打断。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73281667

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档