1ère Générale NSI

 

Term. Générale NSI

 

Terminale STI2D SIN

Bts Ccst

Technico-commercial 3.0

Introduction

 

Test de i2c

 

Clase ina3221 en voltmètre

 

Classe ina3221 complete

 

#
from machine import SoftI2C,Pin
from micropython import const
import time
from time import sleep


# Définir les broches SCL et SDA pour le bus I2C
scl = Pin(22)
sda = Pin(21)

# Créer un objet I2C
i2c = SoftI2C(scl=scl, sda=sda, freq=400000)
"""
# Scanner le bus I2C et afficher les adresses trouvées
adresses_trouvees = i2c.scan()
print("Adresses I2C trouvées :")
for adresse in adresses_trouvees:
    print(f"  - Adresse décimale : {adresse}")
    print(f"  - Adresse hexadécimale : {hex(adresse)}")
#
"""

# Adresse I2C du INA3221
INA3221_ADDR = 0x40

# Registres
CONFIG_REG = 0x00
BUS_VOLTAGE_CH = (None, const(0x02), const(0x04), const(0x06))

BUS_ADC_LSB = 0.008             # VBus ADC LSB is 8mV

class INA3221:
    def __init__(self,
                 scl=22,
                 sda=21,
                 CHen="111"):
        # Définir les broches SCL et SDA pour le bus I2C
        pscl = Pin(scl)
        psda = Pin(sda)
        self.i2c = SoftI2C(scl=pscl, sda=psda, freq=400000)
        self.config(CHen[0],CHen[1],CHen[2])

    def scan(self):
        # Scanner le bus I2C et afficher les adresses trouvées
        adresses_trouvees = self.i2c.scan()
        print("Adresses I2C trouvées :")
        for adresse in adresses_trouvees:
            print(f"  - Adresse décimale : {adresse}")
            print(f"  - Adresse hexadécimale : {hex(adresse)}")

    def config(self,cH1en=1,cH2en=1,cH3en=1,):
        RST   = "0" #15
        CH1en = str(cH1en) #14 
        CH2en = str(cH2en) #13
        CH3en = str(cH3en) #12
        AVG   = "000" #11-9 Average
        VBUSCT= "001" #8-6 Conv. Time
        VSHCT = "000" #5-3 Conv. Time
        MODE  = "110" #2-0 
        config_value = RST+CH1en+CH2en+CH3en+AVG+VBUSCT+VSHCT+MODE
        #print(config_value)
        config_value = self.bin_to_int(config_value)
        self.i2c.writeto_mem(INA3221_ADDR, CONFIG_REG, config_value.to_bytes(2, 'big'))

    def read_config(self):
        reg = self.i2c.readfrom_mem(INA3221_ADDR,CONFIG_REG , 2)
        reg = int.from_bytes(reg, 'big')
        reg = hex(reg)
        print("conf: ",reg)

    def bin_to_int(self,strbin):
        sum = 0
        puis = len(strbin)-1
        for i,c in enumerate(strbin):
            #print(i,c)
            sum+= 2**(puis-i)*int(c)
        #a=hex(sum)
        #print(a)
        return sum

    
    def voltmeter(self, channel=1):
        """Returns the channel's bus voltage in Volts"""
        assert 1 <= channel <= 3, "channel argument must be 1, 2, or 3"
        value_reg = self.i2c.readfrom_mem(INA3221_ADDR, BUS_VOLTAGE_CH[channel] , 2)
        bus_voltage = int.from_bytes(value_reg, 'big') >> 3  # Conversion en 13 bits
        #print(bus_voltage)
        # convert to volts - LSB = 8mV
        return bus_voltage * BUS_ADC_LSB

ina = INA3221(CHen="101")
#ina.scan()
#ina.read_config()
while True:
    v1 = ina.voltmeter(3)
    print(v1)
    sleep(1)
    break


# imports
from micropython import const

__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/neaxi/MicroPython_INA3221"

# pylint: disable=bad-whitespace

_DEFAULT_ADDRESS                 = const(0x40)

