Hi everybody
I'm trying to control various RGB leds using the MIDI protocol. I don't need DMX, SERIAL or i2c. I need pure MIDI, here is the problem...
I use 3 SPI-driven TLC5940 to get 48 precise PWM outputs.
I use an Arduino UNO (Atmega 328).
I use this hardware as a MIDI input (this one seems to work well) :
I use a USB to MIDI I/O cable and I try to drive the LED with Cubase.
I will use the MIDI like it :
NOTE ON:
Channel : 1 (I will use only one channel)
Note : 0..15 RED
16..31 GREEN
32..47 BLUE
Velocity : 0..255 : PWM Value of the desired output.
NOTE OFF:
Note : 0..15 RED
16..31 GREEN
32..47 BLUE
The PWM note value should have 0 (Shut down).0
I use the Arduino FortySevenEffects MIDI Library v4.2 :
My question and my problem is the following:
This example I show you work but with errors, sometimes, it looks like the data don't arrive or have errors. With only one note in one channel, it works like a charm. But when I want to use notes at the same times (chord) it is where the situation is more difficult and errors occurs.
It is an hardware error?
Code error?
The midi baud rate isn't sufficient to do this (yes, I think this is an absurd theory, but who knows...)
And mainly, is it possible to do this with arduino UNO?
Here is the code I made using the MIDI library:
#include <MIDI.h>
#include "Tlc5940.h"
MIDI_CREATE_DEFAULT_INSTANCE();
byte midirgb[48];
void setup() {
Tlc.init();
MIDI.begin();
MIDI.setHandleNoteOn(MyHandleNoteOn);
MIDI.setHandleNoteOff(MyHandleNoteOff);
}
void MyHandleNoteOn(byte channel, byte pitch, byte velocity) {
if (pitch <= 47) {
midirgb[pitch] = 255;
}
}
void MyHandleNoteOff(byte channel, byte pitch, byte velocity) {
if (pitch <= 47) {
midirgb[pitch] = 0;
}
}
void loop() {
for (int i=0; i <= 47; i++){
MIDI.read();
delayMicroseconds(100);
}
Tlc.clear();
for (int i=0; i <= 15; i++){
RGBTLCSet256(i,midirgb[i],midirgb[i+16],midirgb[i+32]);
}
Tlc.update();
}
void RGBTLCSet256(byte ledstrip, byte r, byte g, byte b)
{
if (ledstrip==0){
Tlc.set(15, map(r,0,255,0,4095));
Tlc.set(14, map(g,0,255,0,4095));
Tlc.set(13, map(b,0,255,0,4095));
}
if (ledstrip==1){
Tlc.set(12, map(r,0,255,0,4095));
Tlc.set(11, map(g,0,255,0,4095));
Tlc.set(10, map(b,0,255,0,4095));
}
if (ledstrip==2){
Tlc.set(9, map(r,0,255,0,4095));
Tlc.set(8, map(g,0,255,0,4095));
Tlc.set(7, map(b,0,255,0,4095));
}
if (ledstrip==3){
Tlc.set(6, map(r,0,255,0,4095));
Tlc.set(5, map(g,0,255,0,4095));
Tlc.set(4, map(b,0,255,0,4095));
}
if (ledstrip==4){
Tlc.set(3, map(r,0,255,0,4095));
Tlc.set(2, map(g,0,255,0,4095));
Tlc.set(1, map(b,0,255,0,4095));
}
if (ledstrip==5){
Tlc.set(0, map(r,0,255,0,4095));
Tlc.set(31, map(g,0,255,0,4095));
Tlc.set(30, map(b,0,255,0,4095));
}
if (ledstrip==6){
Tlc.set(29, map(r,0,255,0,4095));
Tlc.set(28, map(g,0,255,0,4095));
Tlc.set(27, map(b,0,255,0,4095));
}
if (ledstrip==7){
Tlc.set(26, map(r,0,255,0,4095));
Tlc.set(25, map(g,0,255,0,4095));
Tlc.set(24, map(b,0,255,0,4095));
}
if (ledstrip==8){
Tlc.set(23, map(r,0,255,0,4095));
Tlc.set(22, map(g,0,255,0,4095));
Tlc.set(21, map(b,0,255,0,4095));
}
if (ledstrip==9){
Tlc.set(20, map(r,0,255,0,4095));
Tlc.set(19, map(g,0,255,0,4095));
Tlc.set(18, map(b,0,255,0,4095));
}
if (ledstrip==10){
Tlc.set(17, map(r,0,255,0,4095));
Tlc.set(16, map(g,0,255,0,4095));
Tlc.set(47, map(b,0,255,0,4095));
}
if (ledstrip==11){
Tlc.set(46, map(r,0,255,0,4095));
Tlc.set(45, map(g,0,255,0,4095));
Tlc.set(44, map(b,0,255,0,4095));
}
if (ledstrip==12){
Tlc.set(43, map(r,0,255,0,4095));
Tlc.set(42, map(g,0,255,0,4095));
Tlc.set(41, map(b,0,255,0,4095));
}
if (ledstrip==13){
Tlc.set(40, map(r,0,255,0,4095));
Tlc.set(39, map(g,0,255,0,4095));
Tlc.set(38, map(b,0,255,0,4095));
}
if (ledstrip==14){
Tlc.set(37, map(r,0,255,0,4095));
Tlc.set(36, map(g,0,255,0,4095));
Tlc.set(35, map(b,0,255,0,4095));
}
if (ledstrip==15){
Tlc.set(34, map(r,0,255,0,4095));
Tlc.set(33, map(g,0,255,0,4095));
Tlc.set(32, map(b,0,255,0,4095));
}
}
Here is the code I made without library (pure serial) and the result is worstest...
#include "Tlc5940.h"
byte midirgb[48];
//These are the midi commands to interact with the arduino
byte midi_on = 0x90;
byte midi_off = 0x80;
byte location_byte;
byte in_note;
byte in_volume;
void check_midi()
{
while (Serial.available() >= 3)//when three bytes available
{
if (Serial.available())
{
location_byte = Serial.read();//read first byte
in_note = Serial.read();//read next byte
in_volume = Serial.read();//read final byte
}
}
}
void setup() {
Tlc.init();
Serial.begin(31250);
}
void loop() {
/*
for (int i=0; i <= 47; i++){
midirgb[i] = 0;
}
*/
for (int i=0; i <= 47; i++){
check_midi();
if (location_byte == midi_on)
{
midirgb[in_note] = in_volume;
} else {
midirgb[in_note] = 0;
}
}
Tlc.clear();
for (int i=0; i <= 15; i++){
RGBTLCSet256(i,midirgb[i],midirgb[i+16],midirgb[i+32]);
}
Tlc.update();
}
void RGBTLCSet256(byte ledstrip, byte r, byte g, byte b)
{
if (ledstrip==0){
Tlc.set(15, map(r,0,255,0,4095));
Tlc.set(14, map(g,0,255,0,4095));
Tlc.set(13, map(b,0,255,0,4095));
}
if (ledstrip==1){
Tlc.set(12, map(r,0,255,0,4095));
Tlc.set(11, map(g,0,255,0,4095));
Tlc.set(10, map(b,0,255,0,4095));
}
if (ledstrip==2){
Tlc.set(9, map(r,0,255,0,4095));
Tlc.set(8, map(g,0,255,0,4095));
Tlc.set(7, map(b,0,255,0,4095));
}
if (ledstrip==3){
Tlc.set(6, map(r,0,255,0,4095));
Tlc.set(5, map(g,0,255,0,4095));
Tlc.set(4, map(b,0,255,0,4095));
}
if (ledstrip==4){
Tlc.set(3, map(r,0,255,0,4095));
Tlc.set(2, map(g,0,255,0,4095));
Tlc.set(1, map(b,0,255,0,4095));
}
if (ledstrip==5){
Tlc.set(0, map(r,0,255,0,4095));
Tlc.set(31, map(g,0,255,0,4095));
Tlc.set(30, map(b,0,255,0,4095));
}
if (ledstrip==6){
Tlc.set(29, map(r,0,255,0,4095));
Tlc.set(28, map(g,0,255,0,4095));
Tlc.set(27, map(b,0,255,0,4095));
}
if (ledstrip==7){
Tlc.set(26, map(r,0,255,0,4095));
Tlc.set(25, map(g,0,255,0,4095));
Tlc.set(24, map(b,0,255,0,4095));
}
if (ledstrip==8){
Tlc.set(23, map(r,0,255,0,4095));
Tlc.set(22, map(g,0,255,0,4095));
Tlc.set(21, map(b,0,255,0,4095));
}
if (ledstrip==9){
Tlc.set(20, map(r,0,255,0,4095));
Tlc.set(19, map(g,0,255,0,4095));
Tlc.set(18, map(b,0,255,0,4095));
}
if (ledstrip==10){
Tlc.set(17, map(r,0,255,0,4095));
Tlc.set(16, map(g,0,255,0,4095));
Tlc.set(47, map(b,0,255,0,4095));
}
if (ledstrip==11){
Tlc.set(46, map(r,0,255,0,4095));
Tlc.set(45, map(g,0,255,0,4095));
Tlc.set(44, map(b,0,255,0,4095));
}
if (ledstrip==12){
Tlc.set(43, map(r,0,255,0,4095));
Tlc.set(42, map(g,0,255,0,4095));
Tlc.set(41, map(b,0,255,0,4095));
}
if (ledstrip==13){
Tlc.set(40, map(r,0,255,0,4095));
Tlc.set(39, map(g,0,255,0,4095));
Tlc.set(38, map(b,0,255,0,4095));
}
if (ledstrip==14){
Tlc.set(37, map(r,0,255,0,4095));
Tlc.set(36, map(g,0,255,0,4095));
Tlc.set(35, map(b,0,255,0,4095));
}
if (ledstrip==15){
Tlc.set(34, map(r,0,255,0,4095));
Tlc.set(33, map(g,0,255,0,4095));
Tlc.set(32, map(b,0,255,0,4095));
}
}
Here is attached the Cubase file I use.
Thanks for your help and sharing your experience
Test midi cubase.zip (9.23 KB)