PCA9685 I2C communication problem

brainelectronics
Posts: 3
Joined: Thu Jan 25, 2018 7:33 pm

PCA9685 I2C communication problem

Postby brainelectronics » Thu Jan 25, 2018 8:04 pm

hey guys,
I try to communicate with a PCA9685 16 bit PWM LED driver chip. I've read the docs, datasheet, even Arduino libs how they do it, everything. I'm using an ESP32.
Communication with other I2C devices is no problem, but this one drives me crazy :evil:

Resetting the chip is no problem, but setting the settings and outputs. The problem is the command of sending a '0x00' to adress '0x00'. After this, no matter what I send, is received as 0. I've already hooked up another device which only should read the data of the I2C bus, and it tells me, surprise: 0

I'm guessing this is because the ACK_VAL is the same as the value I want to transmit. But I have to transmit it :lol:
I'll get the same error/problem if I want to turn on/off the LEDs, because turning on the first LEDs is setting the LED0_ON_x to 4096 and LED0_OFF_x to 0 . This results into a transmission sequence of the following: 0x6, 0x0, 0x10, 0x0, 0x0

Now, please it's your turn for any suggestions :?

Code: Select all

#define ACK_CHECK_EN                       0x1              /*!< I2C master will check ack from slave*/
#define ACK_CHECK_DIS                      0x0              /*!< I2C master will not check ack from slave */
#define ACK_VAL                            0x0              /*!< I2C ack value */
#define NACK_VAL                           0x1              /*!< I2C nack value */

#define PCA9685_ADDR                       0x40             /*!< slave address for PCA9685, offset definable with solder pads */
#define MODE1 0x00          // Mode  register  1
#define MODE2 0x01          // Mode  register  2
#define SUBADR1 0x02        // I2C-bus subaddress 1
#define SUBADR2 0x03        // I2C-bus subaddress 2
#define SUBADR3 0x04        // I2C-bus subaddress 3
#define ALLCALLADR 0x05     // LED All Call I2C-bus address
#define LED0 0x6            // LED0 start register
#define LED0_ON_L 0x6       // LED0 output and brightness control byte 0
#define LED0_ON_H 0x7       // LED0 output and brightness control byte 1
#define LED0_OFF_L 0x8      // LED0 output and brightness control byte 2
#define LED0_OFF_H 0x9      // LED0 output and brightness control byte 3
#define LED_MULTIPLYER 4    // For the other 15 channels
#define ALLLED_ON_L 0xFA    // load all the LEDn_ON registers, byte 0 (turn 0-7 channels on)
#define ALLLED_ON_H 0xFB    // load all the LEDn_ON registers, byte 1 (turn 8-15 channels on)
#define ALLLED_OFF_L 0xFC   // load all the LEDn_OFF registers, byte 0 (turn 0-7 channels off)
#define ALLLED_OFF_H 0xFD   // load all the LEDn_OFF registers, byte 1 (turn 8-15 channels off)
#define PRE_SCALE 0xFE      // prescaler for output frequency
#define CLOCK_FREQ 25000000.0 // 25MHz default osc clock

