cat > ads_plot_polling.py <<'PY' import time import smbus from collections import deque import matplotlib.pyplot as plt BUS = 1 ADDR = 0x48 REG_CONV = 0x00 REG_CONFIG = 0x01 bus = smbus.SMBus(BUS) # Continuous mode, AIN0, PGA ±4.096V, 860 SPS (chip-side) config = 0x8000 | 0x4000 | 0x0200 | 0x0000 | 0x00E0 | 0x0003 bus.write_i2c_block_data(ADDR, REG_CONFIG, [(config >> 8) & 0xFF, config & 0xFF]) FS_VOLTS = 4.096 def read_volts_fast(): # Often faster than read_i2c_block_data raw = bus.read_word_data(ADDR, REG_CONV) raw = ((raw & 0xFF) << 8) | (raw >> 8) # swap endian if raw & 0x8000: raw -= 1 << 16 return raw * FS_VOLTS / 32768.0 WINDOW_SECONDS = 0.5 # rolling window shown SAMPLE_SLEEP = 0.0 # set to 0.01 if you want ~100Hz like your raw script DRAW_FPS = 30 ts = deque() vs = deque() plt.ion() fig, ax = plt.subplots() line, = ax.plot([], []) ax.set_title("ADS1115 AIN0 live (polling, real-time window)") ax.set_xlabel("Time (s)") ax.set_ylabel("Volts") ax.set_ylim(-0.5, 3.5) ax.set_xlim(-WINDOW_SECONDS, 0) t0 = time.perf_counter() last_draw = t0 draw_interval = 1.0 / DRAW_FPS # rate meter last_rate_t = t0 rate_count = 0 while True: v = read_volts_fast() t = time.perf_counter() - t0 ts.append(t) vs.append(v) rate_count += 1 # keep only last WINDOW_SECONDS while ts and (ts[-1] - ts[0]) > WINDOW_SECONDS: ts.popleft() vs.popleft() now = time.perf_counter() # print real sample rate once/sec if now - last_rate_t >= 1.0: sps = rate_count / (now - last_rate_t) print(f"Actual read rate: {sps:.1f} samples/sec") last_rate_t = now rate_count = 0 # redraw at DRAW_FPS if now - last_draw >= draw_interval and len(ts) >= 2: t_end = ts[-1] xs = [ti - t_end for ti in ts] # ends at 0 line.set_data(xs, list(vs)) ax.set_xlim(-WINDOW_SECONDS, 0) fig.canvas.draw_idle() plt.pause(0.001) last_draw = now if SAMPLE_SLEEP > 0: time.sleep(SAMPLE_SLEEP) PY python3 ads_plot_polling.py