Showing posts with label arduino. Show all posts
Showing posts with label arduino. Show all posts

Friday, May 6, 2016

So last week, I got the easy part out of the way: the serial-to-parallel shift out to an array of LEDs. This week, I'm going to be going through how I set-up a 16 bit parallel-to-serial shift in from an array of "buttons" to the Arduino in order to turn those LEDs on at will.

That Shift Register is Talking Some Mad Binary

This is a little less straight-forward than last week's endeavor. I had to take everything into account that was done then and add some practical way to control it.

What helped this time around was looking at the old code I wrote to do this back in 2011. The original code didn't work thanks to Arduino changing things in the compiler and the IDE, but a few hours of beating on it (and my desk) got it to work.

Materials Used:
  • Everything from last week's post
  • More hook-up wire
  • 2 - HCF4021B Shift Registers (Have a datasheet!)
  • 16 - 10kΩ resistors
Why 16 resistors when there will only be 10 buttons in the final product? The 4021 chip I chose freaks out whenever one of the data in pins doesn't have a path to ground. I played around with this in it's 8 bit form and without a single path to ground, it was sending me 11111111 or 255 and nothing else. 

If you're doing this and are getting weird results like the circuit is sending 127 or 255 constantly or whenever a button is pressed, check to see if your resistors are seated securely in the breadboard. The 4021 is a tricky, fickle demon.

Step 1: Put Some Wire on Board

This will at least power the chips

Step 2: The Control Wires


The Clock (yellow) is shared with the 595 circuit. Tie the Clock pins together.  There is no point in having a second clock.
Data (blue) goes to D5. Additionally, a wire needs to go from DS on the top IC to Q7 on the bottom.
The Latch (orange) goes to D4. Tie the Latch pins together. Why the separate Latch? I don't know.

Step 3: The "Button" Debounce Circus

If you have access to 10kΩ DIP resistors, not only will you be better off, but I hate you out of jealousy.

My end-result ended-up being 16 10kΩ resistors straight from the pin line on the breadboard from the chip directly to ground. Since I don't have this many buttons to play with, I just probed the board at certain points with a wire hooked directly to the 5v rail. It does the same thing as a button and is as expensive as a foot of hookup wire.
I used purple in the sketch for lines from pins. RIP Prince

Step 4: The Code

Here's what works:


int latchPin = 4;
int dataPin = 5;
int clockPin = 7;
int led_latchPin = 11;
int led_dataPin = 10;
byte switchVar1 = 72;
byte switchVar2 = 159;

void setup() {
  //start serial
  Serial.begin(9600);

  //define pin modes
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, INPUT);
  pinMode(led_latchPin, OUTPUT);
  pinMode(led_dataPin, OUTPUT);
  unsigned int bitsToSend = 0;
  digitalWrite(led_latchPin, 0);
  bitWrite(bitsToSend, 8, HIGH);
  byte registerOne = highByte(bitsToSend);
  byte registerTwo = lowByte(bitsToSend);
  shiftOut(led_dataPin, clockPin, MSBFIRST, registerTwo);
  shiftOut(led_dataPin, clockPin, MSBFIRST, registerOne);
  digitalWrite(led_latchPin, 1);
}
void loop() {
  int LED;
  digitalWrite(latchPin, 1);
  delayMicroseconds(40);
  digitalWrite(latchPin, 0);
  switchVar1 = shiftIn(dataPin, clockPin);
  switchVar2 = shiftIn(dataPin, clockPin);
  unsigned int allIn = switchVar1 * 256 + switchVar2; //The total value of what is being sent to the Arduino
  if (allIn != 0) {
    switch (allIn) {
      case 1:
        LED = 1;
        break;
      case 2:
        LED = 0;
        break;
      case 4:
        LED = 15;
        break;
      case 8:
        LED = 14;
        break;
      case 16:
        LED = 13;
        break;
      case 32:
        LED = 12;
        break;
      case 64:
        LED = 11;
        break;
      case 128:
        LED = 10;
        break;
      case 256:
        LED = 9;
        break;
      case 512:
        LED = 8;
        break;
      default:
        LED = 8; //Don't know what to do? Go home.
        break;
    }
    Serial.println(switchVar1);
    Serial.println(switchVar2);
    Serial.println(allIn);
    Serial.println("--------------");
    unsigned int bitsToSend = 0;
    digitalWrite(led_latchPin, 0);
    bitWrite(bitsToSend, LED, HIGH);
    byte registerOne = highByte(bitsToSend);
    byte registerTwo = lowByte(bitsToSend);
    shiftOut(led_dataPin, clockPin, MSBFIRST, registerTwo);
    shiftOut(led_dataPin, clockPin, MSBFIRST, registerOne);
    digitalWrite(led_latchPin, 1);
    //changeProgram(LED);
    delay(200);
  }

}


