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()
问题分析与代码改进建议
初始代码的核心问题
- 时间统计完全无效:
thisTime = timer() - start在start定义后立即执行,得到的时间趋近于0,totalElapsed累加的是无意义数值,无法反映实际采集时长。 - 无控制快速采样:内层
while循环没有任何延时,会以Python能达到的最快速度读取chan.value,瞬间填满16384个元素的数组,自然会提前结束程序,完全没有遵循128样本/秒的采样速率。
修正代码的合理性与待调整点
修正代码的定时采样思路是正确的,但存在几个细节问题需要优化:
触发逻辑不完善:当前用单次
if判断触发电平,若程序启动时触发信号未达到阈值,会直接跳过采集流程,应改为循环等待触发:# 等待触发信号 while trig.value <= level: pass数组索引越界:
if data[i] == data[i - 1]在i=0时会访问data[-1]导致报错,需增加判断条件:if i > 0 and data[i] == data[i - 1]: repeats += 1打印语句格式错误:原打印语句会输出带多余引号的字符串,建议改用f-string优化:
print(f">>>>>>>>>>>>>> Total Elapsed: {total_time:.2f}s")连续模式的适配: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
相关产品推荐
相关产品推荐

