Good day esteemed.
Currently, I am attempting to set up a capacitive keyboard (Integrated CY8CMBR3116) with I2C communication to an ESP32-S3, which I am programming using IDF libraries through PlatformIO in Visual Studio Code. I am encountering an issue with I2C communication. I configure the I2C and send the write and read frames as indicated in the datasheet (see Figure 19, 20, and 21), but it never writes or allows me to read the registers of this controller (SEE CODE 1). On the other hand, I have code in Arduino (SEE CODE 2), which does work for me. I only did this to verify since I am currently programming everything on ESP32-S3 with IDF and would like to continue with it.
Could you assist me with “CODE 1” in case I have some error that I am not aware of that might affect the writing and reading of CY8CMBR3116 registers?
CODE1 (configurations):
#define I2C_MASTER_NUM I2C_NUM_0
#define I2C_MASTER_SCL_IO GPIO_NUM_19
#define I2C_MASTER_SDA_IO GPIO_NUM_18
#define I2C_MASTER_FREQ_HZ 10000
#define CY8CMBR3116_ADDR 0x37
#define GPO_OUTPUT_STATE 0x80
#define SENSOR_EN 0x00
#define BUTTON_LBR 0x1F
#define SENSITIVITY0 0x08
#define SENSITIVITY1 0x09
#define SENSITIVITY2 0x0A
#define SENSITIVITY3 0x0B
#define BUTTON_STAT 0xAA
#define CTRL_CMD 0x86
#define SAVE_CHECK_CRC 0x02
#define SW_RESET 0xFF
#define DEVICE_ID 0x90
#define BUZZER_CFG 0x3E
#define SLIDER_CFG 0x5D
#define SPO_CFG 0x4C
#define GPIO_INT_CY8CMBR3116 GPIO_NUM_41
#define GPIO_INT_CY8CMBR3116_MASK (1ULL<<GPIO_NUM_41)
//Definicion de flag para las INT
#define ESP_INTR_FLAG_DEFAULT 0
*******************************WRITE*******************************
void configureCY8CMBR3116(void)
{
// Configurar el CY8CMBR3116 para detectar teclas presionadas
unsigned char configData[128] = {
0xFFu, 0xFFu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
0x00u, 0x00u, 0x00u, 0x00u, 0x80u, 0x80u, 0x80u, 0x80u,
0x80u, 0x80u, 0x80u, 0x80u, 0x80u, 0x80u, 0x80u, 0x80u,
0x80u, 0x80u, 0x80u, 0x80u, 0x03u, 0x00u, 0x00u, 0x00u,
0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x80u,
0x05u, 0x00u, 0x00u, 0x02u, 0x00u, 0x02u, 0x00u, 0x00u,
0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x1Eu, 0x1Eu, 0x00u,
0x00u, 0x1Eu, 0x1Eu, 0x00u, 0x00u, 0x00u, 0x01u, 0x01u,
0x00u, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu,
0xFFu, 0x00u, 0x00u, 0x00u, 0x14u, 0x03u, 0x01u, 0x58u,
0x00u, 0x37u, 0x06u, 0x00u, 0x00u, 0x0Au, 0x00u, 0x00u,
0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x88u, 0x95u
};
esp_err_t ret=-1;
i2c_cmd_handle_t cmd;
while(ret==-1){
ret=0;
cmd = i2c_cmd_link_create();
ret=i2c_master_start(cmd);
ret=i2c_master_write_byte(cmd, (CY8CMBR3116_ADDR << 1) | I2C_MASTER_WRITE, true);
//ret=i2c_master_write_byte(cmd, SENSOR_EN, true);
//ret=i2c_master_write_byte(cmd, 0x00, true);
//ret=i2c_master_stop(cmd);
//ret=i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 100 / portTICK_PERIOD_MS);
//i2c_cmd_link_delete(cmd);
//cmd = i2c_cmd_link_create();
ret=i2c_master_start(cmd);
ret=i2c_master_write_byte(cmd, (CY8CMBR3116_ADDR << 1) | I2C_MASTER_WRITE, true);
ret=i2c_master_write_byte(cmd, SENSOR_EN, true);
//ret=i2c_master_write_byte(cmd, 0x00, true);
//ret=i2c_master_stop(cmd);
//ret=i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
//i2c_cmd_link_delete(cmd);
//cmd = i2c_cmd_link_create();
//ret=i2c_master_start(cmd);
//ret=i2c_master_write_byte(cmd, (CY8CMBR3116_ADDR << 1) | I2C_MASTER_WRITE, true);
//ret=i2c_master_write_byte(cmd, SENSOR_EN, true);
ret=i2c_master_write(cmd, &configData[0], 31, true);
//ret=i2c_master_stop(cmd);
//ret=i2c_master_start(cmd);
//ret=i2c_master_write_byte(cmd, (CY8CMBR3116_ADDR << 1) | I2C_MASTER_WRITE, true);
//ret=i2c_master_write_byte(cmd, BUTTON_LBR, true);
ret=i2c_master_write(cmd, &configData[31], 31, true);
//ret=i2c_master_stop(cmd);
//ret=i2c_master_start(cmd);
//ret=i2c_master_write_byte(cmd, (CY8CMBR3116_ADDR << 1) | I2C_MASTER_WRITE, true);
//ret=i2c_master_write_byte(cmd, BUZZER_CFG, true);
ret=i2c_master_write(cmd, &configData[62], 31, true);
//ret=i2c_master_stop(cmd);
//ret=i2c_master_start(cmd);
//ret=i2c_master_write_byte(cmd, (CY8CMBR3116_ADDR << 1) | I2C_MASTER_WRITE, true);
//ret=i2c_master_write_byte(cmd, SLIDER_CFG, true);
ret=i2c_master_write(cmd, &configData[93], 31, true);
//ret=i2c_master_stop(cmd);
//ret=i2c_master_start(cmd);
//ret=i2c_master_write_byte(cmd, (CY8CMBR3116_ADDR << 1) | I2C_MASTER_WRITE, true);
//ret=i2c_master_write_byte(cmd, 0x7C, true);
ret=i2c_master_write(cmd, &configData[124], 4, true);
ret=i2c_master_stop(cmd);
//ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 100 / portTICK_PERIOD_MS);
ret=i2c_master_start(cmd);
ret=i2c_master_write_byte(cmd, (CY8CMBR3116_ADDR << 1) | I2C_MASTER_WRITE, true);
ret=i2c_master_write_byte(cmd, CTRL_CMD, true);
ret=i2c_master_write_byte(cmd,SAVE_CHECK_CRC, true);
//ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 200 / portTICK_PERIOD_MS);
//ret=i2c_master_stop(cmd);
//ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 100 / portTICK_PERIOD_MS);
vTaskDelay(200 / portTICK_PERIOD_MS);
ret=i2c_master_start(cmd);
ret=i2c_master_write_byte(cmd, (CY8CMBR3116_ADDR << 1) | I2C_MASTER_WRITE, true);
ret=i2c_master_write_byte(cmd, CTRL_CMD, true);
ret=i2c_master_write_byte(cmd,SW_RESET, true);
//ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 200 / portTICK_PERIOD_MS);
ret=i2c_master_stop(cmd);
if(ret==ESP_OK){
printf("Transmission SW_RESET CHECK OKEY");
}
//vTaskDelay(200 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
if(ret==-1){
printf("ERROR CONFIG I2C\n");
}
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
return;
}
*******************************READ*******************************
void readKeypadState(void *pvParameters)
{
uint8_t rx_data[10];
esp_err_t ret2=0;
// uint8_t command[126] = {0x01};
vTaskDelay(2000 / portTICK_PERIOD_MS);
configureCY8CMBR3116();
vTaskDelay(2000 / portTICK_PERIOD_MS); // Espera un segundo antes de enviar nuevamente
i2c_cmd_handle_t cmd;
while (1)
{
/*
cmd2 = i2c_cmd_link_create();
ret2=i2c_master_start(cmd2);
ret2=i2c_master_write_byte(cmd2, (CY8CMBR3116_ADDR << 1) | I2C_MASTER_WRITE, true);
ret2=i2c_master_write_byte(cmd2, BUTTON_STAT, true); // Dirección del registro SENSITIVITY0
ret2=i2c_master_stop(cmd2);
ret2=i2c_master_read(cmd2, &rx_data[0], 2, true);
i2c_cmd_link_delete(cmd2);
*/
//Ubico el puntero en el registro BUTTON_STAT
cmd = i2c_cmd_link_create();
ret2=i2c_master_start(cmd);
ret2=i2c_master_write_byte(cmd, (CY8CMBR3116_ADDR << 1) | I2C_MASTER_WRITE, true);
ret2=i2c_master_write_byte(cmd, BUTTON_STAT, true); // Dirección del registro SENSOR_EN (cualquier registro de lectura servirá)
ret2=i2c_master_start(cmd);
i2c_master_write_byte(cmd, (CY8CMBR3116_ADDR << 1) | I2C_MASTER_READ, true);
i2c_master_read(cmd, rx_data, sizeof(rx_data), I2C_MASTER_ACK);
i2c_master_stop(cmd);
//i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
for(int j=0;j<10;j++)
printf("ESTADO TECLADO%d: %u\n",j,rx_data[j]);
if(ret2==-1){
printf("ERROR READ I2C\n");
}
vTaskDelay(1000 / portTICK_PERIOD_MS); // Espera un segundo antes de enviar nuevamente
}
}
*******************************PIN CONFIG*******************************
static esp_err_t i2c_master_init(void)
{
i2c_config_t confi2c;
confi2c.mode = I2C_MODE_MASTER;
confi2c.sda_io_num = I2C_MASTER_SDA_IO;
confi2c.scl_io_num = I2C_MASTER_SCL_IO;
confi2c.sda_pullup_en = GPIO_PULLUP_ENABLE;
confi2c.scl_pullup_en = GPIO_PULLUP_ENABLE;
confi2c.master.clk_speed = I2C_MASTER_FREQ_HZ; // Velocidad del reloj I2C en Hz
confi2c.clk_flags = 0;
i2c_param_config(I2C_MASTER_NUM, &confi2c);
i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER, 0, 0, 0);
return ESP_OK;
}
void app_main()
{
Init_Pulsador_OFF();
i2c_master_init();
// Inicializacion del Queue para las interrupciones
gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
xTaskCreate(INTERRUPTION_TASK, "INTERRUPTION_TASK", 2048, NULL, 6, NULL);
// Crea la tarea para leer el estado de las teclas capacitivas
xTaskCreate(readKeypadState, "read_task", configMINIMAL_STACK_SIZE * 3, NULL, 7, NULL);
}
CODE 2:
#define SLAVE_ADDR 0x37
#define REGMAP_ORIGIN 0x00
#define BUTTON_LBR 0x1F
#define BUZZER_CFG 0x3E
#define SLIDER_CFG 0x5D
#define CTRL_CMD 0x86
#define SAVE_CHECK_CRC 0x02
#define SW_RESET 0xFF
*******************************WRITE*******************************
void configCY8CMBR3102()
{
int writeerr = 0;
//Write dummy data
Wire.beginTransmission(x); // transmit to device #0x37
Wire.write(REGMAP_ORIGIN); // sends Offset byte
Wire.write(00);
Wire.endTransmission(); // stop transmitting
Wire.beginTransmission(SLAVE_ADDR); // transmit to device #0x37
Wire.write(REGMAP_ORIGIN); // sends Offset byte
Wire.write(00);
Wire.endTransmission(); // stop transmitting
//Arduino function can send only 31 bytes of data
//So whole frame is send in chunks
//from [0] to [30]
Wire.beginTransmission(SLAVE_ADDR);
Wire.write(REGMAP_ORIGIN); //0
size_t sendedSize = Wire.write(&configData[0],31);
Wire.endTransmission();
writeerr = Wire.getWriteError();
if(writeerr == 0) {
Serial.print("First packet sended\n");
}
//from [31] to [61]
Wire.beginTransmission(SLAVE_ADDR);
Wire.write(BUTTON_LBR); //31
sendedSize = Wire.write(&configData[31],31);
Wire.endTransmission();
writeerr = Wire.getWriteError();
if(writeerr == 0) {
Serial.print("Second packet sended\n");
}
//from [62] to [92]
Wire.beginTransmission(SLAVE_ADDR);
Wire.write(BUZZER_CFG); //62
sendedSize = Wire.write(&configData[62],31);
Wire.endTransmission();
writeerr = Wire.getWriteError();
if(writeerr == 0) {
Serial.print("Third packet sended\n");
}
//from [93] to [123]
Wire.beginTransmission(SLAVE_ADDR);
Wire.write(SLIDER_CFG); //93
sendedSize = Wire.write(&configData[93],31);
Wire.endTransmission();
writeerr = Wire.getWriteError();
if(writeerr == 0) {
Serial.print("Fourth packet sended\n");
}
//from [124] to [127]
Wire.beginTransmission(SLAVE_ADDR);
Wire.write(0x7C); //124
sendedSize = Wire.write(&configData[124],4);
Wire.endTransmission();
writeerr = Wire.getWriteError();
if(writeerr == 0) {
Serial.print("Fifth packet sended\n");
}
/*
Write 0x02 to 0x86
Info from datasheet
The device calculates a CRC checksum over the configuration data in this register map and
compares the result with the content of CONFIG_CRC. If the two values match, the device saves
the configuration and the CRC checksum to nonvolatile memory.
*/
Wire.beginTransmission(SLAVE_ADDR); // transmit to device #0x37
Wire.write(CTRL_CMD);
Wire.write(SAVE_CHECK_CRC);
Wire.endTransmission(); // stop transmitting
delay(200);
//Reset
Wire.beginTransmission(SLAVE_ADDR);
Wire.write(CTRL_CMD);
Wire.write(SW_RESET);
Wire.endTransmission(); // stop transmitting
delay(200);
}
*******************************READ*******************************
void ReadAndDisplaySensorStatus()
{
char readedData[2] = {0x00};
Wire.beginTransmission(SLAVE_ADDR);
Wire.write(BUTTON_STATUS);
Wire.endTransmission();
int i=0;
Wire.requestFrom(SLAVE_ADDR, 2); //2 bytes for whole BUTTON_STATUS
while(Wire.available())
{
readedData[i] = Wire.read();
Serial.print("Hex: 0x");
Serial.print(readedData[i], HEX);
Serial.print("\n");
i++;
}
Wire.endTransmission();
DisplaySensorStatus(&readedData[0]);
delay(1000);
}
void setup()
{
Wire.begin(18,19);
Serial.begin(115200); // start serial for output
//For single chip is need to be call only once.
//If do not change configuration
configCY8CMBR3102();
Serial.print("Device configurated\n");
}
void loop()
{
ReadAndDisplaySensorStatus();
delay(50);
}