Ir al contenido

← Lecturas diferenciales ADS1015 con ganancia automática

Banco de ensayo de fusiblesRaspberry PLC 19RI2CAdquisición

Lecturas diferenciales ADS1015 con ganancia automática — ejemplo completo

Lee corriente de shunt y caída de tensión con un ADS1015 por I2C en un Raspberry PLC: canales diferenciales, cambio automático de ganancia y fórmulas reales.

Programa completo y ejecutable para el Raspberry PLC 19R (ads1015-differential-adc-autogain.py): incluye cabecera de conexionado, requisitos y notas de integración.

Descarga el pack completo del proyecto — gratisEste ejemplo + los relacionados + lista de materiales

Vista de solo lectura.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
COMPLETE EXAMPLE — Differential ADC readings with automatic gain (ADS1015)

Equipment: Raspberry PLC 19R (Industrial Shields)
Based on:  fuse test bench project

Wiring:
  - ADS1015 on the PLC I2C bus (address 0x48)
  - A0-A1: terminals of the 60 mOhm shunt (class 0.5) in series with the fuse
  - A2-A3: voltage drop directly across the fuse under test

Requirements:
  pip3 install adafruit-circuitpython-ads1x15
  (I2C enabled with raspi-config)

Integration with the catalog:
  - The current measured here feeds the calibration loop
    (closed-loop-current-calibration.py) and the test
    sequences (fuse-test-sequences.py).
"""

import time
import board
import busio
import adafruit_ads1x15.ads1015 as ADS
from adafruit_ads1x15.analog_in import AnalogIn

# --- Bench constants --------------------------------------------------------
SHUNT_OHM = 0.06          # 60 mOhm shunt
DIVIDER_RATIO = 200.0     # signal conditioning of the measurement loop
CAL_FACTOR = 1.02         # fine correction obtained during calibration

# ADS1015 gains: PGA key -> full scale in volts
PGA_RANGE = {
    "2/3": 6.144,  # gain 2/3 -> ±6.144 V (safe startup)
    "16": 0.256,   # gain 16  -> ±0.256 V (maximum resolution)
}


def create_adc():
    i2c = busio.I2C(board.SCL, board.SDA)
    ads = ADS.ADS1015(i2c, address=0x48)
    return ads


def read_differential(ads, channel, gain):
    """Raw differential reading (signed 16 bits) on the given channel.

    channel: ADS.P0/P1 for the shunt, ADS.P2/P3 for the drop across the fuse.
    """
    ads.gain = gain
    analog_input = AnalogIn(ads, *channel)
    return analog_input.value  # integer -32768..32767 scaled to 16 bits


def read_with_autogain(ads, channel):
    """Start with gain 2/3 (wide range) and drop to x16 if the signal is
    small: this way it never saturates and the full resolution is used."""
    raw = read_differential(ads, channel, 2 / 3)
    estimated_volts = abs(raw) / 65535.0 * 2.0 * PGA_RANGE["2/3"]

    if estimated_volts < PGA_RANGE["16"] * 0.95:
        # Small signal: re-read with gain x16 for maximum resolution
        raw = read_differential(ads, channel, 16)
        return raw, PGA_RANGE["16"]
    return raw, PGA_RANGE["2/3"]


def read_shunt_current(ads):
    """Current (A) from the differential voltage across the shunt.

    Actual bench formula with gain x16 (256 mV range):
      current = (raw/65535) * 2.0 * 0.256 * 200.0 / 0.06 * 1.02
    """
    raw, full_scale = read_with_autogain(ads, (ADS.P0, ADS.P1))
    volts = (raw / 65535.0) * 2.0 * full_scale
    return volts * DIVIDER_RATIO / SHUNT_OHM * CAL_FACTOR


def read_fuse_drop(ads):
    """Voltage drop (V) across the fuse under test (A2-A3)."""
    raw, full_scale = read_with_autogain(ads, (ADS.P2, ADS.P3))
    return (raw / 65535.0) * 2.0 * full_scale


def main():
    ads = create_adc()
    print("ADS1015 ready at 0x48. Measuring every 500 ms (Ctrl+C to exit).")
    print("%-10s %-12s %-12s %-12s" % ("t (s)", "I (A)", "Vdrop (mV)", "R (mOhm)"))

    t0 = time.time()
    while True:
        amps = read_shunt_current(ads)
        vdrop = read_fuse_drop(ads)

        # Hot resistance of the fuse: key figure for the report
        r_mohm = (vdrop / amps * 1000.0) if amps > 0.5 else float("nan")

        print("%-10.1f %-12.2f %-12.1f %-12.2f"
              % (time.time() - t0, amps, vdrop * 1000.0, r_mohm))
        time.sleep(0.5)


if __name__ == "__main__":
    main()
Descarga el pack completo del proyecto — gratisEste ejemplo + los relacionados + lista de materiales