Dimming LEDs with hardware PWM?

I am moving some hardware from DaisyDuino over to libdaisy (mainly due to space constraints) and I have trouble getting the RGB-LED to dimm properly. Over in Arduino-land what I would do is to call analogWrite(pin, 255) for each of the three color channels and it would work as expected.

Now I am aware there is a Led and a RgbLed implementation, but the code for the LED doesn’t look as if it is using hardware PWM?

So my questions:

  1. Is there any way to use hardware PWM on the pins that should support it (or any usable allternative to analogWrite)?

  2. If there is none, is there any example how to setup the a timer interrupt that gives predictable results with the LEDs?

As of now if I run the Led.Set(val) method, any other work that happens in the main loop leads to the LED blinking off and on or not updating as desired – seeing the implementation this is not really surprising. Any pointers to a good solution?

The LED Class is a simple Software PWM. We are still working on a hardware PWM.

Is the RGB LED you’re using something like this one?

1 Like

Yes, I use a Kingbright WP154A4SUREQBFZGW – a 4-terminal common kathode LED. For a schematic see: https://code.hfbk.net/sdiy/daisyy/daisyy-hardware/-/raw/main/images/schematic-1.jpg

I rule out hardware issues, it is on a soldered PCB that works flawlessly and very reliably with my DaisyDuino code. Here my Arduino RgbLed class from said code:

class RGBLed {
  int pin_red;
  int pin_green;
  int pin_blue;

  public:
    RGBLed(int pin_red, int pin_green, int pin_blue);
    void init();
    void off();
    void setColor(int r, int g, int b);
};

RGBLed::RGBLed(int pin_red, int pin_green, int pin_blue) {
  this->pin_red = pin_red;
  this->pin_green = pin_green;
  this->pin_blue = pin_blue;
}

void RGBLed::init() {
  pinMode(this->pin_red, OUTPUT);
  pinMode(this->pin_green, OUTPUT);
  pinMode(this->pin_blue, OUTPUT);
}

void RGBLed::off() {
  digitalWrite(this->pin_red, LOW);
  digitalWrite(this->pin_green, LOW);
  digitalWrite(this->pin_blue, LOW);
}

void RGBLed::setColor(int r, int g, int b) {
  r = min(255, max(0, r));
  g = min(255, max(0, g));
  b = min(255, max(0, b));
  analogWrite(this->pin_red, r);
  analogWrite(this->pin_green, g);
  analogWrite(this->pin_blue, b);
}

Creating the object as follows:

// RGB LED               R    G    B
RGBLed rgb_led = RGBLed(A10, A11, A9);

Of course this all boils down to the analogWrite-function from arduino.h

Looks to me like the Led class, and RgbLed, are set up to be updated at 1kz. Which is the same rate as the Audio callback with 48 buffer size.

Updated from the audio callback, the software PWM would be unaffected by whatever happens in main().

1 Like

Aha! Now I get how it is meant to be used. I will investigate whether this works for my usecase.
This is certainly info that belongs into the docu.

But I guess in the long run hardware PWM would be even better.

Update: Okay that seems to work well for my purposes as of now.

2 Likes