Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 7883

Python • Re: Using a 4-20 mA Transmitter with a Raspberry Pi

$
0
0
You could try this.
At one place you made an error. The 0xFF must be 0x0F (15) which is used to mask the value for lsb.
And maybe msb and lsb is swapped in send order.

Code:

import timefrom smbus2 import SMBusDAC_ADDRESS = 0x60class CurrentLoopTransmitter:    """    NCD 1-Channel 4-20mA Current Loop Transmitter    MCP4725 DAC + XTR115    """    SET_VOLTAGE = 0x40   # Write DAC register (normal mode)    LOWER_LIMIT = 670    UPPER_LIMIT = 3460    MAX_LOOP_VOLTAGE = 36    def __init__(self, bus, address=DAC_ADDRESS, resistor=None):        self.bus = bus        self.address = address        self.resistor = resistor        if resistor is not None:            self.max_voltage = resistor * 20e-3            self.min_voltage = resistor * 4e-3    def set_current(self, current_mA: float):        if not 4 <= current_mA <= 20:            raise ValueError("Current must be between 4 and 20 mA")        raw_value = round(            (current_mA - 4) / 16 * (self.UPPER_LIMIT - self.LOWER_LIMIT) + self.LOWER_LIMIT        )        msb = (raw_value >> 4) & 0xFF        lsb = (raw_value & 0x0F) << 4        try:            self.bus.write_i2c_block_data(self.address, self.SET_VOLTAGE, [msb, lsb])        except OSError as e:            print(f"I²C Error while writing DAC value: {e}")            raise    def set_voltage(self, voltage: float):        if self.resistor is None:            raise RuntimeError("Resistor must be specified for voltage mode")        if voltage > self.MAX_LOOP_VOLTAGE:            raise ValueError(f"Max loop voltage is {self.MAX_LOOP_VOLTAGE} V")        if not self.min_voltage <= voltage <= self.max_voltage:            raise ValueError(                f"Voltage {voltage:.2f} V out of range ({self.min_voltage:.2f}–{self.max_voltage:.2f} V)"            )        current_mA = voltage / self.resistor * 1000        print(f"Voltage: {voltage:5.2f} V | Current: {current_mA:5.2f} mA")        self.set_current(current_mA)def sweep_values(start, stop, steps, duration):    """    Sweep linearly between start and stop and back.    Total duration ≈ duration seconds.    """    delta = (stop - start) / steps    delay = duration / (steps * 2)    for step in range(steps + 1):        yield start + delta * step        time.sleep(delay)    for step in reversed(range(steps)):        yield start + delta * step        time.sleep(delay)                        cl1 = CurrentLoopTransmitter(SMBus(1), resistor=500)cl1.set_voltage(10)cl1.set_voltage(9.4)cl1.set_voltage(2)cl1.set_current(20)try:    cl1.set_voltage(1)except ValueError:    print("CurrentLoopTransmitter has thrown ValueError.")    print(f"The lower limit is currently {cl1.min_voltage}V with a {cl1.resistor}Ω  Resistor.")    print(f"The upper limit is currently {cl1.max_voltage}V.")for voltage in sweep_values(2, 10, 10, 1):    print(f"Setting voltage to {voltage:5.2f}V")    cl1.set_voltage(voltage)

Statistics: Posted by DeaD_EyE — Fri Aug 29, 2025 5:25 pm



Viewing all articles
Browse latest Browse all 7883

Trending Articles