Midi values displayed on oled

Hi.

I have only just begun to learn arduino and its coding.

So far i have hooked up rotary and fader type potentiometers for some simple midi controllers.
I have also connected up an oled display and got it to show the adafruit tutorial images.

I have been looking for more info on how i take the potentiometer information and have it display on the oled but I am having no success on a tutorial or information.

What I want to do is when i turn the pot or move the fader have it show the values for the #cc, midi channel and the 0-127 value. So on screen you see: #CC16 1 120 (CC16 midi channel 1 and the current value from 0-127 as 120)

Can anyone point me in the right direction of a thread or tutorial or give an old guy some pointers?

Really enjoying messing with arduino and would like to get this under my belt, I am trying things as I go but only getting limited success and very random at that!

thanks

Welcome to the forum

Presumably you have the values that you want to display in variables in the sketch. If so, then printing them to the OLED should be easy

I suggest that you start by printing the values to the Serial monitor if you have not already done so

If you look at the examples from the Adafruit library you will see how text and variables are sent to the display

Thanks for the reply @UKHeliBob

I really am green on the arduino and programming, I have bought a couple of books on arduino programming and am trying things. I have been following the Notes and Volts youtube channel tutorials. I have even got the multiplexers running. Can you suggest a good library to look at?

I am not asking for anyone to code this for me I want to learn it myself, I find it easier to learn by example then try adapting for myself and learning other functions that way.

It has more than likely been done before I just don't know where to look.

Thanks again.

What do you want from the library that you are looking for ? If you have an Adafruit library and its demo code runs then stick with that

You say

Have you got a sketch that works with this setup ? If so, please post it, using code tags when you do

Which Arduino are you using ?

Hi @UKHeliBob

I have built the midi controller using the files from notes and volts tutorials along with the 5 pin midi output din socket. So that works and also the multiplexer version works ( took a little time to get to grips with).

I have no knowledge of programming C in any format and as I said i am going step by step making many mistake over successes.

I have this on two different boards, one is an UNO and the other is a Pro Micro which comes up as a leanardo.

To test the oled i downloaded the adafruit display tutorial which shows all the lines, text and snowflakes falling.

I am a provierbial old dog trying to learn a new trick.

I am going through lots of threads on the forum right now seeing if i can find out more info as I go along, then cross cheking things in the books i have here to try and understand how it needs to be written.

I still can't figure out what things i need to grab from git hub yet! lots to learn.

Thanks again.

Have a good easter!

It sounds like you have some code that you would like to add the display to. If so then please post it here as it could form the basis for what you want to do

Hi @UKHeliBob

this is the code i have: on here i have just enabled on pot for now as if the oled is set for one control only i can go from there changing the code for each item and testing it.

any code i have tried is basically garbage and random and I have had many non compiles.

midi_controller_v1-2

#include <MIDI.h>
#include "Controller.h"

/*************************************************************
  MIDI CONTROLLER

  by Notes and Volts
  www.notesandvolts.com

  Version 1.2 **Arduino UNO ONLY!**
 *************************************************************/

MIDI_CREATE_DEFAULT_INSTANCE();

//************************************************************
//***SET THE NUMBER OF CONTROLS USED**************************
//************************************************************
//---How many buttons are connected directly to pins?---------
byte NUMBER_BUTTONS = 0;
//---How many potentiometers are connected directly to pins?--
byte NUMBER_POTS = 1;
//---How many buttons are connected to a multiplexer?---------
byte NUMBER_MUX_BUTTONS = 0;
//---How many potentiometers are connected to a multiplexer?--
byte NUMBER_MUX_POTS = 0;
//************************************************************

//***ANY MULTIPLEXERS? (74HC4067)************************************
//MUX address pins must be connected to Arduino UNO pins 2,3,4,5
//A0 = PIN2, A1 = PIN3, A2 = PIN4, A3 = PIN5
//*******************************************************************
//Mux NAME (OUTPUT PIN, , How Many Mux Pins?(8 or 16) , Is It Analog?);


//Mux M1(10, 16, false); //Digital multiplexer on Arduino pin 10
//Mux M2(A5, 8, true); //Analog multiplexer on Arduino analog pin A0
//*******************************************************************


