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.
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