#
# Registers and bits definitions
#

# Config register
C_REG_CONFIG                      = const(0x00)

C_RESET                           = const(0x8000)
C_ENABLE_CH                       = (None,const(0x4000),const(0x2000),const(0x1000)) # default set

C_AVERAGING_MASK                  = const(0x0E00)
C_AVERAGING_NONE                  = const(0x0000)     # 1 sample, default
C_AVERAGING_4_SAMPLES             = const(0x0200)
C_AVERAGING_16_SAMPLES            = const(0x0400)
C_AVERAGING_64_SAMPLES            = const(0x0600)
C_AVERAGING_128_SAMPLES           = const(0x0800)
C_AVERAGING_256_SAMPLES           = const(0x0A00)
C_AVERAGING_512_SAMPLES           = const(0x0C00)
C_AVERAGING_1024_SAMPLES          = const(0x0E00)

C_VBUS_CONV_TIME_MASK             = const(0x01C0)
C_VBUS_CONV_TIME_140US            = const(0x0000)
C_VBUS_CONV_TIME_204US            = const(0x0040)
C_VBUS_CONV_TIME_332US            = const(0x0080)
C_VBUS_CONV_TIME_588US            = const(0x00C0)
C_VBUS_CONV_TIME_1MS              = const(0x0100)     # 1.1ms, default
C_VBUS_CONV_TIME_2MS              = const(0x0140)     # 2.116ms
C_VBUS_CONV_TIME_4MS              = const(0x0180)     # 4.156ms
C_VBUS_CONV_TIME_8MS              = const(0x01C0)     # 8.244ms

C_SHUNT_CONV_TIME_MASK            = const(0x0038)
C_SHUNT_CONV_TIME_140US           = const(0x0000)
C_SHUNT_CONV_TIME_204US           = const(0x0008)
C_SHUNT_CONV_TIME_332US           = const(0x0010)
C_SHUNT_CONV_TIME_588US           = const(0x0018)
C_SHUNT_CONV_TIME_1MS             = const(0x0020)     # 1.1ms, default
C_SHUNT_CONV_TIME_2MS             = const(0x0028)     # 2.116ms
C_SHUNT_CONV_TIME_4MS             = const(0x0030)     # 4.156ms
C_SHUNT_CONV_TIME_8MS             = const(0x0038)     # 8.244ms

C_MODE_MASK                       = const(0x0007)
C_MODE_POWER_DOWN                 = const(0x0000)     # Power-down
C_MODE_SHUNT_VOLTAGE_TRIGGERED    = const(0x0001)     # Shunt voltage, single-shot (triggered)
C_MODE_BUS_VOLTAGE_TRIGGERED      = const(0x0002)     # Bus voltage, single-shot (triggered)
C_MODE_SHUNT_AND_BUS_TRIGGERED    = const(0x0003)     # Shunt and bus, single-shot (triggered)
C_MODE_POWER_DOWN2                = const(0x0004)     # Power-down
C_MODE_SHUNT_VOLTAGE_CONTINUOUS   = const(0x0005)     # Shunt voltage, continous
C_MODE_BUS_VOLTAGE_CONTINUOUS     = const(0x0006)     # Bus voltage, continuous
C_MODE_SHUNT_AND_BUS_CONTINOUS    = const(0x0007)     # Shunt and bus, continuous (default)

# Other registers
C_REG_SHUNT_VOLTAGE_CH            = (None, const(0x01), const(0x03), const(0x05))
C_REG_BUS_VOLTAGE_CH              = (None, const(0x02), const(0x04), const(0x06))
C_REG_CRITICAL_ALERT_LIMIT_CH     = (None, const(0x07), const(0x09), const(0x0B))
C_REG_WARNING_ALERT_LIMIT_CH      = (None, const(0x08), const(0x0A), const(0x0C))
C_REG_SHUNT_VOLTAGE_SUM           = const(0x0D)
C_REG_SHUNT_VOLTAGE_SUM_LIMIT     = const(0x0E)