//***DEFINE DIRECTLY CONNECTED POTENTIOMETERS************************
//Pot (Pin Number, Command, CC Control, Channel Number)
//**Command parameter is for future use**

Pot PO1(A0, 0, 22, 1);
//Pot PO2(A1, 0, 10, 1);
//Pot PO3(A2, 0, 22, 1);
//Pot PO4(A3, 0, 118, 1);
//Pot PO5(A4, 0, 30, 1);
//Pot PO6(A5, 0, 31, 1);
//*******************************************************************
//Add pots used to array below like this->  Pot *POTS[] {&PO1, &PO2, &PO3, &PO4, &PO5, &PO6};
Pot *POTS[] {&PO1};
//*******************************************************************


//***DEFINE DIRECTLY CONNECTED BUTTONS*******************************
//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
//** Command parameter 0=NOTE  1=CC  2=Toggle CC **

//Button BU1(2, 0, 60, 1, 5 );
//Button BU2(3, 0, 61, 1, 5 );
//Button BU3(4, 0, 62, 1, 5 );
//Button BU4(5, 0, 63, 1, 5 );
//Button BU5(6, 0, 64, 1, 5 );
//Button BU6(7, 0, 65, 1, 5 );
//Button BU7(8, 1, 64, 1, 5 );
//Button BU8(9, 2, 64, 1, 5 );
//*******************************************************************
//Add buttons used to array below like this->  Button *BUTTONS[] {&BU1, &BU2, &BU3, &BU4, &BU5, &BU6, &BU7, &BU8};
Button *BUTTONS[] {};
//*******************************************************************


//***DEFINE BUTTONS CONNECTED TO MULTIPLEXER*************************
//Button::Button(Mux mux, byte muxpin, byte command, byte value, byte channel, byte debounce)
//** Command parameter 0=NOTE  1=CC  2=Toggle CC **

//Button MBU1(M1, 0, 0, 70, 1, 5);
//Button MBU2(M1, 1, 1, 71, 1, 5);
//Button MBU3(M1, 2, 2, 72, 1, 5);
//Button MBU4(M1, 3, 0, 73, 1, 5);
//Button MBU5(M1, 4, 0, 74, 1, 5);
//Button MBU6(M1, 5, 0, 75, 1, 5);
//Button MBU7(M1, 6, 0, 76, 1, 5);
//Button MBU8(M1, 7, 0, 77, 1, 5);
//Button MBU9(M1, 8, 0, 78, 1, 5);
//Button MBU10(M1, 9, 0, 79, 1, 5);
//Button MBU11(M1, 10, 0, 80, 1, 5);
//Button MBU12(M1, 11, 0, 81, 1, 5);
//Button MBU13(M1, 12, 0, 82, 1, 5);
//Button MBU14(M1, 13, 0, 83, 1, 5);
//Button MBU15(M1, 14, 0, 84, 1, 5);
//Button MBU16(M1, 15, 0, 85, 1, 5);
//*******************************************************************
////Add multiplexed buttons used to array below like this->  Button *MUXBUTTONS[] {&MBU1, &MBU2, &MBU3, &MBU4, &MBU5, &MBU6.....};
Button *MUXBUTTONS[] {};

//*******************************************************************


//***DEFINE POTENTIOMETERS CONNECTED TO MULTIPLEXER*******************
//Pot::Pot(Mux mux, byte muxpin, byte command, byte control, byte channel)
//**Command parameter is for future use**

//Pot MPO1(M2, 0, 0, 1, 1);
//Pot MPO2(M2, 1, 0, 7, 1);
//Pot MPO3(M2, 2, 0, 50, 1);
//Pot MPO4(M2, 3, 0, 55, 2);
//Pot MPO5(M2, 4, 0, 50, 1);
//Pot MPO6(M2, 5, 0, 55, 2);
//Pot MPO7(M2, 6, 0, 50, 1);
//Pot MPO8(M2, 7, 0, 55, 2);
//Pot MPO9(M2, 8, 0, 50, 1);
//Pot MPO10(M2, 9, 0, 55, 2);
//Pot MPO11(M2, 10, 0, 50, 1);
//Pot MPO12(M2, 11, 0, 55, 2);
//Pot MPO13(M2, 12, 0, 50, 1);
//Pot MPO14(M2, 13, 0, 55, 2);
//Pot MPO15(M2, 14, 0, 50, 1);
//Pot MPO16(M2, 15, 0, 55, 2);
//*******************************************************************
//Add multiplexed pots used to array below like this->  Pot *MUXPOTS[] {&MPO1, &MPO2, &MPO3, &MPO4, &MPO5, &MPO6.....};
Pot *MUXPOTS[] {};
//*******************************************************************


void setup() {
  MIDI.begin(MIDI_CHANNEL_OFF);
}

void loop() {
  if (NUMBER_BUTTONS != 0) updateButtons();
  if (NUMBER_POTS != 0) updatePots();
  if (NUMBER_MUX_BUTTONS != 0) updateMuxButtons();
  if (NUMBER_MUX_POTS != 0) updateMuxPots();
}


//*****************************************************************
void updateButtons() {

  // Cycle through Button array
  for (int i = 0; i < NUMBER_BUTTONS; i = i + 1) {
    byte message = BUTTONS[i]->getValue();

    //  Button is pressed
    if (message == 0) {
      switch (BUTTONS[i]->Bcommand) {
        case 0: //Note
          MIDI.sendNoteOn(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
          break;
        case 1: //CC
          MIDI.sendControlChange(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
          break;
        case 2: //Toggle
          if (BUTTONS[i]->Btoggle == 0) {
            MIDI.sendControlChange(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
            BUTTONS[i]->Btoggle = 1;
          }
          else if (BUTTONS[i]->Btoggle == 1) {
            MIDI.sendControlChange(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
            BUTTONS[i]->Btoggle = 0;
          }
          break;
      }
    }

    //  Button is not pressed
    if (message == 1) {
      switch (BUTTONS[i]->Bcommand) {
        case 0:
          MIDI.sendNoteOff(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
          break;
        case 1:
          MIDI.sendControlChange(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
          break;
      }
    }
  }
}
//*******************************************************************
void updateMuxButtons() {

  // Cycle through Mux Button array
  for (int i = 0; i < NUMBER_MUX_BUTTONS; i = i + 1) {

    MUXBUTTONS[i]->muxUpdate();
    byte message = MUXBUTTONS[i]->getValue();

    //  Button is pressed
    if (message == 0) {
      switch (MUXBUTTONS[i]->Bcommand) {
        case 0: //Note
          MIDI.sendNoteOn(MUXBUTTONS[i]->Bvalue, 127, MUXBUTTONS[i]->Bchannel);
          break;
        case 1: //CC
          MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 127, MUXBUTTONS[i]->Bchannel);
          break;
        case 2: //Toggle
          if (MUXBUTTONS[i]->Btoggle == 0) {
            MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 127, MUXBUTTONS[i]->Bchannel);
            MUXBUTTONS[i]->Btoggle = 1;
          }
          else if (MUXBUTTONS[i]->Btoggle == 1) {
            MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 0, MUXBUTTONS[i]->Bchannel);
            MUXBUTTONS[i]->Btoggle = 0;
          }
          break;
      }
    }
    //  Button is not pressed
    if (message == 1) {
      switch (MUXBUTTONS[i]->Bcommand) {
        case 0:
          MIDI.sendNoteOff(MUXBUTTONS[i]->Bvalue, 0, MUXBUTTONS[i]->Bchannel);
          break;
        case 1:
          MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 0, MUXBUTTONS[i]->Bchannel);
          break;
      }
    }
  }
}
//***********************************************************************
void updatePots() {
  for (int i = 0; i < NUMBER_POTS; i = i + 1) {
    byte potmessage = POTS[i]->getValue();
    if (potmessage != 255) MIDI.sendControlChange(POTS[i]->Pcontrol, potmessage, POTS[i]->Pchannel);
  }
}
//***********************************************************************
void updateMuxPots() {
  for (int i = 0; i < NUMBER_MUX_POTS; i = i + 1) {
    MUXPOTS[i]->muxUpdate();
    byte potmessage = MUXPOTS[i]->getValue();
    if (potmessage != 255) MIDI.sendControlChange(MUXPOTS[i]->Pcontrol, potmessage, MUXPOTS[i]->Pchannel);
  }
}
Controller.cpp

#include "Controller.h"

//****************************************************************************************
Mux::Mux(byte outpin_, byte numPins_, bool analog_)
{
  outpin = outpin_;
  //enablepin = enablepin_;
  numPins = numPins_;
  analog = analog_;
  if (analog == false) pinMode(outpin, INPUT_PULLUP);
  //pinMode(enablepin, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  if (numPins > 8) pinMode(5, OUTPUT);
}
//****************************************************************************************
//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
Button::Button(byte pin, byte command, byte value, byte channel, byte debounce)
{
  _pin = pin;
  pinMode(_pin, INPUT_PULLUP);
  _value = value;
  _command = command;
  _debounce = debounce;
  _time = 0;
  _busy = false;
  _status = 0b00000010;
  _last = 1;
  Bcommand = command;
  Bvalue = value;
  Bchannel = channel;
  Btoggle = 0;
}

Button::Button(Mux mux, byte muxpin, byte command, byte value, byte channel, byte debounce)
{
  _pin = mux.outpin;
  _numMuxPins = mux.numPins;
  _muxpin = muxpin;
  _value = value;
  _command = command;
  _debounce = debounce;
  _time = 0;
  _busy = false;
  _status = 0b00000010;
  _last = 1;
  Bcommand = command;
  Bvalue = value;
  Bchannel = channel;
  Btoggle = 0;
}

void Button::muxUpdate()
{
  byte temp = _muxpin;
  temp = temp << 2;
  if (_numMuxPins > 8) PORTD = PORTD & B11000011;
  else PORTD = PORTD & B11100011;
  PORTD = PORTD | temp;
}

byte Button::getValue()
{
  // If BUSY bit not set - read button
  if (bitRead(_status, 0) == false) { // If busy false
    if (digitalRead(_pin) == _last) return 2; // If same as last state - exit
  }

  // If NEW Bit set - Key just pressed, record time
  if (bitRead(_status, 1) == true) { // If new is true
    bitSet(_status, 0); // Set busy TRUE
    bitClear(_status, 1); // Set New FALSE
    _time = millis();
    return 255;
  }

  // Check if debounce time has passed - If no, exit
  if (millis() - _time < _debounce) return 255;

  // Debounce time has passed. Read pin to see if still set the same
  // If it has changed back - assume false alarm
  if (digitalRead(_pin) == _last) {
    bitClear(_status, 0); // Set busy false
    bitSet(_status, 1); // Set new true
    return 255;
  }

  // If this point is reached, event is valid. return event type
  else {
    bitClear(_status, 0); // Set busy false
    bitSet(_status, 1); // Set new true
    _last = ((~_last) & 0b00000001); // invert _last
    return _last;
  }
}

void Button::newValue(byte command, byte value, byte channel)
{
  Bvalue = value;
  Bcommand = command;
  Bchannel = channel;
}

//********************************************************************
Pot::Pot(byte pin, byte command, byte control, byte channel)
{
  _pin = pin;
  _control = control;
  _value = analogRead(_pin);
  _value = _value >> 3;
  _oldValue = _value << 3;
  _value = _value << 3;
  Pcommand = command;
  Pcontrol = control;
  Pchannel = channel;
}

void Pot::muxUpdate()
{
  byte temp = _muxpin;
  temp = temp << 2;
  if (_numMuxPins > 8) PORTD = PORTD & B11000011;
  else PORTD = PORTD & B11100011;
  //PORTD = PORTD & B11000011;
  PORTD = PORTD | temp;
}

Pot::Pot(Mux mux, byte muxpin, byte command, byte control, byte channel)
{
  _pin = mux.outpin;
  _numMuxPins = mux.numPins;
  _muxpin = muxpin;
  _control = control;
  muxUpdate();
  _value = analogRead(_pin);
  _value = _value >> 3;
  _oldValue = _value << 3;
  _value = _value << 3;
  Pcommand = command;
  Pcontrol = control;
  Pchannel = channel;
}

byte Pot::getValue()
{
  _value = analogRead(_pin);
  int tmp = (_oldValue - _value);
  if (tmp >= 8 || tmp <= -8) {
    _oldValue = _value >> 3;
    _oldValue = _oldValue << 3;
    return _value >> 3;
  }
  return 255;
}

void Pot::newValue(byte command, byte value, byte channel) {
  Pcommand = command;
  Pcontrol = value;
  Pchannel = channel;
}


Controller.h

#ifndef Controller_h
#define Controller_h

#include <Arduino.h>

//***********************************************************************
class Mux
{
  public:
    Mux(byte outpin_, byte numPins_, bool analog_);
    byte outpin;
    byte numPins;
    bool analog;
};
//************************************************************************
//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
class Button
{
  public:
    Button(byte pin, byte command, byte value, byte channel, byte debounce);
    Button(Mux mux, byte muxpin, byte command, byte value, byte channel, byte debounce);
    byte getValue();
    void muxUpdate();
    void newValue(byte command, byte value, byte channel);
    byte Bcommand;
    byte Bvalue;
    byte Bchannel;
    byte Btoggle;

  private:
    byte _previous;
    byte _current;
    unsigned long _time;
    int _debounce;
    byte _pin;
    byte _muxpin;
    byte _numMuxPins;
    byte _value;
    byte _command;
    bool _busy;
    byte _status;
    byte _last;
    byte _enablepin;
};
//*************************************************************************
class Pot
{
  public:
    Pot(byte pin, byte command, byte control, byte channel);
    Pot(Mux mux, byte muxpin ,byte command, byte control, byte channel);
    void muxUpdate();
    void newValue(byte command, byte value, byte channel);
    byte getValue();
    byte Pcommand;
    byte Pcontrol;
    byte Pchannel;

  private:
    byte _pin;
    byte _muxpin;
    byte _numMuxPins;
    byte _control;
    int _value;
    int _oldValue;
    bool _changed;
    byte _enablepin;
};
//*************************************************************************
#endif

I will look at the code later if I have time. Does it compile for you ?

I know little or nothing about Midi but will help if I can

Something like this? Control Surface: MIDI-Monitor-OLED.ino

MIDI-Monitor-OLED.ino

Hi @UKHeliBob

yes that code works fine.

I just used Chat gpt for the first time and asked how to do this and this is what it came back with, so I am going to study this now and try it after lunch, if it works then I havea basis to try more than one potentiometer and alter the code to add another.

Chat gpt code:

//Below is an example Arduino code that reads the value from a potentiometer, maps it to the
//MIDI range (0-127), and displays it on an OLED display. This code assumes you have an OLED
//display connected to your Arduino and a potentiometer connected to an analog pin.

cpp

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const int potPin = A0; // Analog pin for potentiometer
int potValue = 0; // Variable to store potentiometer value
int mappedValue = 0; // Variable to store mapped MIDI value

void setup() {
  // Initialize OLED display
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  delay(2000); // Pause for 2 seconds

  // Clear the display buffer
  display.clearDisplay();
  display.display();

  // Set up serial communication
  Serial.begin(9600);
}

void loop() {
  // Read potentiometer value
  potValue = analogRead(potPin);

  // Map potentiometer value to MIDI range
  mappedValue = map(potValue, 0, 1023, 0, 127);

  // Display MIDI value on OLED display
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.print("MIDI Value: ");
  display.println(mappedValue);
  display.display();

  // Print MIDI value to serial monitor
  Serial.print("MIDI Value: ");
  Serial.println(mappedValue);

  delay(100); // Adjust delay as needed for your application
}

//Make sure you have the necessary libraries installed for the OLED display. You can install them
//through the Arduino IDE by navigating to Sketch > Include Library > Manage Libraries and
//searching for "Adafruit SSD1306" and "Adafruit GFX Library".

//Connect your OLED display according to its specifications, and connect your potentiometer to
//an analog pin (A0 in this case) on the Arduino.

//This code continuously reads the value from the potentiometer, maps it to the MIDI range 
//(0-127), displays it on the OLED display, and prints it to the serial monitor for debugging
//purposes. Adjust the delay time according to your requirements.

Hi @UKHeliBob @PieterP

After much usage of chat gpt and going through many variations of enquiries i have got it working on one pot using this code. Now i have a good grounding to work from and share as I go.

I am also looking at other variations as I go as well.

single pot midi display

#include <MIDIUSB.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET -1
Adafruit_SSD1306 display(OLED_RESET);

const int potPin = A0;  // Potentiometer connected to analog pin A0
int potValue = 0;       // Variable to store the potentiometer value

void setup() {
  // Initialize the OLED display
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C, 2, 3); // Address 0x3C for 128x32, using pins 2 and 3

  // Set up the potentiometer pin
  pinMode(potPin, INPUT);
}

void loop() {
  // Read the potentiometer value (0-1023) and map it to MIDI range (0-127)
  potValue = map(analogRead(potPin), 0, 1023, 0, 127);

  // Display the potentiometer value on OLED
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.print("MIDI Value:");
  display.setCursor(0, 10);
  display.print(potValue);
  display.display();

  // Send MIDI Control Change message
  midiEventPacket_t event = {0x0B, 0xB0 | 1, potValue}; // Change the first parameter (0x0B) for different MIDI messages
  MidiUSB.sendMIDI(event);

  delay(50); // Adjust delay as needed
}

That sounds good

So it's a wierd one.

I had to change the code and things are showing on the display however, it is not outputting the #cc via usb midi.

I uploaded a sketch that generated a note on and off automatically and uploaded it and it sent the note on and off out over usbmidi fine, using midiox it showed the midi input.

#include <MIDIUSB.h>

const int noteNumber = 60; // MIDI note number (C4)
const int velocity = 100;  // Velocity for the note on message
const int channel = 0;     // MIDI channel (0-15)

// Function prototypes
void sendNoteOn(byte note, byte velocity = 127, byte channel = 0);
void sendNoteOff(byte note, byte velocity = 0, byte channel = 0);

void setup() {
  // No setup required
}

void loop() {
  // Send MIDI note on message
  sendNoteOn(noteNumber, velocity, channel);
  delay(500); // Wait for 500 milliseconds
  
  // Send MIDI note off message
  sendNoteOff(noteNumber, 0, channel);
  delay(500); // Wait for 500 milliseconds
}

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

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

So i know that the leornado is working via usb midi.

For some reason its not outputting the #cc midi when i turn the pot, the display shows to increase from 0-127 fine.

#include <MIDIUSB.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET -1
Adafruit_SSD1306 display(OLED_RESET);

const int potPin = A0;  // Potentiometer connected to analog pin A0
int potValue = 0;       // Variable to store the potentiometer value
int ccNumber = 16;      // MIDI Control Change number (0-127)

void setup() {
  // Initialize the OLED display
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C, 2, 3); // Address 0x3C for 128x32, using pins 2 and 3

  // Set up the potentiometer pin
  pinMode(potPin, INPUT);
}

void loop() {
  // Read the potentiometer value (0-1023) and map it to MIDI range (0-127)
  potValue = map(analogRead(potPin), 0, 1023, 0, 127);

  // Display the potentiometer value on OLED
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.print("MIDI Value:");
  display.setCursor(0, 10);
  display.print(potValue);
  display.display();

  // Send MIDI Control Change message
  midiEventPacket_t event;
  event.header = 0xB0 | 0x00; // Control Change message on MIDI Channel 1
  event.byte1 = ccNumber;     // CC number (0-127)
  event.byte2 = potValue;      // CC value (0-127)
  MidiUSB.sendMIDI(event);
}

This is not correct. The header should be 0x0B, and the first data byte should be 0xB0 | (channel - 1), the second the CC number, and the third the CC value.

You're also missing a MidiUSB.flush().


In my experience, 90% of the C++ and Arduino code generated by ChatGPT contains at least some incorrect information. While its answers can still be useful in some cases, it takes a fair bit of programming experience to filter out the unavoidable nonsense it often spews out.

I would not recommend relying on ChatGPT for learning. Following a well-structured book or course, and teaching yourself how to read documentation and other people's code are much more productive in the long run.

hi @PieterP

I changed that data byte, i saw that.

Since earlier i have go it working however with no oled in the code it runs fine and fast however, with the code for the oled included the midi data outputs very slow, i turn it and the input takes time. I have learned a lot today and am understanding quite a few things. I have an uno here i might try it on also.

