Trouble with midi -> teensy -> accelstepper

Hello!

I'm trying to get midi input from DAW or Pure Data to control a stepper motor location using a Teensy 4.0.

I'm just a hacker with this kind of thing, trying to make code from a couple of different examples work together at the moment. I probably don't understand something simple.

Currently, my sketch will take midi control messages from the computer and print them to the serial bus and sometimes the stepper motor will move into position but more often it will not. My guess is that I'm not updating the passed variable correctly...

Any advice here would be much appreciated!

This is the code I'm working with now:

/* Receive Incoming USB MIDI by reading data.  This approach
   gives you access to incoming MIDI message data, but requires
   more work to use that data.  For the simpler function-based
   approach, see InputFunctionsBasic and InputFunctionsComplete.

   Use the Arduino Serial Monitor to view the messages
   as Teensy receives them by USB MIDI

   You must select MIDI from the "Tools > USB Type" menu

   This example code is in the public domain.
*/

/* /////////////////////////////////////////////////////////////////////////////////////// */

/*  Motor Homing code using AccelStepper and the Serial Monitor
 
Created by Yvan / https://Brainy-Bits.com
This code is in the public domain...
You can: copy it, use it, modify it, share it or just plain ignore it!
Thx!

*/

/* /////////////////////////////////////////////////////////////////////////////////////// */

#include "AccelStepper.h" 
// Library created by Mike McCauley at http://www.airspayce.com/mikem/arduino/AccelStepper/

// AccelStepper Setup
AccelStepper stepperX(1, 3, 2);   // 1 = Easy Driver interface
                                  // NANO Pin 2 connected to STEP pin of Easy Driver
                                  // NANO Pin 3 connected to DIR pin of Easy Driver

// Define the Pins used
#define home_switch 9 // Pin 9 connected to Home Switch (MicroSwitch)

// Stepper Travel Variables
long TravelX;  // Used to store the X value entered in the Serial Monitor
int move_finished=1;  // Used to check if move is completed
long initial_homing=-1;  // Used to Home Stepper at startup

//MIDI input variable
int MIDIin=0;
/* /////////////////////////////////////////////////////////////////////////////////////// */

void setup() {
  Serial.begin(115200);

   pinMode(home_switch, INPUT_PULLUP);
   
   delay(5);  // Wait for EasyDriver wake up

   //  Set Max Speed and Acceleration of each Steppers at startup for homing
  stepperX.setMaxSpeed(100.0);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepperX.setAcceleration(100.0);  // Set Acceleration of Stepper
 

// Start Homing procedure of Stepper Motor at startup

  Serial.print("Stepper is Homing . . . . . . . . . . . ");

  while (digitalRead(home_switch)) {  // Make the Stepper move CCW until the switch is activated   
    stepperX.moveTo(initial_homing);  // Set the position to move to
    initial_homing--;  // Decrease by 1 for next move if needed
    stepperX.run();  // Start moving the stepper
    delay(5);
}

  stepperX.setCurrentPosition(0);  // Set the current position as zero for now
  stepperX.setMaxSpeed(100.0);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepperX.setAcceleration(100.0);  // Set Acceleration of Stepper
  initial_homing=1;

  while (!digitalRead(home_switch)) { // Make the Stepper move CW until the switch is deactivated
    stepperX.moveTo(initial_homing);  
    stepperX.run();
    initial_homing++;
    delay(5);
  }
  
  stepperX.setCurrentPosition(0);
  Serial.println("Homing Completed");
  Serial.println("");
  stepperX.setMaxSpeed(1000.0);      // Set Max Speed of Stepper (Faster for regular movements)
  stepperX.setAcceleration(1000.0);  // Set Acceleration of Stepper

// Print out Instructions on the Serial Monitor at Start
  Serial.println("Enter Travel distance (Positive for CW / Negative for CCW and Zero for back to Home): ");
}