# Mask/enable register
C_REG_MASK_ENABLE                 = const(0x0F)
C_SUM_CONTROL_CH                  = (None,const(0x4000),const(0x2000),const(0x1000)) # def. not set
C_WARNING_LATCH_ENABLE            = const(0x0800)     # default not set
C_CRITICAL_LATCH_ENABLE           = const(0x0400)     # default not set
C_CRITICAL_FLAG_CH                = (None,const(0x0200),const(0x0100),const(0x0080))
C_SUM_ALERT_FLAG                  = const(0x0040)
C_WARNING_FLAG_CH                 = (None,const(0x0020),const(0x0010),const(0x0008))
C_POWER_ALERT_FLAG                = const(0x0004)
C_TIMING_ALERT_FLAG               = const(0x0002)
C_CONV_READY_FLAG                 = const(0x0001)

# Other registers
C_REG_POWER_VALID_UPPER_LIMIT     = const(0x10)
C_REG_POWER_VALID_LOWER_LIMIT     = const(0x11)
C_REG_MANUFACTURER_ID             = const(0xFE)
C_REG_DIE_ID                      = const(0xFF)

# Constants for manufacturer and device ID
C_MANUFACTURER_ID                 = const(0x5449)     # "TI"
C_DIE_ID                          = const(0x3220)

# General constants
C_BUS_ADC_LSB                     = 0.008             # VBus ADC LSB is 8mV
C_SHUNT_ADC_LSB                   = 0.00004           # VShunt ADC LSB is 40µV


