Revox A77 reel to reel counter- Autonomous control wth IR Counter

Hi all!

I want to use a reel to reel machine in a sound installation and I need it to be autonomous meaning that it should never run out of tape in the beginning and the end. At the moment I can remote control the machine with MIDI to an Arduino and relay card I built.

I recently saw this video where an IR sensor is used to count rotations Watch Video . I put the code into an Arduino and was able to get that to work.

The next step is to combine the two codes into one which is where I need some help.

I have made a list of events that need to happen but don't know the way to implement the different parts of it together.

Here are my requirements so far:

Global:

  • Predetermined counter number for beginning (0) and end (100).

  • Command to ignore End number when counter is going backwards. (So the machine will not stop at the end counter number if rewinding)

  • Whenever REW command is activated, counter changes to count backwards.

  • Whenever PLAY, REC, FF commands are activated counter counts forwards.

When end number is reached:
All incoming MIDI commands are ignored.
STOP command is sent.
REW command is sent.

When beginning number is reached:
Stop command is sent.
FF command is sent (Machine should stop again as it reaches 0)
MIDI commands can now control Arduino.

Below is my code so far. I have basically meshed the two codes but the additional functions still need to be implemented. Any help or advice on any part of this code would be great. Thanks!


#include <MIDI.h> // Add Midi Library
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Define labels for the 12 pins
#define REW 2
#define FF 3
#define PLAY 4
#define STOP 5
#define REC 6

//LCD
long x = 0;
int input = A0;
int state = 0;

LiquidCrystal_I2C lcd(0x3F, 16, 2); // set the LCD address to 0x3F for a 16 chars and 2 line display


//Create an instance of the library with default name, serial port and settings
MIDI_CREATE_DEFAULT_INSTANCE();

//Incoming midi messages to be output pin 2-6 when receiving noteON message with note = 60-65
// Buttons to output notes from Midi Out to be recorded in DAW sequencer.
// Midi Note 60 (Rewind), 61 (FF), 62 (Play), 63 (Stop), 64 (Rec)

void setup() {
  
  pinMode (REW, OUTPUT); 
  pinMode (FF, OUTPUT); 
  pinMode (PLAY, OUTPUT); 
  pinMode (STOP, OUTPUT); 
  pinMode (REC, OUTPUT); 
  
  MIDI.begin(13); // Initialize the Midi Library. Respond to notes on channel 13 only.
  
  MIDI.setHandleNoteOn(Press); 
  MIDI.setHandleNoteOff(Release);  

//LCD  
  lcd.init(); // initialize the lcd

  // Print a message to the LCD.
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("  Turn counter ");
  lcd.setCursor(0, 1);
  lcd.print("        =turn  ");
  
}

void loop() { // Main loop
  MIDI.read(); // Continuously check if Midi data has been received
  
  int counter = digitalRead(A0); //Counter
  if (state == 0)
  {
    switch (counter) {

      case 1 : state = 1; lcd.setCursor (0, 1); x = x + 1; lcd.print(x); break;
      case 0 : state = 0; break;

    }
  }

  if (counter == LOW) {
    state = 0;
  }
}

// Press is the function that will be called by the Midi Library
// when a MIDI NOTE ON message is received.
// It will be passed bytes for Channel, Pitch, and Velocity

void Press (byte channel, byte pitch, byte velocity) {  
  if (pitch == 60 ){ 
    digitalWrite(REW,HIGH);  // Send on pin 2 
  }
  if (pitch == 61){
    digitalWrite(FF,HIGH);  // Send on pin 3
  }
  if (pitch == 62){
    digitalWrite(PLAY,HIGH);// Send on pin 4
  }
  if (pitch == 63){
    digitalWrite(STOP,HIGH);  // Send on pin 5
  }
  if (pitch == 64){
    digitalWrite(REC,HIGH); 
    digitalWrite(PLAY,HIGH);// Send on pin 4, 6
  }
}
  
// Release is the function that will be called by the Midi Library
// when a MIDI NOTE OFF message is received.
// * A NOTE ON message with Velocity = 0 will be treated as a NOTE OFF message *
// It will be passed bytes for Channel, Pitch, and Velocity

void Release (byte channel, byte pitch, byte velocity){  
  
  if (pitch== 60){
    digitalWrite(REW,LOW);  // Stop send on pin 2
  }
   if (pitch== 61){
    digitalWrite(FF,LOW);  // Stop send on pin 3
  }
   if (pitch == 62){
    digitalWrite(PLAY,LOW);// Stop send on pin 4
  } 
   if (pitch == 63){
    digitalWrite(STOP,LOW);  // Stop send on pin 5
  }
   if (pitch == 64){
    digitalWrite(REC,LOW);
    digitalWrite(PLAY,LOW);// Stop send on pin 4 AND 6
  }    
}
 