static esp_err_t set_external_pwm_freq(uint16_t freq_hz)
{
     esp_err_t ret;
     /*
     // https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library/blob/master/Adafruit_PWMServoDriver.cpp
    Adafruit Code result:
STARTING RESETTING CHIP
Resetting chip by writing to address: 0x00, value: 0x80
FINISHED RESETTING CHIP
STARTING SETTING FREUQENCY
Attempting to set freq 1000.00
Estimated pre-scale: 5.782
Final pre-scale: 6
Reading oldmode at address: 0x00, value: 0x00
Writing newmode to address: 0x00, value: 0x10
Writing prescaleval to address: 0xfe, value: 0x06
Writing oldmode to address: 0x00, value: 0x00
Writing oldmode | 0xa0 to address: 0x00, value: 0xa0
Mode now 0x00
FINISHED SETTING FREUQENCY
Turning on led 0
Setting PWM 0: 4096->0
Turning off led 0
Setting PWM 0: 0->4096
    ...
     */

    uint8_t oldMode = 0x0;
    uint8_t newMode;
    uint8_t readBackMode = 0;

    float tmpPrescale = (CLOCK_FREQ / 4096 / freq_hz);
    uint8_t prescale_val = floor(tmpPrescale);
    printf("XXXX_1: Prescale value %d (%.3f) (should be 6@1000 Hz)\n", prescale_val, tmpPrescale);

    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);

    // request at register "MODE1", and read result into "oldMode"
    // i2c_master_write_byte(cmd, PCA9685_ADDR << 1 | WRITE_BIT, ACK_CHECK_EN);
    // i2c_master_write_byte(cmd, MODE1, ACK_CHECK_EN);    // select register
    // i2c_master_write_byte(cmd, PCA9685_ADDR << 1 | READ_BIT, ACK_CHECK_EN);
    // i2c_master_read_byte(cmd, oldMode, NACK_VAL);
    // printf("XXXX_2: old mode: 0x%02x\n (should be 0x00)", oldMode);

    newMode = (oldMode & 0x7F) | 0x10;  // sleep

    i2c_master_write_byte(cmd, PCA9685_ADDR << 1 | WRITE_BIT, ACK_CHECK_EN);
    
    // reset command to PCA9685 again
    i2c_master_write_byte(cmd, MODE1, ACK_CHECK_EN);    // select register
    i2c_master_write_byte(cmd, 0x80, ACK_CHECK_EN);    // restart cmd

    // write new mode
    printf("XXXX_4: write new mode: 0x%02x (should be 0x10)\n", newMode);
    i2c_master_write_byte(cmd, MODE1, ACK_CHECK_EN);    // select register
    i2c_master_write_byte(cmd, 0x10, ACK_CHECK_EN);    // set value (sleep)

    // write prescaler
    printf("XXXX_5: write prescaler: 0x%02x (should be 0x06)\n", prescale_val);
    i2c_master_write_byte(cmd, PRE_SCALE, ACK_CHECK_EN);    // select register
    i2c_master_write_byte(cmd, 0x06, ACK_CHECK_EN); // multiplyer for PWM frequency
    
    // [b]write old mode[/b]
    printf("XXXX_6: write oldMode: 0x%02x (should be 0x00)\n", oldMode);
    // uint8_t myData[2] = {MODE1, 0x0};
    // i2c_master_write(cmd, myData, 2, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, MODE1, ACK_CHECK_EN);    // select register
    i2c_master_write_byte(cmd, 0x0, ACK_CHECK_EN);    // set value (sleep)

    printf("XXXX_7: Pause 5ms\n");
    vTaskDelay(5 / portTICK_RATE_MS);

    // re-wirte (oldMode | 0xa0)
    printf("XXXX_8: write oldMode | 0xa0: 0x%02x (should be 0xa0)\n", oldMode|0xa0);
    i2c_master_write_byte(cmd, MODE1, ACK_CHECK_EN);    // select register
    i2c_master_write_byte(cmd, 0xa0, ACK_CHECK_EN);    // set value (sleep)

    // i2c_master_write_byte(cmd, PCA9685_ADDR << 1 | READ_BIT, ACK_CHECK_EN);
    // i2c_master_read_byte(cmd, readBackMode, NACK_VAL);
    // printf("XXXX_9: read back mode now: 0x%02x\n", readBackMode);

    // not used here
    // i2c_master_write_byte(cmd, MODE2, ACK_CHECK_EN);    // select register
    // i2c_master_write_byte(cmd, 0x04, ACK_CHECK_EN);     // totem pole (default)

    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(I2C_EXAMPLE_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);

    printf("Finished setting external PWM\n");

    return ret;
}