void loop() {
  // usbMIDI.read() needs to be called rapidly from loop().  When
  // each MIDI messages arrives, it return true.  The message must
  // be fully processed before usbMIDI.read() is called again.
  
  
  if (usbMIDI.read()) {
    processMIDI();
  }

 

/* midi version??? VVVVVVVVV */

while (usbMIDI.read()>0)  { // Check if values are available in the MIDI Buffer?

  move_finished=0;  // Set variable for checking move of the Stepper
  
  //TravelX= MIDIin;  // Put numeric value from buffer in TravelX variable
  if (TravelX < 0 || TravelX > 1350) {  // Make sure the position entered is not beyond the HOME or MAX position
    Serial.println("");
    Serial.println("Please enter a value greater than zero and smaller or equal to 1350.....");
    Serial.println("");
  } else {
    Serial.print("Moving stepper into position: ");
    Serial.println(TravelX);
  
  stepperX.moveTo(TravelX);  // Set new moveto position of Stepper
  
  delay(100);  // Wait 1 seconds before moving the Stepper
  }
  }

  if (TravelX >= 0 && TravelX <= 1350) {

// Check if the Stepper has reached desired position
  if ((stepperX.distanceToGo() != 0)) {
    
    stepperX.run();  // Move Stepper into position
    
  }

// If move is completed display message on Serial Monitor
  if ((move_finished == 0) && (stepperX.distanceToGo() == 0)) {
    Serial.println("COMPLETED!");
    Serial.println("");
     Serial.println("Enter Travel distance (Positive for CW / Negative for CCW and Zero for back to Home): ");
    move_finished=1;  // Reset move variable
  }
  }

}

void processMIDI(void) {
  byte type, channel, data1, data2, cable;

  // fetch the MIDI message, defined by these 5 numbers (except SysEX)
  //
  type = usbMIDI.getType();       // which MIDI message, 128-255
  channel = usbMIDI.getChannel(); // which MIDI channel, 1-16
  data1 = usbMIDI.getData1();     // first data byte of message, 0-127
  data2 = usbMIDI.getData2();     // second data byte of message, 0-127
  cable = usbMIDI.getCable();     // which virtual cable with MIDIx8, 0-7

  // uncomment if using multiple virtual cables
  //Serial.print("cable ");
  //Serial.print(cable, DEC);
  //Serial.print(": ");

  // print info about the message
  //
  switch (type) {

    case usbMIDI.ControlChange: // 0xB0
      Serial.print("Control Change, ch=");
      Serial.print(channel, DEC);
      Serial.print(", control=");
      Serial.print(data1, DEC);
      Serial.print(", value=");
      Serial.println(data2, DEC);
      break;
      
    default:
      Serial.println("Opps, an unknown MIDI message type!");
  }

 TravelX = data2;

}

void printBytes(const byte *data, unsigned int size) {
  while (size > 0) {
    byte b = *data++;
    if (b < 16) Serial.print('0');
    Serial.print(b, HEX);
    if (size > 1) Serial.print(' ');
    size = size - 1;
  }
}

No, pin 3 is the step pin, the order is step_pin, direction_pin.

The way to run the AccelStepper library is call run() method all the time (ie every time round loop()), don't use delay, and when you want to initiate a move (or a stop) call the moveTo/move/stop method as appropriate.
The library then handles everything in the background via the calls to run() - basically this polls the driver.

The moveTo() function is absolute as in move to a certain place (position) in the current coordinate system. So if you say moveTo(-1) the stepper will step to position -1. If you say moveTo(-1) again the stepper will not move because it is already there.

The move() function is relative. If you say move(-1) the stepper will move 1 step in the reverse direction. If you call move(-1) again, the stepper will move 1 more step in the reverse direction.

Thank you so much for looking at this. Yes. I swapped the pins in the sketch because I wired it wrong.

Just to be clear: The sketch is ~working but not with the speed of response I expected. I can send midi data to the board, the serial monitor prints this data, and the motor will move to the right position BUT to reliably get the stepper motor to move I usually have to send the same midi value many times in quick succession.

Could this a timing thing? Or a buffer thing? I am pretty sure that the problem has to do with the below part of the code because after I inserted a print statement to say "buffering" when it actually runs I only get the print "buffering" when the motor actually moves to the new position (not every time I send the control change message over midi -which prints on every message reliably).

while (usbMIDI.read())  { // Check if values are available in the MIDI Buffer?
Serial.println("buffering");
  move_finished=0;  // Set variable for checking move of the Stepper
  
  //TravelX= MIDIin;  // Put numeric value from buffer in TravelX variable
  if (TravelX < 0 || TravelX > 1350) {  // Make sure the position entered is not beyond the HOME or MAX position
    Serial.println("");
    Serial.println("Please enter a value greater than zero and smaller or equal to 1350.....");
    Serial.println("");
  } else {
    Serial.print("Moving stepper into position: ");
    Serial.println(TravelX);
  
  stepperX.moveTo(TravelX);  // Set new moveto position of Stepper
  
  //delay(10);  // Wait 10ms before moving the Stepper
  }
  }

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.