I have tried to find tutorials for this but havent had any real luck. the chatgpt has worked for now and helped, I will be reading through my books as i go.

Another edit and its working, a very slight lag now.

i used the MidiUSB.flush() in the code and it helped midi is faster now.

Going to try modifying again tomorrow, had enough for today!

#include <MIDIUSB.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

const byte potPin = A0;     // Potentiometer connected to analog pin A0
const byte ccNumber = 16;   // MIDI Control Change number (CC 16)
const byte channel = 1;     // MIDI channel (1-16)

#define OLED_RESET -1
Adafruit_SSD1306 display(OLED_RESET);

void setup() {
  // Initialize OLED display
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C, 2, 3); // Address 0x3C for 128x32, using pins 2 and 3

  // Set potentiometer pin as input
  pinMode(potPin, INPUT);
}

void loop() {
  // Read the potentiometer value
  int potValue = analogRead(potPin);
  
  // Map the potentiometer value to MIDI range (0-127)
  byte midiValue = map(potValue, 0, 1023, 0, 127);
  
  // Display MIDI value on OLED
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.print("MIDI Value:");
  display.setCursor(0, 10);
  display.print(midiValue);
  display.display();
  
  // Send MIDI Control Change message
  sendControlChange(ccNumber, midiValue, channel);
}

void sendControlChange(byte ccNumber, byte ccValue, byte channel) {
  // Construct MIDI Control Change message
  midiEventPacket_t ccMessage = {0x0B, 0xB0 | (channel - 1), ccNumber, ccValue};
  
  // Send MIDI message over USB
  MidiUSB.sendMIDI(ccMessage);
  
  // Flush MIDI buffer
  MidiUSB.flush();
}

adjusted the code.
declared the pot parameters so its not in the loop.
used #define for pot pin and cc
not printing to screen on every pass now just when the value is updated so not constantly refreshing the screen.

works really well today.

#include <MIDIUSB.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define POT_PIN A0           // Define potentiometer pin
#define CC_NUMBER 16         // Define MIDI Control Change number
#define CHANNEL 1            // Define MIDI channel

#define OLED_RESET -1
Adafruit_SSD1306 display(OLED_RESET);

int potValue = 0;            // Variable to store the potentiometer value
int lastPotValue = -1;       // Variable to store the last potentiometer value
bool oledNeedsUpdate = true; // Flag to indicate whether OLED needs updating

void setup() {
  // Initialize OLED display
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C, 2, 3); // Address 0x3C for 128x32, using pins 2 and 3

  // Set potentiometer pin as input
  pinMode(POT_PIN, INPUT);
}