static esp_err_t led_manual(void)
{
    esp_err_t ret;

    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, PCA9685_ADDR << 1 | WRITE_BIT, ACK_CHECK_EN);

    // led 1 
    i2c_master_write_byte(cmd, 0x6, ACK_CHECK_EN);    // select register
    i2c_master_write_byte(cmd, 0x0, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, 0x10, ACK_CHECK_EN);  // turn 
    i2c_master_write_byte(cmd, 0x0, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, 0x0, ACK_CHECK_EN);

    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(I2C_EXAMPLE_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);

    return ret;
}


chegewara
Posts: 2228
Joined: Wed Jun 14, 2017 9:00 pm

Re: PCA9685 I2C communication problem

Postby chegewara » Fri Jan 26, 2018 5:39 am

Did you try to see whats going on with logic analyzer?

brainelectronics
Posts: 3
Joined: Thu Jan 25, 2018 7:33 pm

Re: PCA9685 I2C communication problem

Postby brainelectronics » Fri Jan 26, 2018 10:38 am

Solved the issue by myself. For all other looking for a solution on this chip:
the solution is to close the connection after each command.

I'll also post it at https://github.com/brainelectronics/esp32-pca9685 maybe kolban will add this to his code snippets git ;)

Code: Select all

#include <driver/i2c.h>
#include <esp_log.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <math.h>

#include "sdkconfig.h"

#define I2C_EXAMPLE_MASTER_SCL_IO   4    /*!< gpio number for I2C master clock */
#define I2C_EXAMPLE_MASTER_SDA_IO   5    /*!< gpio number for I2C master data  */
#define I2C_EXAMPLE_MASTER_FREQ_HZ  100000     /*!< I2C master clock frequency */
#define I2C_EXAMPLE_MASTER_NUM      I2C_NUM_0   /*!< I2C port number for master dev */
#define I2C_EXAMPLE_MASTER_TX_BUF_DISABLE   0   /*!< I2C master do not need buffer */
#define I2C_EXAMPLE_MASTER_RX_BUF_DISABLE   0   /*!< I2C master do not need buffer */

#define I2C_ADDRESS     0x40    /*!< lave address for PCA9685 */

#define ACK_CHECK_EN    0x1     /*!< I2C master will check ack from slave */
#define ACK_CHECK_DIS   0x0     /*!< I2C master will not check ack from slave */
#define ACK_VAL         0x0     /*!< I2C ack value */
#define NACK_VAL        0x1     /*!< I2C nack value */
#define MODE1           0x00    /*!< Mode register 1 */
#define MODE2           0x01    /*!< Mode register 2 */
#define SUBADR1         0x02    /*!< I2C-bus subaddress 1 */
#define SUBADR2         0x03    /*!< I2C-bus subaddress 2 */
#define SUBADR3         0x04    /*!< I2C-bus subaddress 3 */
#define ALLCALLADR      0x05    /*!< LED All Call I2C-bus address */
#define LED0            0x6     /*!< LED0 start register */
#define LED0_ON_L       0x6     /*!< LED0 output and brightness control byte 0 */
#define LED0_ON_H       0x7     /*!< LED0 output and brightness control byte 1 */
#define LED0_OFF_L      0x8     /*!< LED0 output and brightness control byte 2 */
#define LED0_OFF_H      0x9     /*!< LED0 output and brightness control byte 3 */
#define LED_MULTIPLYER  4       /*!< For the other 15 channels */
#define ALLLED_ON_L     0xFA    /*!< load all the LEDn_ON registers, byte 0 (turn 0-7 channels on) */
#define ALLLED_ON_H     0xFB    /*!< load all the LEDn_ON registers, byte 1 (turn 8-15 channels on) */
#define ALLLED_OFF_L    0xFC    /*!< load all the LEDn_OFF registers, byte 0 (turn 0-7 channels off) */
#define ALLLED_OFF_H    0xFD    /*!< load all the LEDn_OFF registers, byte 1 (turn 8-15 channels off) */
#define PRE_SCALE       0xFE    /*!< prescaler for output frequency */
#define CLOCK_FREQ      25000000.0  /*!< 25MHz default osc clock */

static char tag[] = "PCA9685";

#undef ESP_ERROR_CHECK
#define ESP_ERROR_CHECK(x)   do { esp_err_t rc = (x); if (rc != ESP_OK) { ESP_LOGE("err", "esp_err_t = %d", rc); assert(0 && #x);} } while(0);

void write_i2c_register_two_words(uint8_t regaddr, uint16_t valueOn, uint16_t valueOff);
void generic_write_i2c_register_word(uint8_t regaddr, uint16_t value);
static void i2c_example_master_init(void);
static void resetPCA9685(void);
static void setFrequencyPCA9685(uint16_t freq);
static void turnAllOff(void);
static void setPWM(uint8_t num, uint16_t on, uint16_t off);
void disp_buf(uint16_t* buf, uint8_t len);


/**
 * @brief      Sets the pwm of the pin
 *
 * @param[in]  num   The pin number
 * @param[in]  on    On time
 * @param[in]  off   Off time
 */
static void setPWM(uint8_t num, uint16_t on, uint16_t off)
{
    uint8_t pinAddress = LED0_ON_L + LED_MULTIPLYER * num;
    write_i2c_register_two_words(pinAddress & 0xff, on, off);
}

/**
 * @brief      Write two 16 bit values to the same register on an i2c device
 *
 * @param[in]  regaddr   The register address
 * @param[in]  valueOn   The value on
 * @param[in]  valueOff  The value off
 */
void write_i2c_register_two_words(uint8_t regaddr, uint16_t valueOn, uint16_t valueOff)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (I2C_ADDRESS << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, regaddr, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, valueOn & 0xff, ACK_VAL);
    i2c_master_write_byte(cmd, valueOn >> 8, NACK_VAL);
    i2c_master_write_byte(cmd, valueOff & 0xff, ACK_VAL);
    i2c_master_write_byte(cmd, valueOff >> 8, NACK_VAL);
    i2c_master_stop(cmd);
    i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000/portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
}

/**
 * @brief      Write a 16 bit value to a register on an i2c device
 *
 * @param[in]  regaddr  The register address
 * @param[in]  value    The value
 */
void generic_write_i2c_register_word(uint8_t regaddr, uint16_t value)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (I2C_ADDRESS << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, regaddr, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, value & 0xff, ACK_VAL);
    i2c_master_write_byte(cmd, value >> 8, NACK_VAL);
    i2c_master_stop(cmd);
    i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000/portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
}

/**
 * @brief      test function to show buffer
 *
 * @param      buf   The buffer
 * @param[in]  len   The length
 */
void disp_buf(uint16_t* buf, uint8_t len)
{
    uint8_t i;
    for (i = 0; i < len; i++)
    {
        printf("%02x ", buf[i]);
        if (( i + 1 ) % 16 == 0)
        {
            printf("\n");
        }
    }
    printf("\n");
}

/**
 * @brief i2c master initialization
 */
static void i2c_example_master_init(void)
{
    ESP_LOGD(tag, ">> PCA9685");
    i2c_config_t conf;
    conf.mode = I2C_MODE_MASTER;
    conf.sda_io_num = I2C_EXAMPLE_MASTER_SDA_IO;
    conf.scl_io_num = I2C_EXAMPLE_MASTER_SCL_IO;
    conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
    conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
    conf.master.clk_speed = I2C_EXAMPLE_MASTER_FREQ_HZ;
    
    int i2c_master_port = I2C_EXAMPLE_MASTER_NUM;
    ESP_ERROR_CHECK(i2c_param_config(i2c_master_port, &conf));
    ESP_ERROR_CHECK(i2c_driver_install(i2c_master_port, conf.mode,
                       I2C_EXAMPLE_MASTER_RX_BUF_DISABLE,
                       I2C_EXAMPLE_MASTER_TX_BUF_DISABLE, 0));
}

/**
 * @brief      Resets the PCA9685
 */
static void resetPCA9685(void)
{
    // Reset chip
    printf("Resetting chip\n");
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (I2C_ADDRESS << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, MODE1, ACK_CHECK_EN);   // 0x0 = "Mode register 1"
    i2c_master_write_byte(cmd, 0x80, ACK_CHECK_EN);    // 0x80 = "Reset"
    i2c_master_stop(cmd);
    i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000/portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
}

/**
 * @brief      Sets the frequency of PCA9685
 *
 * @param[in]  freq  The frequency
 */
static void setFrequencyPCA9685(uint16_t freq)
{
    // Send to sleep
    printf("Setting ext frequency\n");
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (I2C_ADDRESS << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, MODE1, ACK_CHECK_EN);    // 0x0 = "Mode register 1"
    i2c_master_write_byte(cmd, 0x10, ACK_CHECK_EN);     // 0x10 = go to sleep
    i2c_master_stop(cmd);
    i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000/portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);

    // Set prescaler
    printf("\tSetting prescaler\n");
    // calculation on page 25 of datasheet
    uint8_t prescale_val = round((CLOCK_FREQ / 4096 / (0.9*freq)) - 1+0.5);

    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (I2C_ADDRESS << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, PRE_SCALE, ACK_CHECK_EN);    // 0xFE = "Prescaler"
    i2c_master_write_byte(cmd, prescale_val, ACK_CHECK_EN); //6 = 0x06 = "prescaler frequency"
    i2c_master_stop(cmd);
    i2c_master_cmd_begin(I2C_NUM_0, cmd, 100/portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);

    // reset again
    printf("\tResetting again\n");
    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (I2C_ADDRESS << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, MODE1, ACK_CHECK_EN);    // 0x0 = "Mode register 1"
    i2c_master_write_byte(cmd, 0x80, ACK_CHECK_EN);     // 0x80 = "Reset"
    i2c_master_stop(cmd);
    i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000/portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);

    // Send to sleep again
    printf("\tSending to sleep\n");
    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (I2C_ADDRESS << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, MODE1, ACK_CHECK_EN);    // 0x0 = "Mode register 1"
    i2c_master_write_byte(cmd, 0x10, ACK_CHECK_EN);     // 0x10 = go to sleep
    i2c_master_stop(cmd);
    i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000/portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);

    printf("\tWaiting\n");
    vTaskDelay(5/portTICK_PERIOD_MS);

    printf("\tWriting 0xa0 for auto increment\n");
    // Write oldMode again
    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (I2C_ADDRESS << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, MODE1, ACK_CHECK_EN);    // 0x0 = "Mode register 1"
    i2c_master_write_byte(cmd, 0xa0, ACK_CHECK_EN);     // 0xa0 = auto increment
    i2c_master_stop(cmd);
    i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000/portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);

    // // Read back set data
    // cmd = i2c_cmd_link_create();
    // ESP_ERROR_CHECK(i2c_master_start(cmd));
    // ESP_ERROR_CHECK(i2c_master_write_byte(cmd, (I2C_ADDRESS << 1) | I2C_MASTER_READ, 1));
    // i2c_master_read_byte(cmd, data,   0);
    // i2c_master_read_byte(cmd, data+1, 0);
    // i2c_master_read_byte(cmd, data+2, 1);
    // ESP_ERROR_CHECK(i2c_master_stop(cmd));
    // ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_NUM_0, cmd, 100/portTICK_PERIOD_MS));
    // i2c_cmd_link_delete(cmd);
}

/**
 * @brief      Turn all LEDs off
 */
static void turnAllOff(void)
{
    // Turn all LEDs off
    printf("Turning all off\n");

    uint16_t valueOn = 0;
    uint16_t valueOff = 4096;

    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);

    i2c_master_write_byte(cmd, (I2C_ADDRESS << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, ALLLED_ON_L, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, valueOn & 0xff, ACK_VAL);
    i2c_master_write_byte(cmd, valueOn >> 8, NACK_VAL);
    i2c_master_write_byte(cmd, valueOff & 0xff, ACK_VAL);
    i2c_master_write_byte(cmd, valueOff >> 8, NACK_VAL);

    i2c_master_stop(cmd);
    i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000/portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
}

