Comments (10)
Oops, I didn't know that!
I thought I had to assign codes for each led.
Anyway, it works really fine.
Thank you.
from control-surface.
For a limited number of LEDs, you can do something like this:
#include <FastLED.h>
#include <Control_Surface.h>
Array<CRGB, 3> leds = {};
constexpr uint8_t ledpin = 2;
USBMIDI_Interface midi;
using namespace MIDI_Notes;
NoteValueFastLED<> midileds[leds.length] = {
{leds[0], note(C, 0)},
{leds[1], note(D, 4)},
{leds[2], note(G, 2)},
};
void setup() {
// See FastLED examples and documentation for more information.
FastLED.addLeds<NEOPIXEL, ledpin>(leds.data, leds.length);
FastLED.setCorrection(TypicalPixelString);
FastLED.setBrightness(128);
Control_Surface.begin();
}
void loop() {
Control_Surface.loop();
FastLED.show();
}
However, each LED takes up at least 17 bytes of RAM, and matching is more expensive as well (looking up the LED to turn on/off when a MIDI message comes in).
A more efficient approach would be the following:
Basically, you write your own handler/callback that is executed whenever a new MIDI value is received. You can then pass this custom callback to the GenericNoteCCRange
class. This class listens for MIDI Note or Control Change events in a given range (e.g. all notes between C0 and D4), and calls the callback if it receives such a MIDI event.
#include <FastLED.h>
#include <Control_Surface.h>
USBMIDI_Interface midi;
Array<CRGB, 3> leds = {};
constexpr uint8_t ledpin = 2;
using namespace MIDI_Notes;
constexpr uint8_t firstNote = note(C, 0);
constexpr uint8_t lastNote = note(D, 4);
/// This is a custom callback that's executed when MIDI values (note velocity or
/// controller change) change. It's used by the GenericNoteCCRange class below.
class MyNoteCCFastLED {
public:
/// This function is called upon initialization of the GenericNoteCCRange
/// object that owns this callback.
template <class T>
void begin(const T &t) {
update(t);
}
/// This function is called when a single value changes.
/// @param t
/// The GenericNoteCCRange object that had a value change.
/// @param index
/// The index of the value that changed. It is in the range
/// [0, t.length() - 1]
template <class T>
void update(const T &t, uint8_t index) {
uint8_t value = t.getValue(index); // Value is the MIDI value [0, 127]
// Use the index and value here to turn on/off the right LED
uint8_t noteIndex = firstNote + index;
if (noteIndex == note(C, 0))
leds[0] = CRGB{16, 255, 192}.nscale8_video(value * 2); // first LED
else if (noteIndex == note(D, 4))
leds[1] = CRGB{16, 255, 192}.nscale8_video(value * 2); // second LED
else if (noteIndex == note(G, 2))
leds[2] = CRGB{16, 255, 192}.nscale8_video(value * 2); // third LED
}
/// This function is called when all values change and everything has to be
/// updated.
/// @param t
/// The GenericNoteCCRange object that has to be updated entirely.
template <class T>
void update(const T &t) {
// loop over the entire range, and update every note individually.
for (uint8_t index = 0; index < t.length(); ++index)
update(t, index);
}
};
GenericNoteCCRange<MIDIInputElementNote, // Type: Note or CC
lastNote - firstNote + 1, // Length of the range
MyNoteCCFastLED // Callback when value changes
> midileds = {
firstNote, // address of the first note (or controller) in the range
{}, // default initialization of MyNoteCCFastLED callback
};
void setup() {
// See FastLED examples and documentation for more information.
FastLED.addLeds<NEOPIXEL, ledpin>(leds.data, leds.length);
FastLED.setCorrection(TypicalPixelString);
FastLED.setBrightness(128);
Control_Surface.begin();
}
void loop() {
Control_Surface.loop();
FastLED.show();
}
This example seems to compile without errors, but I can't test it on real hardware at the moment.
from control-surface.
There's a Neopixel example here. You can specify your own color mapper if you have to.
from control-surface.
Thank you for your kind answer.
But there's one thing I'm still confused about.
How do I map RGB values by Velocity?
from control-surface.
You have to create a struct with a call operator that takes the velocity (as a uint8_t) as a parameter, and returns an object of type Color containing the R, G and B values.
struct MyColorMapper {
Color operator()(uint8_t velocity) const {
if (velocity == 0)
return {0, 0, 0}; // black
else if (velocity < 64)
return {0, 255, 0}; // green
else
return {255, 0, 0}; // red
}
};
Then you can supply that color mapper to the NoteRangeFastLED class in the example:
NoteRangeFastLED<leds.length, MyColorMapper> midiled = {leds, note(C, 4)};
from control-surface.
I am using using NEOPIXEL RGB led strip, and your example code works fine for me.
But only the first LED on the strip lights up and the rest do not work.
I want to know how to operate the 16 LEDs on the strip, each in a different note.
Thank you for always good library and kind answers.
from control-surface.
That's strange, I just tried it here with a piece of Chinese Neopixel LED strip, and it works as expected. What notes are you sending?
The first LED should be C4, the second C#4, the third D4, D#4, E4, F4, etc. increasing in half steps.
from control-surface.
For future reference, I added the LED index as a parameter to the color mapper, allowing you to get a different color for different LEDs.
A "Rainbow" example can be found here: https://tttapa.github.io/Control-Surface/Doc/Doxygen/d9/d6d/10_8Note-FastLED-ColorMapper_8ino-example.html
from control-surface.
Thank you for your efforts!
Lastly, let me ask you a question.
Can I map notes to each LED on the LEDstrip?
(e.g. LED#1 : C0, LED#2 : D4, LED#3 : G2)
from control-surface.
Awesome, thanks!
from control-surface.
Related Issues (20)
- Bankable::ManyAddresses::CCAbsoluteEncoder HOT 2
- Time Display does not work.
- Does it's support ESP32-S3/C3 via USB port? HOT 7
- How to use 1 shift button to change bank:
- The sketch compiles, but doesn't work HOT 3
- Error when compiling for ESP32 S3 HOT 3
- Metronome Led HOT 3
- Trying to setVelocity for all notebutton values in mux with piezo device HOT 1
- External app/webpage to change CC and Channel values HOT 1
- Hi, I would like to see the USBMIDI_Interface adapted so that you can specify the fixed cablenumber. This would it make possible to use pipes and filters connecting serial ports with virtual usb ports
- Support for MCP23S17 SPI
- error: 'SelectorPC' does not name a type HOT 2
- Switching presets Roland FP-30X HOT 2
- TYPO IN DOCUMENTATION HOT 1
- Error running on M1 Mac Sonoma with Teensy 4.0 HOT 4
- Arduino Nano 33 BLE Support? HOT 3
- Пример CCIncrementDecrementButtons.ino HOT 10
- Select bank HOT 2
- MIDI-монитор-OLED HOT 3
- Arduino Giga R1 Wifi support HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from control-surface.