void loop() {
  // Read the potentiometer value
  potValue = analogRead(POT_PIN);

  // Check if the potentiometer value has changed
  if (potValue != lastPotValue) {
    // Map the potentiometer value to MIDI range (0-127)
    byte midiValue = map(potValue, 0, 1023, 0, 127);
    
    // Update last potentiometer value
    lastPotValue = potValue;

    // Send MIDI Control Change message
    sendControlChange(CC_NUMBER, midiValue, CHANNEL);

    // Set flag to indicate OLED needs updating
    oledNeedsUpdate = true;
  }

  // Update OLED display if needed
  if (oledNeedsUpdate) {
    // Display MIDI value on OLED
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(0, 0);
    display.print("MIDI Value:");
    display.setCursor(0, 10);
    display.print(map(lastPotValue, 0, 1023, 0, 127)); // Display mapped potentiometer value
    display.display();

    // Reset flag
    oledNeedsUpdate = false;
  }

  // Flush MIDI buffer
  MidiUSB.flush();
}

void sendControlChange(byte ccNumber, byte ccValue, byte channel) {
  // Construct MIDI Control Change message
  midiEventPacket_t ccMessage = {0x0B, 0xB0 | (channel - 1), ccNumber, ccValue};
  
  // Send MIDI message over USB
  MidiUSB.sendMIDI(ccMessage);
}