byte shiftIn(int myDataPin, int myClockPin) {
  int i;
  unsigned temp = 0;
  int pinState;
  byte myDataIn = 0;

  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, INPUT);
  for (i = 7; i >= 0; i--)
  {
    digitalWrite(myClockPin, 0);
    delayMicroseconds(2);
    temp = digitalRead(myDataPin);
    if (temp) {
      pinState = 1;
      myDataIn = myDataIn | (1 << i);
    }
    else {
      pinState = 0;
    }
    digitalWrite(myClockPin, 1);
  }
  return myDataIn;
}

 There are very few things in common with last week's code. For those following along at home: my apologies.

Step 5: The Madness Sets In

From there, I probed around - putting the hot wire between the resistors and the 4021 chips. The lights turned on and off. It was a success.

For further troubleshooting, the Arduino will print out the high bit, the low bit and the combined 16 bit value of what is sent back to the console. Additionally, here's the Fritzing sketch I put together for this post.

If you're seeing a behavior like the following, you too have success. If not, troubleshooting will lead to eventual insanity.



Sunday, May 1, 2016

It's been a long time (5-6 years) since I started this project. Things change. With the struggle of work, life, and family, hobbies and interests sometimes have to take a back seat to things with higher priority.
Pretty much unchanged in 5-6 years

Not too long ago, I looked up on my shelf of stuff (you know you have one) and saw a breadboard with some ICs and an Arduino Uno on it. I don't know if it was a sudden outbreak of nostalgia, or if it was the self-loathing of realizing that I never finished such an ambitious project; but I felt a sudden need to complete what I started.

Over the next few weeks, I will be breaking-down the hardware and code of the individual parts of this build. Going from a Mega 2560 board with about a million I/O pins and handing everything in code to as few I/O pins as possible and handling things in hardware is no small task.

Getting Some LEDs to Turn On

Part of the FCB1010 is the LEDs on the board that indicate what pedal was pressed. I previously handled this in code.

I couldn't find any useful or practical tutorials on how to get a 16 bit shift register setup working. That being said, this is not going to even touch on running a basic 8 bit shift register. The following is cobbled together from various sources around the internets and hours of troubleshooting. I apologize ahead of time as my Fritzing skills have much to be desired.

Materials Used:

Step 1: Wire the Power

I hear electronics like electrons.

I used D2 for the constant 5v

Step 2: Wire the Control Lines

I used blue for Data (D10), Yellow for Clock (D7), and Green for Latch (D11).

The two 74HC595 chips share the same latch and clock lines. The data out from the top chip goes to the data in on the bottom. An extra 5v needs to be supplied to the MR pin of the top chip to enable cascading to the bottom chip.

Step 3: Wire the Data Out Circuits

Purple is a nice color. RIP Prince.

Step 4: Add Some LEDs

Since only one will be on at any one time, I figured one resistor would do.

Step 5: There Is No Step 5

Sit back and admire your work. Here's the Fritzing sketch I used if you need any help. 

Step 6: Test Code

Since there won't really be any practical use of hardware to control which light is on or off, the code doesn't really have to be practical either.

All this code does is throw a rotating sequence of high and low bytes of a 16 bit unsigned integer at the shift registers.

#include <stdio.h>
//Pin connected to ST_CP of 74HC595
int latchPin = 11;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 10;

unsigned  data[] = {
0B0000000000000001,
0B0000000000000010,
0B0000000000000100,
0B0000000000001000,
0B0000000000010000,
0B0000000000100000,
0B0000000001000000,
0B0000000010000000,
0B0000000100000000,
0B0000001000000000,
0B0000010000000000,
0B0000100000000000,
0B0001000000000000,
0B0010000000000000,
0B0100000000000000,
0B1000000000000000
};

