import smbus2
import time

# I2C address of the wattmeter
I2C_ADDRESS = 0x45

# Register addresses (from DFRobot documentation)
REG_CALIBRATION = 0x05
REG_BUS_VOLTAGE = 0x02
REG_SHUNT_VOLTAGE = 0x01
REG_POWER = 0x03  # Power register

# Calibration value for the INA219 (specific to your setup)
CALIBRATION_VALUE = 4096

# Scaling factors from INA219 specifications
VOLTAGE_SCALE = 0.004  # 4mV per bit
SHUNT_VOLTAGE_SCALE = 0.00001  # 10µV per bit
SHUNT_RESISTANCE = 0.01  # 10mΩ shunt resistor
POWER_SCALE = 0.04  # Adjusted scale factor for power (20mW per bit)

# Create an SMBus instance
bus = smbus2.SMBus(1)

def write_calibration():
    """Writes the calibration value to the wattmeter."""
    bus.write_word_data(I2C_ADDRESS, REG_CALIBRATION, CALIBRATION_VALUE)

def read_voltage():
    """Reads and calculates the bus voltage in volts."""
    raw_bus_voltage = bus.read_word_data(I2C_ADDRESS, REG_BUS_VOLTAGE)
    raw_bus_voltage = ((raw_bus_voltage & 0xFF) << 8) | (raw_bus_voltage >> 8)  # Swap bytes
    return (raw_bus_voltage >> 3) * VOLTAGE_SCALE  # Convert to volts

def read_current():
    """Reads and calculates the current in amperes."""
    raw_shunt_voltage = bus.read_word_data(I2C_ADDRESS, REG_SHUNT_VOLTAGE)
    raw_shunt_voltage = ((raw_shunt_voltage & 0xFF) << 8) | (raw_shunt_voltage >> 8)  # Swap bytes
    shunt_voltage = raw_shunt_voltage * SHUNT_VOLTAGE_SCALE  # Convert to volts
    return shunt_voltage / SHUNT_RESISTANCE  # Convert to amperes

def read_power():
	voltage = read_voltage()
	current = read_current()
	return voltage * current


if __name__ == "__main__":
    write_calibration()
    time.sleep(0.3)  # Allow calibration to take effect

    while True:
        try:
            voltage = read_voltage()
            current = read_current()
            power = read_power()

            print(f"Voltage: {voltage:.3f} V")
            print(f"Current: {current:.3f} A")
            print(f"Power: {power:.3f} W")
            print("-" * 30)

            time.sleep(1)  # Print every 1 second

        except Exception as e:
            print(f"Error: {e}")
            break  # Exit loop if an error occurs
