Arduino MIDI Rotary Encoder Step Sequencer – Part 2

In my last post, I mentioned other display options for my rotary encoder step sequencer.  To be honest, I wanted an excuse to use some “LED bars” with a rotary encoder, so this post is more by way of an excuse to play rather than a serious option, but in reality it actually works quite well!

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

These are the key Arduino tutorials for the main concepts used in this project:

If you are new to Arduino, see the Getting Started pages.

Parts list

  • Arduino Uno
  • 1x rotary encoder “breakout” (switched encoder type)
  • LEDs and associated resistors for output:
    • 2x 6-way LED “bars” (6 signal pins + GND)
    • 12x LEDs and 12x 1kΩ resistors
  • One of the Arduino MIDI Interfaces or Ready-Made MIDI Modules
  • Breadboard and jumper wires (optional)

The Circuit

ArduinoMIDIRE7SegmentController-Part2_bb

The circuit above is a general description of what I’m aiming for, but in my case I’m using some “LED bars” which I’ve doctored slightly to fit directly onto an Arduino Uno.  The rotary encoder is wired such that it can be pushed directly in A0-A4 as long as our code sets up A0 to be an output pin set to LOW for the GND connection and A1 is set to an output pin set HIGH for VCC.

If you are using discrete LEDS with their own resistors, skip ahead to the code, or read on for a few photos of the “LED bars” I’ve been using.

IMG_5477

Each “bar” consists of six LEDs each with a 1kΩ surface mount resistor, hooked up to six signal pins all with a common ground.  One of these fits perfectly on the Arduino D8-13 connector which has a GND pin next to D13.  If you don’t mind sacrificing D1 and D7 you can also use one on D1-D6, using D7 as a GND pin by setting it to OUTPUT and permanently LOW.  But I want to leave the serial port free to use, so would rather not tie up D1.

My solution is to cut one of the “bars” down slightly to file off the GND pin and then glue it to another one and join the GNDs together.  If you have a look the following photos hopefully you’ll see what I mean.

I’ve used a spare bit of pcb to glue behind the two “bars” to joint them together, getting my cue for the distance from inserting them into an Arduino shield.  The issue being (you may recall) the non-standard distance between D7 and D8 on the Arduino headers.

The result is that D2-D13 map directly over to the six LEDs all sharing a common ground via the GND pin next to D13.

Couple this with the fact I can push an encoder directly into A0 to A4 and I have all the things I need apart from the MIDI interface for another step sequencer.

IMG_5478

The Code

The vast majority of the code is the same as for the Arduino MIDI Rotary Encoder Step Sequencer.  There are a few configuration tweaks required:

  • The number of steps is set to 12, as I have two lots of six LEDs.
  • The pins for the rotary encoder have been changed to allow me to plug it directly into A0-A4, including setting A0 and A1 as GND and VCC respectively.

The major change, naturally, is removing the I2C display handling and adding in some code to drive the LEDs.  This is largely a case of changing the initDisplay and scanDisplay functions.

I’m cheating slightly and using direct PORT IO to output an internally stored pattern directly to the LEDs.  The current state of the display is stored in the leds variable and it gets written out to the Arduino’s digital pins as follows:

void initDisplay() {
  // Initialise the LEDs as outputs 
  DDRD = DDRD | 0b11111100; // D1 to D7 as outputs
  DDRB = DDRB | 0b00111111; // D8 to D13 as outputs
  PORTB = 0; // Everything starts LOW
  PORTD = 0; // Everything starts LOW

  leds = 0;

#ifdef RE_VCC
  pinMode(RE_VCC, OUTPUT);
  pinMode(RE_GND, OUTPUT);
  digitalWrite(RE_GND, LOW);
  digitalWrite(RE_VCC, HIGH);
#endif
}

void scanDisplay() {
  // What the display shows will depend on the encoder mode!
  if (encmode==2) {
    // Note display - just show the current step
    leds = 1<<encstep;
  } else if (encmode==1) {
    // Step display - show the current step
    leds = 1<<encstep;
  } else {
    // Play mode (use 1 to NUM_STEPS)
    leds = 1<<curstep;
  }

  // Map leds variable onto ports as follows:
  // leds0:5 -> PORTD2:7
  // leds6:11 -> PORTB0:5
  PORTD = (PORTD & 0x03) | ((leds & 0x003F)<<2);
  PORTB = (leds & 0x0FC0)>>6;
}

I can’t easily show a useful display for the note adjustments, so instead I just keep showing the current step and rely on ear for the feedback.

I’ve decide to reverse the direction of the encoder in the code (swapping which direction calls incEncoder and decEncoder) but I wanted to keep the “step” display the same, so I swapped the two sections of code corresponding to the “step” mode.

While I was at it, I also spotted and fixed a bug in the NoteOff handling.  To be honest, I wasn’t convinced I was getting proper note off messages in the last project, but I didn’t stop to investigate at the time – I’ve now gone back and fixed it there too!

I was tempted to make the two different display options conditional compilation as part of the previous projects code, but in the end decided to go ahead create a new sketch instead.

Find it on GitHub here.

Closing Thoughts

This started out as an excuse to play with some led “bars” and a rotary encoder and I’ve done that!  But actually it isn’t a bad little device for such a small, and neat (i.e. hardly any wiring) device.

It is a bit of a limitation not being able to see what the current note is during editing, so I might keep experimenting with alternative display options too.  Of course it should be directly possible to combine this with a seven segment display if I wanted to.

Kevin

Leave a comment