You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ADS1115采集128×128电压数组提前终止问题及代码验证

问题:ADS1115采集16384个样本未达预期128秒提前停止,修正代码是否正确?

问题背景

我需要通过chan测量电压,将数据写入128×128的数组(共16384个电压值)。ADS1115采样率设为128样本/秒,理论上采集总时长应为128秒,但实际程序未运行满时长就提前停止。初始代码如下:

import numpy as np
import time
from matplotlib import pyplot as plt

import board
import busio
import adafruit_ads1x15.ads1115 as ADS
from adafruit_ads1x15.analog_in import AnalogIn
from timeit import default_timer as timer


i2c = busio.I2C(board.SCL, board.SDA)
ads = ADS.ADS1115(i2c)
ads.gain = 8
ads.mode = ADS.Mode.CONTINUOUS
ads.data_rate = 128
chan = AnalogIn(ads, ADS.P0, ADS.P1)

trig = AnalogIn(ads, ADS.P2, ADS.P3)


level = 192 # trigger level

totalElapsed = 0

buffer = []

while True:

     if (trig.value > level):
     
         start = timer()
         thisTime =  timer() - start

         while(len(buffer) < 16384):
 
              buffer.append(chan.value)
              
              totalElapsed += thisTime
              
              print("\">>>>>>>>>>>>>> Total Elapsed: \" + str(totalElapsed) + \"s\"")

         # Make into numpy array and reshape to (128,128)
         a = np.array(buffer).reshape((128,128))

         # Reverse alternate rows
         for r in range(1,128,2):
            a[r] = a[r][::-1]


         #Generate image
         plt.imsave('/home/rpi/Downloads/mystm_pic.tiff', a, cmap='afmhot') # file location

         plt.imshow(a, cmap='afmhot')

         plt.show()

编辑补充

我编写了修正后的代码,请问是否正确?

import numpy as np
import time
from matplotlib import pyplot as plt

import board
import busio
import adafruit_ads1x15.ads1115 as ADS
from adafruit_ads1x15.analog_in import AnalogIn
from timeit import default_timer as timer

RATE = 128
SAMPLES = 16384    

i2c = busio.I2C(board.SCL, board.SDA)
ads = ADS.ADS1115(i2c)
ads.gain = 8
ads.mode = ADS.Mode.CONTINUOUS
ads.data_rate = RATE
chan = AnalogIn(ads, ADS.P0, ADS.P1)

trig = AnalogIn(ads, ADS.P2, ADS.P3)


level = 192 # trigger level

sample_interval = 1.0 / ads.data_rate

repeats = 0
skips = 0

data = [None] * SAMPLES

start = time.monotonic()
time_next_sample = start + sample_interval



if (trig.value > level):
     

    for i in range(SAMPLES):
 
         while time.monotonic() < (time_next_sample): 
              pass

         data[i] = chan.value

         # Loop timing
         time_last_sample = time.monotonic()
         time_next_sample = time_next_sample + sample_interval
         if time_last_sample > (time_next_sample + sample_interval):
            skips += 1
            time_next_sample = time.monotonic() + sample_interval

         # Detect repeated values due to over polling
         if data[i] == data[i - 1]:
            repeats += 1

    end = time.monotonic()
    total_time = end - start


    # Make into numpy array and reshape to (128,128)
    a = np.array(data).reshape((128,128))

    # Reverse alternate rows
    for r in range(1,128,2):
       a[r] = a[r][::-1]

    print("\">>>>>>>>>>>>>> Total Elapsed: \" + str(total_time) + \"s\"")    

         #Generate image
    plt.imsave('/home/rpi/Downloads/mystm_pic.tiff', a, cmap='afmhot') # file location

    plt.imshow(a, cmap='afmhot')

    plt.show()

问题分析与代码改进建议

初始代码的核心问题

  1. 时间统计完全无效:thisTime = timer() - start在start定义后立即执行,得到的时间趋近于0,totalElapsed累加的是无意义数值,无法反映实际采集时长。
  2. 无控制快速采样:内层while循环没有任何延时,会以Python能达到的最快速度读取chan.value,瞬间填满16384个元素的数组,自然会提前结束程序,完全没有遵循128样本/秒的采样速率。

修正代码的合理性与待调整点

修正代码的定时采样思路是正确的,但存在几个细节问题需要优化:

  1. 触发逻辑不完善:当前用单次if判断触发电平,若程序启动时触发信号未达到阈值,会直接跳过采集流程,应改为循环等待触发:

    # 等待触发信号
    while trig.value <= level:
        pass
    
  2. 数组索引越界:if data[i] == data[i - 1]在i=0时会访问data[-1]导致报错,需增加判断条件:

    if i > 0 and data[i] == data[i - 1]:
        repeats += 1
    
  3. 打印语句格式错误:原打印语句会输出带多余引号的字符串,建议改用f-string优化:

    print(f">>>>>>>>>>>>>> Total Elapsed: {total_time:.2f}s")
    
  4. 连续模式的适配:ADS1115在CONTINUOUS模式下会自动按设定速率完成采样转换,当前的定时读取逻辑需确保不小于芯片的转换周期(1/128≈7.8ms),避免重复读取同一个样本。

调整后的最终代码

import numpy as np
import time
from matplotlib import pyplot as plt

import board
import busio
import adafruit_ads1x15.ads1115 as ADS
from adafruit_ads1x15.analog_in import AnalogIn

RATE = 128
SAMPLES = 16384    

# 初始化ADS1115
i2c = busio.I2C(board.SCL, board.SDA)
ads = ADS.ADS1115(i2c)
ads.gain = 8
ads.mode = ADS.Mode.CONTINUOUS
ads.data_rate = RATE
chan = AnalogIn(ads, ADS.P0, ADS.P1)
trig = AnalogIn(ads, ADS.P2, ADS.P3)

level = 192  # 触发电平
sample_interval = 1.0 / RATE
repeats = 0
skips = 0
data = [None] * SAMPLES

# 循环等待触发信号
while trig.value <= level:
    pass

start = time.monotonic()
time_next_sample = start + sample_interval

for i in range(SAMPLES):
    # 等待到预设采样时间点
    while time.monotonic() < time_next_sample:
        pass
    
    # 读取当前采样值
    data[i] = chan.value
    
    # 统计重复样本(跳过第一个元素)
    if i > 0 and data[i] == data[i - 1]:
        repeats += 1
    
    # 更新下一次采样时间,处理延迟情况
    time_last_sample = time.monotonic()
    time_next_sample += sample_interval
    # 如果延迟超过一个采样间隔,重置采样时间基准
    if time_last_sample > time_next_sample + sample_interval:
        skips += 1
        time_next_sample = time_last_sample + sample_interval

end = time.monotonic()
total_time = end - start

# 数据格式转换与处理
a = np.array(data).reshape((128, 128))
# 反转偶数行
for r in range(1, 128, 2):
    a[r] = a[r][::-1]

# 输出统计信息
print(f">>>>>>>>>>>>>> Total Elapsed: {total_time:.2f}s")
print(f"跳过的采样次数: {skips}, 重复样本次数: {repeats}")

# 保存并显示图像
plt.imsave('/home/rpi/Downloads/mystm_pic.tiff', a, cmap='afmhot')
plt.imshow(a, cmap='afmhot')
plt.show()

内容的提问来源于stack exchange,提问作者Malum Phobos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 10:57:00