Sending 8 Bytes to a Chip over I2C - MAster Library ....

Gentlemen,

I’m really new in programming Arduino … but I need your help :wink:

I want to program this here …

Can somebody give me a tip?

I tried to setup an array with 8 bytes and used the I2c.write command …

Your help is appreciated :o

Regards from Germany

Hi, welcome to the forum.
Which chip is it ? Or is it a contest to see who finds the chip first ?
Is it a Semtech SX8636 ? That is a capacitive button controller with 8 outputs that can be used as led drivers.
http://www.semtech.com/touch-interface/capacitive-touch-controllers/sx8636/

Do you have some example code ?
The Wire.write() function writes to a i2c device : http://arduino.cc/en/Reference/WireWrite
You can write 8 bytes with that function.

byte buffer[8] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
Wire.write( buffer, 8);

Why do you use an (perhaps outdated?) I2C Master library ? and which one do you use ?

Hello Peter,

yes, it's a semtech SX8644 .... which I will use also as a LED-Driver ...

My code so far .....

The adress of the chip:

#define I2C_TouchControl             0x2B // SEMTECH SX8634 Capacitive Touch Button on Channel 0 of I2C Multiplexer

The SPM-Registers ....

int SpmCfg                  = 0x0D; //SPM Gateway ....
int ActivateSpmCfg          = 0x10; //activate SPM to set configuration
int ReadSpmCfg              = 0x18; // activate SPM Read Modus ....
int SpmBaseAdress           = 0x0E; // Register für die Startadresse .....
int TerminateSpmCfg         = 0x00;

int CompOpMode              = 0x09;
int SetModeActive           = 0x00;
int SetModeSleep            = 0x02;

The Array with the Control-Registers:

uint8_t BtnCfgAdr = 0x20;    //Startadresse Button Parameter
uint8_t SetBtnCfg[8]={0x00,  // 0x20:  Default
                      0x10,  // 0x21:  BtnCfg - 0x10 - Interrupt triggered by Touch
                      0x50,  // 0x22:  Default
                      0x50,  // 0x23:  Default
                      0x01,  // 0x24:  Default
                      0x0A,  // 0x25:  Default
                      0x00,  // 0x26:  Default
                      0x00}; // 0x27:  Default
uint8_t BtnCfg[8];

And here, the programming ....

Step 1:

 I2c.write(I2C_TouchControl, SpmCfg, ActivateSpmCfg); // Activate SPM WRITE - Modus

Works fine. Is doing what it should do .....

Step 2:

 I2c.write(I2C_TouchControl, SpmBaseAdress, BtnCfgAdr); // Set SPM Base Adress to ButtonConfigAdress 0x20 = #32 ....

Works fine. Is doing what it should do ..... BaseAdress is now 0x20.

Now Step 3: Writing the SetBtnCfg Array with the 8 control Registers - you can find above - to the start adress .....

 I2c.write(I2C_TouchControl, SpmBaseAdress, SetBtnCfg,8);

Then I terminate the configuration ....

 I2c.write(I2C_TouchControl, SpmCfg, TerminateSpmCfg); //Deactivate SPM Modus ......
 Serial.println("STEP 3: SPM - Konfiguration beendet  ........ ");
 I2c.write(I2C_TouchControl, 0x09, 0x02); //Sleep Mode
 delay(300);
 I2c.write(I2C_TouchControl, 0x09, 0x00); //Active Mode

And to control it, I read it out .....

 I2c.write(I2C_TouchControl, SpmCfg, ReadSpmCfg);
 I2c.write(I2C_TouchControl, SpmBaseAdress, BtnCfgAdr); // Set SPM Base Adress to ButtonConfigAdress 0x20 = #32 ....
 I2c.read(I2C_TouchControl, SpmBaseAdress, 8, BtnCfg); 
 I2c.write(I2C_TouchControl, SpmCfg, TerminateSpmCfg); //Deactivate SPM Modus ......
 delay(1000);

 Serial.print("Button Startadresse        : 0x"); Serial.println(BtnCfg[0], HEX);  
 Serial.print("BtnCfg                     : 0x"); Serial.println(BtnCfg[1], HEX);
 Serial.print("BtnAvgThresh               : 0x"); Serial.println(BtnCfg[2], HEX); 
 Serial.print("BtnCompNegThresh           : 0x"); Serial.println(BtnCfg[3], HEX); 
 Serial.print("BtnCompNegCntMax           : 0x"); Serial.println(BtnCfg[4], HEX); 
 Serial.print("BtnHysteresis              : 0x"); Serial.println(BtnCfg[5], HEX);
 Serial.print("BtnStuckAtTimeout          : 0x"); Serial.println(BtnCfg[6], HEX); 
 Serial.print("Register 027               : 0x"); Serial.println(BtnCfg[7], HEX); 
  
 Serial.print(" SpmCfg beendet ....   ");

