Interfacing MCP4661 digital potentio with python using T7 board | LabJack
 

Interfacing MCP4661 digital potentio with python using T7 board

4 posts / 0 new
Last post
Jimmy Andrianto
JimmyAndrianto's picture
Interfacing MCP4661 digital potentio with python using T7 board

Hi everyone,

 

I try to read and write the digital potentio (MCP4661) using T7 and LJM_2019_04_03, the communication is use i2c. with same setting, i has done to comunicate with other chip (PCF8574 expander i/o). Its somebody has experience with MCP4661? 

Please find my code, screen capture of my output result (t7_i2c_mcp4661.png) and some digital logic analyzer at attached.

What i make it strange is:

1. On first code after initialize, i try to write volatile register of Wiper0 and Wiper1. The Wiper value is change when i read using ohm meter. But the sum of ACK is bigger then my expectation, its print out 31. I am write 4 byte and without read, it must be 4 ACK right? see my logic analyzer screen capture (i2c_t7_mcp4661_1.png)

2. on second block, i try to read, write and read again the non volatile memory. On first read, i got value is 1 with sum of ACK is 3. i read only 1 byte but i got 3 ACK (i2c_t7_mcp4661_2.png). After that i write the new value (i has try to change the value for enable and disable, but no change) = 0x28, 0x38, 0xF8. on here, i got ACK is 8 and on my logic analyzer, first and second byte is have NACK (i2c_t7_mcp4661_3.png). After that i try to read the register again, the value is not change, is still 1 with ACK is 3 (i2c_t7_mcp4661_4.png)

3. on third block i try to read out all register. the value what i get is strange only 0 or 192 with ACK is only 3

4. on last block i try to write 4 bytes the non volatile register. What i make it doubt, the ACK is 28. And after restart power, the wiper is not change to my new value. The wiper is still on factory value, on midle

 

Its any my code is mistake? i hope i can get help on this forum. Many thanks

Jimmy Andrianto
JimmyAndrianto's picture
Hi everyone,

Hi everyone,

i found my mistake for item 3. When i am read out all register, i am not yet prepare the variable for 32 byte array. I has add it but the result all value is 0 with ACK is only 3. See my attached file

I am very appreciate if you can suggest me what i need to try it as solution. Many thanks

LabJack Support
labjack support's picture
There aren't any LabJack'ers

There aren't any LabJack'ers who are currently experts regarding your particular I2C chip.  Good news on you solving your mistake for number 3.  

It looks like your issue may be due to not properly dynamically allocating an array in python.

Jimmy Andrianto
JimmyAndrianto's picture
SOLVE

SOLVE

 

when need to write or read, its ok when read/write every 1 register address. Here my code for testing

"""
Demonstrates I2C communication using a LabJack. The demonstration uses a
MCP4661 connected to FIO0/FIO1 for the T7 or FIO4/FIO5 for the T4, and
configures the I2C settings. Then a read, write the Digital Potentio
registered.

"""
from random import randrange

from labjack import ljm
import time

# Open first found LabJack
#handle = ljm.openS("ANY", "ANY", "ANY")  # Any device, Any connection, Any identifier
handle = ljm.openS("T7", "ANY", "192.168.3.7")  # T7 device, Any connection, Any identifier
#handle = ljm.openS("T4", "ANY", "ANY")  # T4 device, Any connection, Any identifier
#handle = ljm.open(ljm.constants.dtANY, ljm.constants.ctANY, "ANY")  # Any device, Any connection, Any identifier

info = ljm.getHandleInfo(handle)
print("Opened a LabJack with Device type: %i, Connection type: %i,\n"
      "Serial number: %i, IP address: %s, Port: %i,\nMax bytes per MB: %i" %
      (info[0], info[1], info[2], ljm.numberToIP(info[3]), info[4], info[5]))

deviceType = info[0]

# Configure the I2C communication.
if deviceType == ljm.constants.dtT4:
    # Configure FIO4 and FIO5 as digital I/O.
    ljm.eWriteName(handle, "DIO_INHIBIT", 0xFFFCF)
    ljm.eWriteName(handle, "DIO_ANALOG_ENABLE", 0x00000)

    # For the T4, using FIO4 and FIO5 for SCL and SDA pins. FIO0 to FIO3 are
    # reserved for analog inputs, and digital lines are required.
    ljm.eWriteName(handle, "I2C_SDA_DIONUM", 5)  # SDA pin number = 5 (FIO5)
    ljm.eWriteName(handle, "I2C_SCL_DIONUM", 4)  # SCL pin number = 4 (FIO4)
