Adafruit Trellis, miniUntztrument and midi

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
liamfpower
 
Posts: 6
Joined: Wed Oct 01, 2014 10:13 pm

Adafruit Trellis, miniUntztrument and midi

Post by liamfpower »

Hi, I recently bought an adafruit trellis and 3d printed the miniuntztrument controller and have a couple of questions about modifying the untztrument code.
So far I have modded the Untzrument step sequencer code, the mini OOntz arpeggiator code, and the original mini untztrument code to suit a singletrellis. Usb-Midi with a TeenOnArdu is working fine. What I want to do is have a setup program which reads the switches on the trellis and picks a mode so that I can have all 3 sketches stored on the arduino and choose which one I want to use when I am using the mini Untztrument. How would I go about combining three different code "apps" so I could choose between them at startup using the trellis keypad? Would this be hard to implement. I have a very basic understanding of Arduino coding.

the code I'm using

Code: Select all

// Simple UNTZtrument MIDI step sequencer.
// Requires an Arduino Leonardo w/TeeOnArdu config (or a PJRC Teensy),
// software on host computer for synth or to route to other devices.

#include <Wire.h>
#include <Adafruit_Trellis.h>
#include <Adafruit_UNTZtrument.h>

#define LED 13 // Pin for heartbeat LED (shows code is working)

#ifndef HELLA
// A standard UNTZtrument has four Trellises in a 2x2 arrangement
// (8x8 buttons total).  addr[] is the I2C address of the upper left,
// upper right, lower left and lower right matrices, respectively,
// assuming an upright orientation, i.e. labels on board are in the
// normal reading direction.
Adafruit_Trellis     T[4];
Adafruit_UNTZtrument untztrument(&T[3]);
const uint8_t        addr[] = { 0x70, 0x71, 0x72, 0x73 };
#else
// A HELLA UNTZtrument has eight Trellis boards...
Adafruit_Trellis     T[8];
Adafruit_UNTZtrument untztrument(&T[0], &T[1], &T[2], &T[3],
                                 &T[4], &T[5], &T[6], &T[7]);
const uint8_t        addr[] = { 0x70, 0x71, 0x72, 0x73,
                                0x74, 0x75, 0x76, 0x77 };
#endif // HELLA

#define WIDTH     ((sizeof(T) / sizeof(T[3])) * 1)
#define N_BUTTONS ((sizeof(T) / sizeof(T[0])) * 16)

// Encoder on pins 4,5 sets tempo.  Optional, not present in
// standard UNTZtrument, but won't affect things if unconnected.
enc e(4, 5);

uint8_t       grid[WIDTH];                 // Sequencer state
uint8_t       heart        = 0,            // Heartbeat LED counter
              col          = WIDTH-1;      // Current column
unsigned int  bpm          = 240;          // Tempo
unsigned long beatInterval = 60000L / bpm, // ms/beat
              prevBeatTime = 0L,           // Column step timer
              prevReadTime = 0L;           // Keypad polling timer

// The note[] and channel[] tables are the MIDI note and channel numbers
// for to each row (top to bottom); they're specific to this application.
// bitmask[] is for efficient reading/writing bits to the grid[] array.
static const uint8_t PROGMEM
  note[8]    = {  72, 71, 69, 67, 65, 64, 62,  60 },
  channel[8] = {   1,  1,  1,  1,  1,  1,  1,   1 },
  bitmask[8] = {   1,  2,  4,  8, 16, 32, 64, 128 };

void setup() {
  pinMode(LED, OUTPUT);
#ifndef HELLA
  untztrument.begin(addr[0], addr[1], addr[2], addr[3]);
#else
  untztrument.begin(addr[0], addr[1], addr[2], addr[3],
                    addr[4], addr[5], addr[6], addr[7]);
#endif // HELLA
#ifdef __AVR__
  // Default Arduino I2C speed is 100 KHz, but the HT16K33 supports
  // 400 KHz.  We can force this for faster read & refresh, but may
  // break compatibility with other I2C devices...so be prepared to
  // comment this out, or save & restore value as needed.
  TWBR = 12;
#endif
  untztrument.clear();
  untztrument.writeDisplay();
  memset(grid, 0, sizeof(grid));
  e.setBounds(60 * 4, 480 * 4 + 3); // Set tempo limits
  e.setValue(bpm * 4);              // *4's for encoder detents
}

// Turn on (or off) one column of the display
void line(uint8_t x, boolean set) {
  for(uint8_t mask=1, y=0; y<8; y++, mask <<= 1) {
    uint8_t i = untztrument.xy2i(x, y);
    if(set || (grid[x] & mask)) untztrument.setLED(i);
    else                        untztrument.clrLED(i);
  }
}

