Full LED switching off via pwm

Hi, I have my own library for controlling LEDs that I created a few years ago when I was learning C/C++.

Now after about a year I am going back to arduino. And I made a simple bluetooth keyboard. Which has a braid&paste&selectAll function, and now I added an antiAfk function. Which sends a signal once every x minutes, like the i key, to prevent the game from kicking in due to non-creativity. The keyboard has a single LED. Which flashes every time a key is pressed. If I turn on antiAfk, it flashes while the mode is active.

So I have extended the library to control the leds so that the leds can blink.

The original version of the library:

class LED {
  private:
    int pin;
    boolean state = LOW;
    void init(boolean);
  
  public:
    LED (int);
    void on();
    void off();
    void switchState();
    boolean returnState();
};

LED::LED (int p) {
  pin = p;
  pinMode(pin, OUTPUT);
  digitalWrite(pin, state);
}

void LED::on(){
  init(HIGH);
}

void LED::off(){
  init(LOW);
}

void LED::switchState() {
  init(!state);
}

void LED::init(boolean s) {
  state = s;
  Serial.print("I set ");
  Serial.print("led pin ");
  Serial.print(pin);
  Serial.print(" ");
  Serial.println(state ? "On" : "Off");
  digitalWrite(pin, state);
}

boolean LED::returnState() {
  return state;
}

Library enhanced with blinking:

#include <Arduino.h>
#include "Led.h"

class FlashingLed : public LED
{
private:
  int period = 0;
  unsigned long lastJob = 0;

public:
  FlashingLed(int, int);
  void blink();
  void breath();
};

FlashingLed::FlashingLed(int pin, int _period) : LED(pin)
{
  period = _period;
  lastJob = millis();
}

void FlashingLed::blink()
{
  if (lastJob + period / 2 < millis())
  {
    switchState();
    lastJob = millis();
  }
}
}

But the blinking itself proved to be inappropriate especially in the evening. So there was a further extension to smooth flashing. Which turned out to be ideal

the final version looks like this:

//Led.h
class LED
{
private:
  int pin;
  boolean state = LOW;
  void set(boolean, boolean);
  void fadeOn(int, unsigned int);
  void fadeOff(int, unsigned int);

public:
  LED(int);
  void on();
  void off();
  void switchState(boolean);
  boolean returnState();
};

LED::LED(int p)
{
  pin = p;
  pinMode(pin, OUTPUT);
  digitalWrite(pin, state);
}

void LED::on()
{
  set(HIGH, false);
}

void LED::off()
{
  set(LOW, false);
}

void LED::switchState(boolean breath = false)
{
  set(!state, breath);
}

void LED::set(boolean s, boolean breath)
{
  state = s;
  Serial.print("I set ");
  Serial.print("led pin ");
  Serial.print(pin);
  Serial.print(" ");
  Serial.println(state ? "On" : "Off");
  if (breath)
  {
    fadeOn(5, 1000);
    fadeOff(5, 1000);
  }
  else
  {
    digitalWrite(pin, state);
  }
}

boolean LED::returnState()
{
  return state;
}

void LED::fadeOn(int increment, unsigned int time)
{
  for (byte i = 0; i < 255; i += increment)
  {
    analogWrite(pin, i);
    delay(time / (255 / 5));
  };
}

void LED::fadeOff(int decrement, unsigned int time)
{
  for (byte i = 255; i > 0; i -= decrement)
  {
    analogWrite(pin, i);
    delay(time / (255 / 5));
  };
}

//FlashingLed.h
#include <Arduino.h>
#include "Led.h"

class FlashingLed : public LED
{
private:
  int period = 0;
  unsigned long lastJob = 0;

public:
  FlashingLed(int, int);
  void blink();
  void breath();
};

FlashingLed::FlashingLed(int pin, int _period) : LED(pin)
{
  period = _period;
  lastJob = millis();
}

void FlashingLed::blink()
{
  if (lastJob + period / 2 < millis())
  {
    switchState();
    lastJob = millis();
  }
}

void FlashingLed::breath()
{
  if (lastJob + period/2 < millis()){
    switchState(true);
    lastJob = millis();
  }
}

Everything works as it should, except for one problem. When I want to turn the blinking off. The diode does not turn off completely and a residual voltage of about 0.2-0.4V remains. And the diode still glows very gently. And as a bonus, the diode then doesn't respond to other key presses.

So my question is how to finalize the library so that it goes off completely.

Please show the example sketch that demonstrate problem with switching leds off

your for loop will not decrement to 0.

this might do:

  for (int i = 255; i >= 0; i -= decrement )
  {
    //analogWrite(pin, i);
    //delay(time / (255 / 5));
    Serial.println(i);
  };

two comments:
don't use HW access (pinMode, digitalWrite) in the constructor. It will be executed before setup and this can cause troubles on some microcontrollers. Put them in a begin() method and call it in your setup.

instead of blocking your code with delays you should switch over to millis(). Than your library is really reusable. Otherwise your fading led will block other code.
If you have some time you can check my LED Toolkit and test with the "smooth LED"
https://werner.rothschopf.net/microcontroller/202202_tools_led_en.htm

Thanks for the advice, in the end the problem was in the condition itself I was missing the equality comparison i.e. i >= 0. In addition there was also a wrong data type. When the overflow occurred and the final condition of the loop could not be met

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.