Due, MIDIUSB, UniquePress Transpose

I’ve been trying to combine two seperate sketches in to one for a simple piano style keyboard using a Due MIDI over USB.

My problem is with the the transpose feature using two buttons, one for octave down and one for octave up.

I’m using the MIDIUSB Library by Gary Grewal on GitHub;

Also the uniquePress Button Library by Alexander Brevig, updated by Terry King;

http://arduino-info.wikispaces.com/HAL-LibrariesUpdates

And the sketch by Arturo Guadalupi;

My coding skills are not great, as you find below. I’ve kept the sketch small just to get it working before moving on to more keys etc. Other then my poor coding I’m a little lost with the words I need to use for the MIDIUSB Library, such as the transpose. The only way I think I can get this to work regarding the transpose, is to write-off all the transpose1, if, else, transpose2, etc and change them to actual key notes?

Currently I have the notePitches;
C5, D5b, D5, E5b, E5, F5, G5b, G5, A5b, A5, B5b, B5. One octave.

So my thinking is, when I press the octave down button I change the notePitches to;
C4, D4b, D4, E4b, E4, F4, G4b, G4, A4b, A4, B4b, B4. One octave below and do similar for the octave up button.

Can anyone point me in the direction for some documentation on how to use the MIDIUSB library or a list of the words I should be using with this library.

Like I say, my coding is something to be desired, I need to start adding comments, but I’m having fun in experimenting and learning from my failings.

Regards.

Dizzwold.

/*
   This examples shows how to make a simple seven keys MIDI keyboard with volume control

   Created: 4/10/2015
   Author: Arturo Guadalupi <a.guadalupi@arduino.cc>
   
   http://www.arduino.cc/en/Tutorial/MidiDevice
*/
#include <Button.h>
#include "MIDIUSB.h"
#include "PitchToNote.h"
#define NUM_BUTTONS  12

Button button20 = Button(2, PULLUP);
Button button21 = Button(3, PULLUP);
const int InputTriggerTranspose1 = 2;
const int InputTriggerTranspose2 = 3;
byte transpose1 = 0;
byte transpose2 = 0;

const uint8_t button1 = 53;
const uint8_t button2 = 52;
const uint8_t button3 = 51;
const uint8_t button4 = 50;
const uint8_t button5 = 49;
const uint8_t button6 = 48;
const uint8_t button7 = 47;
const uint8_t button8 = 46;
const uint8_t button9 = 45;
const uint8_t button10 = 44;
const uint8_t button11 = 43;
const uint8_t button12 = 42;

//const int intensityPot = 127;  //A0 input

const uint8_t buttons[NUM_BUTTONS] = {button1, button2, button3, button4, button5, button6, button7, button8, button9, button10, button11, button12};
const byte notePitches[NUM_BUTTONS] = {pitchC5, pitchD5b, pitchD5, pitchE5b, pitchE5, pitchF5, pitchG5b, pitchG5, pitchA5b, pitchA5, pitchB5b, pitchB5};

uint8_t notesTime[NUM_BUTTONS];
uint8_t pressedButtons = 0x00;
uint8_t previousButtons = 0x00;
uint8_t intensity = 127;
//uint8_t intensity;
void setup() {
  for (int i = 0; i < NUM_BUTTONS; i++)
    pinMode(buttons[i], INPUT_PULLUP);
    pinMode(2, INPUT);
    pinMode(3, INPUT);
}

byte pressCount = 0;

void loop() {
  readButtons();
  readIntensity();
  playNotes();

   if(button20.uniquePress())
   pressCount++;

    switch(pressCount)

    {case 1:

      transpose1 = digitalRead(InputTriggerTranspose1);
  if (transpose1 == HIGH) {
    transpose1 = -12;}
    else {
      transpose1 = 0;}

      pressCount = 0;

    break;
    }

    if(button21.uniquePress())
    pressCount++;

    switch(pressCount)

    {case 1:

      transpose2 = digitalRead(InputTriggerTranspose2);
  if (transpose2 == HIGH) {
    transpose2 = +12;}
    else {
      transpose2 = 0;
      
      pressCount = 0;

      break;
      }
      }
  }


// First parameter is the event type (0x0B = control change).
// Second parameter is the event type, combined with the channel.
// Third parameter is the control number number (0-119).
// Fourth parameter is the control value (0-127).

void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

void readButtons()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (digitalRead(buttons[i]) == LOW)
    {
      bitWrite(pressedButtons, i, 1);
      delay(50);
    }
    else
      bitWrite(pressedButtons, i, 0);
  }
}

void readIntensity()
{
  //int val = analogRead(intensityPot);
  //intensity = (uint8_t) (map(val, 0, 1023, 0, 127));
  int val ();
}