void loop() {
  uint8_t       mask;
  boolean       refresh = false;
  unsigned long t       = millis();

  enc::poll(); // Read encoder(s)

  if((t - prevReadTime) >= 20L) { // 20ms = min Trellis poll time
    if(untztrument.readSwitches()) { // Button state change?
      for(uint8_t i=0; i<N_BUTTONS; i++) { // For each button...
        uint8_t x, y;
        untztrument.i2xy(i, &x, &y);
        mask = pgm_read_byte(&bitmask[y]);
        if(untztrument.justPressed(i)) {
          if(grid[x] & mask) { // Already set?  Turn off...
            grid[x] &= ~mask;
            untztrument.clrLED(i);
            usbMIDI.sendNoteOff(pgm_read_byte(&note[y]),
              127, pgm_read_byte(&channel[y]));
          } else { // Turn on
            grid[x] |= mask;
            untztrument.setLED(i);
          }
          refresh = true;
        }
      }
    }
    prevReadTime = t;
    digitalWrite(LED, ++heart & 32); // Blink = alive
  }

  if((t - prevBeatTime) >= beatInterval) { // Next beat?
    // Turn off old column
    line(col, false);
    for(uint8_t row=0, mask=1; row<8; row++, mask <<= 1) {
      if(grid[col] & mask) {
        usbMIDI.sendNoteOff(pgm_read_byte(&note[row]), 127,
          pgm_read_byte(&channel[row]));
      }
    }
    // Advance column counter, wrap around
    if(++col >= WIDTH) col = 0;
    // Turn on new column
    line(col, true);
    for(uint8_t row=0, mask=1; row<8; row++, mask <<= 1) {
      if(grid[col] & mask) {
        usbMIDI.sendNoteOn(pgm_read_byte(&note[row]), 127,
          pgm_read_byte(&channel[row]));
      }
    }
    prevBeatTime = t;
    refresh      = true;
    bpm          = e.getValue() / 4; // Div for encoder detents
    beatInterval = 60000L / bpm;
  }

  if(refresh) untztrument.writeDisplay();

  while(usbMIDI.read()); // Discard incoming MIDI messages
}

Code: Select all

// OONTZ ARPY
// Arpeggiator for the Adafruit OONTZ & HELLA OONTZ
// Plays a MIDI note sequence relative to button pressed
//
// For HELLA OONTZ change HELLA value to 1 (line 20)
// For external MIDI clock sync change EXT_CLOCK value to 1 (line 21)
// Scale can be chosen by specifying a mode on line 129
//
// Optional hardware:
//      Pattern control - connect rotary encoder to pins 4 & 5
//      Tempo control   - connect rotary encoder to pins 8 & 9
//

void setup();   // Added to avoid Arduino IDE #ifdef bug

#include <Wire.h>
#include <Adafruit_Trellis.h>
#include <Adafruit_OONTZ.h>

#define LED       13 // Pin for heartbeat LED (shows code is working)
#define CHANNEL   1  // MIDI channel number
#define HELLA     0  // 0 for standard OONTZ, 1 for HELLA OONTZ
#define EXT_CLOCK 0  // 0 for internal clock, 1 for external

#if HELLA
Adafruit_Trellis T[4];
OONTZ            oontz(&T[3]);
const uint8_t    addr[] = { 0x70, 0x71, 0x72, 0x73 };
#else
Adafruit_Trellis T[4];
OONTZ            oontz(&T[3]);
const uint8_t    addr[] = { 0x70, 0x71,
                            0x72, 0x73 };
#endif

#define WIDTH      ((sizeof(T) / sizeof(T[3])) * 1)
#define HEIGHT     (N_BUTTONS / WIDTH)
#define N_BUTTONS  ((sizeof(T) / sizeof(T[0])) * 16)
#define ARP_NOTES  6
#define NULL_INDEX 255

uint8_t       heart        = 0;  // Heartbeat LED counter
unsigned long prevReadTime = 0L; // Keypad polling timer
//bool          extClock = true;
uint8_t       quantDiv = 8;      // Quantization division, 2 = half note
uint8_t       clockPulse = 0;

#define QUANT_PULSE (96/quantDiv)// Number of pulses per quantization division

uint8_t       noteDivs[] = { 1,2,4,8,16,32};