class INA3221:
    """Driver class for Texas Instruments INA3221 3 channel current sensor device"""

    IS_FULL_API = True

    @staticmethod
    def _to_signed(val):
        if val > 32767:
            return val - 65536
        return val

    @staticmethod
    def _to_unsigned(val):
        if val < 0:
            return val + 65536
        return val

    def write(self, reg, value):
        """Write value in device register"""
        seq = bytearray([reg, (value >> 8) & 0xFF, value & 0xFF])
        print(reg,value,seq)
        self.i2c_device.write(seq)

    def read(self, reg):
        """Return value from device register"""
        buf = bytearray(3)
        buf[0] = reg
        self.write_then_readinto(buf, buf, out_end=1, in_start=1)
        value = (buf[1] << 8) | (buf[2])
        return value

    def update(self, reg, mask, value):
        """Read-modify-write value in register"""
        regvalue = self.read(reg)
        regvalue &= ~mask
        value &= mask
        self.write(reg, regvalue | value)

    def writeto_then_readfrom(
        self,
        address,
        buffer_out,
        buffer_in,
        *,
        out_start=0,
        out_end=None,
        in_start=0,
        in_end=None,
        stop=False
    ):
        """Write data from buffer_out to an address and then
        read data from an address and into buffer_in
        """
        if out_end:
            self.i2c_device.writeto(address, buffer_out[out_start:out_end], stop)
        else:
            self.i2c_device.writeto(address, buffer_out[out_start:], stop)

        if not in_end:
            in_end = len(buffer_in)
        read_buffer = memoryview(buffer_in)[in_start:in_end]
        self.i2c_device.readfrom_into(address, read_buffer, stop)
        

    def write_then_readinto(
        self,
        out_buffer,
        in_buffer,
        *,
        out_start=0,
        out_end=None,
        in_start=0,
        in_end=None
    ):
        """
        Write the bytes from ``out_buffer`` to the device, then immediately
        reads into ``in_buffer`` from the device. The number of bytes read
        will be the length of ``in_buffer``.

        If ``out_start`` or ``out_end`` is provided, then the output buffer
        will be sliced as if ``out_buffer[out_start:out_end]``. This will
        not cause an allocation like ``buffer[out_start:out_end]`` will so
        it saves memory.

        If ``in_start`` or ``in_end`` is provided, then the input buffer
        will be sliced as if ``in_buffer[in_start:in_end]``. This will not
        cause an allocation like ``in_buffer[in_start:in_end]`` will so
        it saves memory.

        :param bytearray out_buffer: buffer containing the bytes to write
        :param bytearray in_buffer: buffer containing the bytes to read into
        :param int out_start: Index to start writing from
        :param int out_end: Index to read up to but not include; if None, use ``len(out_buffer)``
        :param int in_start: Index to start writing at
        :param int in_end: Index to write up to but not include; if None, use ``len(in_buffer)``
        """
        if out_end is None:
            out_end = len(out_buffer)
        if in_end is None:
            in_end = len(in_buffer)

        self.writeto_then_readfrom(
            self.i2c_addr,
            out_buffer,
            in_buffer,
            out_start=out_start,
            out_end=out_end,
            in_start=in_start,
            in_end=in_end,
        )


    def __init__(self, i2c_instance, i2c_addr = _DEFAULT_ADDRESS, shunt_resistor = (0.1, 0.1, 0.1)):
        self.i2c_device = i2c_instance
        self.i2c_addr = i2c_addr
        self.shunt_resistor = shunt_resistor
        #self.write(C_REG_CONFIG, C_AVERAGING_NONE | \
        #           C_VBUS_CONV_TIME_1MS | \
        #           C_MODE_BUS_VOLTAGE_CONTINUOUS  )

        self.write(C_REG_CONFIG, C_MODE_BUS_VOLTAGE_CONTINUOUS  )


    def is_channel_enabled(self, channel=1):
        """Returns if a given channel is enabled or not"""
        assert 1 <= channel <= 3, "channel argument must be 1, 2, or 3"
        bit = C_ENABLE_CH[channel]
        return self.read(C_REG_CONFIG) & bit != 0

    def enable_channel(self, channel=1, enable=True):
        """Enables or disable a given channel"""
        assert 1 <= channel <= 3, "channel argument must be 1, 2, or 3"
        bit = C_ENABLE_CH[channel]
        value = 0
        if enable:
            value = bit
        self.update(C_REG_CONFIG, bit, value)

    def shunt_voltage(self, channel=1):
        """Returns the channel's shunt voltage in Volts"""
        assert 1 <= channel <= 3, "channel argument must be 1, 2, or 3"
        value = self._to_signed(self.read(C_REG_SHUNT_VOLTAGE_CH[channel])) / 8.0
        # convert to volts - LSB = 40uV
        return value * C_SHUNT_ADC_LSB

    def current(self, channel=1):
        """Return's the channel current in Amps"""
        assert 1 <= channel <= 3, "channel argument must be 1, 2, or 3"
        return self.shunt_voltage(channel) / self.shunt_resistor[channel-1]

    def bus_voltage(self, channel=1):
        """Returns the channel's bus voltage in Volts"""
        assert 1 <= channel <= 3, "channel argument must be 1, 2, or 3"
        value = self._to_signed(self.read(C_REG_BUS_VOLTAGE_CH[channel])) / 8
        # convert to volts - LSB = 8mV
        return value * C_BUS_ADC_LSB

    def shunt_critical_alert_limit(self, channel=1):
        """Returns the channel's shunt voltage critical alert limit in Volts"""
        assert 1 <= channel <= 3, "channel argument must be 1, 2, or 3"
        value = self._to_signed(self.read(C_REG_CRITICAL_ALERT_LIMIT_CH[channel])) / 8
        # convert to volts - LSB = 40uV
        return value * C_SHUNT_ADC_LSB

    def set_shunt_critical_alert_limit(self, channel, voltage):
        """Sets the channel's shunt voltage critical alert limit in Volts"""
        assert 1 <= channel <= 3, "channel argument must be 1, 2, or 3"
        value = self._to_unsigned(round(voltage * C_SHUNT_ADC_LSB) * 8)
        self.write(C_REG_CRITICAL_ALERT_LIMIT_CH[channel], value)

    def shunt_warning_alert_limit(self, channel=1):
        """Returns the channel's shunt voltage warning alert limit in Volts"""
        assert 1 <= channel <= 3, "channel argument must be 1, 2, or 3"
        value = self._to_signed(self.read(C_REG_WARNING_ALERT_LIMIT_CH[channel])) / 8
        # convert to volts - LSB = 40uV
        return value * C_SHUNT_ADC_LSB

    def set_shunt_warning_alert_limit(self, channel, voltage):
        """Sets the channel's shunt voltage warning alert limit in Volts"""
        assert 1 <= channel <= 3, "channel argument must be 1, 2, or 3"
        value = self._to_unsigned(round(voltage * C_SHUNT_ADC_LSB) * 8)
        self.write(C_REG_WARNING_ALERT_LIMIT_CH[channel], value)

    @property
    def is_ready(self):
        """Returns the CVRF (ConVersion Ready Flag) from the mask/enable register """
        regvalue = self.read(C_REG_MASK_ENABLE)
        print(regvalue)
        test =  (regvalue & C_CONV_READY_FLAG) != 0x0
        print(test)
        return test
    
