Coder Social home page Coder Social logo

jandelgado / jled Goto Github PK

View Code? Open in Web Editor NEW
318.0 22.0 51.0 7.78 MB

Non-blocking LED controlling library for Arduino and friends.

License: MIT License

C++ 98.85% Makefile 0.51% Shell 0.01% CMake 0.04% C 0.58%
arduino led effect controlling-leds fade breathe non-blocking esp32 esp8266 embedded

jled's Introduction

Preferring Python? I just released jled-circuitpython, a JLed implementation for CircuitPython and MicroPython.

JLed - Advanced LED Library

run tests Coverage Status

An embedded C++ library to control LEDs. It uses a non-blocking approach and can control LEDs in simple (on/off) and complex (blinking, breathing and more) ways in a time-driven manner.

JLed got some coverage on Hackaday and someone did a video tutorial for JLed - Thanks!

JLed in action Interactive JLed playground
JLed in action jled running in the browser

Example

// breathe LED (on gpio 9) 6 times for 1500ms, waiting for 500ms after each run
#include <jled.h>

auto led_breathe = JLed(9).Breathe(1500).Repeat(6).DelayAfter(500);

void setup() { }

void loop() {
  led_breathe.Update();
}

Contents

Features

  • non-blocking
  • effects: simple on/off, breathe, blink, candle, fade-on, fade-off, user-defined (e.g. morse)
  • supports inverted polarity of LED
  • easy configuration using fluent interface
  • can control groups of LEDs sequentially or in parallel
  • Portable: Arduino, ESP8266, ESP32, Mbed, Raspberry Pi Pico and more platforms compatible, runs even in the browser
  • supports Arduino, mbed, Raspberry Pi Pico and ESP32 ESP-IDF SDK's
  • well tested

Cheat Sheet

JLed Cheat Sheet

Installation

Arduino IDE

In the main menu of the Arduino IDE, select Sketch > Include Library > Manage Libraries... and search for jled, then press install.

PlatformIO

Add jled to your library dependencies in your platformio.ini project file, e.g.

...
[env:nanoatmega328]
platform = atmelavr
board = nanoatmega328
framework = arduino
lib_deps=jled
...

Usage

First, the LED object is constructed and configured, then the state is updated with subsequent calls to the Update() method, typically from the loop() function. While the effect is active, Update returns true, otherwise false.

The constructor takes the pin, to which the LED is connected to as the only argument. Further configuration of the LED object is done using a fluent interface, e.g. JLed led = JLed(13).Breathe(2000).DelayAfter(1000).Repeat(5). See the examples section below for further details.

Output pipeline

First the configured effect (e.g. Fade) is evaluated for the current time t. JLed internally uses unsigned bytes to represent brightness values, ranging from 0 to 255. Next, the value is scaled to the limits set by MinBrightness and MaxBrightness (optionally). When the effect is configured for a low-active LED using LowActive, the brightness value will be inverted, i.e., the value will be subtracted from 255. Finally the value is passed to the hardware abstraction, which might scale it to the resolution used by the actual device (e.g. 10 bits for an ESP8266). Finally the brightness value is written out to the configure GPIO.

┌───────────┐    ┌────────────┐    ┌─────────┐    ┌────────┐    ┌─────────┐    ┌────────┐
│ Evaluate  │    │  Scale to  │    │  Low    │YES │ Invert │    │Scale for│    │Write to│
│ effect(t) ├───►│ [min, max] ├───►│ active? ├───►│ signal ├───►│Hardware ├───►│  GPIO  │
└───────────┘    └────────────┘    └────┬────┘    └────────┘    └───▲─────┘    └────────┘
                                        │ NO                        │
                                        └───────────────────────────┘

Effects

Static on and off

Calling On(uint16_t period=1) turns the LED on. To immediately turn a LED on, make a call like JLed(LED_BUILTIN).On().Update(). The period is optional and defaults to 1ms.

Off() works like On(), except that it turns the LED off, i.e., it sets the brightness to 0.

Use the Set(uint8_t brightness, uint16_t period=1) method to set the brightness to the given value, i.e., Set(255) is equivalent to calling On() and Set(0) is equivalent to calling Off().

Technically, Set, On and Off are effects with a default period of 1ms, that set the brightness to a constant value. Specifying a different period has an effect on when the Update() method will be done updating the effect and return false (like for any other effects). This is important when for example in a JLedSequence the LED should stay on for a given amount of time.

Static on example
#include <jled.h>

// turn builtin LED on after 1 second.
auto led = JLed(LED_BUILTIN).On().DelayBefore(1000);

void setup() { }

void loop() {
  led.Update();
}

Blinking

In blinking mode, the LED cycles through a given number of on-off cycles, on- and off-cycle durations are specified independently. The Blink() method takes the duration for the on- and off cycle as arguments.

Blinking example
#include <jled.h>

// blink internal LED every second; 1 second on, 0.5 second off.
auto led = JLed(LED_BUILTIN).Blink(1000, 500).Forever();

void setup() { }

void loop() {
  led.Update();
}

Breathing