And here is the Output:

SPM - Configuration Starts ........ 
STEP 1: SPM - WRITE Modus initiieren  ........ 
 SpmCfg:   0x10
STEP 2: SPM - Adresse schreiben  ........ 
 SpmBaseAddr:   32
 Neue SpmBaseAddr:   0x20
STEP 3: SPM - Konfiguration schreiben  ........ 
STEP 3: SPM - Konfiguration beendet  ........ 
Active again  ........ :-) 
Button Startadresse        : 0x20
BtnCfg                     : 0x10
BtnAvgThresh               : 0x0
BtnCompNegThresh           : 0x0
BtnCompNegCntMax           : 0x0
BtnHysteresis              : 0x0
BtnStuckAtTimeout          : 0x0
Register 027               : 0x0
 SpmCfg beendet ....   **

Unfortunately it is not doing what it should do. Only the first two Registers seems to be ok .... and the chip stops working :fearful:

The readed Registers differ from the SetBtnCfg Array.

I'm using the latest I2c Master library ....... Rev. 5.0, I think. Found it easier to use it ... less coding ::slight_smile:

Thanks for your Support ...

Ingo

I don't know how to help. You use a library of 3 years old for no reason :confused: and I have not used the I2C Master library myself.

This is the manufacturers page for the SX8644 : http://www.semtech.com/touch-interface/capacitive-touch-controllers/sx8644/

Could you make a few functions to read and write the SX8644 registers ?
In those function you could try either the Arduino libraries or the I2C Master library.

I think every register can be read and written, only the status is read-only.
When a byte is read (or written) the SX8644 increases the register selector, to allow to read (or write) the next byte.
That is all very normal, it allows to read (or write) one byte or many bytes, in every location of the registers.
The only thing is to use a repeated start when reading bytes. That is a repeated start after the register selector is written, and before reading.
With the Arduino functions use: Wire.endTransmission(false); for the repeated start.

Do you use that repeated start ?

It will be very hard for me to help any further, since I don't have that chip myself, and you use something out of the ordinary (The I2C Master library).

Peter_n:
I don't know how to help. You use a library of 3 years old for no reason :confused: and I have not used the I2C Master library myself.

This is the manufacturers page for the SX8644 : http://www.semtech.com/touch-interface/capacitive-touch-controllers/sx8644/

Could you make a few functions to read and write the SX8644 registers ?
In those function you could try either the Arduino libraries or the I2C Master library.

I think every register can be read and written, only the status is read-only.
When a byte is read (or written) the SX8644 increases the register selector, to allow to read (or write) the next byte.
That is all very normal, it allows to read (or write) one byte or many bytes, in every location of the registers.
The only thing is to use a repeated start when reading bytes. That is a repeated start after the register selector is written, and before reading.
With the Arduino functions use: Wire.endTransmission(false); for the repeated start.

Do you use that repeated start ?

It will be very hard for me to help any further, since I don't have that chip myself, and you use something out of the ordinary (The I2C Master library).

Thank you Peter,

at least a tipp where to look for. I will Change the library to the Arduino wire-Library.

As I said, I'm realy new in programming an arduino ....

I will do some samples and post it here ...

Regards

Ingo

Good Morning 8)

I set up a test sketch, only to read some data out of the registers …

For writing the registers to activate the SPM I used the wire lib.

