Anyone with experience with NxP PCA9955B and gradation control? - Page 1
Forum section: electronics / projects

author: VinzC
author_rank: Frequent Contributor
timestamp: October 28, 2016, 04:17:31 pm
content: Hi all.I'm currently struggling with a 16-channel LED driver from NxP. So far everything works nicely... except gradation. To make it short, thePCA9955B(note the B suffix) has 16 LED channels that can work in any combination of PWM, variable current and dimming. It has a load of registers that you access through I²C. The minimum you need to do is set the individual current *and* PWM ratio for individual or all channels.I'm using anATmega64M1to drive the thing (hence software I²C with a library that I've written, which also supports clock stretching) and everything works fine as to address thePCA9955Bregisters. The issue is when I want to use gradation (there is a bunch of register to setup); I seem to follow the recommended steps yet gradation doesn't work.Here are the values I send to the LED driver:Code:/** To enable the gradation operation, the following steps are required (from the datasheet):** 1.Program all gradation control registers except the gradation start*bit in GRAD_CNTL register** 2.Program either LDRx = 01 (LED fully ON mode) only, or LDRx = 10*or 11 (PWM control mode) with individual brightness control PWMx*register for duty cycle.** 3.Program output current value IREFx register to non-zero, which will*enable LED output.** 4.Set the gradation start bit in GRAD_CNTL register for enabling*gradation operation.*/const static uint8_t led_driver_init[] PROGMEM = {0x00,// MODE1 (default: 0b10001001): roll-over @ 0x49,// no sub-address, no all-call/* _BV(DIMMING) */ 0,// MODE2: group=dimming, linear adjust, doesn't matter anyway// LEDOUT[3:0]:// 0xAA, 0xAA, 0xAA, 0xAA,// - control through PWMx and PWMALL0xFF, 0xFF, 0xFF, 0xFF,// - control through PWMx and GRPPWM, neither does it matter...0x80, 0x00,// GRPPWM, GRPFREQ};pca9955_write_P( LED_DRIVER_ID, MODE1 /* start register, autoincremented */, led_driver_init, sizeof(led_driver_init) );// Define gradation groupsconst static uint8_t graddata[] PROGMEM = {/* RAMP_RATE_GRP2 */0xC, 16, 0b11010100, 250,/* RAMP_RATE_GRP3 */0xC, 16, 0b11010100, 250,/* GRAD_MODE_SEL1 */0xFF,// Channels 8 to 15 enabled/* GRAD_CNTL */0x50,// Continuous (group 2 & 3)/* stuffing */0, 0, 0, 0, 0, 0};pca9955_write_P( LED_DRIVER_ID, GRAD_MODE_SEL1, &graddata, 1 );pca9955_write_P( LED_DRIVER_ID, RAMP_RATE_GRP2, &graddata, 8 );pca9955_write_P( LED_DRIVER_ID, GRAD_CNTL, &graddata, 1 );// Set all IREF to the default current (EEPROM)pca9955_iref( LED_DRIVER_ID, IREFALL, read_idle_current_default() /* 0x4 */ );// Set all PWM to the default value (EEPROM)pca9955_pwm( LED_DRIVER_ID, PWMALL, read_pwm_default() /* 0x20 */ );uint8_t cntrl = 0xF0;pca9955_write( LED_DRIVER_ID, GRAD_CNTL, &cntrl, 1 );Ramp settings should be something like ramp up & down with 8ms single-step period, 250 times up, 250 times down. Should give approximately a 1 or 2 seconds-long effect.When I read back registersRAMP_RATE_GRP2throughIREF_GRP2(i.e.0x34through0x37) I get four zeroes. I also have set a function that I can call at will to overwrite the same registers with the values above, I still get zeroes. Examples are either sparse or non-existent — all I have found is a C++ class to manage that thing but I'm doing the same. Just don't know the proper initialization sequence — if that's the matter at all...I've also tried without the small initialization bit (with MODE1 & MODE2 registers), no darn change. I'm lost. Does anybody have an idea to make this thing work?Thanks in advance for any hint/suggestion.

author: VinzC
author_rank: Frequent Contributor
timestamp: October 31, 2016, 08:31:57 am
content: Ok, I'm trying to nail down the issue, whether it's my code or anything else and it appears the chip seems to function normally with the original code I found ondeveloper.mbed.com— note the latter platform doesn't support AVR but the code in question is platform-agnostic. I've tried the gradation control using classesPCA9955A and PCA995xA(all in the same ZIP package). Only those two classes are required if you already have a working I²C library. Only minor changes are required to the sample code, like replacing "wait()" with "_delay_ms()". I'm still trying to dissect the code samples until I find what I've been doing wrong. Update soon...

author: Crystal-JU-206
author_rank: Newbie
timestamp: November 01, 2016, 08:48:25 am
content: I'd like to buy OSCSMD-7050. Who knows where to get?

author: VinzC
author_rank: Frequent Contributor
timestamp: December 02, 2016, 10:00:25 am
content: This is an update to my previous post. The issue has been long found, just that I forgot to update. The thing is in certain circumstances PCA9955 expects some registers to be set before others can be used. In my case I was setting gradation registers before I enabled gradation — IIRC.This is how you use gradation with that chip:define gradation groups (ramp up/down, step, hold time & current) with registersRAMP_RATE_GRPx,STEP_TIME_GRPx,HOLD_CNTL_GRPx&IREF_GRPxassign a gradation group ID (between0and3) to the channel you want to animate using registersGRAD_GRP_SELxenable gradation for any of the 16 channels using registersGRAD_MODE_SEL0orGRAD_MODE_SEL1start gradation for all of the assigned groups (see2.) with registerGRAD_CNTLIt's long and it's tedious but the chip is powerful and honestly worth the work.Gradation is done using 4 groups, which any LED can belong to. A LED channel can only belong to one group. You can animate a channel only using the group the LED is assigned therefore there can be only 4 distinct animation types active at a time but any channel can be animated individually using registersGRAD_MODE_SELx.