void task_PCA9685(void *ignore)
{
    i2c_example_master_init();

    resetPCA9685();
    setFrequencyPCA9685(1000);  // set output frequency to 1000Hz (can be +-5 percent)
    turnAllOff();

    printf("Finished setup, entering loop now\n");

    while(1)
    {
        /*
        // led turn on and 100ms off, starting from pin 0...15
        for (uint8_t pin = 0; pin < 16; pin++)
        {
            printf("Turn LED on\n");
            setPWM(pin, 4096, 0);

            vTaskDelay(100/portTICK_PERIOD_MS);

            printf("Turn LED off\n");
            setPWM(pin, 0, 4096);
        }
        */

        // fade led up and down, starting from pin 0...15
        for (uint8_t pin = 0; pin < 7; pin++)
        {
            for (uint16_t i = 0; i < 4096; i+=8)
            {
                // fade up
                setPWM(pin, 0, i);

                vTaskDelay(5/portTICK_PERIOD_MS);
            }

            for (uint16_t i = 0; i < 4096; i+=8)
            {
                // fade down
                setPWM(pin, i, 0);

                vTaskDelay(5/portTICK_PERIOD_MS);
            }

            // ensure it's really off
            setPWM(pin, 0, 4096);

            vTaskDelay(100/portTICK_PERIOD_MS);    
        }
    }

    vTaskDelete(NULL);
}

void app_main()
{
    xTaskCreate(task_PCA9685, "task_PCA9685", 1024 * 2, (void* ) 0, 10, NULL);
}

brelec
Posts: 2
Joined: Wed Mar 14, 2018 1:42 pm

Re: PCA9685 I2C communication problem

Postby brelec » Wed Mar 14, 2018 2:16 pm

Hi
I have the same problems with the PCA9685 i2c communication. With my Oscilloscope and the i2c decoder, I can see that the data's I send are properly received from the slave, but nothing happens. I used the Data for the 4 register LED0_xx according the Data sheet Example1 on page 17. Register Mode1 is written with data 0x00, register Mode2 with 0x10. The OE pin is tied to GND by 10k.
I inserted after writing Mode1 a NotAKN and a STOP, the delay 10us then writing Mode2, again Stop. Now Start and writing the 4 register according the Example1, nothing happens, it makes me cracy !
Do I overlook something? It looks like the Pulsgenerator wouldn't start up. (value default 200Hz).

Can anyone help me perhaps with a C-code sample (initialization, setup of registers and triggering the PWM )

Thanks a lot
brelec

brainelectronics
Posts: 3
Joined: Thu Jan 25, 2018 7:33 pm

Re: PCA9685 I2C communication problem

Postby brainelectronics » Thu Mar 15, 2018 12:52 pm

hi brelec,

just checkout my Github repo. Exept setting register Mode2 everything is as you use it.
Take a look at the example test file at line 85 onwards. As I reset the chip, I also set the MODE1 register. In the next line (line 88) of the test file, I set the desired frequency of the output. In your case, just change the value to your 200. After that you can set any (or all) output pin with the setPWM function.
My Github repo is https://github.com/brainelectronics/esp32-pca9685

hope this solves your problem

brelec
Posts: 2
Joined: Wed Mar 14, 2018 1:42 pm

Re: PCA9685 I2C communication problem

Postby brelec » Sat Mar 17, 2018 3:03 pm

Hi
I thank you very much, reading and almost sleeping with the PCA9685 Datasheet, I would never have been successful :evil: Your Tips were the fantastic, but how can one know that one must NOTAKN after the first 2 bytes. I have many i2c applications running without any problems, so I thought to be experienced enough to work with the PCA chip.

Anyway I'm happy to meet guys like you who can save my nerves :D

Best Regards
brelec

Who is online

Users browsing this forum: JVKran and 84 guests