PCA9685 how to get the duty cycles figured out for RGB

Hey everyone, I am new to arduino and recently I have been messing with some dumb arduino non-addressable strips. I am currently doing a project with them where I am trying to control 14 individual strips using pwm signals. For expanding the pwm outputs in the arduino I have used 3 PCA9685 boards chained together giving me 45 pwm outputs and as the driver to the LEDs I have used a couple of uln2003a modules connected to the PCA9685 boards. But to get a wider range of colors for these LEDs I have to determine the time each channel in RGB stays on for in the final parameter(a) of PCA9685.setPWM(1, 0, a); but I have not been able to figure this out since I am only familiar with the normal RGB format in which to each channel the maximum value is 256, can someone please assist me. All response will be appreciated certainly

Fore example how can I get orange with rgb value of (255,165,0)

Does anyone have suggestions on how to do this, I do not know if picked the correct category for this kind of things.

Hey everyone, I am new to arduino and recently I have been messing with some dumb arduino non-addressable strips. I am currently doing a project with them where I am trying to control 14 individual strips using pwm signals. For expanding the pwm outputs in the arduino I have used 3 PCA9685 boards chained together giving me 45 pwm outputs and as the driver to the LEDs I have used a couple of uln2003a modules connected to the PCA9685 boards. But to get a wider range of colors for these LEDs I have to determine the time each channel in RGB stays on for in the final parameter(a) of PCA9685.setPWM(1, 0, a); but I have not been able to figure this out since I am only familiar with the normal RGB format in which to each channel the maximum value is 256, can someone please assist me. All response will be appreciated certainly. For example how can I get Orange using this system?

The PCA9685 is 12 bit so the max value is 4095. Basically, if you multiply the 8 bit value by 16 you get the equivalent of (255,165,0).

So instead of (255,165, 0) you use (4095, 2560, 0); note that 4095 is just the end of the 'scale', not 255 * 16.


Please don't be impatient, give your topic chance to go around the world.

Hi Mr. sterretje, Thanks very much for the quick reply I will try this and let you know if it works

Please do not cross post; it wastes people's time. Your topics have been merged.

Pick a category and stick to it for the problem; if the category that you did choose is really inappropriate the topic will be moved. Please read How to get the best out of this forum (again).

Extremely Sorry Mr.sterretje I am quite new to the forum and I have to get this problem figured out by the end of the day since I have to finish this project by tonight. So, I had to do so. Promise it will never happen again :pray: :pray:

So, red should be 4095, green should be 2560 and blue should be 0 to make orange, am I right?

Something like that, yeah. Get your calculator out to verify, I see that 2560 should have been 2640; apologies. I don't think it matters much though.

I tested it but it does not work though I get like a green color

Start with (4095,0,0); you should get red.
Next use (0, 4095, 0); you should get green.
Lastly, use (0, 0, 4095); you should get blue.

Please post your code; don't forget the code tags.

#include "Wire.h"
#include "Adafruit_PWMServoDriver.h"

Adafruit_PWMServoDriver PCA9685 = Adafruit_PWMServoDriver(0x40, Wire);

void setup() {
  Serial.begin(9600);
  Wire.begin();
  PCA9685.begin();
  PCA9685.setPWMFreq(1000);  
}

void loop() {

  PCA9685.setPWM(1, 0, 0);
  PCA9685.setPWM(3, 0, 2640);
  PCA9685.setPWM(7, 0, 4095);
}

my code is this

This code is to get orange

I did this and it worked fine with red,green,blue

I fiddled around with the values for each of the channel and the closest to orange I could get was a combination of (4095,150,0)

You did not.

This is the third and last time you've been asked to stop cross-posting. The next time you will be spending a great long while away from the forum.

Please show a schematic of your project and a clear photograph of how you have everything connected.
Specifically in the schematic I'd be looking for the LEDs being connected correctly to pins 1 (blue), 3 (green) and 7 (red).

Start by removing this complication and using small LEDs with a simple series resistor instead. For testing it doesn't really matter which colors you use; you just want to verify all channels work the way you intend them to work.

I bet that you have a hardware design error.

What kind of LEDs does your project need to use?

Be aware that the intensity of LEDs is not the same as on a computer screen.

The below program can make your life easier to fine tune the colours. You will need to add the initialisation of the PCA9685.

#include "Wire.h"
#include "Adafruit_PWMServoDriver.h"

Adafruit_PWMServoDriver PCA9685 = Adafruit_PWMServoDriver(0x40, Wire);
enum COLOURMODE
{
  RED,
  GREEN,
  BLUE,
};

// selection of colour to change
COLOURMODE colourMode = RED;
// allow fine tuning (steps of 1)
bool fineTune = false;

// default values for RGB
int redValue = 4095;
int greenValue = 2640;
int blueValue = 0;


void setup()
{
  Serial.begin(115200);
  Serial.println(F("Colour picker"));
}

void loop()
{
  if (Serial.available())
  {
    char ch = Serial.read();
    switch (ch)
    {
      case 'r':
      case 'R':
        colourMode = RED;
        Serial.println(F("Setting RED"));
        Serial.print(F("Current value = "));
        Serial.println(redValue);
        break;
      case 'g':
      case 'G':
        colourMode = GREEN;
        Serial.println(F("Setting GREEN"));
        Serial.print(F("Current value = "));
        Serial.println(greenValue);
        break;
      case 'b':
      case 'B':
        colourMode = BLUE;
        Serial.println(F("Setting BLUE"));
        Serial.print(F("Current value = "));
        Serial.println(blueValue);
        break;
      case 'f':
      case 'F':
        // toggle fine tuning
        fineTune = !fineTune;
        Serial.print(F("finetune = "));
        Serial.println(fineTune == true ? F("true") : F("false"));
        break;
      case '+':
        incValue();
        break;
      case '-':
        decValue();
        break;
    }

    // print the set values of R, G and B
    printRGB();
    Serial.println();
    // set the colour
    setColour();
  }
}

/*
   Increment value of a colour
*/
void incValue()
{
  switch (colourMode)
  {
    case RED:
      if (fineTune == false)
        redValue += 16;
      else
        redValue++;
      if (redValue > 4095)
        redValue = 4095;
      break;
    case GREEN:
      if (fineTune == false)
        greenValue += 16;
      else
        greenValue++;
      if (greenValue > 4095)
        greenValue = 4095;
      break;
    case BLUE:
      if (fineTune == false)
        blueValue += 16;
      else
        blueValue++;
      if (blueValue > 4095)
        blueValue = 4095;
      break;
  }
}

/*
   Decrement value of a colour
*/
void decValue()
{
  switch (colourMode)
  {
    case RED:
      if (fineTune == false)
        redValue -= 16;
      else
        redValue--;
      if (redValue < 0)
        redValue = 0;
      break;
    case GREEN:
      if (fineTune == false)
        greenValue -= 16;
      else
        greenValue--;
      if (greenValue < 0)
        greenValue = 0;
      break;
    case BLUE:
      if (fineTune == false)
        blueValue -= 16;
      else
        blueValue--;
      if (blueValue < 0)
        blueValue = 0;
      break;
  }
}

/*
   Print R, G and B values
*/
void printRGB()
{
  Serial.print(F("r = ")); Serial.println(redValue);
  Serial.print(F("g = ")); Serial.println(greenValue);
  Serial.print(F("b = ")); Serial.println(blueValue);
}

/*
   Set the colour on the PCA9685
*/
void setColour()
{
  PCA9685.setPWM(1, 0, blueValue);
  PCA9685.setPWM(3, 0, greenValue);
  PCA9685.setPWM(7, 0, redValue);
}

In serial monitor

  1. Use the letters R, G and B to select a colour to change.
  2. Use + and - to increment/decrement the value for a colour.
  3. By default the program increments/decrements in steps of 16; use F to toggle between steps of 1 and steps of 16.

It's tested with the exception of the PCA9685 related stuff.