// Note patterns for arpeggiator
int8_t
arpA[ARP_NOTES][2] = {
    {  0,   0  },
    {  -1,  -1 },
    {  1,   -1 },
    {  1,   1  },
    {  -1,  1  },
    {  -1,  1  },
},
arpB[ARP_NOTES][2] = {
    {  0,   0  },
    {  1,   -1 },
    {  2,   -2 },
    {  2,   -2 },
    {  1,   -1 },
    {  2,   -1 },
},
arpC[ARP_NOTES][2] = {
    {  0,   0  },
    {  -1,  0  },
    {  0,   0  },
    {  0,   -1 },
    {  0,   0  },
    {  1,   0  },
},
arpD[ARP_NOTES][2] = {
    {  0,   0 },
    {  1,   0 },
    {  0,   0 },
    {  1,   0 },
    {  1,   2 },
    {  1,   2 }
},
arpE[ARP_NOTES][2] = {
    {  0,   0 },
    {  1,   0 },
    {  2,   0 },
    {  3,   0 },
    {  3,   1 },
    {  2,   1 }
},
arpF[ARP_NOTES][2] = {
    {  0,   0 },
    {  1,   0 },
    {  -1,  0 },
    {  2,   0 },
    {  -2,  0 },
    {  0,   0 }
},
arpG[ARP_NOTES][2] = {
    {  0,   0 },
    {  1,   -1 },
    {  2,  0 },
    {  3,   -1 },
    {  2,  -1 },
    {  1,   0 }
};

int8_t (*arpCollection[])[ARP_NOTES][2] = { &arpA, &arpB, &arpC, &arpD,
                                            &arpE, &arpF, &arpG };

uint8_t arpCount = sizeof(arpCollection) / sizeof(arpCollection[0]);
int8_t (*arp)[ARP_NOTES][2] = &(*arpCollection)[0];
uint8_t pitchMap[N_BUTTONS];

// Musical mode/scale intervals
uint8_t chromatic[12]   = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 },
        ionian[12]      = { 0, 0, 2, 4, 4, 5, 5, 7, 7, 9,11,11 },
        dorian[12]      = { 0, 0, 2, 3, 3, 5, 5, 7, 7, 9,10,10 },
        phrygian[12]    = { 0, 1, 2, 3, 3, 5, 5, 7, 8, 8,10,10 },
        lydian[12]      = { 0, 0, 2, 2, 4, 4, 6, 7, 7, 9,10,11 },
        mixolydian[12]  = { 0, 0, 2, 2, 4, 5, 5, 7, 7, 9,10,10 },
        aeolian[12]     = { 0, 0, 2, 3, 3, 5, 5, 7, 8, 8,10,10 },
        locrian[12]     = { 0, 1, 1, 3, 3, 5, 6, 6, 8, 8,10,10 };

uint8_t (*scale)[12]    = &dorian;    // Chosen scale

uint8_t firstNote = 16,  // First note, upper left of grid
        colIntvl  = 10,   // Semitones between each column
        rowIntvl  = 5;   // Semitones between each row

boolean pressedButtonIndex[N_BUTTONS] = {false};        // Pressed state for each button
uint8_t arpSeqIndex[N_BUTTONS]        = {NULL_INDEX},   // Current place in button arpeggio sequence
        arpButtonIndex[N_BUTTONS]     = {NULL_INDEX};   // Button index being played for each actual pressed button

// Encoders for tempo and arpeggio selection
enc tempoEncoder(8, 9);
enc arpEncoder(4, 5);
unsigned int  bpm          = 320;          // Tempo
unsigned long beatInterval = 60000L / bpm, // ms/beat
              prevArpTime  = 0L;
//uint8_t       arpVelocityMax  = 102,
//              arpVelocityMin  = 65;


void setup(){
    
    pinMode(LED, OUTPUT);
    
    // 8x8
    if (WIDTH <= 8) {
        oontz.begin(addr[0], addr[1], addr[2], addr[3]);
    }
    
    // HELLA 16x8
    else{
        oontz.begin(addr[0], addr[1], addr[2], addr[3],
                    addr[4], addr[5], addr[6], addr[7]);
    }
    
#ifdef __AVR__
    // Default Arduino I2C speed is 100 KHz, but the HT16K33 supports
    // 400 KHz.  We can force this for faster read & refresh, but may
    // break compatibility with other I2C devices...so be prepared to
    // comment this out, or save & restore value as needed.
    TWBR = 12;
#endif
    oontz.clear();
    oontz.writeDisplay();
    
#if EXT_CLOCK
    // Set up tempo encoder for External clock mode
    uint8_t divCount = sizeof(noteDivs) / sizeof(noteDivs[0]) -1;
    tempoEncoder.setBounds(0, divCount * 4, true); // Set tempo limits
    tempoEncoder.setValue(3 * 4);                  // *4's for encoder detents
#else
    // Set up tempo encoder for Internal clock mode
    tempoEncoder.setBounds(60 * 4, 480 * 4 + 3); // Set tempo limits
    tempoEncoder.setValue(bpm * 4);              // *4's for encoder detents
#endif

    
    //Set up arpeggio pattern encoder
    arpEncoder.setBounds(0, arpCount * 4 - 1, true);
    arpEncoder.setValue(6 * 4);
    
    //Set up the note for the grid
    writePitchMap();

#if EXT_CLOCK
    usbMIDI.setHandleRealTimeSystem(handleRealTimeSystem);
#endif
    
}