void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  for (int j = 0; j < 16; j++) {
    digitalWrite(latchPin, 0);
    int data = data[j];
    byte first = lowByte(data);
    byte second = highByte(data);
    shiftOut(dataPin, clockPin, MSBFIRST, first);
    shiftOut(dataPin, clockPin, MSBFIRST, second);
    digitalWrite(latchPin, 1);
    delay(1000);
  }
}

If you end-up with something that looks like the following, you're done! Yay!



Monday, January 24, 2011


Extending the functionality of my hack job is necessary. I mean, when was the last time you saw someone spend hours building something and just wanted to hit them when they stopped at just good enough? I have some parts on order from the good folks at Sparkfun Electronics for phantom power and panel mount USB hookup (w00t!) and also a little surprise that I will be adding in as soon as I figure out how to mount it.

I had a thought the other day. If I can control volume and wah with the expression pedals, what else can I control? According to the manual (page 17) I can control quite a few things with them (not all are useful though). Then it was just a matter for code and how to shift between modes of operation.

Here is my logic: if you step on two of the effects pedals at once, the program sends the expression pedals into a different mode depending on which two were pressed.

First off, there has to be a global array variable that can be changed depending on what mode is desired. I put “int expression_choice[] = {1,2};” at the top of the code. I arbitrarily assigned wah the value of one and volume the value of two. Array index 0 is on the left and index 1 is on the right for left and right pedals respectively.




Secondly, there has to be something in the loop() function to catch when the two buttons are pressed simultaneously. For this it is necessary to put it BEFORE the effects change buttons in the if statement within the loop(). Here's what I did in order to get Volume/Wah, Double Wah, Reverb/Volume and Delay/Volume.

void loop() {
  //////////////////////
  //Expression Options//
  //////////////////////
  if (digitalRead(23) == LOW && digitalRead(25) == LOW)//1 AND 2
  {
    expression_choice[0] = 1;  //Wah
    expression_choice[1] = 2;  //Volume
  }
  else if (digitalRead(25) == LOW && digitalRead(29) == LOW)//2 AND 3
  {
    expression_choice[0] = 1;  //Wah
    expression_choice[1] = 1;  //Double Wah!
  }
  else if (digitalRead(29) == LOW && digitalRead(27) == LOW)//3 AND 4
  {
    expression_choice[0] = 3;  //Reverb
    expression_choice[1] = 2;  //Volume

  }
  else if (digitalRead(27) == LOW && digitalRead(33) == LOW)//4 AND 5
  {
    expression_choice[0] = 4;  //Delay
    expression_choice[1] = 2;  //Volume

  }
  ///////////
  //EFFECTS//
  ///////////

  //
  //Lower Button Bank
  //

  //Button 1
  else if(digitalRead(23) == LOW)....

Beyond that, I did a bit of a shakeup at the bottom of the code. Since the left and right pedals are no longer strictly wah and volume, I renamed the changeVolume and wahCharacter functions to reflect that. Also in those functions, I added some extra if logic so that based on what value expression_choice is it will reflect that by sending the proper Control Change codes for whatever mode I want. Here's the bottom of the code.

void rightPedal(byte channel, byte volume)
{
  Serial.print(0xB0 | (channel & 0x0F), BYTE); //Control Change
  if(expression_choice[1] == 2){
    Serial.print(0x07, BYTE);//Volume CC number
  }
  else if(expression_choice[0] == 1)
  {
    Serial.print(0x1B, BYTE);//Wah character CC number
  }
  Serial.print(volume & 0x7F, BYTE);//Value (0-127)
}


void leftPedal(byte channel, byte wah)
{
  Serial.print(0xB0 | (channel & 0x0F), BYTE);//Control Change

  if(expression_choice[0] == 1)
  {
    Serial.print(0x1B, BYTE);//Wah character CC number
  }
  else if(expression_choice[0] == 3)
  {
    Serial.print(0x12, BYTE);//Reverb character CC number
  }
  else if(expression_choice[0] == 4)
  {
    Serial.print(0x32, BYTE);//Delay timing CC number
  }

  Serial.print(wah & 0x7F, BYTE);//Value (0-127)
}

void expression(int pin)
{
  static int s_nLastPotValue = 0;
  static int s_nLastMappedValue = 0;
  int nCurrentPotValue = analogRead(pin);
  if(abs(nCurrentPotValue - s_nLastPotValue) < pot_threshold)     return;
  s_nLastPotValue = nCurrentPotValue;
  int nMappedValue = map(nCurrentPotValue, 0, 1023, 0, 127); // Map the value to 0-127
  if(nMappedValue == s_nLastMappedValue)
    return;
  s_nLastMappedValue = nMappedValue;
  if(nMappedValue >= 10)
  {
    if (pin == volume_pin)
    {
     rightPedal(midi_channel, nMappedValue);
    }
    else
    {
      leftPedal(midi_channel, nMappedValue);
    }
  }
  else//Turn it off
  {
    if (pin == volume_pin)
    {
     rightPedal(midi_channel, 0);
    }
    else
    {
      leftPedal(midi_channel, 0);
    }
  }
}

So if all goes according to plan, you should have something that works like this:

Saturday, January 22, 2011

Well, it's all come down to this: a clone of the FCB1010 based on the Arduino MEGA2560 microcontroller.

I got the MEGA2560 in the mail the other day and it is a real pain to use at first. NewSoftSerial.h is a necessary include. On a side note: I would like to thank Arduino for NOT pointing that out anywhere in the documentation and let me assume my brand new microcontroller was bricked for about 3 hours. Jeeze!

Hardware

Before hooking everything up, I had to first do some soldering. Well, not some. A ton. Everything hooked to the resistor packs in the image of my hardware setup below had to be hooked into a daughter board.


And here is the finished daughter board.
Top

Bottom


And here is the Arduino with everything hooked up to it and everything being insulated/held-on by good old-fashioned electrical tape.

I opted for pin/ribbon cable connections between the boards to avoid any spaghetti wiring. It keeps everything organized and neat. And I think it looks cool.

Software

OK so I'm not an experienced electronics engineer or claim to know very much about the topic. As such, I wasn't sure which switch went to which digital pin after I soldered them all in. So I wrote some code to easily tell me. I knew the input pins were 22-33 so I wrote this code, uploaded, opened the serial monitor and started pressing buttons on the footswitch boards.

#include <NewSoftSerial.h>

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  if(digitalRead(22) == LOW){
    Serial.println("22 pressed.");
  }
  if(digitalRead(23) == LOW){
    Serial.println("23 pressed.");
  }
  if(digitalRead(24) == LOW){
    Serial.println("24 pressed.");
  }
  if(digitalRead(25) == LOW){
    Serial.println("25 pressed.");
  }
  if(digitalRead(26) == LOW){
    Serial.println("26 pressed.");
  }
  if(digitalRead(27) == LOW){
    Serial.println("27 pressed.");
  }
  if(digitalRead(28) == LOW){
    Serial.println("28 pressed.");
  }
  if(digitalRead(29) == LOW){
    Serial.println("29 pressed.");
  }
  if(digitalRead(30) == LOW){
    Serial.println("30 pressed.");
  }
  if(digitalRead(31) == LOW){
    Serial.println("31 pressed.");
  }
  if(digitalRead(32) == LOW){
    Serial.println("32 pressed.");
  }
  if(digitalRead(33) == LOW){
    Serial.println("33 pressed.");
  }
}



That step was quick. Figuring out the LED pins was a trail and error test that took a while longer.

The next step was to marry the test effect change code with the wah/volume code. This was no easy task and took hours of troubleshooting with a sniper rifle to get it right. Here is the final functional code to produce a clone of the FCB1010.


#include <NewSoftSerial.h>

int bank = 0x00;//Default bank of 0
int number_in_bank = 0x0A;//10 effects per bank
const int volume_pin = 0;// Pot connected to analog pin 0
const int wah_pin = 1;// Pot connected to analog pin 1
const int pot_threshold = 7;// Threshold amount to guard against false values
const int midi_channel = 0;

void setup() {
  for(int i = 34; i <= 43; i++)//Set up the LED pins and make them float high right off the bat
  {
    pinMode(i, OUTPUT);
    digitalWrite(i, HIGH);
  }

  Serial.begin(31250);//  Set MIDI baud rate:

  changeProgram(0x00,43);//Homed to program 1
}

void loop() {
  ///////////
  //EFFECTS//
  ///////////

  //
  //Lower Button Bank
  //

  //Button 1
  if(digitalRead(23) == LOW)
  {
    changeProgram(0x00,43);
  }
  //Button 2
  if(digitalRead(25) == LOW)
  {
    changeProgram(0x01,41);
  }
  //Button 3
  if(digitalRead(29) == LOW)
  {
    changeProgram(0x02,39);
  }
  //Button 4
  if(digitalRead(27) == LOW)
  {
    changeProgram(0x03,37);
  }
  //Button 5
  else if(digitalRead(33) == LOW)
  {
    changeProgram(0x04,35);
  }
  //Bank Down
  else if(digitalRead(31) == LOW)
  {
    if(bank != 0x01)
    {
      bank -= number_in_bank;
      changeProgram(0x00,43);
      delay(250);
    }
  }

  //
  //Upper Bank
  //

  //Button 6
  else if(digitalRead(22) == LOW)
  {
    changeProgram(0x05,42);
  }
  //Button 7
  else if(digitalRead(24) == LOW)
  {
    changeProgram(0x06,40);
  }
  //Button 8
  else if(digitalRead(26) == LOW)
  {
    changeProgram(0x07,38);
  }
  //Button 9
  else if(digitalRead(28) == LOW)
  {
    changeProgram(0x08,36);
  }
  //Button 10 (0)
  else if(digitalRead(30) == LOW)
  {
    changeProgram(0x09,34);
  }
  //Bank Up
  else if(digitalRead(32) == LOW)
  {
    if(bank != 0x19)
    {
      bank += number_in_bank;
      changeProgram(0x00,43);
      delay(250);
    }
  }
  //////////
  //VOLUME//
  //////////
  expression(volume_pin);
  ///////
  //WAH//
  ///////
  expression(wah_pin);
}

void changeProgram(int effect_number, int LED) {
  int program = bank + effect_number;//Program 1 would be bank(0)+effect_button(0) so 0x00 with 10 effects in the bank
  Serial.print(0xC0, BYTE);//Program Change
  Serial.print(program, BYTE);
  digitalWrite(LED,LOW);  //Light the associated LED

  for(int i =34; i <= 43; i++)//Turn off all the rest of the LEDs
  {
    if(i != LED)
    {
      digitalWrite(i, HIGH);
    }
  }
  delay(250);//Some debounce
}

void changeVolume(byte channel, byte volume)
{
  Serial.print(0xB0 | (channel & 0x0F), BYTE); //Control Change
  Serial.print(0x07, BYTE);//Volume CC number        
  Serial.print(volume & 0x7F, BYTE);//Volume level (0-127)
}


void wahCharacter(byte channel, byte wah)
{
  Serial.print(0xB0 | (channel & 0x0F), BYTE);//Control Change
  Serial.print(0x1B, BYTE);//Wah character CC number
  Serial.print(wah & 0x7F, BYTE);//Wah tone character (0-127)
}

void expression(int pin)
{
  static int s_nLastPotValue = 0;
  static int s_nLastMappedValue = 0;
  int nCurrentPotValue = analogRead(pin);
  if(abs(nCurrentPotValue - s_nLastPotValue) < pot_threshold)
    return;
  s_nLastPotValue = nCurrentPotValue;
  int nMappedValue = map(nCurrentPotValue, 0, 1023, 0, 127); // Map the value to 0-127
  if(nMappedValue == s_nLastMappedValue)
    return;
  s_nLastMappedValue = nMappedValue;
  if(nMappedValue >= 15){
    if (pin == volume_pin)
    { 
     changeVolume(midi_channel, nMappedValue);
    }
    else
    {
      wahCharacter(midi_channel, nMappedValue);
    }
  }
}


Extra

While messing with the code, I discovered that you can run 2 wah pedals off of the same controller. The effects processor takes the setpoints from both of the expression pedals and bounces in between them. It sounds like this [link]

Just change void expression to this:


void expression(int pin)
{
  static int s_nLastPotValue = 0;
  static int s_nLastMappedValue = 0;
  int nCurrentPotValue = analogRead(pin);
  if(abs(nCurrentPotValue - s_nLastPotValue) < pot_threshold)
    return;
  s_nLastPotValue = nCurrentPotValue;
  int nMappedValue = map(nCurrentPotValue, 0, 1023, 0, 127); // Map the value to 0-127
  if(nMappedValue == s_nLastMappedValue)
    return;
  s_nLastMappedValue = nMappedValue;
  if(nMappedValue >= 15){
    wahCharacter(midi_channel, nMappedValue);
  }
}


Still to Come

I have an LCD display on the way. This should be fun.

Possibly messing with shift keys.

<-Part 3   Part 5->

Thursday, January 20, 2011

Since my Arduino Mega just shipped today, I only have volume and wah to test really.

The FCB1010 chassis comes with 2 expression pedals that can be used to vary a plethora of things. For me, I just want things to be the way they used to be: wah on the left, volume on the right.

What makes volume and wah unique from the effects discussed previously are three things: 1. They are variable and work via potentiometers instead of pushbuttons, 2. They are analog inputs and not digital and 3. In the software, they are controlled by a Control Change instead of a Program Change(effects).

The hardware setup is as in the image below if you wish to test.

The code for both is the same. I'll admit I grabbed the code from this site. No shame in not re-inventing the wheel.

The control code for volume is 0x07 and the wah control is 0x11. It took some trial and error to find the wah control code since there is a typo in the documentation. “Wah off/position” should be “Wah on/position”.

Here's the code to enable wah. Just change 0x11 to 0x07 for volume.
// Constant
const int POT_PIN = 0;              // Pot connected to analog pin 0
const int POT_THRESHOLD = 7;        // Threshold amount to guard against false values
const int MIDI_CHANNEL = 0;         // MIDI Channel 1

void setup()
{
    Serial.begin(31250);     // Starts communication with the serial port
}

void loop()
{
    static int s_nLastPotValue = 0;
    static int s_nLastMappedValue = 0;

    int nCurrentPotValue = analogRead(POT_PIN);
    if(abs(nCurrentPotValue - s_nLastPotValue) < POT_THRESHOLD)
        return;
    s_nLastPotValue = nCurrentPotValue;

    int nMappedValue = map(nCurrentPotValue, 0, 1023, 0, 127); // Map the value to 0-127
    if(nMappedValue == s_nLastMappedValue)
        return;
    s_nLastMappedValue = nMappedValue;
    if(nMappedValue >= 15){
    
      MidiVolume(MIDI_CHANNEL, nMappedValue);
    }
}

void MidiVolume(byte channel, byte volume)
{
    Serial.print(0xB0 | (channel & 0x0F), BYTE);    // Control change command
    Serial.print(0x11, BYTE);                       // Volume command
    Serial.print(volume & 0x7F, BYTE);              // Volume 0-127
}


Still to Come


Beyond the breadboard: PCB and wiring
10 effect bank: 2 footswitch boards
Awesome eye candy: LCD screen
<- Part 2       Part 4 ->

Wednesday, January 19, 2011

So I threw out all of the code from the last post. Can't take the bull by the horns like that.

Testing


First off, I set the V-Amp to communicate through the MIDI in on channel 1. Consult the manual on how to do this. Editing the settings on that piece of gear is like working a Chinese puzzle box.

Upon examining the existing hardware, it was determined that the code has to use reverse HIGH/LOW logic. So when a switch goes low, instead of being normally high, it will change effects/effect banks and make the negative end of an LED go low when necessary. Get all that?

Test Program 1 – Bank Up/Bank Down


Like the title suggests, this code just changes the number (bank number) on the V-Amp's 7 segment displays using 2 momentary buttons. There are 5 effects per bank.
See image for hardware required.


int program = 0x00;
int bank = 0x01;
int number_in_bank = 0x05;

void setup() {
  for(int i = 2; i <= 3; i++)
  {
    pinMode(i, INPUT);
  }
 
  //  Set MIDI baud rate:
  Serial.begin(31250);
  changeProgram(program);
}