void playNotes()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (bitRead(pressedButtons, i) != bitRead(previousButtons, i))
    {
      if (bitRead(pressedButtons, i))
      {
        bitWrite(previousButtons, i , 1);
        noteOn(0, notePitches[i], intensity);
        MidiUSB.flush();
      }
      else
      {
        bitWrite(previousButtons, i , 0);
        noteOff(0, notePitches[i], 0);
        MidiUSB.flush();
      }
    }
  }
}

// First parameter is the event type (0x09 = note on, 0x08 = note off).
// Second parameter is note-on/note-off, combined with the channel.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Third parameter is the note number (48 = middle C).
// Fourth parameter is the velocity (64 = normal, 127 = fastest).

void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

Why do you have a switch statement with only one case? That is what an if statement is for.

Your code REALLY needs to be subjected to Tools + Auto Format.

You really need to be consistent in your placement of curly braces. My preference is that there is nothing else on the same line as the { or the }.

It is not clear what you want the MIDIUSB library to do, but I'm reasonably certain that it came with examples.

Hi Paul,

Your correct, I should get shot of the uneeded Button stuff and I will clean the sketch up!

What I wish to achieve, I currently have one octave of keys, octave 5 starting with middle C. I want to have two buttons, one for octave Up to go to octave 6 from 5, and one for octave DOWN to octave 4 from 5. Once in octave 4 I would need to press the UP Button twice to go to octave 5 then 6.

The idea, once I can achieve that is then to have the full octave range from octave 0 C0 MIDI note 0 to octave 10 G10 MIDI note 127. I'm aware that the MIDIUSB library only covers 88 midi notes and I will need to change that at a later date.

I humbly retreat to clean my work.

Dizzwold.

OK,

Hopefully this is a little tidier, but I still can’t find how to transpose an octave up or down.

I’ve looked at the examples and many other posts and sketches, and no wiser?

Dizzwold.

/*
   This examples shows how to make a simple seven keys MIDI keyboard with volume control

   Created: 4/10/2015
   Author: Arturo Guadalupi <a.guadalupi@arduino.cc>

   http://www.arduino.cc/en/Tutorial/MidiDevice
*/
#include <Button.h>
#include "MIDIUSB.h"
#include "PitchToNote.h"
#define NUM_BUTTONS  12

Button button20 = Button(2, PULLUP); // Pin number for button octave down
Button button21 = Button(3, PULLUP); // Pin number for button octave up
const int InputTriggerTranspose1 = 2;
const int InputTriggerTranspose2 = 3;
byte transpose1 = 0;
byte transpose2 = 0;

const uint8_t button1 = 53; // Arduino Due pin numbers for keys
const uint8_t button2 = 52;
const uint8_t button3 = 51;
const uint8_t button4 = 50;
const uint8_t button5 = 49;
const uint8_t button6 = 48;
const uint8_t button7 = 47;
const uint8_t button8 = 46;
const uint8_t button9 = 45;
const uint8_t button10 = 44;
const uint8_t button11 = 43;
const uint8_t button12 = 42;

//const int intensityPot = 127;  //A0 input Not being used

const uint8_t buttons[NUM_BUTTONS] = {button1, button2, button3, button4, button5, button6, button7, button8, button9, button10, button11, button12};
//const byte notePitches[NUM_BUTTONS] = {pitchC5, pitchD5b, pitchD5, pitchE5b, pitchE5, pitchF5, pitchG5b, pitchG5, pitchA5b, pitchA5, pitchB5b, pitchB5};
byte notePitches[NUM_BUTTONS] = {pitchC5, pitchD5b, pitchD5, pitchE5b, pitchE5, pitchF5, pitchG5b, pitchG5, pitchA5b, pitchA5, pitchB5b, pitchB5};

uint8_t notesTime[NUM_BUTTONS];
uint8_t pressedButtons = 0x00;
uint8_t previousButtons = 0x00;
uint8_t intensity = 127; // Set volume to full 0 - 127
//uint8_t intensity;
void setup()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
    pinMode(buttons[i], INPUT_PULLUP);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
}

void loop()
{
  readButtons();
  readIntensity();
  playNotes();

  if (button20.uniquePress());
  {
    transpose1 = digitalRead(InputTriggerTranspose1);
    if (transpose1 == HIGH)
    {
      transpose1 = -12;
    }
    else
    {
      transpose1 = 0;
    }
  }
  if (button21.uniquePress());
  {
    transpose2 = digitalRead(InputTriggerTranspose2);
    if (transpose2 == HIGH)
    {
      transpose2 = +12;
    }
    else
    {
      transpose2 = 0;
    }
  }
}

// First parameter is the event type (0x0B = control change).
// Second parameter is the event type, combined with the channel.
// Third parameter is the control number number (0-119).
// Fourth parameter is the control value (0-127).