void loop(){
    
    checkMidi();
    
    unsigned long t = millis();
    unsigned long tDiff = t - prevReadTime;
    
    enc::poll(); // Read encoder(s)
    
    if(tDiff >= 20L) { // 20ms = min Trellis poll time
        
        if(oontz.readSwitches()) {  // Button state change?
            
            for(uint8_t i=0; i<N_BUTTONS; i++) { // For each button...
                
                //Button was pressed
                if(oontz.justPressed(i)) {
                    
                    //add note to pressed buttons array
                    pressedButtonIndex[i] = true;
                }
                
                //Button was released
                else if(oontz.justReleased(i)) {
                    
                    //remove note from pressed buttons array
                    pressedButtonIndex[i] = false;
                    stopArp(i);
                }
            }
        }
        
        // Iterate array, play arp sequence for pressed buttons
        
#if EXT_CLOCK
        // EXTERNAL CLOCK
        //Set note length from encoder value
        quantDiv     = noteDivs[tempoEncoder.getValue() / 4];
        
#else
        // INTERNAL CLOCK
        if ((t - prevArpTime) >= beatInterval) {
            respondToPresses();
            prevArpTime = t;
        }
        
        //Set Tempo from encoder value
        bpm          = tempoEncoder.getValue() / 4; // Div for encoder detents
        beatInterval = 60000L / bpm;
#endif
        
        //Set current arp notes
        int16_t arpIndex = arpEncoder.getValue() / 4;
        arp = &(*arpCollection)[arpIndex];
        
        //update LEDs
        oontz.writeDisplay();
        
        prevReadTime = t;
        digitalWrite(LED, ++heart & 32); // Blink = alive
        
    }
    
}


void checkMidi(){

#if EXT_CLOCK
    // EXTERNAL CLOCK
    usbMIDI.read(CHANNEL);
    
#else
    // INTERNAL CLOCK
    while(usbMIDI.read(CHANNEL)); // Discard incoming MIDI messages

#endif
    
}


void handleRealTimeSystem(uint8_t data){
    
    if (data == 0xF8) {      // Clock pulse
        
        clockPulse++;
        if (clockPulse > 96) {   //MIDI clock sends 24 pulses per quarter note
            clockPulse = 1;
        }
        else if ((clockPulse % QUANT_PULSE) == 0){
            respondToPresses();
        }
    }
    
    else if (data == 0xFA){  // START message
        clockPulse = 0;
    }
    
//    else if (data == 0xFC){  // STOP message
//
//    }
    
//    else if (data == 0xFB){  // CONTINUE message
//
//
//    }
    
}


void writePitchMap(){
    
    //Write first row of notes, establish column intervals
    for (int i = 0; i < WIDTH; i++){
        pitchMap[i] = i * colIntvl + firstNote;
    }
    
    //Write remaining rows, first row + row intervals
    for (int i = WIDTH; i < N_BUTTONS; i++) {
        pitchMap[i] = i / WIDTH * rowIntvl + pitchMap[i%WIDTH];
    }
    
    //Apply diatonic filter - TESTING
    for (int i = 0; i < N_BUTTONS; i++) {
        uint8_t deg = pitchMap[i] % 12;
        uint8_t oct = pitchMap[i] / 12;
        pitchMap[i] = oct * 12 + (*scale)[deg];
    }
    
    //Test notes
//    int x,y = 0;
//    for (int i = 0; i < (WIDTH); i++) {
//        
//        if (x >= WIDTH){ x = 0; y++; }
//        if (y >= HEIGHT) { break; }
//        
//        uint8_t index = oontz.xy2i(x,y);
//        
//        playNoteForButton(index);
//        delay(200);
//        oontz.writeDisplay();
//        delay(20);
//        stopNoteForButton(index);
//        oontz.writeDisplay();
//        
//        x++;
//    }
    
}


void respondToPresses(){
    
    for (uint8_t i=0; i < N_BUTTONS; i++) {
        if (pressedButtonIndex[i]) {
            playArp(i);
        }
    }
    
}


void setAllLEDs(bool lit){
    
    for (uint8_t i=0; i < N_BUTTONS; i++) {
        if (lit) {
            oontz.setLED(i);
        }
        else{
            oontz.clrLED(i);
        }
    }
    
}