Here’s the code …

  Serial.println("STEP 1: Activate SPM Access ....");
  delay(500);

  Wire.beginTransmission(I2C_TouchControl);  // Start der Kommunikation mit dem Touch-IC
  Wire.write(SpmCfg);                        // Activate Register
  Wire.write(ReadSpmCfg);                    // Put SX SPM in ReadMode ...
  Wire.endTransmission();                        

  Serial.print("Activated Register/Register Content:  0x");Serial.println(ReadSemTech(I2C_TouchControl, SpmCfg,8), HEX);

  Serial.println("STEP 2: Write SPM - Start adress  ........ ");
  delay(500);

  Wire.beginTransmission(I2C_TouchControl);  // Start der Kommunikation mit dem Touch-IC
  Wire.write(SpmBaseAdress);                 // Activate Register for BaseAdress
  Wire.write(BtnCfgAdr);                     // Define BaseAdress with BtnCfgAdr = 0x20
  Wire.endTransmission(); 

  Serial.print("Activated Register/Register Content:  0x");Serial.println(ReadSemTech(I2C_TouchControl, SpmBaseAdress,1), HEX);

  Serial.println("STEP 3: Read Default Register Values  ........ ");
  delay(500);

 Serial.print("Activated BaseAdress:  0x");Serial.println(ReadSemTech(I2C_TouchControl, SpmBaseAdress,1), HEX);

  Wire.beginTransmission(I2C_TouchControl);  // Start der Kommunikation mit dem Touch-IC
  Wire.write(SpmBaseAdress);                 // Activate Register for BaseAdress
  for (i=0; i<7; i = i+1) {
    BtnCfg[i] = Wire.read();                             // Read Register ...
    Wire.endTransmission(false); 
    }

 Serial.print("Button Startadresse        : 0x"); Serial.println(BtnCfg[0], HEX);  
 Serial.print("BtnCfg                     : 0x"); Serial.println(BtnCfg[1], HEX);
 Serial.print("BtnAvgThresh               : 0x"); Serial.println(BtnCfg[2], HEX); 
 Serial.print("BtnCompNegThresh           : 0x"); Serial.println(BtnCfg[3], HEX); 
 Serial.print("BtnCompNegCntMax           : 0x"); Serial.println(BtnCfg[4], HEX); 
 Serial.print("BtnHysteresis              : 0x"); Serial.println(BtnCfg[5], HEX);
 Serial.print("BtnStuckAtTimeout          : 0x"); Serial.println(BtnCfg[6], HEX); 
 Serial.print("Register 027               : 0x"); Serial.println(BtnCfg[7], HEX);

The result up to Step 3 seems to be ok. Only reading the Registers, does not work. Results are not what they should be …

Here are the results:

Found device at address -  0x2B
Found device at address -  0x40
Found device at address -  0x60
Found device at address -  0x70
STEP 1: Activate SPM Access ....
Activated Register/Register Content:  0x18
STEP 2: Write SPM - Start adress  ........ 
Activated Register/Register Content:  0x20
STEP 3: Read Default Register Values  ........ 
Activated BaseAdress:  0x20
Button Startadresse        : 0xFF
BtnCfg                     : 0xFF
BtnAvgThresh               : 0xFF
BtnCompNegThresh           : 0xFF
BtnCompNegCntMax           : 0xFF
BtnHysteresis              : 0xFF
BtnStuckAtTimeout          : 0xFF
Register 027               : 0x0

Probabely my wire.read sequence is wrong …