void controlChange(byte channel, byte control, byte value)
{
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

void readButtons()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (digitalRead(buttons[i]) == LOW)
    {
      bitWrite(pressedButtons, i, 1);
      delay(50);
    }
    else
      bitWrite(pressedButtons, i, 0);
  }
}

void readIntensity()
{
  //int val = analogRead(intensityPot);
  //intensity = (uint8_t) (map(val, 0, 1023, 0, 127));
  int val ();
}

void playNotes()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (bitRead(pressedButtons, i) != bitRead(previousButtons, i))
    {
      if (bitRead(pressedButtons, i))
      {
        bitWrite(previousButtons, i , 1);
        noteOn(0, notePitches[i], intensity);
        MidiUSB.flush();
      }
      else
      {
        bitWrite(previousButtons, i , 0);
        noteOff(0, notePitches[i], 0);
        MidiUSB.flush();
      }
    }
  }
}

// First parameter is the event type (0x09 = note on, 0x08 = note off).
// Second parameter is note-on/note-off, combined with the channel.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Third parameter is the note number (48 = middle C).
// Fourth parameter is the velocity (64 = normal, 127 = fastest).

void noteOn(byte channel, byte pitch, byte velocity)
{
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity)
{
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}
void readIntensity()
{
  //int val = analogRead(intensityPot);
  //intensity = (uint8_t) (map(val, 0, 1023, 0, 127));
  int val ();
}

What is that last line of code supposed to be doing?

I have a Due, but I don't have the IDE set up to deal with it, so I don't have the MIDIUSB library, so I can't help you with the MIDI aspect of the project.

Hi Paul,

Again, your very correct. I didn't even see that there, it's part of the original tutorial "wherever I got it from and was already uncommented like that". Ha-Ho. Well spotted.

I only got my Due yesterday, and to be honest I've only put it down to go to bed. LOL.

Dizzwold.

The notes are stored in the notePitches array, to change octave add or subtract 12 to each note (according to this chart). You’ll have to remove const from the declaration to be able to change the values.

I have not used that library but looked at the header file and it looks like the note definitions go from C1 to C8. You might have two functions, one that adds 12 to each note value and another that subtracts 12 from each value, being careful not to go lower than C1 or higher than C8.

I wrote some demo code, if you want to use it you’ll have to hook octaveUp() and octaveDown() to the two buttons.

#include "PitchToNote.h"
#define NUM_BUTTONS  12



byte notePitches[NUM_BUTTONS] = {
  pitchC5, pitchD5b, pitchD5, pitchE5b, pitchE5, pitchF5, pitchG5b, pitchG5, pitchA5b, pitchA5, pitchB5b, pitchB5};

void setup()
{
  Serial.begin(9600);
  Serial.println("Notes");
  printNotes();
  octaveDpwn();
  Serial.println("Down one octave");
  printNotes();
  octaveUp();
  octaveUp();
  Serial.println("Up two octaves");
  printNotes();

}

// show notes in serail monitor
void printNotes()
{
  for(int i = 0; i < NUM_BUTTONS; i++ )
  {
    Serial.print(notePitches[i]);
    Serial.print("  ");

  } // for

  Serial.println();
}

// shift notes by passed amount 
//
// pass negative number to go down
//
void shiftNotes(int shiftAmt)
{
  for(int i = 0; i < NUM_BUTTONS; i++ )
  {
    notePitches[i] += shiftAmt;

  } // for

}

// adjust notes one octave down
void octaveDpwn()
{
  // if there is an octave below
  if( notePitches[0] > pitchC1 )
  {
    shiftNotes(-12);

  } // if

}

// adjust notes one octave up
void octaveUp()
{
  // if there is an octave above
  if( notePitches[0] < pitchC8 )
  {
    shiftNotes(12);

  } // if

}

void loop()
{



}

Hi Blue Eyes,

Thank you for your input and demo sketch. Very much appreciated, as I've not messed with Arduino's for a couple of years, but I've never known much code anyway.

Dizzwold.

Really getting myself confused now.

I can understand most of the sketch, like it should not let me go higher than the octave C8 and no lower than the octave C1.

the sketch still won’t change octaves and I’ve also lost the last 4 notes. I thought it could be a duff board so I change the pin numbers from 42-53 to 22-33 and still 22,23,24 and 25 won’t play a note. I’ve checked the PitchToNote.h to make sure these notes sre there.

Also for some reason If I removed line 57 to put it on line 65 it doesn’t like line 68?

Dizzwold.

/*
   This examples shows how to make a simple seven keys MIDI keyboard with volume control

   Created: 4/10/2015
   Author: Arturo Guadalupi <a.guadalupi@arduino.cc>

   http://www.arduino.cc/en/Tutorial/MidiDevice
*/
#include <Button.h>
#include "MIDIUSB.h"
#include "PitchToNote.h"
#define NUM_BUTTONS  12

Button button20 = Button(2, PULLUP); // Pin number for button octave down
Button button21 = Button(3, PULLUP); // Pin number for button octave up
//const int octaveDown = 2;
//const int octaveUp = 3;
//byte transpose1 = 0;
//byte transpose2 = 0;

const uint8_t button1 = 33; // Arduino Due pin numbers for keys
const uint8_t button2 = 32;
const uint8_t button3 = 31;
const uint8_t button4 = 30;
const uint8_t button5 = 29;
const uint8_t button6 = 28;
const uint8_t button7 = 27;
const uint8_t button8 = 26;
const uint8_t button9 = 25;
const uint8_t button10 = 24;
const uint8_t button11 = 23;
const uint8_t button12 = 22;

//const int intensityPot = 127;  //A0 input Not being used

const uint8_t buttons[NUM_BUTTONS] = {button1, button2, button3, button4, button5, button6, button7, button8, button9, button10, button11, button12};
//const byte notePitches[NUM_BUTTONS] = {pitchC5, pitchD5b, pitchD5, pitchE5b, pitchE5, pitchF5, pitchG5b, pitchG5, pitchA5b, pitchA5, pitchB5b, pitchB5};
byte notePitches[NUM_BUTTONS] = {pitchC5, pitchD5b, pitchD5, pitchE5b, pitchE5, pitchF5, pitchG5b, pitchG5, pitchA5b, pitchA5, pitchB5b, pitchB5};

uint8_t notesTime[NUM_BUTTONS];
uint8_t pressedButtons = 0x00;
uint8_t previousButtons = 0x00;
uint8_t intensity = 127; // Set volume to full 0 - 127
//uint8_t intensity;
void setup()
{
  Serial.begin(9600);
  Serial.println("Notes");
  printNotes();
  octaveDown();
  Serial.println("Down one octave");
  printNotes();
  octaveUp();
  Serial.println("Up one octave");
  printNotes();
  
  for (int i = 0; i < NUM_BUTTONS; i++ )
  pinMode(buttons[i], INPUT_PULLUP);
  
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
}
void printNotes()
{
  for (int i = 0; i < NUM_BUTTONS; i++ )
    
  {
    Serial.print(notePitches[i]);
    Serial.print("   ");
  }
  Serial.println();
 
}
void shiftNotes(int shiftAmt)
{
  for (int i = 0; i < NUM_BUTTONS; i++ )
  {
    notePitches[i] += shiftAmt;
  }
}
void octaveDown()
{
  if ( notePitches[0] > pitchC1 )
  {
    shiftNotes(-12);
  }
}
void octaveUp()
{
  if ( notePitches[0] < pitchC8 )
  {
    shiftNotes(12);

  }
}

void loop()
{
  readButtons();
  readIntensity();
  playNotes();

  //while (button20.uniquePress());
  //octaveDown();

  //while (button21.uniquePress());
  //octaveUp();

}

// First parameter is the event type (0x0B = control change).
// Second parameter is the event type, combined with the channel.
// Third parameter is the control number number (0-119).
// Fourth parameter is the control value (0-127).

void controlChange(byte channel, byte control, byte value)
{
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

void readButtons()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (digitalRead(buttons[i]) == LOW)
    {
      bitWrite(pressedButtons, i, 1);
      delay(50);
    }
    else
      bitWrite(pressedButtons, i, 0);
  }
}

void readIntensity()
{
  //int val = analogRead(intensityPot);
  //intensity = (uint8_t) (map(val, 0, 1023, 0, 127));
  //int val ();
}

void playNotes()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (bitRead(pressedButtons, i) != bitRead(previousButtons, i))
    {
      if (bitRead(pressedButtons, i))
      {
        bitWrite(previousButtons, i , 1);
        noteOn(0, notePitches[i], intensity);
        MidiUSB.flush();
      }
      else
      {
        bitWrite(previousButtons, i , 0);
        noteOff(0, notePitches[i], 0);
        MidiUSB.flush();
      }
    }
  }
}

// First parameter is the event type (0x09 = note on, 0x08 = note off).
// Second parameter is note-on/note-off, combined with the channel.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Third parameter is the note number (48 = middle C).
// Fourth parameter is the velocity (64 = normal, 127 = fastest).

void noteOn(byte channel, byte pitch, byte velocity)
{
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity)
{
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

I come cap-in-hand.

I’ve made some progress with the help of Blue Eyes. Very grateful for your help Blue Eyes.

I have 12 keys ‘1 octave’, starting at C5. I have 2 buttons, 1 for octave up and 1 for octave down and wish to ‘transpose’ 1 octave up or down from the current octave I’m in.

I’m pretty certain of the area I need to work on ‘snippet below’, but I lack the coding skills / MIDIUSB knowledge. I have tried many things, hense the gaps as I’ve put things in, removed them and so-on.

void shiftNotes(int shiftAmt)
{
  for (int i = 0; i < NUM_BUTTONS; i++ )
  {
    notePitches[i] += shiftAmt;
  }
}

void octaveDown()
{
  if ( notePitches[0] > pitchC1 ) // If current octave is above C1
    //{
    // pitch(-12); // Change notes by 12 semitones down, or 1 octave
    //}
  {
    midiEventPacket_t write = {0, -12, 127}; //Tried it as a midi msg channel,pitch,velocity
    MidiUSB.sendMIDI(write);
  }




}



void octaveUp()
{
  if ( notePitches[0] < pitchC8 ) // If current octave is below C8
  {
    shiftNotes(12); // Change notes by 12 semitones up, or 1 octave

  }
}

As you can see, I’m just playing with the octave down for the moment. Octave down was the same as what octave up is. What it was doing, was instead of looking to see what octave I’m in, then checking to see if I could move an octave up or down “the library has keys A0 to C8”, it was going directly to C1 or C8 when pressing buttons up or down.

I’d be gratful for a point in the correct direction.

The full sketch is below;

/*
   This examples shows how to make a simple seven keys MIDI keyboard with volume control

   Created: 4/10/2015
   Author: Arturo Guadalupi <a.guadalupi@arduino.cc>

   http://www.arduino.cc/en/Tutorial/MidiDevice
*/

#include "MIDIUSB.h"
#include "PitchToNote.h"
#include <Bounce2.h>
#define BUTTON_PIN_1 2
#define BUTTON_PIN_2 3
#define NUM_BUTTONS  12

Bounce debouncer1 = Bounce();
Bounce debouncer2 = Bounce();

const uint8_t button1 = 33; // Arduino Due pin numbers for keys
const uint8_t button2 = 32;
const uint8_t button3 = 31;
const uint8_t button4 = 30;
const uint8_t button5 = 29;
const uint8_t button6 = 28;
const uint8_t button7 = 27;
const uint8_t button8 = 26;
const uint8_t button9 = 25;
const uint8_t button10 = 24;
const uint8_t button11 = 23;
const uint8_t button12 = 22;

//const int intensityPot = 127;  //A0 input Not being used

const uint8_t buttons[NUM_BUTTONS] = {button1, button2, button3, button4, button5, button6, button7, button8, button9, button10, button11, button12};
//const byte notePitches[NUM_BUTTONS] = {pitchC5, pitchD5b, pitchD5, pitchE5b, pitchE5, pitchF5, pitchG5b, pitchG5, pitchA5b, pitchA5, pitchB5b, pitchB5};
byte notePitches[NUM_BUTTONS] = {pitchC5, pitchD5b, pitchD5, pitchE5b, pitchE5, pitchF5, pitchG5b, pitchG5, pitchA5b, pitchA5, pitchB5b, pitchB5};

uint8_t notesTime[NUM_BUTTONS];
uint16_t pressedButtons = 0x00;
uint16_t previousButtons = 0x00;
uint8_t intensity = 127; // Set volume to full 0 - 127
//uint8_t intensity;

void setup()
{
  for (int i = 0; i < NUM_BUTTONS; i++ )
    pinMode(buttons[i], INPUT_PULLUP);

  pinMode(BUTTON_PIN_1, INPUT_PULLUP);
  debouncer1.attach(BUTTON_PIN_1);
  debouncer1.interval(200);

  pinMode(BUTTON_PIN_2, INPUT_PULLUP);
  debouncer2.attach(BUTTON_PIN_2);
  debouncer2.interval(200);
}

void shiftNotes(int shiftAmt)
{
  for (int i = 0; i < NUM_BUTTONS; i++ )
  {
    notePitches[i] += shiftAmt;
  }
}

void octaveDown()
{
  if ( notePitches[0] > pitchC1 ) // If current octave is above C1
    //{
    // pitch(-12); // Change notes by 12 semitones down, or 1 octave
    //}
  {
    midiEventPacket_t write = {0, -12, 127}; //Tried it as a midi msg channel,pitch,velocity
    MidiUSB.sendMIDI(write);
  }




}



void octaveUp()
{
  if ( notePitches[0] < pitchC8 ) // If current octave is below C8
  {
    shiftNotes(12); // Change notes by 12 semitones up, or 1 octave

  }
}

void loop()
{
  readButtons();
  readIntensity();
  playNotes();

  debouncer1.update();
  int value1 = debouncer1.read();
  if ( value1 == LOW )
  {
    octaveDown();
  }

  debouncer2.update();
  int value2 = debouncer2.read();
  if ( value2 == LOW )
  {
    octaveUp();
  }
}

// First parameter is the event type (0x0B = control change).
// Second parameter is the event type, combined with the channel.
// Third parameter is the control number number (0-119).
// Fourth parameter is the control value (0-127).

void controlChange(byte channel, byte control, byte value)
{
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

void readButtons()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (digitalRead(buttons[i]) == LOW)
    {
      bitWrite(pressedButtons, i, 1);
      delay(50);
    }
    else
      bitWrite(pressedButtons, i, 0);
  }
}

void readIntensity()
{
  //int val = analogRead(intensityPot);
  //intensity = (uint8_t) (map(val, 0, 1023, 0, 127));
  //int val ();
}

void playNotes()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (bitRead(pressedButtons, i) != bitRead(previousButtons, i))
    {
      if (bitRead(pressedButtons, i))
      {
        bitWrite(previousButtons, i , 1);
        noteOn(0, notePitches[i], intensity);
        MidiUSB.flush();
      }
      else
      {
        bitWrite(previousButtons, i , 0);
        noteOff(0, notePitches[i], 0);
        MidiUSB.flush();
      }
    }
  }
}

// First parameter is the event type (0x09 = note on, 0x08 = note off).
// Second parameter is note-on/note-off, combined with the channel.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Third parameter is the note number (48 = middle C).
// Fourth parameter is the velocity (64 = normal, 127 = fastest).

void noteOn(byte channel, byte pitch, byte velocity)
{
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity)
{
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

Thank you for any helpful advice.

Dizzwold.

It seems to me that you are making something simple into something way too complicated.
To play a note you look at all the pins in the buttons array and see which is being held down.
Then you find the note number in the notePitches and finally add an offset to it before sending it out to the MIDI.

This offset will be held in a variable and will have only three possible values -12, 0 and 12. Your octave shift buttons will change this variable by +12 for shift up and -12 for shift down with a check on the bounds value. That means you don't allow the value to go below -12 or above +12. Your octave up / down functions don't seem to do anything like that.

Like all beginners you are trying to do too much at once and getting yourself in a muddle. Start off simply by writing code that will change this shift variable and keep it in range, and print it out after each press. Forget the MIDI bit until you get this simple thing going first.

Only when that is working go on to the MIDI part where you simply add this offset value to every note you send.

EDIT:-
I said "and will have only three possible values -12, 0 and 12."
Their is nothing to stop you having the offset any multiple of 12 you like if you want to cover more octaves. Simply constrain the value to the limits you want to work with. It might be good to have some LEDs that indicate what octave you are in.

Some progress made, but a couple of issues due to my lack of coding.

The 1st issue, I can now get the octave down button to work, but not the octave up button. I think this lies in the following snippet ‘full sketch to follow’. It’s the 1st ‘else and playnotes’ thats stopping the octave up from working. So should I be using ‘while’, a ‘break’, or more 'if’s?

void loop()
{
  readButtons();
  readIntensity();
  //playNotes();

  debouncer1.update();
  int value1 = debouncer1.read();
  if ( value1 == LOW )
  {
    octaveDown();
  }
  else
  {
    playNotes();
  }
 
  debouncer2.update();
  int value2 = debouncer2.read();
  if ( value2 == LOW )
  {
    octaveUp();
  }
  else
  {
    playNotes();
  }
}

The 2nd issue is currently octave down will only work while the button is constanly pressed. I would like to press the octave down button and it will stay in that octave. So do I need to research how to somehow latch the button or use a button count, what sould I be looking for?

Just some pointers please for what I should be looking/researching.

/*
   This examples shows how to make a simple seven keys MIDI keyboard with volume control

   Created: 4/10/2015
   Author: Arturo Guadalupi <a.guadalupi@arduino.cc>

   http://www.arduino.cc/en/Tutorial/MidiDevice
*/

#include "MIDIUSB.h"
#include "PitchToNote.h"
#include "Bounce2.h"
#define BUTTON_PIN_1 2
#define BUTTON_PIN_2 3
#define NUM_BUTTONS  12

Bounce debouncer1 = Bounce();
Bounce debouncer2 = Bounce();

const uint8_t button1 = 33; // Arduino Due pin numbers for keys
const uint8_t button2 = 32;
const uint8_t button3 = 31;
const uint8_t button4 = 30;
const uint8_t button5 = 29;
const uint8_t button6 = 28;
const uint8_t button7 = 27;
const uint8_t button8 = 26;
const uint8_t button9 = 25;
const uint8_t button10 = 24;
const uint8_t button11 = 23;
const uint8_t button12 = 22;

//const int intensityPot = 127;  //A0 input Not being used

const uint8_t buttons[NUM_BUTTONS] =
{button1, button2, button3, button4, button5, button6, button7, button8, button9, button10, button11, button12};

byte notePitches[NUM_BUTTONS] =
{pitchC5, pitchD5b, pitchD5, pitchE5b, pitchE5, pitchF5, pitchG5b, pitchG5, pitchA5b, pitchA5, pitchB5b, pitchB5};

uint8_t notesTime[NUM_BUTTONS];
uint16_t pressedButtons = 0x00;
uint16_t previousButtons = 0x00;
uint8_t intensity = 127; // Set volume to full 0 - 127
//uint8_t intensity;

void setup()
{
  for (int i = 0; i < NUM_BUTTONS; i++ )
    pinMode(buttons[i], INPUT_PULLUP);

  pinMode(BUTTON_PIN_1, INPUT_PULLUP);
  debouncer1.attach(BUTTON_PIN_1);
  debouncer1.interval(200);

  pinMode(BUTTON_PIN_2, INPUT_PULLUP);
  debouncer2.attach(BUTTON_PIN_2);
  debouncer2.interval(200);
}

void octaveDown()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (bitRead(pressedButtons, i) != bitRead(previousButtons, i))
    {
      if (bitRead(pressedButtons, i))
      {
        bitWrite(previousButtons, i , 1);
        noteOn(0, notePitches[i] - 12, intensity);
        MidiUSB.flush();
      }
      else
      {
        bitWrite(previousButtons, i , 0);
        noteOff(0, notePitches[i], 0);
        MidiUSB.flush();
      }
    }
  }
}

