Go Down

Topic: MIDI mapping Slider/Knob Values (Read 2220 times) previous topic - next topic

blabberbytes

So trying to map the data coming in the mindflex EEG sensor to sliders/knobs. So far all I understand how to map is using the noteON/noteOFF commands.
How do i map the data so that effects the the whole range of a slider/knob rather than just turning it on and off? Thanks!

PieterP

Use Control Change events.
Map the raw data from the sensor to [0, 127], and send it as 0b 1011 nnnn  0ccc cccc  0vvv vvvv, where nnnn is the MIDI channel, ccccccc the controller number and vvvvvvv the mapped sensor value.

Pieter

blabberbytes

#2
Aug 14, 2017, 08:23 pm Last Edit: Aug 15, 2017, 05:32 am by blabberbytes
Can you write some example code for me? I'm pretty noobish. I'm trying to do something like having the MIDI slider go to 0 if attValue < 50 and go to 127 if attValue > 50.

Code: [Select]
void loop() {
 // Expect packets about once per second.
 if (brain.update()) {
 Serial.println(brain.readCSV());
 
 // Attention runs from 0 to 100.
 attValue = brain.readAttention();
 }
 
 // Make sure we have a signal.
 if(brain.readSignalQuality() == 0) {
 
 // Light up the green LED
 if (attValue < 50) {

// MIDI slider goes to 0

}else{


// MIDI slider goes to 127
 
 
 }


Thanks I appreciate the help



PieterP

What Arduino are you using?
If it's an UNO or a MEGA, just write out the three bytes of the MIDI event over the Serial port using Serial.write(byte).

Pieter

blabberbytes

Quote
What Arduino are you using?
I'm using an UNO. I have no idea what I am doing...lol but I am trying!!! Here is some of my code. I'm getting errors on MIDI Hairless. Please What am I doing Wrong? I am not able to assign the data to midi.

Code: [Select]
#include <Brain.h>
Brain brain(Serial);
const int greenPin = 4;
const int yellowPin = 7;
const int redPin = 8;
long interval = 500;
long previousMillis = 0;
int ledState = LOW;
int attValue;
void setup() {
  // Set up the LED pin.
  pinMode(greenPin, OUTPUT);
  pinMode(yellowPin, OUTPUT);
  pinMode(redPin, OUTPUT);

  // Start the hardware serial.
  Serial.begin(9600);
}
void loop() {
  // Expect packets about once per second.
  if (brain.update()) {
    Serial.println(brain.readCSV());

    // Attention runs from 0 to 100.
    attValue = brain.readMeditation()/8;
  }

  // Make sure we have a signal.
  if (brain.readSignalQuality() == 0) {

    MIDImessage(176,1,attValue);
    delay(200);

    // Light up the green LED
    if (attValue < 50) {
      digitalWrite( greenPin, LOW);
      digitalWrite( yellowPin, LOW);
      digitalWrite( redPin, HIGH);
    }
    //Light up the red LED
    else if (attValue > 70)
    {
      digitalWrite( redPin, LOW);
      digitalWrite( greenPin, HIGH);
      digitalWrite( yellowPin, LOW);
    }
    //Light up the Yellow LED
    else if (attValue < 70 and attValue > 50)
    {
      digitalWrite( yellowPin, HIGH);
      digitalWrite( greenPin, LOW);
      digitalWrite( redPin, LOW);

    }
  }
}

void MIDImessage(byte command, byte data1, byte data2) //pass values out through standard Midi Command
{
   Serial.write(command);
   Serial.write(data1);
   Serial.write(data2);
}



Grumpy_Mike

Quote
I'm getting errors on MIDI Hairless.
Code: [Select]
Serial.begin(9600)
Use the same baud rate as Hairless is set to.

MIDI is concerned with discrete note on, note off events. Is that what you want to do?

Or do you want a continuous note who's pitch depends on the output from the sensor?

blabberbytes

Hey THanks for the reply.

Quote
Use the same baud rate as Hairless is set to.
I've since changed them so they are both 9600 and it seems to still be giving me the same error.

Quote
MIDI is concerned with discrete note on, note off events. Is that what you want to do?

Or do you want a continuous note who's pitch depends on the output from the sensor?
I Think I want the latter? I'll explain what I'm trying to do you'll probably know better. I am getting data from an EEG Mindflex device and I want it to change the value of a slider based on that data. I'm super novice and have only been doing arduino/code for a short period of time.

Grumpy_Mike

#7
Aug 16, 2017, 07:54 pm Last Edit: Aug 16, 2017, 09:20 pm by Grumpy_Mike
A speed of 9600 is way too slow, change both to the fastest that Hairless will do.

This line:-
Code: [Select]

    MIDImessage(176,1,attValue);

Is sending a Control Program change MIDI message, That will change the voice or sound of the note. It is only a two byte message and you are sending three bytes hence the error message.

The note on message is 0x90.
Now you want to send a note, a value of 1 is inaudible. You want this to be something in the range of 40 to 70.
You seem to be using the signal to change the velocity of the note, I am sure that is not you want to do.

At a guess you want to have that line as:-
Code: [Select]

    MIDImessage(0x90,attValue,100);


However you also need a note off message otherwise the note will hang, that is sound continuously.
So just to get you going, replace that line with:-
Code: [Select]

    MIDImessage(0x90,attValue,100);
   delay(100);
  MIDImessage(0c80,attValue,0);

PieterP

#8
Aug 16, 2017, 08:01 pm Last Edit: Aug 16, 2017, 08:06 pm by PieterP
This line:-
Code: [Select]

    MIDImessage(176,1,attValue);

Is sending a Control change MIDI message, That will change the voice or sound of the note. It is only a two byte message and you are sending three bytes hence the error message.
I think you're confusing Control Change with Program change.
To change the value of a slider, you definitely use Control Change (or Pitch Bend, but that's irrelevant here), and it is indeed a 3-byte message (unlike Program Change, which is only two bytes).

So as long as attValue is between 0 and 0x7F,  the above is a valid MIDI message.

Code: [Select]

Brain brain(Serial);
...
    Serial.println(brain.readCSV());
...
    attValue = brain.readMeditation()/8;
...
  if (brain.readSignalQuality() == 0) {
My guess is that Brain (whatever that is) is doing all kinds of things on the Serial port. (The same Serial port you are trying to use for MIDI.) So it's no wonder that Hairless keeps on throwing errors.

Pieter

Grumpy_Mike

#9
Aug 16, 2017, 09:23 pm Last Edit: Aug 16, 2017, 09:24 pm by Grumpy_Mike
Quote
I think you're confusing Control Change with Program change.
Yes quite correct, although the rest of it is right.

Quote
(or Pitch Bend, but that's irrelevant here)
I have a feeling that before the thread is over, we will need to use pitch bend in the solution.

Quote
My guess is that Brain (whatever that is)
I think the OP has one of those brain sensors, that pretends to measure brain activity.

Yes drop that line:-
Code: [Select]
Serial.println(brain.readCSV());

blabberbytes

#10
Aug 17, 2017, 08:42 am Last Edit: Aug 17, 2017, 08:49 am by blabberbytes
Okay so tried a few things. First I tried change the baud rate to 115200 on mid hairless and in the code. I noticed after I did that I wasn't receiving packets anymore. The LEDs I have hooked stopped reacting to the data.

So I changed it back to 9600. I then removed the

Code: [Select]
Serial.println(brain.readCSV());

Which didnt give me and midi data.

I then tried to remove the

Code: [Select]
if (brain.readSignalQuality() == 0)

And that allowed me to midi map a slider. But it just kept going from 0-100 in one second intervals and my LEDs were not working.

Maybe this is helpful? https://github.com/kitschpatrol/Brain
Suggestions?

Grumpy_Mike

You do not seem to have done what I said in reply #7

You need to do all the suggestions at one time. Then if it is not working you post your code again and say what it is doing.

PieterP

#12
Aug 17, 2017, 11:54 am Last Edit: Aug 17, 2017, 11:59 am by PieterP
How do i map the data so that effects the the whole range of a slider/knob rather than just turning it on and off?
I'm trying to do something like having the MIDI slider go to 0 if attValue < 50 and go to 127 if attValue > 50.
You seem to contradict yourself.

If you want to be able to control the slider over its entire range, you have to send a value between 0 and 127. (0 being the lowest slider position, 127 the highest, 63 somewhere in the middle, etc.)
Quote from: http://developer.neurosky.com/docs/doku.php?id=esenses_tm
MEDITATION eSense
This unsigned one-byte value reports the current eSense Meditation meter of the user, which indicates the level of a user's mental "calmness" or "relaxation". Its value ranges from 0 to 100.
So to control the slider, you have to map the meditation value [0, 100] to a MIDI value [0, 127]:
Code: [Select]
uint8_t midiVal = meditation * 127 / 100;
Then send it over MIDI:
Code: [Select]
MIDImessage(0xB0 | (channel - 1), controllerNumber, midiVal); Where 0xB0 (176 dec) is the status byte for control change messages, channel is the MIDI channel, controllerNumber is the MIDI controller number that you can map in your audio software.
I really recommend reading some MIDI documentation first. (https://www.midi.org/)

If you want to do what you said in the second quote:
Code: [Select]
uint8_t midiVal = meditation >= 50 ? 127 : 0;
( ? : is the ternary operator)

You can't use the hardware UART for the brain sensor and for MIDI at the same time.
Either use SoftwareSerial for the brain, or get an Arduino that has more than one hardware UART, or one hardware UART and USB.
If you get a board like the Leonardo, you can use USB MIDI (much easier than Hairless), and the hardware UART can be used by the brain sensor.

Pieter

blabberbytes

Quote
ou do not seem to have done what I said in reply #7

You need to do all the suggestions at one time. Then if it is not working you post your code again and say what it is doing.
Okay good point.  There does seem to be an issue with changing the Baud rate from 9600 to 115200. I also tried 19200 and mid hairless al together stops reading the midi, (no green blinks) also i have a processing sketch that visualizes the brain waves and it will not receive the packets when i change the rate. on arduino and processing.

When I make the changes you mentioned in #7, i am now able to midi map, but it just keeps rapidly turning on and off and eventually stops.

Code: [Select]
#include <MIDI.h>

#include <Brain.h>
Brain brain(Serial);
const int greenPin = 4;
const int yellowPin = 7;
const int redPin = 8;
long interval = 500;
long previousMillis = 0;
int ledState = LOW;
int attValue;

void setup() {
  // Set up the LED pin.
  pinMode(greenPin, OUTPUT);
  pinMode(yellowPin, OUTPUT);
  pinMode(redPin, OUTPUT);

  // Start the hardware serial.
  Serial.begin(115200);
}

void loop() {
  // Expect packets about once per second.
  if (brain.update()) {
    //Serial.println(brain.readCSV());

    // Attention runs from 0 to 100.
    attValue = brain.readMeditation() / 8;

  }

  // Make sure we have a signal.
  if (brain.readSignalQuality() == 0) {
   
      MIDImessage(0x90, attValue, 100);
      delay(100);
      MIDImessage(0x80, attValue, 0);

    // Light up the green LED
    if (attValue < 50) {


      digitalWrite( greenPin, LOW);
      digitalWrite( yellowPin, LOW);
      digitalWrite( redPin, HIGH);
    }
    //Light up the red LED
    else if (attValue > 70)
    {

      digitalWrite( redPin, LOW);
      digitalWrite( greenPin, HIGH);
      digitalWrite( yellowPin, LOW);
    }
    //Light up the Yellow LED
    else if (attValue < 70 and attValue > 50)
    {

      digitalWrite( yellowPin, HIGH);
      digitalWrite( greenPin, LOW);
      digitalWrite( redPin, LOW);

    }
  }
}

void MIDImessage(byte command, byte data1, byte data2) //pass values out through standard Midi Command
{
  Serial.write(command);
  Serial.write(data1);
  Serial.write(data2);
}




PieterP

Okay good point.  There does seem to be an issue with changing the Baud rate from 9600 to 115200. I also tried 19200 and mid hairless al together stops reading the midi, (no green blinks) also i have a processing sketch that visualizes the brain waves and it will not receive the packets when i change the rate. on arduino and processing.
With an UNO, you can NOT send MIDI and other data to the computer at the same time, especially if you have something connected to pins 0 and 1.

Go Up