void playArp(uint8_t buttonIndex){
    
    uint8_t seqIndex, seqButtonIndex, seqNote,
            x, y;
    seqIndex = arpSeqIndex[buttonIndex] + 1;
    
    // Loop sequence
    if (seqIndex >= ARP_NOTES) {
        seqIndex = 0;
    }
    
    // Find current button coordinates
    oontz.i2xy(buttonIndex, &x, &y);
    
    // Add note offsets
    x = (int8_t)x + (*arp)[seqIndex][0];
    y = (int8_t)y + (*arp)[seqIndex][1];
    
    // Wrap notes to grid
    if (x >= WIDTH) {x %= WIDTH;}
    if (y >= HEIGHT) {y %= HEIGHT;}
    
    // Find new note and index
    seqNote = findNoteFromXY(x, y);
    seqButtonIndex = oontz.xy2i(x, y);
    
    // Stop prev note in sequence
    stopNoteForButton(arpButtonIndex[buttonIndex]);
    
    // Store new note
    arpSeqIndex[buttonIndex] = seqIndex;
    arpButtonIndex[buttonIndex] = seqButtonIndex;
    
    // Play new note
    playNoteForButton(seqButtonIndex);
    
}


void stopAll(){
    
    for (uint8_t i=0; i < N_BUTTONS; i++) {
        if (pressedButtonIndex[i]) {
            stopArp(i);
        }
    }
    
}


void stopArp(uint8_t button){
    
    //stop playing the note
    stopNoteForButton(arpButtonIndex[button]);
    
    //store an invalid button index in its place
    arpSeqIndex[button] = NULL_INDEX;  //check for invalid
    
}


uint8_t findNoteFromIndex(uint8_t buttonIndex){
    
    uint8_t x, y;
    oontz.i2xy(buttonIndex, &x, &y);
    
    return findNoteFromXY(x,y);
    
}


uint8_t findNoteFromXY(uint8_t x, uint8_t y){
    
    return pitchMap[y * WIDTH + x];
    
}


void playNoteForButton(uint8_t buttonIndex){
    
  // Set a random velocity
//  uint8_t vel = random(arpVelocityMin, arpVelocityMax);
  
    usbMIDI.sendNoteOn(findNoteFromIndex(buttonIndex), 100, CHANNEL);   //default velocity of 100
    oontz.setLED(buttonIndex);
    
}


void stopNoteForButton(uint8_t buttonIndex){
    
    usbMIDI.sendNoteOff(findNoteFromIndex(buttonIndex), 0, CHANNEL);
    oontz.clrLED(buttonIndex);
    
}

Code: Select all

#include <Wire.h>
#include <Adafruit_Trellis.h>

#define LED     13 // Pin for heartbeat LED (shows code is working)
#define CHANNEL 1  // MIDI channel number

Adafruit_Trellis trellis;

uint8_t       heart        = 0;  // Heartbeat LED counter
unsigned long prevReadTime = 0L; // Keypad polling timer
uint8_t       mod;
uint8_t       vel;
uint8_t       fxc;
uint8_t       rate;  

uint8_t note[] = {
  60, 61, 62, 63,
  56, 57, 58, 59,
  52, 53, 54, 55,
  48, 49, 50, 51
};

void setup() {
  pinMode(LED, OUTPUT);
  trellis.begin(0x70); // Pass I2C address
#ifdef __AVR__
  // Default Arduino I2C speed is 100 KHz, but the HT16K33 supports
  // 400 KHz.  We can force this for faster read & refresh, but may
  // break compatibility with other I2C devices...so be prepared to
  // comment this out, or save & restore value as needed.
  TWBR = 12;
#endif
  trellis.clear();
  trellis.writeDisplay();

}

void loop() {
  unsigned long t = millis();
  if((t - prevReadTime) >= 20L) { // 20ms = min Trellis poll time
    if(trellis.readSwitches()) {  // Button state change?
      
      for(uint8_t i=0; i<16; i++) { // For each button...
        if(trellis.justPressed(i)) {
          usbMIDI.sendNoteOn(note[i], 127, CHANNEL);
          
          trellis.setLED(i);
        } else if(trellis.justReleased(i)) {
          usbMIDI.sendNoteOff(note[i], 0, CHANNEL);
          trellis.clrLED(i);
        }
      }
      trellis.writeDisplay();
    }
    uint8_t newModulation = map(analogRead(0), 0, 1023, 0, 127);
    if(mod != newModulation) {
      mod = newModulation;
      usbMIDI.sendControlChange(1, mod, CHANNEL);
    }
    uint8_t newVelocity = map(analogRead(1), 0, 1023, 0, 127);
    if(vel != newVelocity) {
      vel = newVelocity;
      usbMIDI.sendControlChange(11, vel, CHANNEL);
    }
    uint8_t newEffect = map(analogRead(2), 0, 1023, 0, 127);
    if(fxc != newEffect) {
      fxc = newEffect;
      usbMIDI.sendControlChange(12, fxc, CHANNEL);
    }
    uint8_t newRate = map(analogRead(3), 0, 1023, 0, 127);
    if(rate !=newRate) {
      rate = newRate;
      usbMIDI.sendControlChange(13, rate, CHANNEL);
    }
    prevReadTime = t;
    digitalWrite(LED, ++heart & 32); // Blink = alive
  }
  while(usbMIDI.read()); // Discard incoming MIDI messages
}
Thanks in advance for your help. let me know if this is too ambitious for a beginner coder.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Adafruit Trellis, miniUntztrument and midi

Post by adafruit_support_rick »

Not especially difficult. What I would do is to copy all three loop functions to the same sketch. Then I would rename them to something like "mode1", "mode2", and "mode3"

Then, I would write a new loop function that looks at the switches and calls the proper mode function.

User avatar
liamfpower
 
Posts: 6
Joined: Wed Oct 01, 2014 10:13 pm

Re: Adafruit Trellis, miniUntztrument and midi

Post by liamfpower »

Ok, so going from this I would define the modes before the void.setup()
for example
#define ARPEGGIATOR 1
#define STEPSEQ 1
#define KEYB 1

and in the setup I would do something like
trellis.setLed(0);
trellis.blinkRate(1);
trellis.writeDisplay();
//Repeated for buttons 1-3, mode buttons//

Then in the loop I would put

if (trellis.justPressed(0)) {
(Mode == ARPEGGIATOR)
else trellis.readSwitches();

if (trellis.justPressed(1)) {
(Mode == STEPSEQ)
else trellis.readSwitches();

etc. with the three modes? obviously the code would be correctly formatted, but is that how I would do it?
If a button was pressed then run this mode, otherwise read switches or something similar.

And in the loop I had all three sketches defined with their modes like in the adafruit trellis test sketch with momentary and latching modes?
if (MODE == MOMENTARY) {CODE}
if (MODE == LATCHING) {CODE}

Am I in the right direction?
Thanks

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Adafruit Trellis, miniUntztrument and midi

Post by adafruit_support_rick »

No. You would rename the three loop functions, like this:

Code: Select all

  void Arpeggiator()
  {
       < Code from loop() in arpeggiator sketch goes here >
  }

  void StepSequence()
  {
       < Code from loop() in step sequencer sketch goes here >
  }

  void Keyboard()
  {
       < Code from loop() in keyboard sketch goes here >
  }
Then, have a new loop function that checks the switches and calls one of the functions:

Code: Select all

void loop()
{
  if ( <check arpeggio mode switch here> )
    Arpeggiator();
  else
    if ( <check sequencer switch here > )
      StepSequencer();
    else
      if ( <check keyboard switch here > )
        Keyboard();
} 
}

User avatar
axelmoody
 
Posts: 3
Joined: Sun Nov 23, 2014 12:22 pm

Re: Adafruit Trellis, miniUntztrument and midi

Post by axelmoody »

I'm interested in it as well but I didn't figure out.

I would like just to use the mini Untztrument like a drum machine with ableton (where I can send midi signals to Arduino).

How can I receive midi from Ableton?

Best,
Axel

User avatar
liamfpower
 
Posts: 6
Joined: Wed Oct 01, 2014 10:13 pm

Re: Adafruit Trellis, miniUntztrument and midi

Post by liamfpower »

Hi axelmoody.
After scratching my head for a while trying to figure out how to modify the mini untztrument code to get it to work the way I wanted it. I realised that the best way to get the most functionality out of the trellis is to use the trellis monome code found here:
https://github.com/rbnstubbs/trellis-monome
I used and arduino UNO instead of leonardo and downloaded monomecereal
http://monome.org/docs/app:monomecereal
I changed the debounce time in the trellismonome code to 20 milli, otherwise the the OSC messages would not be sent correctly.
once I uploaded the trellis monome 0.5.1 code to my UNO
I opened up monomecereal in the free max runtime
and tested it, using my arduino's com port as the serial connection.
Once that is working fine, then you can use any of the monome apps which do all kinds of interesting things with midi, I don't use ableton but if you get max for live you can use all the apps made for that as well.

I found this to be a much better and more creative way to use the miniuntztrument.
Thanks
Liam

User avatar
axelmoody
 
Posts: 3
Joined: Sun Nov 23, 2014 12:22 pm

Re: Adafruit Trellis, miniUntztrument and midi

Post by axelmoody »

Thanks for your answer Liam!

Just another question, im using thr Leonardo, do you think that makes any difference?

User avatar
liamfpower
 
Posts: 6
Joined: Wed Oct 01, 2014 10:13 pm

Re: Adafruit Trellis, miniUntztrument and midi

Post by liamfpower »

Hey yeah, I tried uploading the trellis monome code to the leonardo and it didnt work for some reason. The code wouldn't compile properly/upload properly on the arduino side, which I think might have something to do with the leonardo using a different atmega chip. Luckily I had an arduino UNO hanging around which I could connect up according to the original adafruit trellis inststructions. Its just an idea, because I found it pretty hard to do much else with just 16 pads.

User avatar
axelmoody
 
Posts: 3
Joined: Sun Nov 23, 2014 12:22 pm

Re: Adafruit Trellis, miniUntztrument and midi

Post by axelmoody »

Sorry if I bother you again, but it's my first time with OSC and I don't know precisely how to complete this procedure.

Do you have time to explain me that? :)