void octaveUp()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (bitRead(pressedButtons, i) != bitRead(previousButtons, i))
    {
      if (bitRead(pressedButtons, i))
      {
        bitWrite(previousButtons, i , 1);
        noteOn(0, notePitches[i] + 12, intensity);
        MidiUSB.flush();
      }
      else
      {
        bitWrite(previousButtons, i , 0);
        noteOff(0, notePitches[i], 0);
        MidiUSB.flush();
      }
    }
  }
}

void loop()
{
  readButtons();
  readIntensity();
  //playNotes();

  debouncer1.update();
  int value1 = debouncer1.read();
  if ( value1 == LOW )
  {
    octaveDown();
  }
  else
  {
    playNotes();
  }
 
  debouncer2.update();
  int value2 = debouncer2.read();
  if ( value2 == LOW )
  {
    octaveUp();
  }
  else
  {
    playNotes();
  }
}

// First parameter is the event type (0x0B = control change).
// Second parameter is the event type, combined with the channel.
// Third parameter is the control number number (0-119).
// Fourth parameter is the control value (0-127).

void controlChange(byte channel, byte control, byte value)
{
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

void readButtons()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (digitalRead(buttons[i]) == LOW)
    {
      bitWrite(pressedButtons, i, 1);
      delay(50);
    }
    else
      bitWrite(pressedButtons, i, 0);
  }
}

void readIntensity()
{
  //int val = analogRead(intensityPot);
  //intensity = (uint8_t) (map(val, 0, 1023, 0, 127));
  //int val ();
}

void playNotes()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (bitRead(pressedButtons, i) != bitRead(previousButtons, i))
    {
      if (bitRead(pressedButtons, i))
      {
        bitWrite(previousButtons, i , 1);
        noteOn(0, notePitches[i], intensity);
        MidiUSB.flush();
      }
      else
      {
        bitWrite(previousButtons, i , 0);
        noteOff(0, notePitches[i], 0);
        MidiUSB.flush();
      }
    }
  }
}

// First parameter is the event type (0x09 = note on, 0x08 = note off).
// Second parameter is note-on/note-off, combined with the channel.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Third parameter is the note number (48 = middle C).
// Fourth parameter is the velocity (64 = normal, 127 = fastest).

