DIY Chewie Monsta Looper (Based on Ed Sheeran's)

10,991

21

98

Introduction: DIY Chewie Monsta Looper (Based on Ed Sheeran's)

So I had heard of Ed Sheeran for a few years now and never really paid him much attention. I liked some of this songs on the radio but thought he was just another pop artist until I say him perform "Shape of You" at the 2017 Grammys. I was blown away! I didn't really even like the song but to watch him perform it live by himself with his loop pedal was mesmerizing. I scoured the internet looking for info on this pedal and found that there wasn't much out there. I finally found an article saying that it was custom built by Ed and his guitar tech which disappointed me until I finally came across and Instructable by "edsutcliffe" ( https://www.instructables.com/id/DIY-Chewie-Monst... ) that had the "secret sauce" on exactly how it worked. I was excited and I got right to work. However, while working through the instructable I ran into several "gotchas" along the way which is why I wrote this instructable. edsutcliffe's page does a great job of describing the pieces and how they go together. My intention here is to fill in some of the gaps that drove me crazy and cost me hours if not days of time trying to solve problems. So while I'm not going to walk you through step by step how to build the loop pedal (most of which you can find on edsutcliffe's page), I'm going to walk you through the key integration issues that plagued me.

Step 1: The Pedal

While seeming to be the most critical piece, the pedal itself is the easiest and most straight forward part of the project. My advice here is to start slow and build a rough mock up first and experiment with it. I found that until you actually start using it that its difficult to know what you want. You may think that three tracks are enough but after playing a bit you may find that you really would like a fourth track. Changing it later isn't the easiest thing to do. Even while I was building my second version of the pedal I went back and forth about adding a button for "UNDO" but decided against it. I later found that it we really be useful but I didn't leave enough space for it. I ended up having to take the "programmers" way out and multitask the CLEAR button. Now I have it so that a short press triggers UNDO and a long press triggers CLEAR.

Beyond that, the only other consideration here is whether you want to use pedals or foot switches. I went with foot switches initially just for cost but I recently built a second board using pedals and found them much easier to use.

There are lots of options on Amazon but the ones I used are below.

Step 2: Arduino

In the instructable, rather than telling you to just by a manufactured Arduino board it list each component and has you build your own. In my opinion this is ridiculous given that a mfg board cost ~$10 on the internet so do yourself a favor and just go with that.

https://www.amazon.com/Elegoo-EL-CB-001-ATmega328P...

Now down to my first "gotcha". One important item that isn't discussed anywhere is how to create the sketch (code) for the Arduino which is pretty critical since the buttons wont do anything without this. So Im providing my code for you to use. Again, Im not going to walk you through step by step how to program the Arduino. If you go to their homepage they have plenty of tutorials on how to do that. If you are savvy enough then feel free to edit it however works best for you.

The Basics

  • The pedal has 8 buttons and 2 LEDs
  • A button press sends a MIDI command message from the Arduino
  • Buttons (While I'm describing each button's function, the Arduino code itself does nothing but send a MIDI command. the MIDI command must be tied to a script in Mobius which will be covered later)
  • Buttons consist of two groups
    • Global = Sends the same MIDI command regardless the mode
    • Mode-based = Sends different MIDI command based on the mode
  • Mode-based:
    • MODE = this button changes the "mode" of the pedal (Record / Play / Volume Control)
      • Short press toggles between Record and Play mode

      • Long press (more than 1 sec) goes to Volume control mode.

    • REC/PLAY
      • In REC mode = In RESET mode it will start the loop and close the loop on next press and go to Overdub mode. After that it toggles between Play and Overdub of the current track.
      • In PLAY mode = Unmutes and restarts all tracks
    • X / STOP
      • In REC mode = Applies "instant multiply" function to the current track.
      • In PLAY mode = Mute and Pause all tracks
    • TRACK 1/2/3
      • In REC mode = In RESET mode it will start the loop and close the loop on next press and go to Play mode. After that it toggles between Play and Overdub of the selected track.
      • In PLAY mode = Toggle between Mute and Play
      • In Volume Control mode = Track 2 cycles through the tracks, Track 1 reduces the output level (volume) of the current track by 5, Track 3 increases the output level of the current track by 5.
  • Global
    • RESET = applies "Global Reset" function
    • CLEAR
      • Short press (<1000ms) applies "UNDO" function to the current track
      • Long press (>=1000ms) applies "CLEAR" function to the current track
  • LEDs
    • REC LED = Red, on when in Record mode.
    • VOL LED = Blue, on when in Volume Control mode.
  • Pins
    • REC/PLAY = pin 3
    • RESET = pin 4
    • X/STOP = pin 5
    • CLEAR = pin 6
    • TRACK 1 = pin 7
    • TRACK 2 = pin 8
    • TRACK 3 = pin 9
    • MODE = pin 10
    • REC LED = pin 11
    • VOL LED = pin 12

Note: A community friend, Claudio, made some enhancement to the sketch and shared it back with us. Thanks, Claudio!

Step 3: The MIDI Interface

This is an area I feel wasn't covered very clearly in the other instructable. Basically, as discussed in the Arduino section, the pedal and Arduino just outputs a MIDI command based on the button pressed. In order to be used you need to send the MIDI to the PC running Mobius. I found 3 ways to do this and it's dependent on the type of audio interface you buy (more to come).

  1. Option 1 - Depending on what audio interface you buy, some have built in MIDI in/out ports. If this is the case then you can just follow the instructable and pull out the serial channel on the Arduino and connect it to the MIDI In port. You will then be able to select this as your MIDI controller source later when you setup Mobius
  2. Option 2 - My audio interface didn't have a built in MIDI port so this presented a challenge. So I initially pulled out the serial channel as in option 1 and purchased a separate MIDI-to-USB adapter. While this did work, I found it to be clunky and unreliable. Plus I was frustrated because this would be a 3rd USB connection and my PC only had two. I could disconnect the cable to the Arduino which I was using for power and debugging but that meant I would need an external power supply for it.
  3. Option 3 - I didn't understand why I couldn't get the MIDI commands over the USB connection and have the same connection power the Arduino. I knew there must be a way. After a lot of internet searching I finally found a way by using two freeware apps.
    • loopMIDI - Ironically named, this free apps enables you to create a "virtual" MIDI port on your PC. All you have to do is install it and define a virtual MIDI Out port and that's it. It will run automatically at boot up. https://www.tobias-erichsen.de/software/loopmidi.h...
    • Hairless MIDI - This program enables you to create a "serial bridge" so that you can map the serial COM port used to program your Arduino to the virtual MIDI port you just created with loopMIDI. And Whalla! You now only need a single USB connection from the PC to the Arduino. http://projectgus.github.io/hairless-midiserial/

    • NOTE: If you choose to use option 3 then you need to make sure that the Arduino code has the serial channel baud rate set to 38400 instead of the standard 31250 that MIDI uses.

    • // Set MIDI baud rate:

    • //Serial.begin(31250);

    • // Set baud rate to 38400 for Hairless MIDI

    • Serial.begin(38400)

Step 4: The Audio Interface

So this is probably the most important component that you will have to select. Since low cost was a key driver for me I looked for an inexpensive audio interface. I ended up settling on the BEHRINGER U-PHORIA UM2 (https://www.amazon.com/Behringer-UM2-BEHRINGER-U-P... ) because it was low cost and had 2 input channels and 2 output channels which is all I needed. There are lots of options out there but it could slightly change the Mobius setup later.

Please understand that you do get what you pay for. While the UM2 does a great job for its price, I occasionally run into issues such as a random "pop" sound if I overdub too many layers or sometime get static and have to reboot the interface. So if you are serious about performing with this pedal then spring for a higher quality audio interface.

I really thought this would be straight forward but this ended up being the hardest problem for me to solve and almost resulted in me abandoning the project. When you first plug it in to your PC, Windows will automatically install a driver and you think you are set, right? Wrong. After I first set it up and starting recording tracks I found that the latency was so bad (more than a second) that the pedal was basically unusable. I had to be doing something wrong. Again, after a ton of internet searching I found the problem. Windows will install a default MME driver for the audio interface. MME drivers are very high latency and not suitable for real-time recording. I had to go to the Behringer website and find the ASIO driver for my specific interface. ASIO drivers are specifically designs to minimize latency which is what you need here. After installing this driver the recording latency was not even detectable by the human ear. So the takeaway here is that whatever audio interface you use please make sure you get the ASIO driver from the manufacturer and save yourself the headache that I experienced.

Step 5: Mobius

Let's face it, without Mobius all we have so far is a MIDI controller pedal board. Mobius is a free software program created by Circular Labs (http://www.circularlabs.com/ ) that does all of the recording and looping. It's really an amazing program. That being said, the documentation from Circular Lab I found to be very lacking. After the install you get a window with 8 tracks and tons of buttons, meters, and counter. It took me a while to figure out how to navigate the GUI and configure it for me needs. Fortunately I found a youtube video posted by edsutcliffe that walks you through the configuration step by step.

After that, the only part of the setup that I had trouble with was mapping a certain input channel to a certain track. In the video, they are using a 4 channel interface and each channel shows up independently in Mobius. The UM2 interface that I used actually uses a single stereo channel and utilizes the right and left channels independently. So I only see 1 "channel" in mobius but I can map a single channel by moving the "Pan" setting all the way to the left or to the right. So I have track 1 and 2 with pan set all the way to the right so that only channel 2 (instrument) gets recorded. Then for track 3 I left pan in the middle so that I can record either the mic or the guitar on it. If I want to only record the mic then I would pan all the way to the left channel.

Step 6: Mobius Scripts and MIDI Bindings

The final piece of the puzzle is the Mobius scripts and MIDI bindings. Even though I'm very familiar for computer programming, I found the Mobius scripting language to be a little confusing and not well documented. It took me a long time and a lot of tweaking to get them the way a wanted but in the end they work for what I need. The steps for binding the scripts to MIDI commands in Mobius are described in detail in the youtube video in step 5.

Well that's it. Hopefully these tips will help you out with your build and you will be able to avoid the frustrations that I ran into.

Step 7: Version 1.5

So after using my pedal for almost two years I decided that I wanted to make a slight change to how it worked. I ran into some cases where the "PLAY ALL" feature made things cumbersome. Often I would have a track muted and I want to stop all the track and just restart the two tracks there were playing. With the current operation, all three tracks would restart and I'd quickly have to mute the unwanted track. Unfortunately, I was not able to find a good way to do this in Mobius. In order to accomplish this I had to do it inside the Arduino code. Remember that the pedal and Arduino code were pretty much "dumb". It only sent a MIDI command when a pedal was pressed and the Mobius scripts did all the rest. With this change, I basically moved all of the playback intelligence into the Arduino code and track the states of each individual track. So this ended up being almost a complete rewrite of the Arduino code. I even ended up building a small debug pedal board to develop and test the new code. If you are interested in my new method then read on, otherwise the functions described above will work just fine.


In order to make the "PLAY ALL" work as I wanted I had to add a new state to each track with I call "ARM". Before, when in PLAY mode, pressing the track pedal would toggle between MUTE and PLAY. Now, a pedal press will go from PLAY to MUTE but then toggle between ARM and MUTE. A track will not be unmuted until its in ARM state and then the PLAY pedal is pressed. When the STOP pedal is pressed, all tracks in PLAY are put in ARM and only they will be restarted when PLAY is pressed. The problem is that there is no indication in Mobius relative to the ARM state. So to solve this I added a tri-color LED to each track where MUTE is off, PLAY is green, REC/OVERDUB is red, and ARM is amber.

Now I made a "bone-head" mistake while doing this. My Arduino UNO didn't have enough digital I/O to drive the new LEDs so I upgraded to the Arduino Mega (https://www.amazon.com/gp/product/B01H4ZLZLQ/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1). So the code posted uses the pin layout for it instead of the UNO. I later realized that I could have moved 6 of the pedals to the analog inputs and then use the digitals to drive the LEDs. My code can easily be modified to work this way and if there is enough interest I will even do it myself and post it. However, the Mega is only about $5 more than the UNO and gives you 32 more I/O so I don't think its a big deal.

The last thing I want to talk about are the track LEDs themselves. I used these from Amazon (https://www.amazon.com/gp/product/B077XBMJFZ/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1). I called them "tri-color" LEDs but if you search for them they will be under "bi-color". This is because they only contain two LEDs, a green and red. However by turning them both on at the same time you get amber. Also keep in mind that since they are "common anode" and that you apply 5V to the common pin and have to connect the Arduino pin to the cathode. This makes the LEDs "active low" so they will be off when the Arduino pin is high and on when it's low. If you buy different LEDs that aren't common anode then the Arduino code wont work as written but can easily be adapted. Lastly, I spent a far amount of time tweaking the resistor values until I as able to get the color amber that I wanted. Green is brighter than red so I to use a 1K ohm resistor to reduce its brightness. Another option is to connect the LEDs to the PWM digital channels and control the brightness the analogWrite(pin, value) function.

FYI - apparently Instructables.com does not allow users to upload .zip files anymore so I put all the scripts and aurduino code in github. Please access it here.

https://github.com/mjoseph81/loop_pedal_public

Well, I hope you enjoyed this instructable. Let me know if you have any questions and happy looping.

2 People Made This Project!

Recommendations

  • Retro Tech Challenge

    Retro Tech Challenge
  • Rocks, Gems, and Stones Speed Challenge

    Rocks, Gems, and Stones Speed Challenge
  • Soup & Stew Speed Challenge

    Soup & Stew Speed Challenge

98 Comments

0
radeb1
radeb1

Question 3 months ago on Step 2

Hi all, I've built the same version, but having issues with midi binding, firstly not sure that my arduino board is working correctly, am I supposed to see the tx led on the board flash when a command is sent via a push button. Im using a presonus studio 24c as my interface via midi which I've wired per Ed Sutcliffes version.

0
MattJ134
MattJ134

Answer 2 months ago

Hi and thanks for the question. Are you using Hairless Midi to interface to your PC or are you using the serial midi channel? If you are using hairless midi then you should be able to check the "debug" box and it will display what it receives. If you are using serial midi then you need to use the serial listening built into the Arduino IDE to monitor the serial output. You need to make sure your arduino is correctly sending the midi commands before you troubleshoot mobius.

0
jozicm98
jozicm98

4 months ago

Hey, almost done with this project, just have no idea how to map the midi footswitches to these controls, any idea on how to?

0
ZealotC
ZealotC

Reply 4 months ago

Hey, I can help you which step are you getting confused in?. basically you first have to make sure that you are receiving midi signals into Mobius, for that go into mobius midi device section and select your device name.
Then in mobius- configuration - midi control, tick on midi capture and press any pedal to see if you get values update or not. If you get values updated then it means your pedal is working. if it doesn't show anything, make sure your baud rate in Hairless midi is correct. and Hairless Midi is sending signals to selected midi device created through loopmidi

Now you just have to assign specific scripts to a specific pedal.
if you are confused about which value to which function, its provided in step 6 above.

Hope it helps.

0
ZealotC
ZealotC

Question 5 months ago

Hi,
I have made a pedal with UNO, everything is working fine however, the long press on Clear button isn't working. however, the mode button long-press is working fine.
I've not changed the code. How might have it happened?

0
MattJ134
MattJ134

Answer 5 months ago

which version of the arduino code are you using?

0
ZealotC
ZealotC

Reply 5 months ago

I'm using 1.3a modded by (Claudio Cas) one.
The changes I have made to the code are adding a 4th track (From comment of Mr.Monkey) to pin 6 and moved the clear which was in pin 6 to pin 2.

0
MattJ134
MattJ134

Reply 5 months ago

the code for undo/clear is below. When you press the pedal it will immediately trigger "undo". if you continue pressing the pedal for more than 1 sec then it will trigger clear. I'd start by confirming that the correct midi commands are being triggered for each function. Once you verify that, you need to make sure those midi command are set as bindings to those mobius functions.

const uint8_t undo_cmd = 0x11;

const uint8_t clear_cmd = 0x12;

//Logic for CLEAR button

if (btnEval[1] == 0 && InNotARetrigger(1)){

//handle short press

if(btnEval[1] != priorBtnEval[1]){

sendCmd(1, undo_cmd, 127);

//handle long press

}else if((millis() - clearLongPress) >= longPressTime){

sendCmd(1, clear_cmd, 127);

clearLongPress = millis();

}

}else{

//reset last time clear was pressed

clearLongPress = millis();

}

0
ZealotC
ZealotC

Reply 5 months ago

I tried using this part too, but still doesn't work
Here is the current code, I hope you can figure It out, Im 0 at programming.
Extremely Thankful to you for being super responsive
/*
* FILE : looper_pedal_midi_volume_undo.ino
* AUTHOR : Matt Joseph
* MOD : Claudio Cas
* DATE : 8/23/2019
* VERSION : 1.3a
*
*
* DESCRIPTION
* https://www.instructables.com/id/DIY-Chewie-Monst...
*
*
*
* REV HISTORY
* 1.0) Initial release per description
* 1.1) Added volume control functionality
* 1.2) Added bit shift latching function for button reads
* Updated MIDI command values for each output
* 1.3) release date 8/20/2018
* Added "UNDO" function to "CLEAR" button
* Short press (<1000ms) activates "UNDO"
* Long press (>=1000ms) activates "CLEAR"
* 1.3a) release date 8/23/2019
* Added code for debounce button press without using delay() in mail loop: improve responsiveness of button (more precise loop start and close)
* default value is 60ms, you can tweak changing the minRetriggerTime variable

*/
#define NUM_BUTTONS 8
#define NUM_BUTTONS 8
const uint8_t btn_rec_play = 3; //REC-PLAY
const uint8_t btn_reset = 4; //RESET
const uint8_t btn_mult_stop = 5; //MULT-STOP
const uint8_t btn_clear = 2; //CLEAR
const uint8_t btn_track4 = 6; //TRACK 1
const uint8_t btn_track1 = 7; //TRACK 2
const uint8_t btn_track2 = 8; //TRACK 3
const uint8_t btn_track3 = 9; //TRACK 4
const uint8_t btn_mode = 10; //MODE
const uint8_t recLED = 11;
const uint8_t volLED = 12;
const uint8_t reset_cmd = 0x10;
const uint8_t undo_cmd = 0x11;
const uint8_t clear_cmd = 0x12;
const uint8_t play_start_cmd = 0x20;
const uint8_t rec_start_cmd = 0x30;
const uint8_t vol_start_cmd = 0x40;
const uint8_t buttons[NUM_BUTTONS] = {btn_reset, btn_clear, btn_rec_play, btn_mult_stop, btn_track1, btn_track2, btn_track3, btn_track4};
const int ledPin = LED_BUILTIN;// the number of the LED pin
int ledState = LOW; // ledState used to set the LED
int mode = 0; // 0=Play, 1=Record, 2=Volume control
int modeValue = 1;
int previousMode = 0;
int previousModeValue = 1;
unsigned long modeLongPress = 0;
unsigned long clearLongPress = 0;
int longPressTime = 1000;
int modeChange = 0;
int modeStateChange = 0;
uint8_t modeBuffer = 0xFF;
uint8_t modeEval = 0xFF;
uint8_t priorModeEval = 0xFF;
uint8_t btnBuffer[NUM_BUTTONS] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
uint8_t btnEval[NUM_BUTTONS] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
uint8_t priorBtnEval[NUM_BUTTONS] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
// Retrigger and debouce
const int minRetriggerTime = 60; //Min millis between 2 button press
unsigned long lastCmdSendTimeStamp[NUM_BUTTONS+1] = {0,0,0,0,0,0,0,0}; //NUM_BUTTON + 1 (Mode Button have different handler)
const int btn_mode_idx = 7;
void setup() {
// Set MIDI baud rate:
//Serial.begin(31250);
// Set baud rate to 38400 for Hairless MIDI
Serial.begin(38400);
//Serial.begin(115200); // !!! make sure that the baud rate of you port in os, in hairless MIDI settings and in the sketch is the same
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
pinMode(recLED, OUTPUT);
pinMode(volLED, OUTPUT);
for (int i = 0; i < NUM_BUTTONS; i++){
pinMode(buttons[i], INPUT_PULLUP);
}
pinMode(btn_mode, INPUT_PULLUP);
}
void loop() {
readButtons();
}
/*
* Check if the current press is a valid and not a bounce of signal
* Ignore button press before minRetriggerTime ms
*/
bool InNotARetrigger(int ButtonNum)
{
unsigned long lastPressTime = lastCmdSendTimeStamp[ButtonNum];
if(millis() - lastPressTime >= minRetriggerTime)
{
lastCmdSendTimeStamp[ButtonNum] = millis();
return true;
}
return false;
}
void readButtons()
{
//check state of MODE button
modeValue = digitalRead(btn_mode); //read current input
modeBuffer = modeBuffer << 1; //shift buffer 1 bit left
bitWrite(modeBuffer, 0, modeValue); //add new sample to buffer
priorModeEval = modeEval; //update last evaluated value of MODE
modeEval = modeBuffer & 0x07; //keep last 3 samples for evaluation (0b00000111)
if ( modeEval == 0x00 && InNotARetrigger(btn_mode_idx)) //Evaluated input has at least 3 sequential 0s
{
if (modeEval != priorModeEval) //if evaluated MODE has changed from 1 to 0 for 3 consecutive samples (button pressed)
{
modeChange = 1;
//Toggle MODE betwee PLAY and REC
if (mode == 0)
{
mode = 1;
}else{
mode = 0;
}
}else if(millis() - modeLongPress >= longPressTime) //if evaluated MODE has stayed 0 for at least "longPressTime" (1000ms)
{
//Set MODE to VOL_CTL
if(mode != 2)
{
mode = 2;
modeChange = 1;
}
}
}else if(modeEval == 0x07){ //If evaulated MODE is 1 for 3 consecutive samples (button not pressed)
//logic to reset the timer for vol mode
modeLongPress = millis(); //reset the timer for when MODE was pressed to current time
modeChange = 0;
}
//light record LED if in Record mode
if (mode == 1)
{
digitalWrite(recLED, HIGH);
}else{
digitalWrite(recLED, LOW);
}
//light volume control LED if in Volume Control mode
if (mode == 0)
{
digitalWrite(volLED, HIGH);
}else{
digitalWrite(volLED, LOW);
}
//Read remaining buttons
memcpy(priorBtnEval, btnEval, NUM_BUTTONS*sizeof(uint8_t)); //save copy of last button evaluated values
//Read the rest of the buttons
for (int i = 0; i < NUM_BUTTONS; i++)
{
btnBuffer[i] = btnBuffer[i] << 1; //shift buffer 1 bit left
bitWrite(btnBuffer[i], 0, digitalRead(buttons[i])); //add new sample to buffer
btnEval[i] = btnBuffer[i] & 0x07; //keep last 3 samples for evaluation
}
//send midi for mode button on state change
if (modeChange == 1)
{
//Reset modeChange flag
modeChange = 0;
//If in play or vol ctrl mode send midi cmd to stop any active recording
if(mode==0)
{
sendCmd(1, play_start_cmd, 127);
}else if(mode==2){
sendCmd(1, play_start_cmd, 127);
}else{
sendCmd(1, rec_start_cmd, 127);
}
}
//Check button status and send correct MIDI Command
//RESET and CLEAR buttons do not depend on MODE. Evaulate them separately
//Logic for RESET button
if (btnEval[0] == 0 && InNotARetrigger(0)){
if(btnEval[0] != priorBtnEval[0])
{sendCmd(1, reset_cmd, 127);}
}
//Logic for CLEAR button
if (btnEval[1] == 0 && InNotARetrigger(1)){
//handle short press
if(btnEval[1] != priorBtnEval[1]){
sendCmd(1, undo_cmd, 127);
//handle long press
}else if((millis() - clearLongPress) >= longPressTime){
sendCmd(1, clear_cmd, 127);
clearLongPress = millis();
}
}else{
//reset last time clear was pressed
clearLongPress = millis();
}
//////////////////////
/* //Logic for CLEAR button
if (btnEval[1] == 0 && InNotARetrigger(1)){
//handle short press
if(btnEval[1] != priorBtnEval[1]){
sendCmd(1, undo_cmd, 127);
//handle long press
}else if((millis() - clearLongPress) >= longPressTime){
sendCmd(1, clear_cmd, 127);
clearLongPress = millis();
}
}else{
//reset last time clear was pressed
clearLongPress = millis();
}
*/
////////////////////////
if(mode==0){
//Check for button presss and send correct note in Play mode for the rest of the buttons
//Start at index 2 in the array since RESET and CLEAR are handled outside the loop
for( int i=2;i if (btnEval[i] == 0 && InNotARetrigger(i)){
if(btnEval[i] != priorBtnEval[i])
{sendCmd(1, play_start_cmd+i, 127);}
}
}
}else if(mode==1){
//Check for button presss and send correct note in REC mode for the rest of the buttons
//Start at index 2 in the array since RESET and CLEAR are handled outside the loop
for( int i=2;i if (btnEval[i] == 0 && InNotARetrigger(i)){
if(btnEval[i] != priorBtnEval[i])
{sendCmd(1, rec_start_cmd+i, 127);}
}
}
}else if(mode==2){
//Check for button presss and send correct note in VOL mode for the rest of the buttons
//Start at index 4 in the array since VOL CTL only uses TRACK1/2/3 buttons
for( int i=4;i if (btnEval[i] == 0 && InNotARetrigger(i)){
if(btnEval[i] != priorBtnEval[i])
{sendCmd(1, vol_start_cmd+i, 127);}
}
}
}
//delay(30); // Not use delay anymore (cas 1.3a)
}
// Sends a MIDI control command. Doesn't check to see that cmd is greater than 127, or that data values are less than 127:
// first parameter is the event type, combined with the channel.
// Second parameter is the control number number (0-119).
// Third parameter is the control value (0-127).
void sendCmd(int channel, int command, int value) {
Serial.write(0xB0 | (channel-1));
Serial.write(command);
Serial.write(value);
}

0
MattJ134
MattJ134

Reply 5 months ago

I don't see any difference in your code although I don't know why you have it duplicated and commented out. Have you tried enabling the "debug midi message" option in Hairless MIDI and verifying if you are getting the correct command values when the undo/clear button is pressed? (undo = 0x11 = 17, clear = 0x12 = 18)

That will at least tell you if the code is working. If so then you need to debug the mobius bindings. If its not then try moving the clear button back to pin 6 and see if that makes a difference.

0
ZealotC
ZealotC

Reply 5 months ago

Hey there,
I tried changing the pins too, no change in the midi msg, I only get 17, long press or short. :(

0
MattJ134
MattJ134

Reply 5 months ago

So it looks like your rig it never hitting the "else" clause in the statement below. My suspicion is that your button it rapidly bouncing between 0 and 1 causing the "if(btnEval[1] != priorBtnEval[1])" check to be true and executing the short press. I would first try with a different physicals button to see if that works. If not then you will need to out serial.print() statements to print the values of your variables out to the debug console to see what is going on. Something like "Serial.Print(btnEval[1])" to see how the button is being evaluated.

you could also try to uncomment the "delay(30);" line of code which will slow down the button evaluation to see if that helps debouncing.

//handle short press if(btnEval[1] != priorBtnEval[1]){ sendCmd(1, undo_cmd, 127); //handle long press }else if((millis() - clearLongPress) >= longPressTime){ sendCmd(1, clear_cmd, 127); clearLongPress = millis();

0
amritsarba
amritsarba

Reply 4 months ago

I solved this by copying the logic of reset from v1.5 to v1.3 and its working. Thanks

0
amritsarba
amritsarba

Question 4 months ago

Hi there, I am now planning to switch to v1.5 of the code, I read on the recent discussion with patricklouiebookings about logic being moved from mobius scripts to code, does this mean that I dont have to use any scripts in mobius? also I saw you have put mobius script for v1.5 in the github. v1.3 was easy to setup in mobius because there were only 2 modes for each, now since there are many, would you mind helping me with the mobius bindings, sharing a screenshot of your mobius script setup with the values of midi will be much helpful thanks.

Thank you again for being so much active in helping others also build. Cheers

0
MattJ134
MattJ134

Answer 4 months ago

Hi, there are still some scripts that are required for v1.5 which are the ones in github, however there are less than the v1.3 since many binding are now direct mobius function mappings and not scripts. There is already a screenshot of the binding in the v1.5 section of the instructable.

0
ZealotC
ZealotC

Reply 4 months ago

Thanks, found it. (Same guy from different account)

0
patricklouiebookings
patricklouiebookings

Question 5 months ago

hi again, sorry for all the questions but i reslly suck at programming

i have now added a fourth track and it is working.
stop all start all sort of works but if i mute/pause a track then start all the muted track is still muted. can you change the code so that no matter what tracks are on of off, when i press stop all then start all all tracks(or leds as im gonna use my own scripts so i just need all the leds to turn green and the arduino to send a midi note).

the second thing i want to change is that when i first start the loop (hit track one) when i hit it again it goes into play track, not overdub track(the track led turns green, not red. i want the led to stay red, but only track one on the first 2 presses). is this possible?

number three is that i dont want all leds to turn on when i first start the loop. i only want the track 1 led to turn red upon starting a loop. is this possible?

if you can write/change the code for me i'll send you 20 bucks on paypal as i have wasted so much time on these problems and i have given up haha. i will put the code i have modded in here. i figured that as you wrote the code you would know what to change and it would prob be a piece of cake for you


#include <MIDI.h>
/*
* FILE : looper_pedal_midi_v1.5.ino
* AUTHOR : Matt Joseph
* DATE : 6/27/2020
* VERSION : 1.5
*
*
* DESCRIPTION
* https://www.instructables.com/id/DIY-Chewie-Monsta-Looper-Based-on-Ed-Sheerans/
*
*
*
* REV HISTORY
* 1.0) Initial release per description
* 1.1) Added volume control functionality
* 1.2) Added bit shift latching function for button reads
* Updated MIDI command values for each output
* 1.3) release date 8/20/2018
* Added "UNDO" function to "CLEAR" button
* Short press (<1000ms) activates "UNDO"
* Long press (>=1000ms) activates "CLEAR"
* 1.3a) release date 8/23/2019 (Claudio Cas)
* Added code for debounce button press without using delay() in mail loop: improve responsiveness of button (more precise loop start and close)
* default value is 60ms, you can tweak changing the minRetriggerTime variable
* 1.4) release date 8/26/2019
* Minor updates to release 1.3a changes
* 1.5) release date TBD
* Moved all loop playback logic from Mobius scripts to Arduino code
* added logic to "ARM" tracks for unmuting
*/
#define NUM_BUTTONS 8
#define NUM_TRACKS 4
#define OFF 0
#define GREEN 1
#define RED 2
#define AMBER 3
//PIN ASSIGNMENTS
const uint8_t btn_rec_play = 3; //REC-PLAY
const uint8_t btn_reset = 4; //RESET
const uint8_t btn_mult_stop = 5; //MULT-STOP
const uint8_t btn_clear = 6; //CLEAR
const uint8_t btn_track1 = 7; //TRACK 1
const uint8_t btn_track2 = 8; //TRACK 2
const uint8_t btn_track3 = 9; //TRACK 3
const uint8_t btn_track4 = 13; //TRACK 4
const uint8_t btn_mode = 10; //MODE
const uint8_t recLED = 11;
const uint8_t volLED = 12;
const uint8_t t1_green_led = 30;
const uint8_t t1_red_led = 49;
const uint8_t t2_green_led = 23;
const uint8_t t2_red_led = 51;
const uint8_t t3_green_led = 26;
const uint8_t t3_red_led = 53;
const uint8_t t4_green_led = 22;
const uint8_t t4_red_led = 47;
//MIDI values for each function
const uint8_t reset_cmd = 10;
const uint8_t undo_cmd = 11;
const uint8_t clear_cmd = 12;
const uint8_t play_play_cmd = 20;
const uint8_t play_stop_cmd = 21;
const uint8_t play_track_cmd[4] = {22, 23, 24, 25};
const uint8_t restart_track_cmd[4] = {26, 27, 28, 29};
const uint8_t rec_rec_cmd = 30;
const uint8_t rec_mult_cmd = 31;
const uint8_t rec_track_cmd[3] = {32, 33, 34};
const uint8_t vol_track_cmd[3] = {42, 43, 44};
const uint8_t mute_track_cmd[3] = {52, 53, 54};
const uint8_t pause_track_cmd[3] = {72, 73, 74};
const uint8_t buttons[NUM_BUTTONS] = {btn_reset, btn_clear, btn_rec_play, btn_mult_stop, btn_track1, btn_track2, btn_track3, btn_track4};
int mode = 1; // 0=Play, 1=Record, 2=Volume control
int modeValue = 1;
int previousMode = 0;
int previousModeValue = 1;
unsigned long modeLongPress = 0;
unsigned long clearLongPress = 0;
int longPressTime = 1000;
int modeChange = 0;
int modeStateChange = 0;
uint8_t modeBuffer = 0xFF;
uint8_t modeEval = 0xFF;
uint8_t priorModeEval = 0xFF;
uint8_t btnBuffer[NUM_BUTTONS] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
uint8_t btnEval[NUM_BUTTONS] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
uint8_t priorBtnEval[NUM_BUTTONS] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
int track_play_state[4] = {0,0,0,0}; //0=play, 1=mute, 2=arm, 3=record
int track_rec_state[4] = {0,0,0,0}; //0=rec, 1=overdub, 2=play
int rec_mode = 0; //0=reset, 1=record
int play_mode = 0; //0=stopped, 1=playing
int active_track_index = 0;
int active_track[4] = {1,2,3,4};
// Retrigger and debouce
const int minRetriggerTime = 100; //Min millis between 2 button press
unsigned long btnLastPressTime[NUM_BUTTONS] = {0,0,0,0,0,0,0,0};
unsigned long modeLastPressTime = 0;
void setup() {
// Set MIDI baud rate:
//Serial.begin(31250);
// Set baud rate to 38400 for Hairless MIDI
Serial.begin(31250);
// set the LED pins as output:
pinMode(recLED, OUTPUT);
pinMode(volLED, OUTPUT);
// set up the TRACK LEDs
pinMode(t1_green_led, OUTPUT);
pinMode(t1_red_led, OUTPUT);
pinMode(t2_green_led, OUTPUT);
pinMode(t2_red_led, OUTPUT);
pinMode(t3_green_led, OUTPUT);
pinMode(t3_red_led, OUTPUT);
pinMode(t4_green_led, OUTPUT);
pinMode(t4_red_led, OUTPUT);
//Track LEDs are "active-low" so init to HIGH so they are OFF
digitalWrite(t1_green_led, HIGH);
digitalWrite(t1_red_led, HIGH);
digitalWrite(t2_green_led, HIGH);
digitalWrite(t2_red_led, HIGH);
digitalWrite(t3_green_led, HIGH);
digitalWrite(t3_red_led, HIGH);
digitalWrite(t4_green_led, HIGH);
digitalWrite(t4_red_led, HIGH);
// set up buttons, they are "active-low" so set to "PULLUP"
for (int i = 0; i < NUM_BUTTONS; i++){
pinMode(buttons[i], INPUT_PULLUP);
}
pinMode(btn_mode, INPUT_PULLUP);
}
void loop() {
readButtons();
}
/*
* Check if the current press is a valid and not a bounce of signal
* Ignore button press before minRetriggerTime ms
*/
bool retriggerTimeExpired(unsigned long lastPressTime)
{
if(millis() - lastPressTime >= minRetriggerTime)
{
return true;
}else{
return false;
}
}
void readButtons()
{
int i = 0;
int j = 0;
int k = 0;
//check state of MODE button
modeValue = digitalRead(btn_mode); //read current input
modeBuffer = modeBuffer << 1; //shift buffer 1 bit left
bitWrite(modeBuffer, 0, modeValue); //add new sample to buffer
priorModeEval = modeEval; //update last evaluated value of MODE
modeEval = modeBuffer & 0x07; //keep last 3 samples for evaluation (0b00000111)
if ( modeEval == 0x00 && retriggerTimeExpired(modeLastPressTime)) //Evaluated input has at least 3 sequential 0s
{
if (modeEval != priorModeEval) //if evaluated MODE has changed from 1 to 0 for 3 consecutive samples (button pressed)
{
modeChange = 1;
modeLastPressTime = millis();
//Toggle MODE betwee PLAY and REC
if (mode == 0)
{
mode = 1;
}else{
mode = 0;
}
}else if(millis() - modeLongPress >= longPressTime) //if evaluated MODE has stayed 0 for at least "longPressTime" (1000ms)
{
//Set MODE to VOL_CTL
if(mode != 2)
{
mode = 2;
modeChange = 1;
}
}
}else if(modeEval == 0x07){ //If evaulated MODE is 1 for 3 consecutive samples (button not pressed)
//logic to reset the timer for vol mode
modeLongPress = millis(); //reset the timer for when MODE was pressed to current time
modeChange = 0;
}
//light record LED if in Record mode
if (mode == 1)
{
digitalWrite(recLED, HIGH);
}else{
digitalWrite(recLED, LOW);
}
//light volume control LED if in Volume Control mode
if (mode == 0)
{
digitalWrite(volLED, HIGH);
}else{
digitalWrite(volLED, LOW);
}
//Read remaining buttons
memcpy(priorBtnEval, btnEval, NUM_BUTTONS*sizeof(uint8_t)); //save copy of last button evaluated values
//Read the rest of the buttons
for (int i = 0; i < NUM_BUTTONS; i++)
{
btnBuffer[i] = btnBuffer[i] << 1; //shift buffer 1 bit left
bitWrite(btnBuffer[i], 0, digitalRead(buttons[i])); //add new sample to buffer
btnEval[i] = btnBuffer[i] & 0x07; //keep last 3 samples for evaluation
}
//send midi for mode button on state change
if (modeChange == 1)
{
//Reset modeChange flag
modeChange = 0;
//If in play or vol ctrl mode send midi cmd to stop any active recording
if(mode==0){
for(k=0;k<NUM_TRACKS;k++){
track_rec_state[k] = 2;
if(track_play_state[k] != 1){
track_play_state[k] = 0;
sendCmd(1, play_track_cmd[k], 127);
if(rec_mode == 1){
setTrackLED(k, GREEN);
}
}
}
}else if(mode==2){
for(k=0;k<NUM_TRACKS;k++){
track_rec_state[k] = 2;
if(track_play_state[k] != 1){
track_play_state[k] = 0;
sendCmd(1, play_track_cmd[k], 127);
if(rec_mode == 1){
setTrackLED(k, GREEN);
}
}
}
}else{
//sendCmd(1, rec_rec_cmd, 127);
}
}
//Check button status and send correct MIDI Command
//RESET and CLEAR buttons do not depend on MODE.
//Logic for RESET button
if (btnEval[0] == 0 && retriggerTimeExpired(btnLastPressTime[0])){
if(btnEval[0] != priorBtnEval[0]) {
sendCmd(1, reset_cmd, 127);
for(k=0;k<NUM_TRACKS;k++){
//clear the track states
track_play_state[k] = 0;
track_rec_state[k] = 0;
//Set track LEDs to OFF
setTrackLED(k, OFF);
}
rec_mode = 0;
play_mode = 0;
}
btnLastPressTime[0] = millis();
}
//Logic for CLEAR button
if (btnEval[1] == 0 && retriggerTimeExpired(btnLastPressTime[1])){
//handle short press
if(btnEval[1] != priorBtnEval[1]){
sendCmd(1, undo_cmd, 127);
btnLastPressTime[1] = millis();
//handle long press
}else if((millis() - clearLongPress) >= longPressTime){
sendCmd(1, clear_cmd, 127);
clearLongPress = millis();
}
}else{
//reset last time clear was pressed
clearLongPress = millis();
}
//Check for button presss and send correct note in Play mode for the rest of the buttons
//Use index 2 for PLAY button
i=2;
if (btnEval[i] == 0 && retriggerTimeExpired(btnLastPressTime[i])){
if(btnEval[i] != priorBtnEval[i]){
if(mode==0){
//bring tracks in and restart the loop from STOP mode
if(play_mode==0){
play_mode=1;
for(j=0; j<NUM_TRACKS; j++){
//Play all tracks in 'ARM' or 'REC' state
if(track_play_state[j]==2 || track_play_state[j]==3){
//Unmute and restart
sendCmd(1, mute_track_cmd[j], 127);
sendCmd(1, restart_track_cmd[j], 127);
track_play_state[j] = 0;
//Set track LED to GREEN
setTrackLED(j,GREEN);
}else if(track_play_state[j]==1){
//Restart the track
sendCmd(1, restart_track_cmd[j], 127);
}
}
}else{ //bring tracks in without restarting the loop
for(j=0; j<NUM_TRACKS; j++){
//Play all tracks in 'ARM' or 'REC' state
if(track_play_state[j]==2 || track_play_state[j]==3){
sendCmd(1, mute_track_cmd[j], 127);
track_play_state[j] = 0;
//Set track LED to GREEN
setTrackLED(j,GREEN);
}
}
}
}else if(mode==1){
//Set tracks previously in REC state to PLAY and change LED to GREEN
for(j=0; j<NUM_TRACKS; j++){
if(track_play_state[j]==3){
//Play all tracks in 'REC' state
track_play_state[j] = 0;
//Set track LED to GREEN
setTrackLED(j,GREEN);
}
}
track_play_state[active_track_index]=3; //Set track mode to REC so that we can change the LED later
if(rec_mode==0){
rec_mode = 1;
play_mode=1;
// REC on all tracks on first loop (from RESET mode)
//The Mobius script handles all tracks so we only need to send one command
sendCmd(1, rec_rec_cmd, 127);
for(k=0;k<NUM_TRACKS;k++){
track_rec_state[k] = 0;
//Set track LEDs to RED
setTrackLED(k, RED);
}
}else if(rec_mode==1){
//Set active track to overdub when prior state was Record, set other tracks to play
if(track_rec_state[active_track_index]==0){
//The Mobius script handles all tracks so we only need to send one command
sendCmd(1, rec_rec_cmd, 127);
for(k=0;k<NUM_TRACKS;k++){
if(k == active_track_index){
track_rec_state[k] = 1;
//SET track LEDs
setTrackLED(k,RED);
}else{
track_rec_state[k] = 2;
//SET track LEDs
setTrackLED(k,GREEN);
}
}
}else if(track_rec_state[active_track_index]==1){
//Set active track to play when prior state was overdub
sendCmd(1, rec_rec_cmd, 127);
track_rec_state[active_track_index] = 2;
//Set LED on active track to GREEN
setTrackLED(active_track_index,GREEN);
}else if(track_rec_state[active_track_index]==2){
//Set active track to overdub when prior state was play
sendCmd(1, rec_rec_cmd, 127);
track_rec_state[active_track_index] = 1;
//Set LED on active track to RED
setTrackLED(active_track_index,RED);
}
}
}
}
btnLastPressTime[i] = millis();
}
//Use index 3 for STOP button
i=3;
if (btnEval[i] == 0 && retriggerTimeExpired(btnLastPressTime[i])){
if(btnEval[i] != priorBtnEval[i]){
if(mode==0){
for(j=0; j<NUM_TRACKS; j++){
if(track_play_state[j]==0){
//Change all tracks in 'PLAY' state to 'ARM' so that they will be started with PLAY is pressed
track_play_state[j] = 2;
//Set track LED to OFF
setTrackLED(j,OFF);
sendCmd(1, mute_track_cmd[j], 127);
}else if(track_play_state[j]==1){
//have to unmute the track before you can pause it
//sendCmd(1, mute_track_cmd[j], 127);
//sendCmd(1, pause_track_cmd[j], 127);
}
}
play_mode=0; //set play_mode to 'stopped' so that tracks will restart when PLAY is pressed;
}else if(mode==1){
sendCmd(1, rec_mult_cmd, 127);
}
}
btnLastPressTime[i] = millis();
}
//Use index 4 for TRACK 1 button
i=4;
j=0;
handleTrackPress(i, j);
//Use index 5 for TRACK 2 button
i=5;
j=1;
handleTrackPress(i, j);
//Use index 6 for TRACK 3 button
i=6;
j=2;
handleTrackPress(i, j);
//Use index 6 for TRACK 3 button
i=7;
j=3;
handleTrackPress(i, j);
delay(10);
}
// Sends a MIDI control command. Doesn't check to see that cmd is greater than 127, or that data values are less than 127:
// first parameter is the event type, combined with the channel.
// Second parameter is the control number number (0-119).
// Third parameter is the control value (0-127).
void sendCmd(int channel, int command, int value) {
Serial.write(0xB0 | (channel-1));
Serial.write(command);
Serial.write(value);
}
void handleTrackPress(int btn_index, int track_index){
int i;
int j;
int k;
i=btn_index;
j=track_index;
if (btnEval[i] == 0 && retriggerTimeExpired(btnLastPressTime[i])){
if(btnEval[i] != priorBtnEval[i]){
active_track_index=j;
if(mode==0){
if(track_play_state[j]==0){
track_play_state[j]=1; //MUTE track
sendCmd(1, mute_track_cmd[j], 127);
//Set track LED to OFF
setTrackLED(j,OFF);
}else if(track_play_state[j]==1){
track_play_state[j]=2; //ARM track
//sendCmd(1, arm_track_cmd[j], 127); //Mobuis doesnt understand 'ARM' so don't sending a midi command
//Set track LED to AMBER
setTrackLED(j,AMBER);
}else{
track_play_state[j]=1; //MUTE track
//sendCmd(1, mute_track_cmd[j], 127);
//Set track LED to OFF
setTrackLED(j,OFF);
}
}else if(mode==1){
if(rec_mode==0){
rec_mode = 1;
play_mode=1;
// REC on all tracks on first loop (from RESET mode)
//The Mobius script handles all tracks so we only need to send one command
sendCmd(1, rec_track_cmd[j], 127);
for(k=0;k<NUM_TRACKS;k++){
track_rec_state[k] = 0;
//Set track LEDs to RED
setTrackLED(k, RED);
}
}else{
//Set track to play when prior state was Record, set other tracks to play
//The Mobius script handles all tracks so we only need to send one command
sendCmd(1, rec_track_cmd[j], 127);
if(track_rec_state[j]==0){
for(k=0;k<NUM_TRACKS;k++){
track_rec_state[k] = 2;
//Set track LEDs to OFF
setTrackLED(k, GREEN);
}
}else if(track_rec_state[j]==1){
//Set track to play when prior state was overdub
track_rec_state[j] = 2;
//Set LED on active track to GREEN
setTrackLED(j,GREEN);
//set non-active tracks to PLAY
for(k=0;k<NUM_TRACKS;k++){
if(k != active_track_index){
track_rec_state[k] = 2;
//Set LED on active track to GREEN
setTrackLED(k,GREEN);
}
}
}else if(track_rec_state[j]==2){
//Set active track to overdub when prior state was play, check if any other track is in overdub and set it to play
track_rec_state[j] = 1;
//Set LED on active track to RED
setTrackLED(j,RED);
//set non-active tracks to PLAY
for(k=0;k<NUM_TRACKS;k++){
if(k != active_track_index){
track_rec_state[k] = 2;
//Set LED on active track to GREEN
setTrackLED(k,GREEN);
}
}
}
}
}else if(mode==2){
//volume control
sendCmd(1, vol_track_cmd[j], 127);
}
}
btnLastPressTime[i] = millis();
}
}
void setTrackLED(int track_index, int color){
//track_index: 0=track1, 1=track2, 2=track3 3=track4
//color: 0=OFF, 1=GREEN, 2=RED, 3=AMBER
//Track 1
if(track_index==0){
if(color==0){
digitalWrite(t1_green_led, HIGH);
digitalWrite(t1_red_led, HIGH);
}else if(color==1){
digitalWrite(t1_green_led, LOW);
digitalWrite(t1_red_led, HIGH);
}else if(color==2){
digitalWrite(t1_green_led, HIGH);
digitalWrite(t1_red_led, LOW);
}else if(color==3){
digitalWrite(t1_green_led, LOW);
digitalWrite(t1_red_led, HIGH);
}else{
digitalWrite(t1_green_led, HIGH);
digitalWrite(t1_red_led, LOW);
}
}else if(track_index==1){
if(color==0){
digitalWrite(t2_green_led, HIGH);
digitalWrite(t2_red_led, HIGH);
}else if(color==1){
digitalWrite(t2_green_led, LOW);
digitalWrite(t2_red_led, HIGH);
}else if(color==2){
digitalWrite(t2_green_led, HIGH);
digitalWrite(t2_red_led, LOW);
}else if(color==3){
digitalWrite(t2_green_led, LOW);
digitalWrite(t2_red_led, HIGH);
}else{
digitalWrite(t2_green_led, HIGH);
digitalWrite(t2_red_led, LOW);
}
}else if(track_index==2){
if(color==0){
digitalWrite(t3_green_led, HIGH);
digitalWrite(t3_red_led, HIGH);
}else if(color==1){
digitalWrite(t3_green_led, LOW);
digitalWrite(t3_red_led, HIGH);
}else if(color==2){
digitalWrite(t3_green_led, HIGH);
digitalWrite(t3_red_led, LOW);
}else if(color==3){
digitalWrite(t3_green_led, LOW);
digitalWrite(t3_red_led, HIGH);
}else{
digitalWrite(t3_green_led, HIGH);
digitalWrite(t3_red_led, LOW);
}
}else if(track_index==3){
if(color==0){
digitalWrite(t4_green_led, HIGH);
digitalWrite(t4_red_led, HIGH);
}else if(color==1){
digitalWrite(t4_green_led, LOW);
digitalWrite(t4_red_led, HIGH);
}else if(color==2){
digitalWrite(t4_green_led, HIGH);
digitalWrite(t4_red_led, LOW);
}else if(color==3){
digitalWrite(t4_green_led, LOW);
digitalWrite(t4_red_led, HIGH);
}else{
digitalWrite(t4_green_led, HIGH);
digitalWrite(t4_red_led, LOW);
}
}else {
//do nothing
}
}


0
MattJ134
MattJ134

Reply 5 months ago

Hi,
Sorry to hear you are having issues. It looks like you did a pretty good job modifying the code to add a 4th track. Im not totally following your issue. It the mute/restart problem only with the new track or with all of them. I noticed that you didnt added a 4th value to the arrays below so I think the code doesn't know what to do when these commands are triggered for track 4. The code works with loops based on the track index so if since you have 4 tracks but only 3 values in the array the code is probably panicking and erroring out when track 4 is activated.

const uint8_t rec_track_cmd[3] = {32, 33, 34};
const uint8_t mute_track_cmd[3] = {52, 53, 54};
const uint8_t pause_track_cmd[3] = {72, 73, 74};

As to your 2nd question, my pedal is designed to go from record to play then to overdub when you use the separate track buttons. if you want to go from record to overdub on the current track then press the play/rec button instead of the track button. If you want to change this so the the track button also goes to overdub then you'd need to modify the "handleTrackPress" function something like this. (WARNING: I HAVE NOT TESTED THIS CODE)

//Set track to play when prior state was Record, set other tracks to play //The Mobius script handles all tracks so we only need to send one command sendCmd(1, rec_track_cmd[j], 127); if(track_rec_state[j]==0){ for(k=0;k<NUM_TRACKS;k++){ track_rec_state[k] = 2; //Set track LEDs to OFF setTrackLED(k, GREEN);
change to

track_rec_state[j] = 1; //Set LED on active track to RED setTrackLED(j,RED); //set non-active tracks to PLAY for(k=0;k<NUM_TRACKS;k++){ if(k != active_track_index){ track_rec_state[k] = 2; //Set LED on active track to GREEN setTrackLED(k,GREEN);

0
patricklouiebookings
patricklouiebookings

Reply 5 months ago

Ok modded all the code. Last question. Is it possible to change the code so that when i stop all the tracks then start them again they all kick on(all the leds go to green). Sometimes If i in playmode pause for exemple track 2 then press stop all. Then play all track track 2 does not turn on. Is it possible to change this so that no matter what all tracks stop on stop and all tracks play on play? As i Said Im gonna use my own scripts so i only need the leds to change

0
MattJ134
MattJ134

Reply 5 months ago

While it is possible, my intent of the v1.5 code was specifically to not do this which is why i added the "ARM" state to each track. You need to put the tracks in "ARM" (amber LED) state in order to unmute them using the "PLAY" button. The function that you are looking for is exactly how the v1.3 Claudias code works. However that code does not have the logic to drive LEDs for the tracks.