User avatar
Bedoche
 
Posts: 1
Joined: Fri Jan 30, 2015 2:59 pm

Re: Adafruit Trellis, miniUntztrument and midi

Post by Bedoche »

Hi everybody,

I'm new in this world and would like some indications to run my TrellisMonome
I bought an untztrument and an arduino uno to get a kind of arduinome, Everything seems ok, I can run Monomcereal and Trellis Monome Test, when I hit a pad it lights up and I see it in the app. So I thought it would be ready to go with some monome apps or to use with 7up or mlrv but I can't find my monome in others apps. It seems that it works fine juste with the Trellis Monome Test. I read a lot of things on both adafruit and Monome forums but I can't figure why I can't go further...
Hope to use it soon but I think I might need your help for now...

User avatar
liamfpower
 
Posts: 6
Joined: Wed Oct 01, 2014 10:13 pm

Re: Adafruit Trellis, miniUntztrument and midi

Post by liamfpower »

Hi Bedoche, you can get it working with the Serial Pyio program available on github. The monomecereal patch sends messages in such a way (/grid/key) that you have to manually convert patches to be able to use it with the untztrument. Monome serial uses (/press)

you need to get Serial pyIO the later version (0.6). You also have to download pythona nd run serial pyio in python.That got it working, but only with older monome serial apps.
I bit the bullet and bought another grid controller.

User avatar
startrez
 
Posts: 9
Joined: Wed Oct 29, 2014 1:27 pm

Re: Adafruit Trellis, miniUntztrument and midi

Post by startrez »

adafruit_support_rick wrote:No. You would rename the three loop functions, like this:

Code: Select all

  void Arpeggiator()
  {
       < Code from loop() in arpeggiator sketch goes here >
  }

  void StepSequence()
  {
       < Code from loop() in step sequencer sketch goes here >
  }

  void Keyboard()
  {
       < Code from loop() in keyboard sketch goes here >
  }
Then, have a new loop function that checks the switches and calls one of the functions:

Code: Select all

void loop()
{
  if ( <check arpeggio mode switch here> )
    Arpeggiator();
  else
    if ( <check sequencer switch here > )
      StepSequencer();
    else
      if ( <check keyboard switch here > )
        Keyboard();
} 
}

So I started working on combining sketches and was using this as a starting point. My question is this, could i perform different void setups () after checking the switch following the same model, aka Do i need to define one setup and combine all of the setup info once or can I keep them separate and run them once i check the switch setting?

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Adafruit Trellis, miniUntztrument and midi

Post by adafruit_support_rick »

You can only have one setup function. You'll have to combine the setup operations.

User avatar
XtShock
 
Posts: 3
Joined: Wed Apr 29, 2015 3:21 am

Re: Adafruit Trellis, miniUntztrument and midi

Post by XtShock »

I apologize before hand. I'm new to this and I'm sort of stuck here. I wanted to make the exact miniUntztrement that Adafruit posted a tutorial of. I printed the housing and wired everything and now the only thing I need to figure out is why my code isn't verifying. I copied and pasted the exact same code they posted and I'm receiving the error:

Arduino: 1.6.3 (Mac OS X), TD: 1.22, Board: "Arduino Leonardo"

