1

I'm trying to write a simple code for initializing and running the PCA9685. I tested the board with Adafruit library and it's working.

But I just want to develop a simple code to include it in my various modules library for future projects.

I wrote a code, but I think I'm not understanding the work of the internal registers.

But according to the datasheet I configured only the auto increment and left the rest to default settings. Then I headed up to the last registers which are the all_led_on and all_led_offas wanting to run the outputs on/off to blink the LEDs. But I think these two registers are for enabling/disabling the pins. Is that right?

This is my code:

void pca9685_init(void){
    uint8_t i,val[]={0x20,0x04};
    i2c_start(PCA9685_BASE_WR);
    i2c_tx(PCA9685_MODE1);
    for(i=0;i<2;i++)i2c_tx(val[i]);
    i2c_stop();
}

void pca9685_all_on(void){
    uint8_t i,val[]={0x00,0x10};
    i2c_start(PCA9685_BASE_WR);
    i2c_tx(PCA9685_ALL_LED_ON_L);
    for(i=0;i<2;i++)i2c_tx(val[i]);
    i2c_stop();
}

void pca9685_all_off(void){
    uint8_t i,val[]={0x00,0x10};
    i2c_start(PCA9685_BASE_WR);
    i2c_tx(PCA9685_ALL_LED_OFF_L);
    for(i=0;i<2;i++)i2c_tx(val[i]);
    i2c_stop();
}
  • 1
    If you want it simple, then use the arduino Wire library and stop fooling around with i2c code that does not work. It took many years to remove bugs from the arduino wire library. The i2c bus is not that simple, so you might never get the quality level of the arduino wire library. What you do is making it overcomplicated and wasting your time. Sorry for my harsh words, I want to make very clear that you should not continue this way. Well, that is at least my opinion, trying to help you. – Jot Jan 24 at 18:29
  • Absolutely I understand you and respect your goal that you don't want me to waste time with the actual communication library. But my i2c library worked for all my i2c modules and revised different i2c libraries to get it not perfect, but at least to run the basic functions of sending and receiving. Writing my own code helped me a lot in learning how to write code, it's difficult to me to go into projects without learning the internals. But I agree an internal library like Wire should be a very good choice. – Perch Eagle Jan 24 at 18:40
  • 2
    @PerchEagle You shouldn't be afraid of the space bar. I know it's big and imposing, but don't be scared of pressing it once in a while ;) – Majenko Jan 24 at 22:35
  • I got you, the code looks so compact lol. – Perch Eagle Jan 25 at 7:07
  • I thought about the space aspect just a moment, but I have a question: what are the appropriate locations to put space into? My most important location is when I use arithmetic, logical or rational operators. But I don't put them to the braces, or after the functions' names. It feel it well fit, but maybe you're right, it maybe more compact than what I feel. – Perch Eagle Jan 25 at 11:19
2

The registers aren't for just turning the LEDs on or off. They are for setting the ON and OFF times of the PWM. Bit 12 of each combined value is used as a "full" setting, so:

To set the LEDs on to full brightness you need to set:

  • PCA9685_ALL_LED_OFF_L to 0x00
  • PCA9685_ALL_LED_OFF_H to 0x00
  • PCA9685_ALL_LED_ON_L to 0x00
  • PCA9685_ALL_LED_OFF_H to 0x10

This sets the off time to 0 counts and the on to be "full on".

It doesn't really matter what value you set the OFF to as long as you set ON to "full on" and off isn't set to "full off".

For off you should set the ON to 0 and the OFF to "full off" (reverse the above settings).

Section 7.3.3 of the datasheet says:

The turn-on time of each LED driver output and the duty cycle of PWM can be controlled independently using the LEDn_ON and LEDn_OFF registers.

There will be two 12-bit registers per LED output. These registers will be programmed by the user. Both registers will hold a value from 0 to 4095. One 12-bit register will hold a value for the ON time and the other 12-bit register will hold the value for the OFF time. The ON and OFF times are compared with the value of a 12-bit counter that will be running continuously from 0000h to 0FFFh (0 to 4095 decimal).

Update on ACK requires all 4 PWM channel registers to be loaded before outputs will change on the last ACK.

The ON time, which is programmable, will be the time the LED output will be asserted and the OFF time, which is also programmable, will be the time when the LED output will be negated. In this way, the phase shift becomes completely programmable. The resolution for the phase shift is 1⁄ 4096 of the target frequency.

So you have to set all 4 registers together for anything to happen.

There are also some examples shown in the datasheet as well which explain it better.

In simple terms:

  • There is a free-running counter that counts from 0 to 4095
  • When the ON time matches the counter the LED turns on.
  • When the OFF time matches the counter the LED turns off.
  • If a channel is "FULL OFF" it will be off regardless.
  • If a channel is "FULL ON" and not "FULL OFF" it will be on regardless.
  • "FULL OFF" always takes priority over everything else - even "FULL ON".

Some simple examples:

  • All off: ON=0x0000 OFF=0x1000
  • All on full: ON=0x1000 OFF=0x0000
  • 50% duty: ON=0x0000 OFF=0x0800
  • 25% duty: ON=0x0000 OFF=0x0400
  • 25% duty with phase shift: ON=0x0100 OFF=0x0500
  • Yep, you're right. I did it, I have to update the 4 registers for all_on state, and again all 4 registers for all_off state. – Perch Eagle Jan 25 at 11:23
  • 1
    @PerchEagle The datasheet isn't that obvious. As you can see by the edit history of my answer it took me a while to understand it fully. – Majenko Jan 25 at 11:24
  • Thanks dude again for the help I really appreciate it, it's not the first time you help me, now I learned that, I can proceed to go to the pwm operations and develop the library. – Perch Eagle Jan 25 at 12:33
  • I have a quick question, why there's 12-bit for on and 12-bit for off. I wrote different values for only on time and got certain results and different results for off time, and also got different results. So what's the deal exactly with this chip? Is the full range of this device is 4096 ON + 4096 OFF = 8192. – Perch Eagle Jan 31 at 6:20
  • 1
    No. There is a single 12 bit counter. It turns on or off when the counter matches the on or off value. That way you can control the phase as well as the duty cycle. – Majenko Jan 31 at 9:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.