In breathing mode, the LED smoothly changes the brightness using PWM. The Breathe() method takes the period of the effect as an argument.

Breathing example
#include <jled.h>

// connect LED to pin 13 (PWM capable). LED will breathe with period of
// 2000ms and a delay of 1000ms after each period.
auto led = JLed(13).Breathe(2000).DelayAfter(1000).Forever();

void setup() { }

void loop() {
  led.Update();
}

It is also possible to specify fade-on, on- and fade-off durations for the breathing mode to customize the effect.

// LED will fade-on in 500ms, stay on for 1000ms, and fade-off in 500ms.
// It will delay for 1000ms afterwards and continue the pattern.
auto led = JLed(13).Breathe(500, 1000, 500).DelayAfter(1000).Forever();

Candle

In candle mode, the random flickering of a candle or fire is simulated. The builder method has the following signature: Candle(uint8_t speed, uint8_t jitter, uin16_t period)

  • speed - controls the speed of the effect. 0 for fastest, increasing speed divides into halve per increment. The default value is 7.
  • jitter - the amount of jittering. 0 none (constant on), 255 maximum. Default value is 15.
  • period - Period of effect in ms. The default value is 65535 ms.

The default settings simulate a candle. For a fire effect for example use call the method with Candle(5 /*speed*/, 100 /* jitter*/).

Candle example
#include <jled.h>

// Candle on LED pin 13 (PWM capable). 
auto led = JLed(13).Candle();

void setup() { }

void loop() {
  led.Update();
}

FadeOn

In FadeOn mode, the LED is smoothly faded on to 100% brightness using PWM. The FadeOn() method takes the period of the effect as an argument.

The brightness function uses an approximation of this function (example with period 1000):

fadeon function

FadeOn example
#include <jled.h>

// LED is connected to pin 9 (PWM capable) gpio
auto led = JLed(9).FadeOn(1000).DelayBefore(2000);

void setup() { }

void loop() {
  led.Update();
}

FadeOff

In FadeOff mode, the LED is smoothly faded off using PWM. The fade starts at 100% brightness. Internally it is implemented as a mirrored version of the FadeOn function, i.e., FadeOff(t) = FadeOn(period-t). The FadeOff() method takes the period of the effect as argument.

Fade

The Fade effect allows to fade from any start value from to any target value to with the given duration. Internally it sets up a FadeOn or FadeOff effect and MinBrightness and MaxBrightness values properly. The Fade method take three arguments: from, to and duration.

fade from-to

Fade example
#include <jled.h>

// fade from 100 to 200 with period 1000
auto led = JLed(9).Fade(100, 200, 1000);

void setup() { }

void loop() {
  led.Update();
}

User provided brightness function

It is also possible to provide a user defined brightness evaluator. The class must be derived from the jled::BrightnessEvaluator class and implement two methods:

  • uint8_t Eval(uint32_t t) const - the brightness evaluation function that calculates a brightness for the given time t. The brightness must be returned as an unsigned byte, where 0 means LED off and 255 means full brightness.
  • uint16_t Period() const - period of the effect.

All time values are specified in milliseconds.

The user_func example demonstrates a simple user provided brightness function, while the morse example shows how a more complex application, allowing you to send morse codes (not necessarily with an LED), can be realized.

User provided brightness function example

The example uses a user provided function to calculate the brightness.

class UserEffect : public jled::BrightnessEvaluator {
  public:
    uint8_t Eval(uint32_t t) const override {
        // this function changes between 0 and 255 and
        // vice versa every 250 ms.
        return 255*((t/250)%2);
    }
    // duration of effect: 5 seconds.
    uint16_t Period() const override { return 5000; }
};

Delays and repetitions

Initial delay before effect starts

Use the DelayBefore() method to specify a delay before the first effect starts. The default value is 0 ms.

Delay after effect finished

Use the DelayAfter() method to specify a delay after each repetition of an effect. The default value is 0 ms.

Repetitions

Use the Repeat() method to specify the number of repetitions. The default value is 1 repetition. The Forever() methods sets to repeat the effect forever. Each repetition includes a full period of the effect and the time specified by DelayAfter() method.

State functions

Update

Call Update() periodically to update the state of the LED. Update returns true if the effect is active, and false when it finished.

IsRunning

IsRunning() returns true if the current effect is running, else false.

Reset

A call to Reset() brings the JLed object to its initial state. Use it when you want to start-over an effect.

Immediate Stop

Call Stop() to immediately turn the LED off and stop any running effects. Further calls to Update() will have no effect, unless the Led is reset using Reset() or a new effect is activated. By default, Stop() sets the current brightness level to MinBrightness.

Stop() takes an optional argument mode of type JLed::eStopMode:

  • if set to JLed::eStopMode::KEEP_CURRENT, the LEDs current level will be kept
  • if set to JLed::eStopMode::FULL_OFF the level of the LED is set to 0, regardless of what MinBrightness is set to, effectively turning the LED off
  • if set to JLed::eStopMode::TO_MIN_BRIGHTNESS (default behavior), the LED will set to the value of MinBrightness
// stop the effect and set the brightness level to 0, regardless of min brightness
led.Stop(JLed::eStopMode::FULL_OFF);

Misc functions

Low active for inverted output

Use the LowActive() method when the connected LED is low active. All output will be inverted by JLed (i.e., instead of x, the value of 255-x will be set).

Minimum- and Maximum brightness level

The MaxBrightness(uint8_t level) method is used to set the maximum brightness level of the LED. A level of 255 (the default) is full brightness, while 0 effectively turns the LED off. In the same way, the MinBrightness(uint8_t level) method sets the minimum brightness level. The default minimum level is 0. If minimum or maximum brightness levels are set, the output value is scaled to be within the interval defined by [minimum brightness, maximum brightness]: a value of 0 will be mapped to the minimum brightness level, a value of 255 will be mapped to the maximum brightness level.

The uint_8 MaxBrightness() const method returns the current maximum brightness level. uint8_t MinBrightness() const returns the current minimum brightness level.

Controlling a group of LEDs

The JLedSequence class allows controlling a group of JLed objects simultaneously, either in parallel or sequentially, starting the next JLed effect when the previous finished. The constructor takes the mode (PARALLEL, SEQUENCE), an array of JLed objects and the size of the array, e.g.

JLed leds[] = {
    JLed(4).Blink(750, 250).Repeat(10),
    JLed(3).Breathe(2000).Repeat(5);
};

auto sequence = JLedSequence(JLedSequence::eMode::PARALLEL, leds).Repeat(2);

void setup() {
}

void loop() {
    sequence.Update();
}

Because the size of the array is known at compile time in this example, it is not necessary to pass the array size to the constructor. A second constructor is available in case the JLed array is created dynamically at runtime: JLed(eMode mode, JLed* leds, size_t n).

The JLedSequence provides the following methods:

  • Update() - updates the active JLed objects controlled by the sequence. Like the JLed::Update() method, it returns true if an effect is running, else false.
  • Use the Repeat(n) method to specify the number of repetitions. The default value is 1 repetition. The Forever() methods sets to repeat the sequence forever.
  • Stop() - turns off all JLed objects controlled by the sequence and stops the sequence. Further calls to Update() will have no effect.
  • Reset() - Resets all JLed objects controlled by the sequence and the sequence, resulting in a start-over.

Framework notes

JLed supports the Arduino and mbed frameworks. When using platformio, the framework to be used is configured in the platform.ini file, as shown in the following example, which for example selects the mbed framework:

[env:nucleo_f401re_mbed]
platform=ststm32
board = nucleo_f401re
framework = mbed
build_flags = -Isrc 
src_filter = +<../../src/>  +<./>
upload_protocol=stlink

An mbed example is provided here. To compile it for the F401RE, make your plaform.ini look like:

...
[platformio]
default_envs = nucleo_f401re_mbed
src_dir = examples/multiled_mbed
...

Platform notes

ESP8266

The DAC of the ESP8266 operates with 10 bits, every value JLed writes out gets automatically scaled to 10 bits, since JLed internally only uses 8 bits. The scaling methods make sure that min/max relationships are preserved, i.e., 0 is mapped to 0 and 255 is mapped to 1023. When using a user-defined brightness function on the ESP8266, 8-bit values must be returned, all scaling is done by JLed transparently for the application, yielding platform-independent code.

ESP32

When compiling for the ESP32, JLed uses ledc functions provided by the ESP32 ESP-IDF SDK. (See esspressif documentation for details).

The ledc API connects so-called channels to GPIO pins, enabling them to use PWM. There are 16 channels available. Unless otherwise specified, JLed automatically picks the next free channel, starting with channel 0 and wrapping over after channel 15. To manually specify a channel, the JLed object must be constructed this way:

auto esp32Led = JLed(jled::Esp32Hal(2, 7)).Blink(1000, 1000).Forever();

The jled::Esp32Hal(pin, chan) constructor takes the pin number as the first argument and the ESP32 ledc channel number on the second position. Note that using the above-mentioned constructor results in non-platform independent code, so it should be avoided and is normally not necessary.

For completeness, the full signature of the Esp32Hal constructor is

Esp32Hal(PinType pin, 
         int chan = kAutoSelectChan, 
         uint16_t freq = 5000,
         ledc_timer_t timer = LEDC_TIMER_0)

which also allows to override the default frequency and timer used, when needed.

Using ESP-IDF

Since JLed uses the ESP-IDF SDK, JLed can also be directly used in ESP-IDF projects, without the need of using the Arduino Framework (which is also possible). See these repositories for example projects:

STM32

Arduino framework

I had success running JLed on a STM32 Nucleo64 F401RE board using this STM32 Arduino core and compiling examples from the Arduino IDE. Note that the stlink is necessary to upload sketches to the microcontroller.

Raspberry Pi Pico

When using JLed on a Raspberry Pi Pico, the Pico-SDK and tools must be installed. The Pico supports up to 16 PWM channels in parallel. See the pico-demo for an example and build instructions.

Example sketches

Example sketches are provided in the examples directory.

PlatformIO

To build an example using the PlatformIO ide, uncomment the example to be built in the platformio.ini project file, e.g.:

[platformio]
; uncomment example to build
src_dir = examples/hello
;src_dir = examples/breathe

Arduino IDE

To build an example sketch in the Arduino IDE, select an example from the File > Examples > JLed menu.

Extending

Support new hardware

JLed uses a very thin hardware abstraction layer (hal) to abstract access to the actual MCU/framework used (e.g. ESP32, ESP8266). The hal object encapsulate access to the GPIO and time functionality of the MCU under the framework being used. During the unit test, mocked hal instances are used, enabling tests to check the generated output. The Custom HAL project provides an example for a user define HAL.

Unit tests

JLed comes with an exhaustive host-based unit test suite. Info on how to run the host-based provided unit tests is provided here.

Contributing

  • fork this repository
  • create your feature branch
  • add code
  • add unit test(s)
  • add documentation
  • make sure the cpp linter does not report any problems (run make lint). Hint: use clang-format with the provided settings
  • commit changes
  • submit a PR

FAQ

How do I check if a JLed object is still being updated?

  • Check the return value of the JLed::Update method: the method returns true if the effect is still running, otherwise false.
  • The JLed::IsRunning method returns true if an effect is running, else false.

How do I restart an effect?

Call Reset() on a JLed object to start over.

How do I change a running effect?

Just 'reconfigure' the JLed with any of the effect methods (e.g. FadeOn, Breathe, Blink etc). Time-wise, the effect will start over.

Author and Copyright

Copyright 2017-2022 by Jan Delgado, jdelgado[at]gmx.net.

License

MIT

jled's People

Contributors

amahlaka avatar boraozgen avatar jamesmyatt avatar jandelgado avatar oori avatar per1234 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jled's Issues

Various ESP32 pins do not work properly

Hi,

I have spent past two days trying to get various ESP32 pins to work, and I can't find rhyme to reason what is going on. A simple blinking test should work regardless, yet...

In my application, I use a number of pins for various LEDs (White and RGB), as well pins for proximity input, RTC (via I2C pin 21/22).

Using this https://randomnerdtutorials.com/esp32-pinout-reference-gpios/ as a reference on "free" pins, I can say that only a small sub-set of pins actually work with this library.

For example 16, 17, 26, 27 won't, but 2, 4, 18, 25 do. Others are hit-and-miss for me as well.

How to combine FadeOn(), On(), and FadeOff()

Fantastic library! I've implemented a number of your functions already in my project but I'm stumped on how to do this: I need to simulate an old, incandescent blinking Christmas tree light which involves:

  1. Fade up over a period of 100ms
  2. Stay on for a period of 1500ms
  3. Fade off over a period of 100ms
  4. Stay off for period of 500ms
  5. Repeat

(This is different than your Breathe() function which fades up for half the set period and then immediately fades off for the other half)

Is this possible with the Sequence() function? I looked at the example but saw there was a "delay(1)" in the loop which I need to avoid.

jled library question

Hello Jan.
Firstly I´ll appreciate your contribution, it is a very useful library!!.
I'm wondering to know if there is any way to start over when use the repeat option.
The idea is to blink the led X times when a button is pressed , then stop, and when the same button is pressed again, blink it X times again
Thanks!!

[Question] Static on and off

Hi @jandelgado , please help me to check the code below. Why led.Off().Update() won't turn off the LED? Thank you.

#include <jled.h>

JLed led(LED_BUILTIN);

void setup() {
  led.On().Update();
  delay(2000);
  led.Off().Update();
  delay(2000);
}

void loop() {
  led.Update();
}

Arduino Mega Pin issue

Hi Jandelgado,

I seem to be having a different issue with using pins on the Arduino Mega. The project works great on any PWM pins, but I can't seem to get anything running on the extra pins in the A1-8 and 22-53 pin ranges. I had a good read of the similar issue posted about the ESP, and the alternative GPIO(?) numbers don't seem to work either. I can get these pins to work by using the standard digitalWrite blink function, however. Once again, thanks for all your hard work on this project. Any ideas on this are appreciated!

Here is the code I'm using:

#include <jled.h>