1 Like

the above seems very convoluted. why not compare "counter" to it's previous value (e.g. counterLst) and increment "x" when it changes from low to high.

    static int counterLst = 0;
           int counter    = digitalRead(A0);

    if (counterLst != counter)  {
        counterLst = counter;
        if (HIGH == counter)
            x++:
    }

Thanks gcjr! Works great! Here is the link to the test video

So to make this project easier think about, I think phasing it out into smaller chunks would make it easier to approach.

So the next chunk I am working on would be to make the counter go forwards or backwards depending on what MIDI message is received. This would make it into a regular digital counter that anyone could setup and use in their machines and is really the foundation of this project.

So when note on 60 is received (rewind) x=x-1 should be substituted in the counter code.
When note on 61,62,64 is received (FF, Play, Rec) x=x+1 should be substituted in the counter code.

I have been playing around with this and I havent figured out how to substitute an equation in a part of code. Any advice would be great! Thanks!

Below is the current code with the simpler counter code for reference:


#include <MIDI.h> // Add Midi Library
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Define labels for the 12 pins
#define REW 2
#define FF 3
#define PLAY 4
#define STOP 5
#define REC 6

//LCD
long x = 0;
int input = A0;
int state = 0;



LiquidCrystal_I2C lcd(0x3F, 16, 2); // set the LCD address to 0x3F for a 16 chars and 2 line display

int tapeBegin= 0;
int tapeEnd= 50;

//Create an instance of the library with default name, serial port and settings
MIDI_CREATE_DEFAULT_INSTANCE();

//Incoming midi messages to be output pin 2-6 when receiving noteON message with note = 60-65
// Buttons to output notes from Midi Out to be recorded in DAW sequencer.
// Midi Note 60 (Rewind), 61 (FF), 62 (Play), 63 (Stop), 64 (Rec)

void setup() {
  
  pinMode (REW, OUTPUT); 
  pinMode (FF, OUTPUT); 
  pinMode (PLAY, OUTPUT); 
  pinMode (STOP, OUTPUT); 
  pinMode (REC, OUTPUT); 
  
  MIDI.begin(13); // Initialize the Midi Library. Respond to notes on channel 13 only.
  
  MIDI.setHandleNoteOn(Press); 
  MIDI.setHandleNoteOff(Release);  

//LCD  
  lcd.init(); // initialize the lcd

  // Print a message to the LCD.
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("  Turn counter ");
  lcd.setCursor(0, 1);
  lcd.print("        =turn  ");
  
}

void loop() { // Main loop
  MIDI.read(); // Continuously check if Midi data has been received

static int counterLst = 0;
           int counter    = digitalRead(A0);

    if (counterLst != counter)  {
        counterLst = counter;
        if (HIGH == counter)
            x++;
            lcd.setCursor (0, 1);
            lcd.print(x);
    } 
}

// Press is the function that will be called by the Midi Library
// when a MIDI NOTE ON message is received.
// It will be passed bytes for Channel, Pitch, and Velocity

void Press (byte channel, byte pitch, byte velocity) {  
  if (pitch == 60 ){ 
    digitalWrite(REW,HIGH);// Send on pin 2 
  }
  if (pitch == 61){
    digitalWrite(FF,HIGH);  // Send on pin 3
  }
  if (pitch == 62){
    digitalWrite(PLAY,HIGH);// Send on pin 4
  }
  if (pitch == 63){
    digitalWrite(STOP,HIGH);  // Send on pin 5
  }
  if (pitch == 64){
    digitalWrite(REC,HIGH); 
    digitalWrite(PLAY,HIGH);// Send on pin 4, 6
  }
}
  
// Release is the function that will be called by the Midi Library
// when a MIDI NOTE OFF message is received.
// * A NOTE ON message with Velocity = 0 will be treated as a NOTE OFF message *
// It will be passed bytes for Channel, Pitch, and Velocity

void Release (byte channel, byte pitch, byte velocity){  
  
  if (pitch== 60){
    digitalWrite(REW,LOW);  // Stop send on pin 2
  }
   if (pitch== 61){
    digitalWrite(FF,LOW);  // Stop send on pin 3
  }
   if (pitch == 62){
    digitalWrite(PLAY,LOW);// Stop send on pin 4
  } 
   if (pitch == 63){
    digitalWrite(STOP,LOW);  // Stop send on pin 5
  }
   if (pitch == 64){
    digitalWrite(REC,LOW);
    digitalWrite(PLAY,LOW);// Stop send on pin 4 AND 6
  }    
}
 

Ok so in order to make the counter go forwards while activating the FF, PLAY, and REC pins and backward by activating the REW pin, I have been trying different things modifying the counter code within the Loop function usually with the results being the counter advancing continuously positive or advancing continuously negative regardless of what pin is HIGH.