void loop() {
 
  if(digitalRead(2) == LOW){
    program += number_in_bank;
    changeProgram(program);
    delay(500);
  }
  if(digitalRead(3) == LOW){
    program -= number_in_bank;
    changeProgram(program);
    delay(500);
  }
}

void changeProgram(int program) {
  Serial.print(0xC0, BYTE);
  Serial.print(program, BYTE);
}


Verdict: WORKS!

Test Program 2 – One whole switchboard


This code will utilize one whole switchboard from the FCB1010. The button hooked into pin 2 of the Arduino will move the effects up one bank (add 5).
See image for hardware required.



int program = 0x00;
int bank = 0x00;
int number_in_bank = 0x05;

void setup() {
  for(int i = 2; i <= 7; i++)
  {
    pinMode(i, INPUT);
  }
 
  //  Set MIDI baud rate:
  Serial.begin(31250);
  changeProgram(program);
}

void loop() {
 
  if(digitalRead(2) == LOW)
  {
    program += number_in_bank;
    bank += number_in_bank;
    changeProgram(program);
    delay(500);
  }
  else if(digitalRead(7) == LOW)
  {
    program = bank + 0x00;
    changeProgram(program);
    delay(500);
  }
  else if(digitalRead(6) == LOW)
  {
    program = bank + 0x01;
    changeProgram(program);
    delay(500);
  }
  else if(digitalRead(5) == LOW)
  {
    program = bank + 0x02;
    changeProgram(program);
    delay(500);
  }
  else if(digitalRead(4) == LOW)
  {
    program = bank + 0x03;
    changeProgram(program);
    delay(500);
  }
  else if(digitalRead(3) == LOW)
  {
    program = bank + 0x04;
    changeProgram(program);
    delay(500);
  }
}

void changeProgram(int program) {
  Serial.print(0xC0, BYTE);
  Serial.print(program, BYTE);
}


Verdict: I tried factoring out the repetitive code into an elegant loop. It just plain didn't work. As written: WORKS!

Test 3 – LEDs


Factored-out some code. Also, the FCB1010 has LEDs that light up that correspond with whatever effect is active. This has to be accounted for in the code.

See image for hardware required.

int program = 0x00;
int bank = 0x00;
int number_in_bank = 0x05;

void setup() {
  for(int i = 2; i <= 7; i++)
  {
    pinMode(i, INPUT);
  }
 for(int i = 8; i <= 12; i++)
 {
   pinMode(i, OUTPUT);
   digitalWrite(i, HIGH);
 }
  //  Set MIDI baud rate:
  Serial.begin(31250);
  changeProgram(program,0x00,0);
}

void loop() {
 
  if(digitalRead(2) == LOW)
  {
    program += number_in_bank;
    bank += number_in_bank;
    changeProgram(program,0x00,0);
    delay(500);
  }
  else if(digitalRead(7) == LOW)
  {
    changeProgram(program,0x00,12);
  }
  else if(digitalRead(6) == LOW)
  {
    changeProgram(program, 0x01,11);
  }
  else if(digitalRead(5) == LOW)
  {
    changeProgram(program,0x02,10);
  }
  else if(digitalRead(4) == LOW)
  {
    changeProgram(program, 0x03, 9);
  }
  else if(digitalRead(3) == LOW)
  {
    changeProgram(program,0x04,8);
  }
}

void changeProgram(int program, int effect_number, int LED) {
  program = bank + effect_number;
  Serial.print(0xC0, BYTE);
  Serial.print(program, BYTE);
  digitalWrite(LED,LOW);
 
  for(int i = 8; i <= 12; i++){
    if(i != LED)
    {
      digitalWrite(i, HIGH);
    }
  }
  delay(500);
}


Verdict: WORKS!!!!!!1!!one!!!

Future Installments


I ran out of I/O and I lack the know-how to build a multiplexing circuit. As such, I will have to wait until the Arduino MEGA256 arrives to add more stuff. (Sad face)

Still to go: add another 5 effects changing switches and a down bank switch (Another footswitch board), expression pedals and (optional) an LED/LCD screen telling me what effect is active.
<- Part 1       Part 4 ->

Sunday, January 16, 2011