void noteOn(byte channel, byte pitch, byte velocity)
{
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity)
{
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

Thank you for any advice.

Dizzwold

Hi,

I’ve fixed the octave up not working by commenting out the 1st ‘else { playNotes}’, But still ask for adivce on a 1 button press/latch/count?

/*
   This examples shows how to make a simple seven keys MIDI keyboard with volume control

   Created: 4/10/2015
   Author: Arturo Guadalupi <a.guadalupi@arduino.cc>

   http://www.arduino.cc/en/Tutorial/MidiDevice
*/

#include "MIDIUSB.h"
#include "PitchToNote.h"
#include "Bounce2.h"
#define BUTTON_PIN_1 2
#define BUTTON_PIN_2 3
#define NUM_BUTTONS  12

Bounce debouncer1 = Bounce();
Bounce debouncer2 = Bounce();

const uint8_t button1 = 33; // Arduino Due pin numbers for keys
const uint8_t button2 = 32;
const uint8_t button3 = 31;
const uint8_t button4 = 30;
const uint8_t button5 = 29;
const uint8_t button6 = 28;
const uint8_t button7 = 27;
const uint8_t button8 = 26;
const uint8_t button9 = 25;
const uint8_t button10 = 24;
const uint8_t button11 = 23;
const uint8_t button12 = 22;

//const int intensityPot = 127;  //A0 input Not being used

const uint8_t buttons[NUM_BUTTONS] =
{button1, button2, button3, button4, button5, button6, button7, button8, button9, button10, button11, button12};

byte notePitches[NUM_BUTTONS] =
{pitchC5, pitchD5b, pitchD5, pitchE5b, pitchE5, pitchF5, pitchG5b, pitchG5, pitchA5b, pitchA5, pitchB5b, pitchB5};

uint8_t notesTime[NUM_BUTTONS];
uint16_t pressedButtons = 0x00;
uint16_t previousButtons = 0x00;
uint8_t intensity = 127; // Set volume to full 0 - 127
//uint8_t intensity;

void setup()
{
  for (int i = 0; i < NUM_BUTTONS; i++ )
    pinMode(buttons[i], INPUT_PULLUP);

  pinMode(BUTTON_PIN_1, INPUT_PULLUP);
  debouncer1.attach(BUTTON_PIN_1);
  debouncer1.interval(200);

  pinMode(BUTTON_PIN_2, INPUT_PULLUP);
  debouncer2.attach(BUTTON_PIN_2);
  debouncer2.interval(200);
}

void octaveDown()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (bitRead(pressedButtons, i) != bitRead(previousButtons, i))
    {
      if (bitRead(pressedButtons, i))
      {
        bitWrite(previousButtons, i , 1);
        noteOn(0, notePitches[i] - 12, intensity);
        MidiUSB.flush();
      }
      else
      {
        bitWrite(previousButtons, i , 0);
        noteOff(0, notePitches[i], 0);
        MidiUSB.flush();
      }
    }
  }
}

void octaveUp()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (bitRead(pressedButtons, i) != bitRead(previousButtons, i))
    {
      if (bitRead(pressedButtons, i))
      {
        bitWrite(previousButtons, i , 1);
        noteOn(0, notePitches[i] + 12, intensity);
        MidiUSB.flush();
      }
      else
      {
        bitWrite(previousButtons, i , 0);
        noteOff(0, notePitches[i], 0);
        MidiUSB.flush();
      }
    }
  }
}

void loop()
{
  readButtons();
  readIntensity();
  //playNotes();

  debouncer1.update();
  int value1 = debouncer1.read();
  if ( value1 == LOW )
  {
    octaveDown();
  }
  //else
  //{
  //  playNotes();
  //}

  debouncer2.update();
  int value2 = debouncer2.read();
  if ( value2 == LOW )
  {
    octaveUp();
  }
  else
  {
    playNotes();
  }
}

// First parameter is the event type (0x0B = control change).
// Second parameter is the event type, combined with the channel.
// Third parameter is the control number number (0-119).
// Fourth parameter is the control value (0-127).

void controlChange(byte channel, byte control, byte value)
{
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

void readButtons()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (digitalRead(buttons[i]) == LOW)
    {
      bitWrite(pressedButtons, i, 1);
      delay(50);
    }
    else
      bitWrite(pressedButtons, i, 0);
  }
}

void readIntensity()
{
  //int val = analogRead(intensityPot);
  //intensity = (uint8_t) (map(val, 0, 1023, 0, 127));
  //int val ();
}

void playNotes()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (bitRead(pressedButtons, i) != bitRead(previousButtons, i))
    {
      if (bitRead(pressedButtons, i))
      {
        bitWrite(previousButtons, i , 1);
        noteOn(0, notePitches[i], intensity);
        MidiUSB.flush();
      }
      else
      {
        bitWrite(previousButtons, i , 0);
        noteOff(0, notePitches[i], 0);
        MidiUSB.flush();
      }
    }
  }
}

// First parameter is the event type (0x09 = note on, 0x08 = note off).
// Second parameter is note-on/note-off, combined with the channel.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Third parameter is the note number (48 = middle C).
// Fourth parameter is the velocity (64 = normal, 127 = fastest).

void noteOn(byte channel, byte pitch, byte velocity)
{
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity)
{
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

Dizzwold.

But still ask for adivce on a 1 button press/latch/count?

Ok why are you using the bitRead function? There is no need for it and it is just complicating matters.
To read a push button you need to detect when it becomes pressed not while it is pressed. So you take a note of the previous state. Then you can test a push ( assuming pushed = LOW ) with a compound if statement:-

if(buttonPushed == LOW && previousPush == HIGH ) { // then do stuff

the && is a logical AND.
If you want to extend this to many buttons then you make the previousPush and the buttonPushed into arrays and look at each in turn, so for say 10 buttons you do:-

for(int i=0;i<10;i++){
     if(buttonPushed[i] == LOW && previousPush[i] == HIGH ) { // then do stuff
     }
}

Hi Grumpy_Mike,

Yes I know, it’s very Heath Robinson and appreciate they may be many better ways.

Thanks for your input, I was looking at ‘if (state == High && newState == LOW)’, so I was on the correct track with that part.

I need to find an L plate for an avitar. LOL.

dizzwold.