The following counter code (in loop) illustrates what I want to do but now the counter doesn't move.

How should I be thinking about this?


#include <MIDI.h> // Add Midi Library
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Define labels for the 12 pins
#define REW 2
#define FF 3
#define PLAY 4
#define STOP 5
#define REC 6

//LCD
long x = 0;
int input = A0;
int state = 0;



LiquidCrystal_I2C lcd(0x3F, 16, 2); // set the LCD address to 0x3F for a 16 chars and 2 line display

//Counter variables Beginning & End

int tapeBegin= 0;
int tapeEnd= 50;

//Create an instance of the library with default name, serial port and settings
MIDI_CREATE_DEFAULT_INSTANCE();

//Incoming midi messages to be output pin 2-6 when receiving noteON message with note = 60-65
// Buttons to output notes from Midi Out to be recorded in DAW sequencer.
// Midi Note 60 (Rewind), 61 (FF), 62 (Play), 63 (Stop), 64 (Rec)

void setup() {
  
  pinMode (REW, OUTPUT); 
  pinMode (FF, OUTPUT); 
  pinMode (PLAY, OUTPUT); 
  pinMode (STOP, OUTPUT); 
  pinMode (REC, OUTPUT); 
  
  MIDI.begin(13); // Initialize the Midi Library. Respond to notes on channel 13 only.
  
  MIDI.setHandleNoteOn(Press); 
  MIDI.setHandleNoteOff(Release);  

//LCD  
  lcd.init(); // initialize the lcd

  // Print a message to the LCD.
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("  Turn counter ");
  lcd.setCursor(0, 1);
  lcd.print("        =turn  ");
  
}

void loop() { // Main loop
  MIDI.read(); // Continuously check if Midi data has been received
 
  static int counterLst = 0;
         
           int counter    = digitalRead(A0);
   if (counterLst != counter)  {
        counterLst = counter;
        if (HIGH == counter && FF==HIGH || PLAY == HIGH || REC == HIGH);
            x++;
        if (HIGH==counter && REW==HIGH);
            x--;
     
            lcd.setCursor (0, 1);
            lcd.print(x);
   }
}

// Press is the function that will be called by the Midi Library
// when a MIDI NOTE ON message is received.
// It will be passed bytes for Channel, Pitch, and Velocity

void Press (byte channel, byte pitch, byte velocity) {  
  if (pitch == 60 ){ 
    digitalWrite(REW,HIGH);// Send on pin 2 
  }
  if (pitch == 61){
    digitalWrite(FF,HIGH);  // Send on pin 3
  }
  if (pitch == 62){
    digitalWrite(PLAY,HIGH);// Send on pin 4
  }
  if (pitch == 63){
    digitalWrite(STOP,HIGH);  // Send on pin 5
  }
  if (pitch == 64){
    digitalWrite(REC,HIGH); 
    digitalWrite(PLAY,HIGH);// Send on pin 4, 6
  
   }  
}
  
// Release is the function that will be called by the Midi Library
// when a MIDI NOTE OFF message is received.
// * A NOTE ON message with Velocity = 0 will be treated as a NOTE OFF message *
// It will be passed bytes for Channel, Pitch, and Velocity

void Release (byte channel, byte pitch, byte velocity){  
  
  if (pitch== 60){
    digitalWrite(REW,LOW);  // Stop send on pin 2
  }
   if (pitch== 61){
    digitalWrite(FF,LOW);  // Stop send on pin 3
  }
   if (pitch == 62){
    digitalWrite(PLAY,LOW);// Stop send on pin 4
  } 
   if (pitch == 63){
    digitalWrite(STOP,LOW);  // Stop send on pin 5
  }
   if (pitch == 64){
    digitalWrite(REC,LOW);
    digitalWrite(PLAY,LOW);// Stop send on pin 4 AND 6
  }    
}
 

does it matter which button was pressed? shouldn't the count values depend solely on the movement of the counter?

might consider a single function, instead of 2

    state = on == "midi note" ? HIGH : LOW;

    switch (press)  {
    case 60:
        digitalWrite (REW, state);
        break;
    case 61:
        digitalWrite (FF, state);
        break;
    case 62:
        digitalWrite (PLAY, state);
        break;
    case 63:
        digitalWrite (STOP, state);
        break;
    case 64:
        digitalWrite (REC, state);
        digitalWrite (PLAY, state);
        break;
    }

At the moment, the digital counter only goes 1 way either, x++ or x-- whatever is specified in the original counter code. I thought about using the button press to activate either + or - direction of the counter. The REW button is the only button with a negative counter.