You are missing a requestFrom().

  Wire.beginTransmission(I2C_TouchControl);  // Start der Kommunikation mit dem Touch-IC
  Wire.write(SpmBaseAdress);                 // Activate Register for BaseAdress
  Wire.endTransmission(false);               // repeated start !
 
  // The chip is ready for an I2C session to read
  // The Wire.requestFrom is a complete I2C session on its own.
  // After that the data is in the buffer in the Wire library.
  int n = Wire.requestFrom( I2C_TouchControl, 8);    // request 8 bytes ?

  Serial.print( F("8 bytes requested, received: ));
  Serial.println( n);

  // read only 'n' bytes, since that is how many was received.
  for( int i=0; i<n; i++)
  {
    BtnCfg[i] = Wire.read();                             // Read Register ... 
  }

Thanks Peter:)

I expected something like this …

I changed the code:

  Serial.println("STEP 3: Read Default Register Values  ........ ");
  delay(500);

 Serial.print("Activated BaseAdress:  0x");Serial.println(ReadSemTech(I2C_TouchControl, SpmBaseAdress,1), HEX);

  Wire.beginTransmission(I2C_TouchControl);  // Start der Kommunikation mit dem Touch-IC
  Wire.write(SpmBaseAdress);                 // Activate Register for BaseAdress
  Wire.endTransmission(false);               // repeated start !
 
  // the chip is ready for and I2C session to read
  int n = Wire.requestFrom( I2C_TouchControl, 8);    // 8 bytes ?

  Serial.print(F("8 bytes requested, received: "));
  Serial.println( n);

  // read only 'n' bytes, since that is how many was received.
  for( int i=0; i<n; i++) {
    BtnCfg[i] = Wire.read();                             // Read Register ...
    }
 Serial.print("Button Startadresse        : 0x"); Serial.println(BtnCfg[0], HEX);  
 Serial.print("BtnCfg                     : 0x"); Serial.println(BtnCfg[1], HEX);
 Serial.print("BtnAvgThresh               : 0x"); Serial.println(BtnCfg[2], HEX); 
 Serial.print("BtnCompNegThresh           : 0x"); Serial.println(BtnCfg[3], HEX); 
 Serial.print("BtnCompNegCntMax           : 0x"); Serial.println(BtnCfg[4], HEX); 
 Serial.print("BtnHysteresis              : 0x"); Serial.println(BtnCfg[5], HEX);
 Serial.print("BtnStuckAtTimeout          : 0x"); Serial.println(BtnCfg[6], HEX); 
 Serial.print("SldCfg                     : 0x"); Serial.println(BtnCfg[7], HEX);

This is now the result:

STEP 1: Activate SPM Access ....
Activated Register/Register Content:  0x18
STEP 2: Write SPM - Start adress  ........ 
Activated Register/Register Content:  0x20
STEP 3: Read Default Register Values  ........ 
Activated BaseAdress:  0x20
8 bytes requested, received: 8
Button Startadresse        : 0x20
BtnCfg                     : 0x0
BtnAvgThresh               : 0x0
BtnCompNegThresh           : 0x0
BtnCompNegCntMax           : 0x0
BtnHysteresis              : 0x0
BtnStuckAtTimeout          : 0x0
SldCfg                     : 0x0

Still a difference to the values shown in the datasheet on page 39:

The 8 bytes are received, so the chip does give 8 bytes when requested. That part is good.
The values are zero, that might not be good.

Instead of requesting 8 bytes from 0x20 and further, you can request just 1 byte or more than 8. You could also dump all the registers to the serial monitor.
Is is possible to write a value in a register and read the value to see if the register did change ?

If you can't change a register, you could check the return value of Wire.endTransmission(). The return value contains an error code. So if the chip did not properly acknowledge during the I2C session, an error is returned.

I know I2C, but I don't know that chip, so I have no idea why the registers are zero, or if it is in standby or so.

Interesting for me is, that Register 0x20 has already the wrong value.

I wrote the BtnCfg-Array to the chip. And the second register changed ....

n = 1: 0x20
n = 2: 0x10
n = 3: 0x0
n = 4: 0x0
n = 5: 0x0
n = 6: 0x0
n = 7: 0x0
n = 8: 0x0
STEP 1: Activate SPM Access for Register Config ....
Activated Register/Register Content:  0x10
STEP 2: Write SPM - Start adress  ........ 
Activated Register/Register Content:  0x20
STEP 3: Read Default Register Values  ........ 
Activated BaseAdress:  0x20
STEP 3: SPM - Konfiguration schreiben  ........ 
STEP 3: SPM - Konfiguration beendet  ........ 
Active again  ........ :-) 
n = 1: 0x20
n = 2: 0x10
n = 3: 0x0
n = 4: 0x0
n = 5: 0x0
n = 6: 0x0
n = 7: 0x0
n = 8: 0x0

Will try to read it seperately .... also read the error-messages

There are two SX8644 on my PCB. Both show the same behaviour .... and they are working. Default config of chips is working ... you can see LED's working by touch.

Thanks so far

Peter_n:
If you can't change a register, you could check the return value of Wire.endTransmission(). The return value contains an error code. So if the chip did not properly acknowledge during the I2C session, an error is returned.

I know I2C, but I don't know that chip, so I have no idea why the registers are zero, or if it is in standby or so.

The Error Code is always "0" .... so no errors .....

NERO_Audiophile:
Gentlemen,

I'm really new in programming Arduino .... but I need your help :wink:

I want to program this here ...

Can somebody give me a tip?

I tried to setup an array with 8 bytes and used the I2c.write command ......

Your help is appreciated :o

Regards from Germany

Some thoughts .....

In Step 2 it is defined where the SPM-Base Adress should be .... writing an adress to SpmBaseAdress ...

In Step 3 8 Bytes should be written in "BURST-Modus" consecutive .....

Could it be, that I have to use a pointer to the value in SpmBaseAdress? Just thinking .....

I did not look at this before, let’s focus on writing the SPM.
Yes, you need to write the address(pointer) as BaseAddress. And it must be 0 or 8 or 16 and so on. The value 0x20 is 32, so that is okay.

Those 4 steps are each a Wire.beginTransmission() - Wire.write() - Wire.write() - Wire.endTransmission().
Each step with a full stop at the end, so no need for a repeated start.

1 ) 0x0D (SpmCfg), 0x10
2 ) 0x0E (SpmBaseAdress), 0x20 (the Base Address)
3 ) 0x00 (TerminateSpmCfg ?), <8 data bytes>
4 ) 0x0D (SpmCfg), 0x00

Could you write those 4 steps ? so I can check it.
I’m confused with all the register names and so. And in front of the data the value 0x00 should be written, so the data is written to register 0…7, while the base address is 0x20, so actually the registers 0x20…0x27 will be written. That’s confusing.

