This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nRF52 DK & PCA9685 (TWI bug)

Hi,everybody!

I started to connect the PCA9685 to the  nRF52 DK and ran into a strange problem. When initializing the PWM module, it does not work.Initialization requires the setting of registers to certain values, which is nothing complicated.

The problem was solved by using delays between dispatches. But I would still like to understand the reasons for this behavior. This is not the first time this has happened to me. And examples of using TWI were written without delay. 

Below is an example of mine which is working. If you remove the delays, it doesn't work.

INIT_DELAY = 1000

void pca9685_init (void)
{
	uint8_t mode1_reg_default_value = 0b00110000u;
	uint8_t mode2_reg_default_value = 0b00000000u;



	 pca9685_write_u8(0x00, mode1_reg_default_value);
	  nrf_delay_us(INIT_DELAY);
	pca9685_write_u8( 0x01, mode2_reg_default_value);
	 nrf_delay_us(INIT_DELAY);

    // Turn all channels off to begin with.
    uint8_t data[4] = { 0x00, 0x00, 0x00, 0x10 };
     pca9685_write_data( PCA9685_REGISTER_ALL_LED_ON_L, data, 4);
     nrf_delay_us(INIT_DELAY);

	 pca9685_set_pwm_frequency(1000);
	  nrf_delay_us(INIT_DELAY);
	 pca9685_wakeup();
	  nrf_delay_us(INIT_DELAY);
}

void pca9685_write_u8 (uint8_t reg,uint8_t val)
{
  uint8_t buff[2] = {reg,val};
    nrf_drv_twi_tx(&m_twi,PCA9685_ADDRESS,buff, 2, false);
}

void pca9685_write_data (reg, data, length)
{
  uint8_t buff[length+1];
  buff[0] = reg;
  memcpy(&buff[1], data, length);
  nrf_drv_twi_tx(&m_twi,PCA9685_ADDRESS,buff, sizeof(buff), false);
}
  
void pca9685_read_u8( uint8_t address, uint8_t *dest)
{
nrf_drv_twi_tx(&m_twi,PCA9685_ADDRESS,address, 1, false);
nrf_delay_us(1000);
	nrf_drv_twi_rx(&m_twi, PCA9685_ADDRESS, dest,1);
}

Parents
  • Hi,

    Could describe exactly what happens if you omit the delay and how it's not what you expected it to be? 

    It seems like you're not checking the return value from the nrf_drv_twi functions, which you should so we could understand what exactly the issue is. 

    For example:

        err_code = nrf_drv_twi_tx(&m_twi, slave_addr, reg, 1, false);
        APP_ERROR_CHECK(err_code);

    My guess is that driver returns NRF_ERROR_BUSY without the delays, as you're not using any flag to signalize when the driver is finished with a transfer. I would suggest that you take a look at your twi_sensor example in the SDK, it uses a flag to signalize that the driver is ready for a new transfer.

     
    best regards
    Jared 
Reply
  • Hi,

    Could describe exactly what happens if you omit the delay and how it's not what you expected it to be? 

    It seems like you're not checking the return value from the nrf_drv_twi functions, which you should so we could understand what exactly the issue is. 

    For example:

        err_code = nrf_drv_twi_tx(&m_twi, slave_addr, reg, 1, false);
        APP_ERROR_CHECK(err_code);

    My guess is that driver returns NRF_ERROR_BUSY without the delays, as you're not using any flag to signalize when the driver is finished with a transfer. I would suggest that you take a look at your twi_sensor example in the SDK, it uses a flag to signalize that the driver is ready for a new transfer.

     
    best regards
    Jared 
Children
Related