else:
    # For the T7 and other devices, using FIO0 and FIO1 for the SCL and SDA
    # pins.
    ljm.eWriteName(handle, "I2C_SDA_DIONUM", 1)  # SDA pin number = 1 (FIO1)
    ljm.eWriteName(handle, "I2C_SCL_DIONUM", 0)  # SCL pin number = 0 (FIO0)

# Speed throttle is inversely proportional to clock frequency. 0 = max.
ljm.eWriteName(handle, "I2C_SPEED_THROTTLE", 65536) #65516)  # Speed throttle = 65516 (~100 kHz)

# Options bits:
#    bit 0: 1 = Reset the I2C bus before attempting communication.
#    bit 1: 0 = Restarts will use a stop and a start, 1 = Restarts will not use a stop.
#    bit 2: 1 = disable clock stretching.
ljm.eWriteName(handle, "I2C_OPTIONS", 2)

# ---------------------------------------- MCP4661 ----------------------------------------
# value : 0 --> Raw = 8k8, Rbw = 93ohm
# value : 255 --> Raw = 131ohm, Rbw = 8k8
# Ra --vvv- Rw -vvv-- Rb

print("\n--- MCP4661 - Digital Potensio ---\n")

# labjack.com/support/datasheets/t-series/digital-io/i2c/i2c-simulation-tool
# Ad3_Ad2_Ad1_Ad0__A2(pin 12)_A1(pin 13)_A0(pin 1)_x
# I2C address need to right shift 1 bit (ox52 >> 1 = 0x29)
addwDigPot = 0x29

ljm.eWriteName(handle, "I2C_SLAVE_ADDRESS", addwDigPot) 

# Memory map address
aregVolWiper0 = 0
aregVolWiper1 = 1
aregNonVolWiper0 = 2
aregNonVolWiper1 = 3
aregTCON = 4
aregStatus = 5
aregWP = 0xF

def prReg(addReg):
    if addReg == aregVolWiper0:
        print(" Wiper 0\n")
    elif addReg == aregVolWiper1:
        print(" Wiper 1\n")
    elif addReg == aregNonVolWiper0:
        print(" Wiper Lock 0\n")
    elif addReg == aregNonVolWiper1:
        print(" Wiper Lock 1\n")
    elif addReg == aregTCON:
        print(" TCON\n")
    elif addReg == aregStatus:
        print(" Status\n")
    elif addReg == aregWP:
        print(" Write Protect\n")
    else:
        print(" - Unknown Register: %i\n" % addReg)
    
def mcpWrite(addReg, wVal):
    b1 = (addReg << 4) | 0
    tmpW = (wVal & 0x0100) / 256
    b1 |= tmpW
    b2 = wVal & 0x00FF

    numBytesTx = 2
    numBytesRx = 0
    aBytes = [b1, b2]
    #print("Write : ")
    prReg(addReg)
    print("%s" %  " ".join([("%.0f" % val) for val in aBytes]))
    ljm.eWriteName(handle, "I2C_NUM_BYTES_TX", numBytesTx)  # Set the number of bytes to transmit
    ljm.eWriteName(handle, "I2C_NUM_BYTES_RX", numBytesRx)  # Set the number of bytes to receive
    ljm.eWriteNameByteArray(handle, "I2C_DATA_TX", numBytesTx, aBytes)
    ljm.eWriteName(handle, "I2C_GO", 1)  # Do the I2C communications.

    aBytes = ljm.eReadNameByteArray(handle, "I2C_DATA_RX", numBytesRx)
    jmlhack = ljm.eReadName(handle, "I2C_ACKS")
    print("Jmlh ACK: %i\n" % jmlhack)