Peter_n:
I did not look at this before, let’s focus on writing the SPM.
Yes, you need to write the address(pointer) as BaseAddress. And it must be 0 or 8 or 16 and so on. The value 0x20 is 32, so that is okay.

Those 4 steps are each a Wire.beginTransmission() - Wire.write() - Wire.write() - Wire.endTransmission().
Each step with a full stop at the end, so no need for a repeated start.

1 ) 0x0D (SpmCfg), 0x10
2 ) 0x0E (SpmBaseAdress), 0x20 (the Base Address)
3 ) 0x00 (TerminateSpmCfg ?), <8 data bytes>
4 ) 0x0D (SpmCfg), 0x00

Could you write those 4 steps ? so I can check it.
I’m confused with all the register names and so. And in front of the data the value 0x00 should be written, so the data is written to register 0…7, while the base address is 0x20, so actually the registers 0x20…0x27 will be written. That’s confusing.

Taaadaaaaaaa :smiley: :smiley: :smiley: That’s it …

Here’s the code …

 // STEP 1: Write SpmCfg(5,4): 01 and SpmCfg(3):3: 
  Wire.beginTransmission(I2C_TouchControl);
  Wire.write(0x0D); //SpmCfg
  Wire.write(0x10); //Activate write in SPM
  Wire.endTransmission();
  
  // STEP 2: Write BaseAdress to SpmBaseAddr 
  Wire.beginTransmission(I2C_TouchControl);
  Wire.write(0x0E); //SpmBaseAdress
  Wire.write(0x20); // Base Adress for Button Interrupt behaviour
  Wire.endTransmission();

  // STEP 3: Write 8 Bytes to SpmBaseAdress ....
  Wire.beginTransmission(I2C_TouchControl);
  Wire.write(0x00);
  Wire.write(SetBtnCfg, 8);
  Wire.endTransmission();  
  
  // STEP 4: Deactivate SPM Modus
  Wire.beginTransmission(I2C_TouchControl);  // Start der Kommunikation mit dem Touch-IC
  Wire.write(0x0D); //SpmCfg
  Wire.write(0x00); //TerminateSpmCfg
  Wire.endTransmission();

  Serial.println("STEP 3: SPM - Konfiguration beendet  ........ ");
  Wire.beginTransmission(I2C_TouchControl);
  Wire.write(CompOpMode);
  Wire.write(SetModeSleep);
  Wire.endTransmission();

  delay(50);
  
  Wire.beginTransmission(I2C_TouchControl);
  Wire.write(CompOpMode);
  Wire.write(SetModeActive);
  Wire.endTransmission();

  Serial.println("Active again  ........ :-) ");

  // STEP 1: Read Modus 
  Wire.beginTransmission(I2C_TouchControl);
  Wire.write(SpmCfg);
  Wire.write(ReadSpmCfg);
  Wire.endTransmission();

 // STEP 2: Write BaseAdress to SpmBaseAddr 
  Wire.beginTransmission(I2C_TouchControl);
  Wire.write(SpmBaseAdress);
  Wire.write(BtnCfgAdr);
  Wire.endTransmission();


  Wire.beginTransmission(I2C_TouchControl);  // Start der Kommunikation mit dem Touch-IC
  Wire.write(0X00);                 // Activate Register for BaseAdress
  Wire.endTransmission(false);               // repeated start !

  Wire.requestFrom(I2C_TouchControl, 8);    // request 8 bytes 
  int i = 0;
  while (Wire.available())  // read only 'n' bytes, since that is how many was received.
  {//  for( int i=0; i<7; i++) {
    byte c = Wire.read();                             // Read Register ...
    Serial.println(c, HEX);
    i++;
    }
}

And here’s the result:

STEP 3: SPM - Konfiguration beendet  ........ 
Active again  ........ :-) 
0
10
50
50
1
A
0
0

That’s exakt what is in the configuration array:

byte SetBtnCfg[8]={0x00, // 0x20: Default
0x10, // 0x21: BtnCfg - 0x10 - Interrupt triggered by Touch
0x50, // 0x22: Default
0x50, // 0x23: Default
0x01, // 0x24: Default
0x0A, // 0x25: Default
0x00, // 0x26: Default
0x00}; // 0x27: Default

And why we have to write 0x00 in step 3 before writing the data-array? :o But that’s not so important to answer now :wink:

Thank you Peter :slight_smile:

Now I can continue my project …

Phew! that was not so easy. I'm glad you have something as a base to control the chip now.

The chip wants 0x00 before the data array, because the datasheet says so. It's just something weird.

One more chip controlled by an Arduino :slight_smile: