Jump to content
  • 0

I2C SubAddress not working properly in the Script Tool


Jonboy

Question

I have been having difficulty getting a simple script setup  in the Script Tool to read and write a sequence of registers to a device through I2C on my Analog Discovery 2. Most of the I2C configuration commands that correlate to the manual controls on the Protocol I2C window such as SCL, SDA pins assignments, Frequency, Address, ReadBytes, and WriteBytes are working properly. 

However, the SubAddress does not seem to be functioning properly and does not update from the script like the other parameters.  Perhaps there is a different function call or parameter to set instead of what I am trying to do.  The last line of the following code is how I would expect the SubAddress to be changed.  This code executes without error, but doesn't update the parameter.  For example, If I set the Device Address value to 0x00 and the Sub Address (my device's register address to read) value to 0x01, then execute this script, I see the Address field of the Protocol tool change to 0x48, but the SubAddress field stays set to 0x01 when I expected it would be change to 0x02.

Protocol.I2C.Mode.value = 1;                       //Set the I2C Protocol tool into Master Mode
Protocol.I2C.SCL.value = 0;                        //Set the SCL pin to be DIO 0
Protocol.I2C.SDA.value = 1;                        //Set the SDA pin to be DIO 1
Protocol.I2C.SCL.Frequency.value = 100000;         //Set the SCL clock frequency to 100 kHz
Protocol.I2C.Clockstretching.enable = 1;           //Enable Clock Stretching
Protocol.I2C.ReadBytes.value = 1;                  //Set the Read Bytes number to 1 for reading one byte of data
Protocol.I2C.WriteBytes.value = 1;                 //Set the Write Bytes number to 1 for writing one byte of data
Protocol.I2C.Address.value = 0x48;                 //Set the I2C Protocol Device Address

//The following line of code executes but does not actually change the SubAddress parameter
Protocol.I2C.SubAddress.value = 0x02;              //Set the SubAddress (Device register address)

Unfortunately there is no scripting information provided in the Help Reference Document for the Protocol tool, or any example code files for basic I2C (or SPI scripts) that simply read and write registers.  But if I look at the I2C Custom scripting as an example, I would assume the commands for the Script Tool would be similar.  There are 3 read functions available:

// 1.)Read(address) --> returns true when acknowledged otherwise false

Protocol.I2C.Read(0x48)   
//Returns true for me

// 2.) Read(address, count of bytes) --> returns the read bytes array

Protocol.I2C.Read(0x48, 1) 
//Returns the value of the register corresponding the the GUI's SubAddress that was manually entered on the Protocol page, but not the script assignment

// 3.) Read(address, [sub address byte1, byte 2,...], count of bytes) --> writes the subaddress bytes, repeated starts to read data bytes returns the read data bytes array

Protocol.I2C.Read(0x48, 0x01, 1) 
//I would expect I could read one byte from register 0x01 of device 0x48.  however, this function doesn't work properly.  Is this the proper way to read a single 8-bit register?  Since the SubAddress can't be set through the script, I hoped this would allow me to read the register value without having to manually changing the SubAddress in the GUI. 

Could you please check to see if the SubAddress commands are working properly between the Script and Protocol tools and/or explain the proper way to script the Protocol I2C tool for writing and reading 8-bit registers if I am not approaching this properly.  Thank You!

Link to comment
Share on other sites

5 answers to this question

Recommended Posts

I have used the I2C scripting with a sub address successfully, using the Protocol tool. My example was reading the SHT21, using this line:

var reg_humidity = Read(0x40, 0xE5, 3);

Note that this function is using 7-bit addresses. When you are able to talk with your I2C device successfully using the 'I2C Master' tool, you can use the settings there to write a script. From the documentation of the scripting in the I2C Protocol tool, it seems than Read(address, bytes) does not use the sub address specified in the tool (although I did not test this).

 

Link to comment
Share on other sites

Hi @Jonboy

You have in private message a beta version fixing the return value problem.

The I2C Read/Write functions are slightly different for the Script. For subaddress and write data it requires array.
In Read function the count and subaddress arguments are reverse order compared to Custom.

Protocol.I2C.Read(address, optional count of bytes, [optional array of subaddress])
Protocol.I2C.Read(0x40, 3, [0,1]) 
> Start, h80 [ h40 | WR ], h00, h01,
> Restart, h81 [ h40 | RD ], h39, h9F, h1E NAK, Stop

Protocol.I2C.Write(address, optional [array of data])
Protocol.I2C.Write(0x40, [0,1])
> Start, h80 [ h40 | WR ], h00, h01, Stop

Link to comment
Share on other sites

Hi @attila

Thank you for bug fix in the beta version and the additional information.  This helps a lot and I am able to read data through my script which is a big improvement.  I only have one additional point of confusion on how to write data to a subaddress.  There does not appear to be a parameter in the write function for the subaddress like there was in the read function. How do I write data to a particular subaddress through the script tool?

For example let's say I want to write a little script to work with a temp sensor (PN: TMP102) that has a device address set to 0x48 and four 2-byte registers with subaddresses 0-4.  From the protocol tool I can type in 0x48 into the "address" field, and the specific register number into the subaddress field (0-4), set the Bytes to read to "2", and click the Read button to return the two bytes of data from that particular register.  I can also write to this specific subaddress in the same way.  To read/write a different register, I simply change the subaddress field to match the register I want to read or write.  (As a side note, the write bytes field is set to 1 byte and disabled in the beta version but the read bytes field is configurable which I don't understand or know if this is a bug or by design).

However, in the script tool, I don't have any control over the subadress field and therefore can't seem to write to a specific register.  As a specific example of something I would like to do, how could I read the contents of register (subaddress) 2, write a new value to register 2, and then read that register back to confirm the write was successful?

I would like to do something like the following:

// Read 2 bytes of data from device address 0x48, subaddress 2)

Protocol.I2C.Read(0x48, 2, [2]);   // Protocol.I2C.Read(address, optional count of bytes, [optioinal array of subaddress])

> Lets say it returns [0x4B, 0x00]

// I need help with the following write function but lets assume the following works

// Write 2 bytes of data [0x55, 0x00] to device address 0x48, subaddress 2

Protocol.I2C.Write(0x48, [0x55, 0x00], [2]);  // Protocol.I2C.Write(address, optional [array of data bytes to write], optional [array of subaddress])

// Read 2 bytes of data from device address 0x48, subaddress 2) to verify the write was successful and the register contains the value of the data we just wrote

Protocol.I2C.Read(0x48, 2, [2]);  //Read 2 bytes of data from device address 0x48, subaddress 2)

>> It should return [0x55, 0x00]

How do I alter the write function call in this example to target subaddress 2?  Thank You!

Link to comment
Share on other sites

Hi @Jonboy

Special sub-addressing is only required for read operations. In this process the sub-address write is followed by a restart and read.
https://www.i2c-bus.org/repeated-start-condition/
For write operations you can just concatenate the "sub-address" with the array of data you have to write.

var a = [1,2] // sub-address
var b = [3,4] // data
var c = a.concat(b)
Protocol.I2C.Write(0x48, c)

 

Link to comment
Share on other sites

Hi @attila

Thank you for your support and explanations.  Concatenating the sub-adress and data fields works and I am now able to read and write specific register at will. 

I had been approaching this from the thought that the Script tool was controlling the features of the Protocol tool.  Other parameters such as the Frequency, Read Bytes, etc. were updated through the script code when executed.  Since I have to set the sub-address field in the Protocol window when manually reading/writing bytes, I assumed that the sub-address must be treated as it's own parameter in the Script tool.  However, the sub-address never seemed to get updated and was causing me confusion.  Thanks again for for the detailed explanations on function calls.

 

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...