def mcpRead(addReg):
    b1 = (addReg << 4) | 0x0C

    numBytesTx = 1
    numBytesRx = 2
    aBytes = [b1, 0]
    
    #print("%s" %  " ".join([("%.0f" % val) for val in aBytes]))
    ljm.eWriteName(handle, "I2C_NUM_BYTES_TX", numBytesTx)  # Set the number of bytes to transmit
    ljm.eWriteName(handle, "I2C_NUM_BYTES_RX", numBytesRx)  # Set the number of bytes to receive
    ljm.eWriteNameByteArray(handle, "I2C_DATA_TX", numBytesTx, aBytes)
    aBytes = [0] * numBytesRx
    aBytes = ljm.eReadNameByteArray(handle, "I2C_DATA_RX", numBytesRx)
    ljm.eWriteName(handle, "I2C_GO", 1)  # Do the I2C communications.

    tmpW = (aBytes[0] << 8) + aBytes[1]
    print("read %i bytes = %s" %
        (numBytesRx, " ".join([("%.0f" % val) for val in aBytes])))
    jmlhack = ljm.eReadName(handle, "I2C_ACKS")
    print("Jmlh ACK: %i\n" % jmlhack)
    print("tmpW: %i\n" % tmpW)
    return tmpW

def mcpUp(addReg):
    b1 = (addReg << 4) | 0x04
    
    numBytesTx = 1
    numBytesRx = 0
    aBytes = [b1]
    
    print("Incr ")
    prReg(addReg)
    ljm.eWriteName(handle, "I2C_NUM_BYTES_TX", numBytesTx)  # Set the number of bytes to transmit
    ljm.eWriteName(handle, "I2C_NUM_BYTES_RX", numBytesRx)  # Set the number of bytes to receive
    ljm.eWriteNameByteArray(handle, "I2C_DATA_TX", numBytesTx, aBytes)

    ljm.eWriteName(handle, "I2C_GO", 1)  # Do the I2C communications.
    aBytes = ljm.eReadNameByteArray(handle, "I2C_DATA_RX", numBytesRx)

    jmlhack = ljm.eReadName(handle, "I2C_ACKS")
    print("Jmlh ACK: %i\n" % jmlhack)

def mcpDown(addReg):
    b1 = (addReg << 4) | 0x08
    
    numBytesTx = 1
    numBytesRx = 0
    aBytes = [b1]

    print("Decr ")
    prReg(addReg)
    ljm.eWriteName(handle, "I2C_NUM_BYTES_TX", numBytesTx)  # Set the number of bytes to transmit
    ljm.eWriteName(handle, "I2C_NUM_BYTES_RX", numBytesRx)  # Set the number of bytes to receive
    ljm.eWriteNameByteArray(handle, "I2C_DATA_TX", numBytesTx, aBytes)

    ljm.eWriteName(handle, "I2C_GO", 1)  # Do the I2C communications.
    aBytes = ljm.eReadNameByteArray(handle, "I2C_DATA_RX", numBytesRx)

    jmlhack = ljm.eReadName(handle, "I2C_ACKS")
    print("Jmlh ACK: %i\n" % jmlhack)

# ------------------------- Write Volatile Memory Add (0h, 1h, 4h) -------------------------
# AD3 AD2 AD1 AD0  Cmd1 Cmd0 x D8 --> 4 bit pd hight byte sbg Address memory map, 
# Cmd1:0 = 00 --> Write
# Cmd1:0 = 01 --> Increment
# Cmd1:0 = 10 --> Decrement
# Cmd1:0 = 11 --> Read
# Volatile Wiper0 (00h) = 0xC0
# Volatile Wiper1 (10h) = 0x80
# Volatile TCON (40h) = no change

print("\n--- MCP4661 - Increment Volatile Wiper0 & Decrement Wiper1 ---\n")
# change to new value
newval = 0
print("Wiper0 change to midle value")
mcpWrite(aregVolWiper0, newval)
time.sleep(3)
print("Wiper1 change to midle value")
mcpWrite(aregVolWiper1, newval)
time.sleep(3)

# Step by step (incr/decr)
print("incr/decr step by step every second")
for i in range(10):
    mcpUp(aregVolWiper0)
    mcpUp(aregVolWiper1)
    time.sleep(1)