JLed leds[] = {

// Blue LEDs (Works great)

JLed(12).Breathe(1000).DelayAfter(2900),
JLed(11).Breathe(1000). DelayBefore(100). DelayAfter(2800). MaxBrightness(100),
JLed(13).Breathe(1000). DelayBefore(200). DelayAfter(2700). MaxBrightness(100),
JLed(10).Breathe(1000). DelayBefore(300). DelayAfter(2600). MaxBrightness(100),
JLed(9).Breathe(1000). DelayBefore(500). DelayAfter(2400).  MaxBrightness(100), 
JLed(8).Breathe(1000). DelayBefore(700). DelayAfter(2200).  MaxBrightness(100), 
JLed(7).Breathe(1000). DelayBefore(900). DelayAfter(2000).  MaxBrightness(100), 
JLed(6).Breathe(1000). DelayBefore(1100). DelayAfter(1800). MaxBrightness(100),
JLed(5).Breathe(1000). DelayBefore(1300). DelayAfter(1600). MaxBrightness(100),
JLed(4).Breathe(1000). DelayBefore(1500). DelayAfter(1400). MaxBrightness(100),
JLed(3).Breathe(1000). DelayBefore(1700). DelayAfter(1200). MaxBrightness(100),
JLed(2).Breathe(1000). DelayBefore(1900). DelayAfter(1000). MaxBrightness(100),

// White LEDs (doesn't work)

JLed(A8).Blink (250, 250). MaxBrightness(100),
JLed(14).Blink(250, 250). MaxBrightness(100),
JLed(29).Blink(250, 250). MaxBrightness(100). Repeat(5),
JLed(25).Blink(250, 250). MaxBrightness(100). Repeat(5),
JLed(49).Blink(250, 250). MaxBrightness(100). Repeat(5),
JLed(48).Blink(250, 250). MaxBrightness(100). Repeat(10),

};
auto sequence = JLedSequence(JLedSequence::eMode::PARALLEL, leds).Repeat(1000);

void setup() { }

void loop() {

sequence.Update();


delay(1);

}

Cheers,
Steph

Reversed logic

First of all, great job!
I have a question: my LED is driven by a PNP transistor, so high level is off, low level is on.
Is there any way to reverse Jled logic?

ESP8266: Watchdog Timer Reset when using v4.0.0-rc0 release

Hi, I'm trying to use a basic example on a NodeMCU ESP8266 board, but I am getting Watchdog Timer Resets.

Error:

 ets Jan  8 2013,rst cause:4, boot mode:(1,6)

wdt reset

Code:

#include <Arduino.h>

#include <jled.h>

JLed led = JLed(LED_BUILTIN).On().DelayBefore(2000);

void setup() {
}

void loop() {
  led.Update();
}

Am I doing something wrong?

Thanks!

Problem with Pololu A-Star 328PB at 8MHz

I looked again:
Just on the Pololu A-Star 328PB at 8MHz. This giving missing pulses:
auto led = JLed(ledPin).Blink(1, 1000).Forever();
With Blink(2, 1000) it is fine
Not a big problem for me..., so can leave it or when you have time repair it.
Many thanks
Albert

ESP32 Unable to define channel

Hi,

i have problem with assign pins and channels using Esp32Hal(pin, chan). I get a message that Esp32Hal is not defined. I tried to include also esp32-hal.h library but without effect. Using only pin number works everythig fine but i would like to have more control of channels. I tried to explore what could cause this issue but the code is too complex for me.

I tried also just copy paste example from readme and it doesnt work either.

Thanks for your help.

How do I set up conditionals?

I am trying to use your library for the first time for non-blocking LED effects in a Teensy 3.5 sketch. Your examples work fine, however they don't demonstrate how to blink an LED in response to a conditional, such as a button press.

In this case I would like to blink an LED fast 20 times when a button is pressed.

I have tried numerous things, and I think that this should work but it doesn't:

#include <Bounce.h>
#include <jled.h>

const int ledBell1 = 2;
Bounce button0 = Bounce(23, 5); // 5 ms debounce time
JLed jledBell1 = JLed(ledBell1);

void setup() {
}

void loop() {
  button0.update();
  jledBell1.Update();

  if (button0.risingEdge()) {
    JLed jledBell1 = JLed(2).Blink(100,100).Repeat(20);
  }
}

I have also tried adding a second jledBell1.Update(); after the re-declaration in the if block, and it still doesn't work. Occasionally the LED will come on solid. Serial.print'ing the return value from Update() returns either 0 or 1 depending on if the LED is on or off, but the LED never blinks. Can you help me understand why this doesn't work? I can't imagine this isn't supported in the library as it would make it fairly useless. Thank you.

Extend JLedSequence with and ability to suspend it (On/Off).

Hi,

After looking into the library code, I think I have an idea how a sequence could be suspended. This might be a quick fix, or a dirty hack, not sure - I just know I need it.

Two new methods would be created: .Off() and .On():

.Off() would allocate a new private/protected array leds_saved_, and copy the sequence's leds_ into leds_saved_. Then it would call leds_[i].Off() to turn them off. Finally, might have to call Update() once the iteration though LEDs is done?

.On() would copy the leds_saved_ array back into leds_, and free leds_saved_. Might need to call Reset() once the copy is done, too?

Unfortunately, I don't have the savviness to do this myself as I'm not familiar with the library and my C++ skills aren't up to snafu either.

10-bit doesn't appear to work on UserFuncs

I scratched my head for awhile until I figured it out but it appears the max brightness the UserFunc can support is 255. I'm using a Wemos D1 mini pro (pretty common esp8266 board) and the pwm brightness level is 10bit. I was trying to write a custom UserFunc that would blink the onboard LED between off and a lower maximum brightness. However, it's an active-low LED so I need to set it to 1023 for it to be off which I cannot do with the library expecting uint8_t.

I read that you added 10-bit support but I'm not sure how to activate it in Platform.io. My platform.ini file for my project contains:

[env:d1_mini]
platform = espressif8266
board = d1_mini
framework = arduino

Has the UserFunc code also been modified to support 10-bit? If so, can you point me in the direction to get going? If i create a function and just have it return 1023, the LED lights up the same as if I did a return 255 (because it's a BYTE and hence clips it to 255).

Thanks for the great library!

-Josh

Large dynamic memory use

This example takes 40byte dynamic memory:
auto led = JLed(ledPin).Blink(3, 1000).Forever();
Maybe this can be reduced.

DelayAfter value not cleared by Stop?

Hi there, I was struggling to transition from other effects to Blink (for example, On -> Blink, Off-> Blink, FadeOn -> Blink). The Blink on-time seemed correct, but the off-time was way too long. I created this small program to test a theory and thought I would share in case it's useful.

The program below should change effects every 10 seconds, 4 times:
FadeOn (1s ramp, 1s delay: 5 fades)
Blink(500,500) (10 blinks)
FadeOn (same as before)
Blink(500,500) (same as before)

When I run it, the fade works correctly, but the blink only blinks 5 times -- as if it was Blink(500,1500)

But the second blink is correct. The only difference is that, in the second call to Blink, I added DelayAfter(0).

Is it possible that the DelayAfter value, used in the Fade effect, is being carried over to the Blink effect?

For reference, I am using ESP32 DevKitC.

===============================

`#include <jled.h>
#define LED_PIN 15

auto led = JLed(LED_PIN).FadeOn(1000).DelayAfter(1000).Forever();

uint8_t state = 0;

void setup() {
Serial.begin(115200);
}

void loop()
{

uint32_t now = millis();

if( (now > 10000) && (state == 0) )
{
led.Stop();
led.Blink(500,500).Forever();
state++;
}
else if( (now > 20000) && (state == 1) )
{
led.Stop();
led.FadeOn(1000).DelayAfter(1000).Forever();
state++;
}
else if( (now > 30000) && (state == 2) )
{
led.Stop();
led.Blink(500,500).DelayAfter(0).Forever();
state++;
}

led.Update();

}`

FadeOff leaves LED glimming

When the FadeOff function reaches the last period step, the LED still glows as it is not fully switched off. There should be an implemented auto-off after end of fading time.

Library version: 4.5.1
Controller: ESP32-WROOM-32 at a small dev board (AZdelivery)
My Code:

#include "jled.h
#define PIN_LED_INSIDE 1
auto LEDInsideOn = JLed(PIN_LED_INSIDE).LowActive();

bool schalter = true;

void setup() {
  LEDInsideOn.On();
  LEDInsideOn.Update();
  delay(500);
  LEDInsideOn.FadeOff(10000);
  LEDInsideOn.Update();
}

void loop() {
  LEDInsideOn.Update();
}

I dont have the original schematic by hand and can not find it in the web. It's a LowSide switched LED in principle like this;
image

Brightness Logic Inverted

So i am using my esp32 wemos lolin32 board, for some reason the brightness logic is inverted. Set(255) cause LED to turn Off and Set( 0) causes LED to turn on. The Brightness scale is 255 to 0 , with 255 being the max and 0 being the lowest. The max brightness function also behaves a little erroneously when used with effects but correcting the brightness logic would solve this problem. The same is the case with effects(without adding max brightness) fade on becomes fade off and vice versa. I think it may be a problem that code isn't best suited for some/all of the esp32 boards?

Feature request: Return status from Update()

I have a use case where it would be helpful to know if an LED sequence is queued so that I can stay awake until it is complete. Looking at your code is seems to me that if you returned a boolean status from the Update() method, that would likely do the trick.

I made some changes and it appears to work but not sure if I have covered all the corner cases with my testing. Please let me know if you would like a PR.

Reset fuction not restarting code

Hi @jandelgado ,

I love what you've built here and how easy it is compared to other methods. I'm making a project with a picture of a heart and breathing LEDs to show the electrical pulses in an anatomical heart.

The pulses need to have precise timing which I was able to set up well. When the code runs, however, using the Reset() function doesn't seem to let the code start again, it just stops playing after the first one. See attached images and code I'm using.

Here's a link to a video of the project.

Any ideas appreciated, big thanks again for your hard work on this.

Code:
JLED Blinking Heart.zip

Cheers,
Steph

Update MaxBrightness Dynamically?

Apart from the incremental functions, is there a way to update the MaxBrightness value dynamically?

auto ledStrbLts = JLed(9).Breathe(110, 113, 110)
                    .MaxBrightness(200).DelayAfter(500).Forever();

void loop()  
{

// int newBrightness = random(20, 255);
//ledStrbLits.MaxBrightness(newBrightness); ??????
  ledStrbLts.Update();

}

Change time of efect in loop function

How I can change time of effect in loop function or add variable as time?

#include <Arduino.h>
#include<jled.h>
// blink internal LED every second; 1 second on, 0.5 second off.
auto led = JLed(LED_BUILTIN).Blink(100, 500).Forever();
void setup() {}
void loop()
{
led = JLed(LED_BUILTIN).Blink(1000, 500).Forever(); //this not work
led.Update();
}

FadeTo method

Hi and thanks for your awesome library! The only feature im missing is something like a FadeTo(duration) method, which works like FadeOn/FadeOff, but without switching the LED on or off.

JLed(pin).FadeTo(duration).MaxBrightness(155) should fade the LED from any level to level 155.

Being an Arduino/C++ beginner, i don't know if this would be possible with a user class but maybe the method would be usefull for others too :)

Question: Changing sequence

I suspect that I am showing my lack of c++ knowledge here so apologies in advance.

How can I update my sequence to a new sequence whilst my program is running?

JLed standard[] = {
    JLed(5).On().DelayAfter(2000),
    JLed(4).On().DelayAfter(1000),
    JLed(5).Off(),
    JLed(4).Off(), 
    JLed(14).On().DelayAfter(2000),
    JLed(14).Off(),
    JLed(4).On().DelayAfter(1000),
    JLed(4).Off(),    
};

JLed pelican[] = {
    JLed(14).Blink(500, 500).Repeat(3),
    JLed(5).Blink(500, 500).Repeat(3),
};

JLedSequence sequence(JLedSequence::eMode::SEQUENCE, standard);

Thanks

Different brightness level in effects

It would be very cool for you to implement option of setting max brightness of effect.
Currently trying to use your library with RGB led and missing this simple feature very much...

Chain sequences together

Hi,

I have a use case where we need to chain a number of sequences together into "emotions", for an art installation. The sequences in an "emotion" should play one after another, but only upon an external trigger. How do we go about that?

It appears there's no way to know whether the sequence is running, or has completed. Basically, a flag where its known if a specific sequence is playing, has already played out, might allow to chain run them one after another, in a specific (or random) order.

Thanks.

ESP32 Non-linear period when set longer than 65000ms

Caveat: I am a total noob, I'm sorry if I missed something that should be obvious.

I was trying to create a long (15min) fade up, and I was getting very strange fluctuations in the actual period vs the period setting. Since it is hard to tell exactly how long a fade cycle takes due to led brightness perception, I used the user_func example and changed the period. Up to a period of 65000ms the actual period matches the setting, then it goes squirrelly:

66000 = 1 blink of the led
68000 = 3 sec
70000 = 6 sec
80000 = 15 sec
90000 = 25 sec
900000 = 47sec
1000000 = 17sec

Various questions

Hi
Thanks for this great software !
What exactly is non-blocking, something similar to multitasking like with freertos ?
Would it be possible to change the start and end values ( brightness ) on these effects, especially breathe ?
Do you know these flameless candles ?
I would like to build something similar, just bigger.
I would have 4 solenoids moving the flame and 5 channels for the LEDs.
I would use a ESP32 to have some kind of remote control : ON / OFF, Brightness, Speed.

Thanks and best regards

Harald

Change exisiting effect

Hi,

so i am using esp32 to light up 5 different leds in a JLed array.
i am using random function to initialize the delay to breathe function of these leds when they are declared.
Now what i want is to again change the breathing times of these leds in the void loop(). Any way to that.
Q. Is there any way i can change the running breathe effect during runtime to again call random and change its duration.
Note: Kindly also show a code that shows how to change a running effect in the FAQ.

#include <jled.h>
#define led1 27
#define led2 26
#define led3 25
#define led4 33
#define led5 32
#define freq  5000
#define ledChannel  0
#define resolution  8
int rnum [5];
int ledno[] = {led1,led2,led3,led4,led5};
JLed leds[] = {
  JLed(ledno[0]).Breathe(rnum[0]=random(2000,8000)).DelayAfter(1000).Forever(),
  JLed(ledno[1]).Breathe(rnum[1]=random(2000,8000)).DelayAfter(1000).Forever(),
  JLed(ledno[2]).Breathe(rnum[2]=random(2000,8000)).DelayAfter(1000).Forever(),
  JLed(ledno[3]).Breathe(rnum[3]=random(2000,8000)).DelayAfter(1000).Forever(),
  JLed(ledno[4]).Breathe(rnum[4]=random(2000,8000)).DelayAfter(1000).Forever()
  };
  JLedSequence sequence(JLedSequence::eMode::PARALLEL, leds);

void setup() {
  // put your setup code here, to run once:
 Serial.begin(115200);
}

void loop() {
sequence.Update();
}

Edit: Made the code easier to understand.

HardFault on SAMD21

Great library!, works splendidly on STM32 and ESPs. Tried running jled on a SAMD21 (PlatformIO Framework But is crashes with HardFault here:

->clone(brightness_eval_buf_);

All v4 versions have this issue, v3 works fine. Did not have time to attach the debugger. Thanks!

Forever() not working for sequences

Hei @jandelgado,
thank you for this great library. After adapting the HAL-layer I am able to use it on an STM32F3 with CubeMX.
I was planning to use sequences for outputting status-blinkcodes. However, when I do this:

JLedSequence sequence(JLedSequence::eMode::SEQUENCE, leds);
sequence.Forever();

the sequence stops after the first iteration.

I think the issue might be the following line in Update():

is_running_ = ++iteration_ < num_repetitions_ &&
                      num_repetitions_ != kRepeatForever;

Because num_repetitions_ is set to kRepeatForever by Forever(), the second half of the above statement and thereby is_running will always be false.

I modified the line as follows and this seems to be working.

is_running_ = ++iteration_ < num_repetitions_ ||
                      num_repetitions_ == kRepeatForever;

Or am I getting something wrong?

Kind regards
Christoph

How to switch LED's current effect inside loop()

If I try writing code without dynamic LED effect switching like it's written below, it works normally:

#include "jled.h"
// do the parentheses actually break the library import?

#define myLED 13
JLed led(myLED);
//JLed led = JLed(myLed).On() - this does work too, but I don't see the difference

void setup() {
    led.On();
}

void loop() {
    led.Update();
}

But if I want to switch the LED's effect at the runtime according to a condition, nothing happens, the LED just ignores the instructions:

#include "jled.h"

JLed led = JLed(13).On().DelayAfter(2000);
bool _st;

void setup() {}

void loop() {
  if (someCondition) _st = true; //for example, switching the effect using a button
  if (_st) led.Blink(360, 360);
  led.Update();
}

How do I get rid of this problem?

Simple use case: How to blink only one time and stop

Hi jandelgado,
really a great job !
Unfortunately I have a very simple use case, and I'm not sure how to use your lib.
Based on a trigger, I simply need a unique non-blocking blink (on for 100ms then off) until the next trigger.
For the moment I use your lib like this:

led.Blink(100, 0).Repeat(1).Update(); -- NOK, led stay on after the first trigger
led.Blink(100, 1).Repeat(1).Update(); -- OK, on for 100ms then off

is there a simpler way to achieve this ?
If not, I would suggest to add an interface that could be used like this:

led.On(100).Update();

What do you think ?
Regards
Vince

Question: Can millis() be replaced with another time method

I would like to use jled in a low power application. I have set up the periodic event system (on the SAMD21) to wake the mcu every 125ms. I noticed that the jled hal uses the millis() function to determine the time. The problem with millis() in a low power application is that the systick timer it uses is suspended when the mcu is sleeping. To maintain accurate time in my application, I keep track of time using another custom method that tracks elapsed time using the periodic events.

Is it possible to replace the call to millis() with a call to a custom time method? I think the following line needs to change in arduino_hal.h:

uint32_t millis() const { return ::millis(); }

Can I simply change it as follows:

uint32_t millis() const { return myClass::newmillis(); }

Is there a way to do this without changing the jled library?

[Question] Best way to change "animation"

Example:
I have only one LED. If the programm runs "smoothly" the led has the animation "Breathe()".
But if an error occours (wifi-lost) then the led should switch to fast blinking.

At the moment my implementation looks like this. Everytime I need to switch the animation, I create a new JLED-Instance. It works, but maybe there is a more "elegant" solution. Maybe related to Issue #10

JLed leds[] = {
		JLed(BUILTIN_LED).Breathe(2000).Forever()
};

loop(){
       leds[0].Update();
}

errorOccoured(){
     leds[0] = JLed(BUILTIN_LED).Blink(200, 200).Forever();
}

Sequences and single setups on same PIN

When sequence like

JLed test_run[] = {
JLed(44).Set(10).Forever(),
JLed(45).Set(10).Forever()
};
JLedSequence abc(JLedSequence::eMode::PARALLEL, test_run);

is run on Mega PWM pins 44&45 misfire on other Mega pins starts, like complete MTU goes wild. When values under Set() are different, even like Set(11)! everything works fine. Very strange behaviour. Heere a video link:

https://www.dropbox.com/s/ec1rs7k644es4zk/20200124_221817.mp4?dl=0

Notes on video: There are other sequences that runs as well, but when upper code is deployed it starts to work randomly. Otherwise, it waits for buttons.

Is the Running Function implemented?

I am trying to use this library for a project and the last thing I need is the IsRunning function. When I try to use it I get "Class JLed has no member named isRunning" Looking in the library jled.h file there is no mention of this function.

Question: What should I expect from following code?

Hey, thank you for creating the lib. It is fun to play with it.

I have some doubts.

JLed(LED).DelayBefore(150).Blink( 4650, 50).Repeat(20).DelayAfter(150).Breathe(5000).Forever();

//Why only breath is working?

and

JLed(LED).DelayBefore(150).Breathe(5000).Repeat(20).DelayAfter(150).Blink( 4650, 50).Forever();

//Why only blink is working?

I expected delay 150ms, blink (4650,50), repeat 20 times, delay for 150ms and then breath for 5000ms and repeat these all forever.

Anything wrong I am doing?

Is it possible to append a sequence?

Regarding the sequence class, is it possible to dynamically append to a sequence? For example, I would like to queue a sequence with some number of effects and then sometime later before the effects are complete, I would like to queue another effect to the end of the sequence. Can this be done with the existing library?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.