So I'm a guitarist that has been playing for right around 12 years. As such, I've amassed some equipment that is quite pricey.

Last week a power surge took out my Behringer FCB1010 midi foot controller that I use to control my Behringer V-Amp Pro multieffects processor. Double damn it!

I was sad and pissed off. I think I went through the seven stages of grief when I saw a bunch of surface mount resistors and transistors let the magic smoke out on the foot controller's main circuit board. Then a thought occurred to me. The controller board is nothing more than a crude microcontroller like a BASIC Stamp or an Arduino. All of the actual physical controls were in tact (pushbuttons and rheostats). I could build a better foot controller with an Arduino.

Planning

I have all of the original manuals for both the V-Amp and the FCB1010 that show the MIDI implementation and control codes. So those values just need plugged into the code.

I want this new controller to have the following features:
  1. Run on phantom power through the MIDI out port
  2. USB port mounted where the mains power used to come into the chassis for programming without tearing the thing apart.
  3. Fully-functional volume and wah expression pedals
  4. All selector switches function as labeled.

Reverse Engineering

All drawings are the circuit boards unmodified. Some changes may be necessary.
The footswitch PCB Both identical to this:
The MIDI out PCB (MIDI in won't be used so omitted):

The Code

I'm really crappy at coding for a microcontroller that I haven't even received in the mail yet. As such, the code so far is just my thought process as to how it will work. This is just for the changing of banks and changing of programs via MIDI. Any help would be appreciated.
const byte BANKSELECT = 0x00;        //0-31
const byte CONTROL_CHANGE = 0xB0;    //For Volume and Wah
const byte PROGRAMCHANGE = 0xC0;    //0-127
const int MIDI_CHANNEL = 0;;  
const int SERIAL_PORT_RATE = 31250;
const int UPPERLIMIT = 127;
const int LOWERLIMIT = 0;
const int UPPER_BANK = 25;
const int LOWER_BANK = 1;
const int LED[] = {1,2,3,4,5,6,7,8,9,10};
const int SWITCH[] = {11,12,13,14,15,16,17,18,19,20,21,22};
int ACTIVE = 0;

void setup(){
  int BANK_PROGS[][5] = {};
  //Populate bank_progs array
  int i,j;
   int COUNTER = 0;
  for(i=1; i<26; i++)
  {
    for(j=0; j<5; i++)
      BANK_PROGS[i][j] == COUNTER;
      COUNTER++;
    {
    
    }
  }

  int x;
  for(x=0; x<10; x++){
    pinMode(LED[x], OUTPUT);
  }
  for(x=0; x<13; x++){
    pinMode(SWITCH[x], INPUT);
  }
  byte BANK = 0x01;            //Default Bank is homed
  Serial.begin(SERIAL_PORT_RATE);
}

void loop(){
  //Search for a high switch
  int x;
  for(x=0; x<10; x++){
    int SWITCHSTATE = digitalRead(SWITCH[x]);
    if(SWITCHSTATE == HIGH){
      if(x=5)
      {
        BANK_CHANGE(1);
      }else if(x=11)
      {
        BANK_CHANGE(0);
      }
      else
      {
        int program = 0;
        EFFECT_CHANGE(x);
      }
      ACTIVE = x;
    }
  }
  //TURN THE ACTIVE LED ON
  digitalWrite(LED[ACTIVE], HIGH);

}

void BANK_CHANGE(int BANKDIFF){
  int BANK=0;
  if(BANKDIFF==1){
  //Bank Up  
    if(BANK!=UPPER_BANK){
      BANK = BANK+2;
    }else{
      BANK = 0x00;
    }
  
  }else{
    //Bank Down
    if(BANK != 0){
      BANK = BANK-2;
    }else{
      BANK = UPPER_BANK;      
    }
  }
  Serial.print(CONTROL_CHANGE, BYTE);
  Serial.print(BANKSELECT, BYTE);
  Serial.print(BANK, BYTE);
}

void EFFECT_CHANGE(byte program){
    Serial.print(PROGRAMCHANGE, BYTE);
    Serial.print(program, BYTE);
}

Stay tuned for more as this project develops.
Part 2 ->
Subscribe to RSS Feed Follow me on Twitter!