# ----------------------- Read Status Register (5h + cmd1:0=Ch --> 5Ch) -----------------------
# x x x x  EEWA WL1 WL0 WP
# EEWA --> EEPROM Write Active status bit (1 = Write cycling is currently occuring)
# WL1  --> WiperLock Status bit for Resistor Network 1 (1 = Write protected)
# WL0  --> WiperLock Status bit for Resistor Network 0 (1 = Write protected)
# WP   --> EEPROM Write Protect Status bit (1 = EEPROM Write protected)
wTCON = mcpRead(aregTCON)
print("Read TCON Register \n")
wStatus = mcpRead(aregStatus)
print("Read Status Register \n")
print("TCON: %i , Status: %i \n" % (wTCON, wStatus))

# ----------------------- Disable WL0, WL1, WP -----------------------
# Add   DecrCmd(x8h)   IncrCmd(x4h)
# 2xh   WL0 Enable     WL0 disabled
# 3xh    WL1 Enable     WL1 disabled
# Fxh   WP Enabled     WP disabled

print("\n--- MCP4661 - DISABLE WL0, WL1, WP ---\n")
mcpUp(aregNonVolWiper0)
mcpUp(aregNonVolWiper1)
mcpUp(aregWP)

# ----------------------- Read Status Register (5h + cmd1:0=Ch --> 5Ch) -----------------------
# x x x x  EEWA WL1 WL0 WP
# EEWA --> EEPROM Write Active status bit (1 = Write cycling is currently occuring)
# WL1  --> WiperLock Status bit for Resistor Network 1 (1 = Write protected)
# WL0  --> WiperLock Status bit for Resistor Network 0 (1 = Write protected)
# WP   --> EEPROM Write Protect Status bit (1 = EEPROM Write protected)
wTCON = mcpRead(aregTCON)
print("Read TCON Register \n")
wStatus = mcpRead(aregStatus)
print("Read Status Register \n")
print("TCON: %i , Status: %i \n" % (wTCON, wStatus))

# ----------------------- WRITE Non Volatile Wiper0 (20h) & Wiper1 (30h) -----------------------

print("\n--- MCP4661 - Write Non Volatile ---\n")

newval = 128
mcpWrite(aregNonVolWiper0, newval)
print("--- Write Non Volatile Wiper0 = %i" % newval)
wpr = mcpRead(aregNonVolWiper0)
print("    Read Wiper0: %i\n" % wpr)
mcpWrite(aregNonVolWiper1, newval)
print("--- Write Non Volatile Wiper1 = %i" % newval)
wpr = mcpRead(aregNonVolWiper1)
print("    Read Wiper1: %i\n" % wpr)

# ----------------------- Enable WL0, WL1, WP -----------------------
# Add   DecrCmd(x8h)   IncrCmd(x4h)
# 2xh   WL0 Enable     WL0 disabled
# 3xh    WL1 Enable     WL1 disabled
# Fxh   WP Enabled     WP disabled

print("\n--- MCP4661 - ENABLE WL0, WL1, WP ---\n")
mcpDown(aregNonVolWiper0)
mcpDown(aregNonVolWiper1)
mcpDown(aregWP)

# ----------------------- Read Status Register (5h + cmd1:0=Ch --> 5Ch) -----------------------
# x x x x  EEWA WL1 WL0 WP
# EEWA --> EEPROM Write Active status bit (1 = Write cycling is currently occuring)
# WL1  --> WiperLock Status bit for Resistor Network 1 (1 = Write protected)
# WL0  --> WiperLock Status bit for Resistor Network 0 (1 = Write protected)
# WP   --> EEPROM Write Protect Status bit (1 = EEPROM Write protected)
wTCON = mcpRead(aregTCON)
print("Read TCON Register \n")
wStatus = mcpRead(aregStatus)
print("Read Status Register \n")
print("TCON: %i , Status: %i \n" % (wTCON, wStatus))

# ----------------------- Read all memory map -----------------------

print("\n--- MCP4661 - Read all memory map ---\n")

numBytesRx = 16
aWord = [0] * numBytesRx
x = 0
for x in range(16):
    aWord[x] = mcpRead(x)

print("read %i bytes = %s" %
    (len(aWord), " ".join([("%.0f" % val) for val in aWord])))

print("\n--- Please try unplug & plug the USB connector and see the wiper value ---\n")

# Close handle
ljm.close(handle)