0

I have a problem. I am controlling my WS2812B using an Arduino, but I have a problem with the breathing effect. I created a class in the code that looks like this:

String breathDirection = "Down";

void breath_effect()
{
fill_solid(leds, TOTAL_LEDS, primary);
float currentBrightness = FastLED.getBrightness();

if (currentBrightness <= 1)
{
  breathDirection = "Up";
}
else if (currentBrightness >= brightness)
{
  breathDirection = "Down";
}

float brightnessCorrection = static_cast<float>(brightness) / 200;
if (breathDirection == "Down")
{
  currentBrightness = currentBrightness - brightnessCorrection;
  FastLED.setBrightness(currentBrightness);
}
else if (breathDirection == "Up")
{
  Serial.println("Binnen");
  Serial.println(currentBrightness);
  currentBrightness = currentBrightness + brightnessCorrection;
  Serial.println(currentBrightness);
  FastLED.setBrightness(currentBrightness);
}
}

Now the breathing effect only works when the brightness variable is set to 200. If I set it on a different value below 200, it goes down, but never comes up. The currentBrightness is each round the same value. What is going wrong here?

A. Vreeswijk
  • 822
  • 1
  • 19
  • 57

3 Answers3

0

You need to set global variables:

//Global scope:

const float _brightInterval = 1.0f;
const float _maxBright = 255.0f; //i'm not sure whats your max bright here
const float _minBright = 1.0f;

float _brightness = _maxBright;

And instead of strings i would use states. It's faster and saves memory.

enum states
    {
        hold,
        down,
        up
    };
states _state;

then in the loop do something like this:

switch (_state)
    {
    case states::down:
        _brightness -= _brightInterval;
        break;
    case states::up:
        _brightness += _brightInterval;
        break;
    case states::hold:
        _brightness -= _brightInterval / 10.0f; //hold makes it go down but in a lower rate.
    default:
        break;
    }

    if (_brightness >= _maxBright)
        _state = states::hold;
    else if (_brightness <= (_maxBright - 50.0f) && _state == states::hold)
        _state = states::down;
    else if (_brightness <= _minBright)
        _state = states::up;

FastLED.setBrightness(_brightness);

Try to change those values to achieve your desired effect. The (_maxBright - 50.0f) in the second if, is the step when it starts to accelerate down. change it to maybe (_maxBright - 10.0f)

Martin
  • 66
  • 5
0

The best would be to write some value examples on paper and do a manual walkthrough your breathing logic. Some issues I saw on first quick look:

if (currentBrightness <= 0)  ==>    if (currentBrightness == 0) // truncate float to uint8_t

So here we only have up when 0, if its 1 this case is skipped. Imho the logic has to be

     if (currentBrightness == 0 || brightness > currentBrightness)
      {
          breathDirection = "Up";
      } 
      else if (currentBrightness == 255 || currentBrightness >= brightness)
  ....

it makes no sense using float here because the port takes only values from 0 to 255. If a float is delivered truncate it by converting it to uint8_t. Drawing a state diagram helps with logics like that. The division by 200 delivers for values < 200 always 0 (int division)

Codebreaker007
  • 2,911
  • 1
  • 10
  • 22
0

You could try using a breathing function, which is just a wave-type function such as a circular wave, triangular wave, or gaussian wave. Here's an example with a triangular wave (taken from my tutorial: Arduino Breathing LED Functions):

// RGB LED Triangle Wave Breathing LED

int led_pins[4] = {3,5,6};
int jj = 0; // 0 = red, 1 = green, 2 = blue
float smoothness_pts = 500;//larger=slower change in brightness

void setup() {
  Serial.begin(9600);
  for (int ii = 0;ii<sizeof(led_pins)/sizeof(int);ii++){
    pinMode(led_pins[ii],OUTPUT);
  }
}

void loop() {
  for (int ii=0;ii<smoothness_pts;ii++){
    float pwm_val = 255.0*(1.0 -  abs((2.0*(ii/smoothness_pts))-1.0));
    analogWrite(led_pins[jj],int(pwm_val));
    delay(5);
    Serial.println(int(pwm_val));
  }
}

You can set the brightness parameter in the float 'pwm_val' to anything from 1 - 255 (it's 255.0 here, by default (max of PWM on Arduino)). Here's the resulting 'breathing' profile printed out to the serial plotter:

RGB LED Triangle Breathing Function

Maker Portal
  • 61
  • 1
  • 3