import sys
from machine import Pin, SoftI2C
#from ina3221 import *

ina = INA3221(i2c)
ina.enable_channel(3)
volt = ina.bus_voltage(3)
print(volt)


from machine import I2C, Pin

 


# Initialisation de l'I2C
i2c = I2C(1, scl=Pin(22), sda=Pin(21), freq=100000)

# Adresse I2C du INA3221
INA3221_ADDR = 0x40

def int_to_binary(num):
  if num == 0:
    return "0"

  binary_string = ""
  while num > 0:
    remainder = num % 2
    binary_string = str(remainder) + binary_string
    num //= 2
  return binary_string

 

def bin_to_int(strbin):
    sum = 0
    puis = len(strbin)-1
    for i,c in enumerate(strbin):
        #print(i,c)
        sum+= 2**(puis-i)*int(c)
    a=hex(sum)
    print(a)
    return sum

 


RST   = "0" #15
CH1en = "1" #14 
CH2en = "0" #13
CH3en = "1" #12
AVG   = "000" #11-9
VBUSCT= "001" #8-6
VSHCT = "000" #5-3
MODE  = "110" #2-0
config_value = RST+CH1en+CH2en+CH3en+AVG+VBUSCT+VSHCT+MODE
#print(config_value)
#config_value = bin_to_int(config_value)

# Registres
CONFIG_REG = 0x00
BUS_VOLTAGE_REG_CH1 = 0x06
"""
# Configuration du registre de configuration
#config_value = 0x5006  # Exemple de valeur de configuration
#print(config_value)
#config_value = C_RESET
#print(len(config_value))
i2c.writeto_mem(INA3221_ADDR, CONFIG_REG, config_value.to_bytes(2, 'big'))

reg = i2c.readfrom_mem(INA3221_ADDR,CONFIG_REG , 2)
#reg = int.from_bytes(reg, 'big') >> 3  # Conversion en 13 bits
reg = int.from_bytes(reg, 'big')
reg = hex(reg)
print("a",reg)


while True:
    # Lecture de la tension de bus du canal 1
    bus_voltage_raw = i2c.readfrom_mem(INA3221_ADDR, BUS_VOLTAGE_REG_CH1, 2)
    reg = int.from_bytes(bus_voltage_raw, 'big')
    print(reg)
    binary = int_to_binary(reg)
    print(binary)
    binary = binary[:-3]
    print(binary)
    volt = bin_to_int(binary)
    print(volt)
    print(volt*0.008)

 

    bus_voltage = int.from_bytes(bus_voltage_raw, 'big') >> 3  # Conversion en 13 bits
    print(bus_voltage)
    bus_voltage *= 0.008  # Conversion en volts (1 LSB = 8 mV)

    print("Tension de bus du canal 1 : {:.3f} V".format(bus_voltage))
    time.sleep(2)
    break
"""

 

En poursuivant votre navigation sur mon site, vous acceptez l’utilisation des Cookies et autres traceurs  pour réaliser des statistiques de visites et enregistrer sur votre machine vos activités pédagogiques. En savoir plus.