# 3 faders/3 pots external NRPN midi controller

**URL:** <https://forums.allen-heath.com/t/3-faders-3-pots-external-nrpn-midi-controller/32903>\
**Category:** CQ General Discussions\
**Created:** [8 September 2026 11:11 UTC](https://forums.allen-heath.com/t/3-faders-3-pots-external-nrpn-midi-controller/32903 "2026-09-08T11:11:33Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![frenchie](https://avatars.discourse-cdn.com/v4/letter/f/71e660/32.png) [@frenchie](https://forums.allen-heath.com/u/frenchie)\
**Post date:** [8 September 2026 11:11 UTC](https://forums.allen-heath.com/t/3-faders-3-pots-external-nrpn-midi-controller/32903/1 "2026-09-08T11:11:33Z")

</div>

Hello.  
Here is a little update of my 3 potentiometers and 3 faders NRPN external midi controller for the CQ range mixer.

-it connect to the CQ via USB midi.

-it use 1 arduino pro micro (leonardo)

-3 potentiometers and 3 faders.

-wiring diagram:

 ![KvEyzMyLUu](https://us1.discourse-cdn.com/flex002/uploads/allenheathdigitalcommunity/original/2X/7/7d2653a0a3ab6f8af6f8e951529bba0013c9f573.png)

-Arduino sketch:

```auto
#include <USB-MIDI.h>

#include <EEPROM.h> 

USBMIDI_CREATE_DEFAULT_INSTANCE();

const byte numPots = 6;

const byte potPins[numPots] = {A0, A1, A2, A3, A7, A8};

const int EEPROM_START_ADDRESS = 0; 

int currentPotValue[numPots] = {0, 0, 0, 0, 0, 0};

int lastPotValue[numPots] = {0, 0, 0, 0, 0, 0};

const int tolerance = 2;

const unsigned int DEFAULT_NRPN[numPots] = {8193, 8253, 8192, 8220, 8252, 8222};

unsigned int nrpnParameters[numPots]; 

const byte midiChannel = 1;

// Define the CC numbers used for configuration

const byte CC_CONFIG_MSB_START = 10; // CC 10-15 pour les MSB des 6 pots

const byte CC_CONFIG_LSB_START = 20; // CC 20-25 pour les LSB des 6 pots

void setup() {

  MIDI.begin(midiChannel);

  MIDI.setHandleControlChange(onControlChange);

  // Serial.begin(9600); 

  loadNRPNConfig();

  

  // ✨ NOUVEAU : Envoi de la configuration enregistrée au démarrage

  // Le navigateur doit être prêt à recevoir cette donnée après la connexion.

  sendCurrentConfigToHost(); 

}

void loop() {

  for (byte i = 0; i < numPots; i++) {

    currentPotValue[i] = analogRead(potPins[i]);

    if (abs(currentPotValue[i] - lastPotValue[i]) > tolerance) {

      unsigned int mappedValue = map(currentPotValue[i], 0, 1023, 0, 16383);

      sendNRPNValue(midiChannel, nrpnParameters[i], mappedValue);

      lastPotValue[i] = currentPotValue[i];

    }

  }

  delay(10);

  MIDI.read();

}

// Fonction de rappel appelée lorsque l'Arduino reçoit un message Control Change

void onControlChange(byte channel, byte control, byte value) {

  if (channel == midiChannel) {

    // Vérifie si c'est un message de configuration MSB (CC 10-15)

    if (control >= CC_CONFIG_MSB_START && control < (CC_CONFIG_MSB_START + numPots)) {

      byte potIndex = control - CC_CONFIG_MSB_START;

      nrpnParameters[potIndex] = (nrpnParameters[potIndex] & 0x007F) | ((unsigned int)value << 7);

    }

    // Vérifie si c'est un message de configuration LSB (CC 20-25)

    else if (control >= CC_CONFIG_LSB_START && control < (CC_CONFIG_LSB_START + numPots)) {

      byte potIndex = control - CC_CONFIG_LSB_START;

      nrpnParameters[potIndex] = (nrpnParameters[potIndex] & 0xFF80) | value;

      

      saveNRPNConfig(potIndex, nrpnParameters[potIndex]);

    }

  }

}

// Fonction utilitaire pour envoyer un message NRPN complet

void sendNRPNValue(byte channel, unsigned int parameterNumber, unsigned int value) {

  MIDI.beginNrpn(parameterNumber, channel);

  MIDI.sendNrpnValue(value, channel);

}

// --- Fonctions EEPROM (inchangées) ---

void loadNRPNConfig() {

  unsigned int checkValue = 0xFFFF;

  

  EEPROM.get(EEPROM_START_ADDRESS, checkValue);

  

  if (checkValue == 0xFFFF) {

    for (byte i = 0; i < numPots; i++) {

      nrpnParameters[i] = DEFAULT_NRPN[i];

      saveNRPNConfig(i, nrpnParameters[i]);

    }

    // Serial.println("EEPROM non initialisée. Chargement et écriture des valeurs par défaut.");

  } else {

    for (byte i = 0; i < numPots; i++) {

      int address = EEPROM_START_ADDRESS + (i * sizeof(unsigned int));

      EEPROM.get(address, nrpnParameters[i]);

    }

    // Serial.println("EEPROM chargée avec les valeurs enregistrées.");

  }

}

void saveNRPNConfig(byte potIndex, unsigned int nrpnValue) {

  int address = EEPROM_START_ADDRESS + (potIndex * sizeof(unsigned int));

  EEPROM.put(address, nrpnValue);

}

// ✨ NOUVELLE FONCTION : Envoie la config NRPN actuelle au logiciel hôte (le navigateur)

void sendCurrentConfigToHost() {

  // L'Arduino va s'envoyer ses propres valeurs enregistrées au navigateur.

  for (byte i = 0; i < numPots; i++) {

    unsigned int nrpnValue = nrpnParameters[i];

    

    // Split 14-bit NRPN into MSB and LSB

    const byte msb_param = (nrpnValue >> 7) & 0x7F;

    const byte lsb_param = nrpnValue & 0x7F;

    

    // Use the custom CCs for configuration (CC 10-15 and CC 20-25)

    const byte cc_msb_number = CC_CONFIG_MSB_START + i;

    const byte cc_lsb_number = CC_CONFIG_LSB_START + i;

    // Envoi du MSB

    MIDI.sendControlChange(cc_msb_number, msb_param, midiChannel);

    // Envoi du LSB (déclenchera l'affichage sur l'interface après réception complète)

    MIDI.sendControlChange(cc_lsb_number, lsb_param, midiChannel);

  }

}

```

-build your own enclosure, I do not provide 3d files directly here but on demand via MP (for free) for this version only:

 ![HDeLs21pSly0cyju5Tf_-g](https://us1.discourse-cdn.com/flex002/uploads/allenheathdigitalcommunity/original/2X/3/367cb5f0123bf476f45c15446f98013d2478aecf.jpeg)

-once the Arduino sketch is upload, you can program your midi device directly online at this address:  
-[https://cq-faders.netlify.app/](https://cq-faders.netlify.app/)

 ![8xSCQFC3FP](https://us1.discourse-cdn.com/flex002/uploads/allenheathdigitalcommunity/original/2X/4/4ac69375d50c414be2958c31b73af71fc21e4944.png)

If the CQ is connected to the same PC while programming, there is a “learn function” to auto\_copy the NRPN value of the CQ fader your move.  
Otherwise, choose it via the drop/down menu.

With Mac route midi with midipipe, and with IOS route midi with midiMittr.

Enjoy and report/feedback if you like it.