Build options changed, rebuilding all
Adafruit_Trellis_Midi.ino: In function 'void setup()':
Adafruit_Trellis_Midi.ino:39:3: error: 'usbMIDI' was not declared in this scope
Adafruit_Trellis_Midi.ino: In function 'void loop()':
Adafruit_Trellis_Midi.ino:52:11: error: 'usbMIDI' was not declared in this scope
Adafruit_Trellis_Midi.ino:56:11: error: 'usbMIDI' was not declared in this scope
Adafruit_Trellis_Midi.ino:65:7: error: 'usbMIDI' was not declared in this scope
Adafruit_Trellis_Midi.ino:70:7: error: 'usbMIDI' was not declared in this scope
Adafruit_Trellis_Midi.ino:75:7: error: 'usbMIDI' was not declared in this scope
Adafruit_Trellis_Midi.ino:80:7: error: 'usbMIDI' was not declared in this scope
Adafruit_Trellis_Midi.ino:85:9: error: 'usbMIDI' was not declared in this scope
Error compiling.

This report would have more information with
"Show verbose output during compilation"
enabled in File > Preferences.

Here is the original code:

Code: Select all

#include <Wire.h>
#include <Adafruit_Trellis.h>
 
#define LED     13 // Pin for heartbeat LED (shows code is working)
#define CHANNEL 1  // MIDI channel number
 
Adafruit_Trellis trellis;
 
uint8_t       heart        = 0;  // Heartbeat LED counter
unsigned long prevReadTime = 0L; // Keypad polling timer
uint8_t       mod;
uint8_t       vel;
uint8_t       fxc;
uint8_t       rate;  
 
uint8_t note[] = {
  60, 61, 62, 63,
  56, 57, 58, 59,
  52, 53, 54, 55,
  48, 49, 50, 51
};
 
void setup() {
  pinMode(LED, OUTPUT);
  trellis.begin(0x70); // Pass I2C address
#ifdef __AVR__
  // Default Arduino I2C speed is 100 KHz, but the HT16K33 supports
  // 400 KHz.  We can force this for faster read & refresh, but may
  // break compatibility with other I2C devices...so be prepared to
  // comment this out, or save & restore value as needed.
  TWBR = 12;
#endif
  trellis.clear();
  trellis.writeDisplay();
  mod = map(analogRead(0), 0, 1023, 0, 127);
  vel = map(analogRead(1), 0, 1023, 0, 127);
  fxc = map(analogRead(2), 0, 1023, 0, 127);
  rate = map(analogRead(3),0, 1023, 0, 127);
  usbMIDI.sendControlChange(1, mod, CHANNEL);
  usbMIDI.sendControlChange(11, vel, CHANNEL);
  usbMIDI.sendControlChange(12, fxc, CHANNEL);
  usbMIDI.sendControlChange(13, rate, CHANNEL);
}
 
void loop() {
  unsigned long t = millis();
  if((t - prevReadTime) >= 20L) { // 20ms = min Trellis poll time
    if(trellis.readSwitches()) {  // Button state change?
      
      for(uint8_t i=0; i<16; i++) { // For each button...
        if(trellis.justPressed(i)) {
          usbMIDI.sendNoteOn(note[i], 127, CHANNEL);
          
          trellis.setLED(i);
        } else if(trellis.justReleased(i)) {
          usbMIDI.sendNoteOff(note[i], 0, CHANNEL);
          trellis.clrLED(i);
        }
      }
      trellis.writeDisplay();
    }
    uint8_t newModulation = map(analogRead(0), 0, 1023, 0, 127);
    if(mod != newModulation) {
      mod = newModulation;
      usbMIDI.sendControlChange(1, mod, CHANNEL);
    }
    uint8_t newVelocity = map(analogRead(1), 0, 1023, 0, 127);
    if(vel != newVelocity) {
      vel = newVelocity;
      usbMIDI.sendControlChange(11, vel, CHANNEL);
    }
    uint8_t newEffect = map(analogRead(2), 0, 1023, 0, 127);
    if(fxc != newEffect) {
      fxc = newEffect;
      usbMIDI.sendControlChange(12, fxc, CHANNEL);
    }
    uint8_t newRate = map(analogRead(3), 0, 1023, 0, 127);
    if(rate !=newRate) {
      rate = newRate;
      usbMIDI.sendControlChange(13, rate, CHANNEL);
    }
    prevReadTime = t;
    digitalWrite(LED, ++heart & 32); // Blink = alive
  }
  while(usbMIDI.read()); // Discard incoming MIDI messages
}
I would really appreciate the help.
Last edited by adafruit_support_rick on Fri May 01, 2015 10:06 am, edited 1 time in total.
Reason: please use Code tags when posting code (</> button)

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Adafruit Trellis, miniUntztrument and midi

Post by adafruit_support_rick »

Did you install the TeeOnArdu library referenced in the tutorial?

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”