state = on == "midi note" ? HIGH : LOW;

    switch (press)  {
    case 60:
        x--;
        digitalWrite (REW, state);
        break;
    case 61:
        x++;
        digitalWrite (FF, state);
        break;
    case 62:
        x++;
        digitalWrite (PLAY, state);
        break;
    case 63:
        digitalWrite (STOP, state);
        break;
    case 64:
        x++;
        digitalWrite (REC, state);
        digitalWrite (PLAY, state);
        break;
    }

HI Greg, I see the logic now. How would I integrate this into my code? I am assuming it would go after the counter code? I was experimenting with the code below, am I on the right track?
Thank you for your patience.

void loop() { // Main loop
  MIDI.read(); // Continuously check if Midi data has been received
 
  static int counterLst = 0;
         
           int counter    = digitalRead(A0);
if (counterLst != counter)  {
        counterLst = counter;
        if (HIGH == counter)
        
if (state==Press)

    switch (counter)  {
    case 60:
    x--;
        digitalWrite (REW, state);
        break;
    case 61:
    x++;
        digitalWrite (FF, state);
        break;
    case 62:
    x++;
        digitalWrite (PLAY, state); 
        break;
    case 63:
    x++;
        digitalWrite (STOP, state);
        break;
    case 64:
    x++;
        digitalWrite (REC, state);
        digitalWrite (PLAY, state);
        break;
    }
     
            lcd.setCursor (0, 1);
            lcd.print(x);
}
}

// Press is the function that will be called by the Midi Library
// when a MIDI NOTE ON message is received.
// It will be passed bytes for Channel, Pitch, and Velocity

void Press (byte channel, byte pitch, byte velocity) {  
  if (pitch == 60 ){ 
    digitalWrite(REW,HIGH);// Send on pin 2 
  }

i'm just glancing at this. i think you need to keep track (set a flag) of which direction the button causes the tape to move it and depending on that flag update the count in the proper direction, not just when a button is pressed (my mistake)

Ok so I figured out how to make the counter go backwards and forwards, but only one time. For example, if I press FF, the counter goes forwards. If I press REW, the counter goes backwards, If I press FF, again the counter counts backwards.

Perhaps the pressing Stop button can initialize the flag states? How would I do that?

What am I missing?



#include <MIDI.h> // Add Midi Library
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Define labels for the 12 pins
#define REW 2
#define FF 3
#define PLAY 4
#define STOP 5
#define REC 6

//LCD
long x = 0;
int input = A0;


//Flags
int flagRew;
int flagFf;
int flagPlay;
int flagStop;
int flagRec;

LiquidCrystal_I2C lcd(0x3F, 16, 2); // set the LCD address to 0x3F for a 16 chars and 2 line display

//Counter variables Beginning & End

int tapeBegin = 0;
int tapeEnd = 50;

//Create an instance of the library with default name, serial port and settings
MIDI_CREATE_DEFAULT_INSTANCE();

//Incoming midi messages to be output pin 2-6 when receiving noteON message with note = 60-65
// Buttons to output notes from Midi Out to be recorded in DAW sequencer.
// Midi Note 60 (Rewind), 61 (FF), 62 (Play), 63 (Stop), 64 (Rec)

void setup() {
  pinMode (REW, OUTPUT); 
  pinMode (FF, OUTPUT); 
  pinMode (PLAY, OUTPUT); 
  pinMode (STOP, OUTPUT); 
  pinMode (REC, OUTPUT); 
  
  MIDI.begin(13); // Initialize the Midi Library. Respond to notes on channel 13 only.
  
  MIDI.setHandleNoteOn(Press); 
  MIDI.setHandleNoteOff(Release);  

//LCD  
  lcd.init(); // initialize the lcd

  // Print a message to the LCD.
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("  Turn counter ");
  lcd.setCursor(0, 1);
  lcd.print("        =turn  ");

int flagRew = 0;
int flagFf = 0;
int flagPlay = 0;
int flagStop = 0;
int flagRec = 0;

}

void loop() { // Main loop
MIDI.read(); // Continuously check if Midi data has been received

static int counterLst = 0;

int counter = digitalRead(A0);

  if (flagRew == 1){
    if (counterLst != counter)  {
        counterLst = counter;
        if(HIGH == counter)
          x--;
    }
  }
   if (flagFf == 1) {
    if (counterLst != counter)  {
        counterLst = counter;
        if(HIGH == counter)
          x++;
    }
  }
  if (flagPlay == 1) {
    if (counterLst != counter)  {
        counterLst = counter;
        if(HIGH == counter)
          x++;
    }
  }
  if (flagRec == 1) {
    if (counterLst != counter)  {
        counterLst = counter;
        if(HIGH == counter)
          x++; 
    } 
  }   
  lcd.setCursor (0, 1);
  lcd.print(x);
}

// Press is the function that will be called by the Midi Library
// when a MIDI NOTE ON message is received.
// It will be passed bytes for Channel, Pitch, and Velocity

void Press (byte channel, byte pitch, byte velocity) {  
  if (pitch == 60 ){ 
    digitalWrite(REW,HIGH);// Send on pin 2 
    flagRew = 1;
  }
  if (pitch == 61){
    digitalWrite(FF,HIGH);  // Send on pin 3
    flagFf = 1;
  }
  if (pitch == 62){
    digitalWrite(PLAY,HIGH);// Send on pin 4
    flagPlay = 1;
  }
  if (pitch == 63){
    digitalWrite(STOP,HIGH);  // Send on pin 5
     flagStop = 1;
  }
  if (pitch == 64){
    digitalWrite(REC,HIGH); 
    digitalWrite(PLAY,HIGH);// Send on pin 4, 6
    flagRec = 1;
  }  
}
  
// Release is the function that will be called by the Midi Library
// when a MIDI NOTE OFF message is received.
// * A NOTE ON message with Velocity = 0 will be treated as a NOTE OFF message *
// It will be passed bytes for Channel, Pitch, and Velocity

void Release (byte channel, byte pitch, byte velocity){  
  if (pitch == 60){
    digitalWrite(REW,LOW);  // Stop send on pin 2
  }
   if (pitch== 61){
    digitalWrite(FF,LOW);  // Stop send on pin 3
  }
   if (pitch == 62){
    digitalWrite(PLAY,LOW);// Stop send on pin 4
  } 
   if (pitch == 63){
    digitalWrite(STOP,LOW);  // Stop send on pin 5
  }
   if (pitch == 64){
    digitalWrite(REC,LOW);
    digitalWrite(PLAY,LOW);// Stop send on pin 4 AND 6
  }    
}
 

you should have a single flag that determines the direction, not one for each button.

in loop(), there should be just 2 cases: flag set or the else case

in your current code, where is flagRew ever cleared to zero.

Ok I think I got it. Thank you so much for your guidance! Here is a video of it in action

Now onto the last phase and the one that will complete this program. At predetermined beginning and end counter values, when the machine reaches the tapeEnd value it will automatically REW back to the tapeBegin value.

Any advice on how to approach this would be much appreciated!

Thanks again!


#include <MIDI.h> // Add Midi Library
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Define labels for the 12 pins
#define REW 2
#define FF 3
#define PLAY 4
#define STOP 5
#define REC 6

//LCD
long x = 0;
int input = A0;

//Flags
int flag;

LiquidCrystal_I2C lcd(0x3F, 16, 2); // set the LCD address to 0x3F for a 16 chars and 2 line display

//Counter variables Beginning & End

int tapeBegin = 0;
int tapeEnd = 50;

//Create an instance of the library with default name, serial port and settings
MIDI_CREATE_DEFAULT_INSTANCE();

//Incoming midi messages to be output pin 2-6 when receiving noteON message with note = 60-65
// Buttons to output notes from Midi Out to be recorded in DAW sequencer.
// Midi Note 60 (Rewind), 61 (FF), 62 (Play), 63 (Stop), 64 (Rec)

void setup() {
  pinMode (REW, OUTPUT); 
  pinMode (FF, OUTPUT); 
  pinMode (PLAY, OUTPUT); 
  pinMode (STOP, OUTPUT); 
  pinMode (REC, OUTPUT); 
  
  MIDI.begin(13); // Initialize the Midi Library. Respond to notes on channel 13 only.
  
  MIDI.setHandleNoteOn(Press); 
  MIDI.setHandleNoteOff(Release);  

//LCD  
  lcd.init(); // initialize the lcd

  // Print a message to the LCD.
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("  Turn counter ");
  lcd.setCursor(0, 1);
  lcd.print("        =turn  ");
}

void loop() { // Main loop
MIDI.read(); // Continuously check if Midi data has been received

int counterDirection;
static int counterLst = 0;

int counter = digitalRead(A0);

    if (counterLst != counter) {
        counterLst = counter;
        if (HIGH == counter)
          
          switch(flag) {
            case 1:
              x--;
              break;
            case 0:
              x++;
              break;
          }
    lcd.setCursor (0, 1);
    lcd.print(x);
    }
}

// Press is the function that will be called by the Midi Library
// when a MIDI NOTE ON message is received.
// It will be passed bytes for Channel, Pitch, and Velocity

void Press (byte channel, byte pitch, byte velocity) {  
  if (pitch == 60 ){ 
    digitalWrite(REW,HIGH);// Send on pin 2 
    flag=1;
  }
  if (pitch == 61){
    digitalWrite(FF,HIGH);  // Send on pin 3
    flag=0;
  }
  if (pitch == 62){
    digitalWrite(PLAY,HIGH);// Send on pin 4
    flag=0;
  }
  if (pitch == 63){
    digitalWrite(STOP,HIGH);  // Send on pin 5
    flag=0;
  }
  if (pitch == 64){
    digitalWrite(REC,HIGH); 
    digitalWrite(PLAY,HIGH);// Send on pin 4, 6
    flag=0;
  }  
}
  
// Release is the function that will be called by the Midi Library
// when a MIDI NOTE OFF message is received.
// * A NOTE ON message with Velocity = 0 will be treated as a NOTE OFF message *
// It will be passed bytes for Channel, Pitch, and Velocity

void Release (byte channel, byte pitch, byte velocity){  
  if (pitch== 60){
    digitalWrite(REW,LOW);  // Stop send on pin 2
  }
   if (pitch== 61){
    digitalWrite(FF,LOW);  // Stop send on pin 3
  }
   if (pitch == 62){
    digitalWrite(PLAY,LOW);// Stop send on pin 4
  } 
   if (pitch == 63){
    digitalWrite(STOP,LOW);  // Stop send on pin 5
  }
   if (pitch == 64){
    digitalWrite(REC,LOW);
    digitalWrite(PLAY,LOW);// Stop send on pin 4 AND 6
  }    
}
 

it sounds like you always want this to happen, that is there is nothing that enables it.

if so, in loop(), after updating the count, check if it reaches that max value and set another Rewind flag and whatever is necessary to rewind the tape.

while in that mode, monitor the count to see when it reaches the stop point and stop the tape when reached and clear the Rewind flag

instead of "flag", set a "dir" variable to either 1 or -1 and simply add that to x: x += dir; instead of all that logic

1 Like

Sorry just read your post again. Will try your suggestions for the automation. Thanks

Ok so I have been trying this for a several hours and need some more help. I can get the machine to stop when it reaches the tapeEnd value. But I need it to stop for a few seconds (4 sec) before activating rewind to let the tape stop turning.

I have been trying to use millis() but haven't successfully integrated it. As soon as it reaches tapeEnd both STOP and REW seem to engage and the machine doesn't stop. What am I missing?

void loop() { // Main loop
MIDI.read(); // Continuously check if Midi data has been received
//Counter variables Beginning & End
int tapeBegin = 100;
int tapeEnd = 160;

//millis
unsigned long previousTime=0;
unsigned long tapeWait1=4000;

unsigned long currentTime= millis();

int counterDirection;
static int counterLst = 0;
int counter = digitalRead(A0);

    if (counterLst != counter) {
        counterLst = counter;
        if (HIGH == counter)
         
          switch(flag) {
            case 1:
              x--;
              break;
            case 0:
              x++;
              break;
          }
          
    if (x >= tapeEnd){
      digitalWrite (STOP,HIGH);
      if (currentTime - previousTime >= tapeWait1){
        digitalWrite (REW,HIGH);
        flag=1;
      } 
   }       
  }          
      lcd.setCursor (0, 1);
    lcd.print(x);
}

do you really need 4 sec?

assuming you don't need to do anything else, hence the reason for using millis(), why not just add a 1 sec delay after stopping and before rewinding? (do you even need to stop)?

4 sec can be adjusted as needed per machine. This value is the maximum time it takes for the reels to stop turning after stop is pressed.

Another detail is that the way the tape machine activates is via a relay board that is activated by the Arduino. To activate Rewind for example, I need to open the 'REW' relay then close the relay. in order to be able to activate another button. So a (REW, HIGH) would need to be followed by a (REW,LOW) after 100 ms or so which kind of complicates things a little.

In this version of code, if I add a delay, the counter stops counting at my tapeEnd value.

What I need to happen is as soon as the counter reaches the tapeEnd value, it activates (STOP, HIGH), delay (or millis() timer), (STOP, LOW). Wait 4 sec for the reels to stop turning. Then activate (REW,HIGH), delay, (REW,LOW) to go back to the tapeBegin value. All while not interrupting the counter. Phew!

At the moment, I cannot figure it out. What's the first step?

Thanks!


#include <MIDI.h> // Add Midi Library
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Define labels for the 12 pins
#define REW 2
#define FF 3
#define PLAY 4
#define STOP 5
#define REC 6

//LCD
long x = 130;
int input = A0;

//Flags
int flag;

//Tape Begin and End Values
int tapeBegin = 120;
int tapeEnd = 150;

LiquidCrystal_I2C lcd(0x3F, 16, 2); // set the LCD address to 0x3F for a 16 chars and 2 line display

//Create an instance of the library with default name, serial port and settings
MIDI_CREATE_DEFAULT_INSTANCE();

//Incoming midi messages to be output pin 2-6 when receiving noteON message with note = 60-65
// Buttons to output notes from Midi Out to be recorded in DAW sequencer.
// Midi Note 60 (Rewind), 61 (FF), 62 (Play), 63 (Stop), 64 (Rec)

void setup() {
  pinMode (REW, OUTPUT);
  pinMode (FF, OUTPUT);
  pinMode (PLAY, OUTPUT);
  pinMode (STOP, OUTPUT);
  pinMode (REC, OUTPUT);

  MIDI.begin(13); // Initialize the Midi Library. Respond to notes on channel 13 only.

  MIDI.setHandleNoteOn(Press);
  MIDI.setHandleNoteOff(Release);

  //LCD
  lcd.init(); // initialize the lcd

  // Print a message to the LCD.
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("  Turn counter ");
  lcd.setCursor(0, 1);
  lcd.print("        =turn  ");

  int flag = 0;
}

void loop() { // Main loop
  MIDI.read(); // Continuously check if Midi data has been received
  //Counter variables Beginning & End

  int counterDirection;
  //Counter Loop
  static int counterLst = 0;
  int counter = digitalRead(A0);
  if (counterLst != counter) {
    counterLst = counter;
    if (HIGH == counter)
      switch (flag) {
        case 1:
          x--;
          break;
        case 0:
          x++;
          break;
      }
  }
  if (x >= tapeEnd) {
    digitalWrite (STOP, HIGH);
    delay (500);
    digitalWrite (STOP, LOW);
  }
  lcd.setCursor (0, 1);
  lcd.print(x);
}

// Press is the function that will be called by the Midi Library
// when a MIDI NOTE ON message is received.
// It will be passed bytes for Channel, Pitch, and Velocity

void Press (byte channel, byte pitch, byte velocity) {
  if (pitch == 60 ) {
    digitalWrite(REW, HIGH); // Send on pin 2
    flag = 1;
  }
  if (pitch == 61) {
    digitalWrite(FF, HIGH); // Send on pin 3
    flag = 0;
  }
  if (pitch == 62) {
    digitalWrite(PLAY, HIGH); // Send on pin 4
    flag = 0;
  }
  if (pitch == 63) {
    digitalWrite(STOP, HIGH); // Send on pin 5
    flag = 0;
  }
  if (pitch == 64) {
    digitalWrite(REC, HIGH);
    digitalWrite(PLAY, HIGH); // Send on pin 4, 6
    flag = 0;
  }
}

// Release is the function that will be called by the Midi Library
// when a MIDI NOTE OFF message is received.
// * A NOTE ON message with Velocity = 0 will be treated as a NOTE OFF message *
// It will be passed bytes for Channel, Pitch, and Velocity

void Release (byte channel, byte pitch, byte velocity) {
  if (pitch == 60) {
    digitalWrite(REW, LOW); // Stop send on pin 2
  }
  if (pitch == 61) {
    digitalWrite(FF, LOW); // Stop send on pin 3
  }
  if (pitch == 62) {
    digitalWrite(PLAY, LOW); // Stop send on pin 4
  }
  if (pitch == 63) {
    digitalWrite(STOP, LOW); // Stop send on pin 5
  }
  if (pitch == 64) {
    digitalWrite(REC, LOW);
    digitalWrite(PLAY, LOW); // Stop send on pin 4 AND 6
  }
}

it seems you need a stop() sub-function: STOP HIGH, delay (100), STOP LOW and probably another delay (100) that needs to be called before Play, FF, Rew, as well as when a Stop cmd is received

sounds like you don't have a specific mode to rewind the tape, you simply do it when tapeEnd is reached.

perhaps you should have a autoRewind flag that is set when tapeEnd is reached along with calling stop() and then REW HIGH.

there's a 3rd if condition under loop() for autoRewind in which the code monitors for tapeBegin, at which point it executes stop() and clears the autoRewind flag

Well, I kind of figured it out. The automation works and the counter goes the correct direction, but every time the counter hits tapeEND or tapeBegin, it stops at that value (120 or 150) and doesn't count the revolutions after stop has been pressed during the automation.

Is there any way to let the counter keep going after stop is pressed during the automation? It seems to be the (x>tapeEnd) (x<tapeBegin) statements that make the counter stop counting. Could it also be the delays that are messing with the counter?

During normal operation, the counter keeps counting after the stop button is pressed.


#include <MIDI.h> // Add Midi Library
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Define labels for the 12 pins
#define REW 2
#define FF 3
#define PLAY 4
#define STOP 5
#define REC 6

//LCD
long x = 130;
int input = A0;

//Flags
int flag;
int flag1;

//Tape Begin and End Values
int tapeBegin = 120;
int tapeEnd = 150;

LiquidCrystal_I2C lcd(0x3F, 16, 2); // set the LCD address to 0x3F for a 16 chars and 2 line display

//Create an instance of the library with default name, serial port and settings
MIDI_CREATE_DEFAULT_INSTANCE();

//Incoming midi messages to be output pin 2-6 when receiving noteON message with note = 60-65
// Buttons to output notes from Midi Out to be recorded in DAW sequencer.
// Midi Note 60 (Rewind), 61 (FF), 62 (Play), 63 (Stop), 64 (Rec)

void setup() {
  pinMode (REW, OUTPUT);
  pinMode (FF, OUTPUT);
  pinMode (PLAY, OUTPUT);
  pinMode (STOP, OUTPUT);
  pinMode (REC, OUTPUT);

  MIDI.begin(13); // Initialize the Midi Library. Respond to notes on channel 13 only.

  MIDI.setHandleNoteOn(Press);
  MIDI.setHandleNoteOff(Release);

  //LCD
  lcd.init(); // initialize the lcd

  // Print a message to the LCD.
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("  Turn counter ");
  lcd.setCursor(0, 1);
  lcd.print("        =turn  ");

  int flag = 0;
}

void stopRoutine() {
  digitalWrite (STOP, HIGH);
  delay(100);
  digitalWrite(STOP, LOW);
  delay(100);
}
void rewRoutine() {
  flag = 1;
  digitalWrite (REW, HIGH);
  delay(100);
  digitalWrite(REW, LOW);
  delay(100);
}
void ffRoutine() {
  flag = 0;
  digitalWrite (FF, HIGH);
  delay(100);
  digitalWrite(FF, LOW);
  delay(100);
}
void playRoutine() {
  flag = 0;
  digitalWrite (PLAY, HIGH);
  delay(100);
  digitalWrite(PLAY, LOW);
  delay(100);
}
void recRoutine() {
  flag = 0;
  digitalWrite (REC, HIGH);
  delay(100);
  digitalWrite(REC, LOW);
  delay(100);
}

void loop() { // Main loop
  MIDI.read(); // Continuously check if Midi data has been received
  //Counter variables Beginning & End

  //Counter Loop
  static int counterLst = 0;
  int counter = digitalRead(A0);
  if (counterLst != counter) {
    counterLst = counter;
    if (HIGH == counter)
      switch (flag) {
        case 1:
          x--;
          if (x < tapeBegin) {
            stopRoutine();
            delay (4000);
            ffRoutine();
            if (x = tapeBegin) {
              stopRoutine();
            }
          }
          break;
        case 0:
          x++;
          if (x > tapeEnd) {
            stopRoutine();
            delay (4000);
            rewRoutine();
          }
          break;
      }
  }
  lcd.setCursor (0, 1);
  lcd.print(x);
}

// Press is the function that will be called by the Midi Library
// when a MIDI NOTE ON message is received.
// It will be passed bytes for Channel, Pitch, and Velocity

void Press (byte channel, byte pitch, byte velocity) {
  if (pitch == 60 ) {
    digitalWrite(REW, HIGH); // Send on pin 2
    flag = 1;
  }
  if (pitch == 61) {
    digitalWrite(FF, HIGH); // Send on pin 3
    flag = 0;
  }
  if (pitch == 62) {
    digitalWrite(PLAY, HIGH); // Send on pin 4
    flag = 0;
  }
  if (pitch == 63) {
    digitalWrite(STOP, HIGH); // Send on pin 5
  }
  if (pitch == 64) {
    digitalWrite(REC, HIGH);
    digitalWrite(PLAY, HIGH); // Send on pin 4, 6
    flag = 0;
  }
}

// Release is the function that will be called by the Midi Library
// when a MIDI NOTE OFF message is received.
// * A NOTE ON message with Velocity = 0 will be treated as a NOTE OFF message *
// It will be passed bytes for Channel, Pitch, and Velocity

void Release (byte channel, byte pitch, byte velocity) {
  if (pitch == 60) {
    digitalWrite(REW, LOW); // Stop send on pin 2
  }
  if (pitch == 61) {
    digitalWrite(FF, LOW); // Stop send on pin 3
  }
  if (pitch == 62) {
    digitalWrite(PLAY, LOW); // Stop send on pin 4
  }
  if (pitch == 63) {
    digitalWrite(STOP, LOW); // Stop send on pin 5
  }
  if (pitch == 64) {
    digitalWrite(REC, LOW);
    digitalWrite(PLAY, LOW); // Stop send on pin 4 AND 6
  }
}

this is a question

i tried suggesting that tracking tapeEnd and tapeBegin were in a separate if statement, separate from if counterLst, not within it.

are you going to name all your sub-routines, somethingRoutine(). all your variables, somethingVariable()

when you receive a midi command to rewind, you set REW HIGH. in rewRoutine(), why do you set it low after 100 msec, will it continue to rewind after setting it LOW?

should stop() insure that all other buttons (?) are set LOW?