@@ -1,153 +1,125 @@
#include < AccelStepper.h>
#include < Servo.h>
#include < MIDI.h>
// Stepper motor driver A
const int enableStepperA = 48 ;
const int MS1StepperA = 49 ;
const int MS2StepperA = 50 ;
const int MS3StepperA = 51 ;
const int stepStepperA = 52 ;
const int setDirStepperA = 53 ;
// Stepper motor driver B
const int enableStepperB = 13 ;
const int MS1StepperB = 12 ;
const int MS2StepperB = 11 ;
const int MS3StepperB = 10 ;
const int stepStepperB = 9 ;
const int setDirStepperB = 8 ;
const int damperServoPin = 21 ;
const int fretterServoPin = 20 ;
struct StepperMotor {
int enablePin;
int MSAPin;
int MSBPin;
int MSCPin;
int stepPin;
int setDirectionPin;
};
const int damperOffPos = 127 ;
const int damperOnPos = 135 ;
StepperMotor fretterStepper1 = {48 , 49 , 50 , 51 , 52 , 53 };
StepperMotor fretterStepper2 = {13 , 12 , 11 , 10 , 9 , 8 };
// StepperMotor pickerStepper = {13, 12, 11, 10, 9, 8};
const int fretterOffPos = 55 ;
const int fretterOnPos = 42 ;
int fretterStepper1APosition = 0 ;
int fretterStepper1BPosition = 0 ;
int fretterStepper2APosition = 0 ; // don't need 2B to reach top note
// possible on position for the fretter on the other side OFF=110°, ON=130°
int fretterStepper1Direction = HIGH;
int fretterStepper2Direction = LOW;
const int maxStepperSpeed = 1000 ;
const int totalSteps = 200 ;
const int noteSteps = 200 ;
const int halvedNoteSteps = 20 ;
int fretter1APositions[4 ] = {71 , 194 , 311 , 421 };
int fretter1BPositions[6 ] = {410 , 508 , 601 , 688 , 770 , 848 };
int fretter2APositions[13 ] = {617 , 548 , 483 , 421 , 363 , 308 , 256 , 207 , 160 , 117 , 76 , 37 , 0 };
int fretter1OffPos = 45 ;
const double scale_length = 816.00 ; // in mm
const int numberFrets = 13 ;
int fretterArm1AOnPos = 50 ;
int FretterArm1BOnPos = 45 ;
// Stepper motor driver A
// const int enableStepperA = 48;
// const int MS1StepperA = 49;
// const int MS2StepperA = 50;
// const int MS3StepperA = 51;
// const int stepStepperA = 52;
// const int setDirStepperA = 53;
// //Stepper motor driver B
// const int enableStepperB = 13;
// const int MS1StepperB = 12;
// const int MS2StepperB = 11;
// const int MS3StepperB = 10;
// const int stepStepperB = 9;
// const int setDirStepperB = 8;
const int damperServoPin = 21 ;
const int fretter1ServoPin = 20 ;
const int fretter2ServoPin = 40 ;
// length from nut to bridge = 816 mm
// max length travelled by stepper = 450 mm
const int damperOffPos = 123 ;
const int damperOnPos = 120 ;
int numberNotesPlayed = 0 ;
int stepsToTake = 0 ;
// possible on position for the fretter on the other side OFF=110°, ON=130°
const int totalSteps = 200 ;
const int noteSteps = 40 ;
bool playingNote = false ;
bool frettingNote = false ;
double fretPositions[numberFrets];
Servo damper;
Servo fretter;
AccelStepper fretterStepper (1 , stepStepperA, setDirStepperA);
AccelStepper pickerStepper (2 , stepStepperB, setDirStepperB);
// MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, midi1);
// d = s - (s/(2^(n/12)))
// d = distance of fret from nut (mm)
// s = scale length (mm)
// n = fret number
void makeFretPositions () {
for (int n = 1 ; n < (numberFrets - 1 ); n++) {
fretPositions[n-1 ] = scale_length - (scale_length/pow (2.0 , (n/12.0 )));
}
}
Servo fretter1;
// Servo fretter2;
MIDI_CREATE_INSTANCE (HardwareSerial, Serial1, midi1);
void setup () {
// midi1.setHandleNoteOn(noteOnHandler);
// midi1.setHandleNoteOff(noteOffHandler);
// midi1.begin(MIDI_CHANNEL_OMNI); // Listen to all incoming MIDI messages
midi1.setHandleNoteOn (noteOnHandler);
midi1.setHandleNoteOff (noteOffHandler);
midi1.begin (MIDI_CHANNEL_OMNI); // Listen to all incoming MIDI messages
damper.attach (damperServoPin);
fretter .attach (fretterServoPin );
fretter1 .attach (fretter1ServoPin );
// Stepper A => Fretter
pinMode (MS1StepperA , OUTPUT);
pinMode (MS2StepperA , OUTPUT);
pinMode (MS3StepperA , OUTPUT);
pinMode (enableStepperA , OUTPUT);
pinMode (stepStepperA , OUTPUT);
pinMode (setDirStepperA , OUTPUT);
pinMode (fretterStepper1. MSAPin , OUTPUT);
pinMode (fretterStepper1. MSBPin , OUTPUT);
pinMode (fretterStepper1. MSCPin , OUTPUT);
pinMode (fretterStepper1. enablePin , OUTPUT);
pinMode (fretterStepper1. stepPin , OUTPUT);
pinMode (fretterStepper1. setDirectionPin , OUTPUT);
// microstep resolution
digitalWrite (MS1StepperA , LOW);
digitalWrite (MS2StepperA , LOW);
digitalWrite (MS3StepperA , LOW);
digitalWrite (fretterStepper1. MSAPin , LOW);
digitalWrite (fretterStepper1. MSBPin , LOW);
digitalWrite (fretterStepper1. MSCPin , LOW);
// set initial direction
digitalWrite (setDirStepperA, HIGH );
digitalWrite (fretterStepper1. setDirectionPin , fretterStepper1Direction );
// enable (active low)
digitalWrite (enableStepperA, LOW);
// Stepper B => Picker
pinMode (MS1StepperB, OUTPUT);
pinMode (MS2StepperB, OUTPUT);
pinMode (MS3StepperB, OUTPUT);
pinMode (enableStepperB, OUTPUT);
pinMode (stepStepperB, OUTPUT);
pinMode (setDirStepperB, OUTPUT);
digitalWrite (MS1StepperB, LOW);
digitalWrite (MS2StepperB, LOW);
digitalWrite (MS3StepperB, LOW);
digitalWrite (setDirStepperB, HIGH);
digitalWrite (enableStepperB, LOW);
fretterStepper.setMaxSpeed (maxStepperSpeed);
fretterStepper.setSpeed (maxStepperSpeed);
pickerStepper.setMaxSpeed (maxStepperSpeed);
pickerStepper.setSpeed (maxStepperSpeed);
// this will be done with an automated calibration sequence in the future
fretterStepper.setCurrentPosition (0 );
digitalWrite (fretterStepper1.enablePin , LOW);
// pinMode(pickerStepper.MSAPin, OUTPUT);
// pinMode(pickerStepper.MSBPin, OUTPUT);
// pinMode(pickerStepper.MSCPin, OUTPUT);
// pinMode(pickerStepper.enablePin, OUTPUT);
// pinMode(pickerStepper.stepPin, OUTPUT);
// pinMode(pickerStepper.setDirectionPin, OUTPUT);
// // microstep resolution
// digitalWrite(pickerStepper.MSAPin, LOW);
// digitalWrite(pickerStepper.MSBPin, LOW);
// digitalWrite(pickerStepper.MSCPin, LOW);
// // set initial direction
// digitalWrite(pickerStepper.setDirectionPin, HIGH);
// // enable (active low)
// digitalWrite(pickerStepper.enablePin, LOW);
damper.write (damperOffPos);
fretter.write (fretterOffPos);
makeFretPositions ();
fretter1.write (fretter1OffPos);
Serial.begin (9600 );
}
// void noteOnHandler(byte channel, byte pitch, byte velocity) {
// Serial.println("running noteOnHandler");
// Serial.print("channel: ");
// Serial.println(channel);
// Serial.print("pitch: ");
// Serial.println(pitch);
// Serial.print("velocity: ");
// Serial.println(velocity);
// if(velocity > 0) {
// int fret = convertPitchToFret(pitch);
// fretNote(fret);
// }
// }
// void convertPitchToFret(byte pitch) {
// // lookup table of some kind here
// return fret;
// }
// void noteOffHandler(byte channel, byte pitch, byte velocity) {
// Serial.println("This will be where the magic happens");
// }
void dampNote () {
Serial.println (" damping note" );
applyServoEffector (damper, 200 , damperOnPos);
applyServoEffector (damper, 200 , damperOffPos);
applyServoEffector (damper, 0 , damperOffPos);
}
void fretNote (Servo fretter) {
// applyServoEffector...
}
void applyServoEffector (Servo servo, int delayTime, int position) {
@@ -158,71 +130,121 @@ void applyServoEffector(Servo servo, int delayTime, int position) {
// wheel diameter = 22.3 mm
// distance travelled in one stepper motor revolution (200 steps) = 22.3(3.14) = 70.022 mm
// distance travelled in one step = 70.022/200 = 0.35011 mm
void fretNote (int fret) {
double fretPosition = fretPositions[fret - 1 ];
stepsToTake = fretPosition/0.35011 ;
Serial.println (" Fretting note!" );
Serial.print (" moving to fret " );
Serial.println (fret);
Serial.print (" fretPosition: " );
Serial.println (fretPosition);
Serial.print (" stepsToTake: " );
Serial.println (stepsToTake);
fretterStepper.moveTo (stepsToTake);
fretterStepper.setSpeed (maxStepperSpeed);
frettingNote = true ;
}
void playNote () {
Serial.println (" playing note!" );
Serial.print (" noteSteps: " );
Serial.println (noteSteps);
pickerStepper.moveTo (noteSteps);
pickerStepper.setSpeed (maxStepperSpeed);
playingNote = true ;
// moveTo() also recalculates the speed for the next step, so need to set speed after calling it
moveStepper (pickerStepper, noteSteps, HIGH);
}
void checkForNote () {
if (Serial.available () > 0 ) {
int fretToMoveTo = Serial.parseInt ();
// fretter.write(fretToMoveTo);
fretNote (fretToMoveTo);
}
void noteOnHandler (byte channel, byte pitch, byte velocity) {
// Serial.println("running noteOnHandler");
// Serial.print("channel: ");
// Serial.println(channel);
// Serial.print("pitch: ");
// Serial.println(pitch);
// Serial.print("velocity: ");
// Serial.println(velocity);
int note = (int )(pitch);
Serial.print (" pitch: " );
Serial.println (note);
if (velocity > 0 ) {
if (note == 36 ) {
// open string => A3
// moveToPosition(fretterStepper1, )
}
else if (note > 36 && note <= 40 ) {
// A3# to C3#
int stepsFromOrigin = fretter1APositions[note - 37 ];
Serial.print (" Steps: " );
Serial.println (stepsFromOrigin);
if (fretterStepper1APosition < stepsFromOrigin) {
fretterStepper1Direction = HIGH; // go away from origin;
}
else {
fretterStepper1Direction = LOW;
}
int stepsToMove = stepsFromOrigin - fretterStepper1APosition;
moveStepper (fretterStepper1, abs (stepsToMove), fretterStepper1Direction);
fretterStepper1APosition += stepsToMove;
fretterStepper1BPosition += stepsToMove;
// fretNote();
}
else if (note > 40 && note <= 46 ) {
int stepsFromOrigin = fretter1BPositions[note - 41 ];
Serial.print (" Steps: " );
Serial.println (stepsFromOrigin);
if (fretterStepper1BPosition < stepsFromOrigin) {
fretterStepper1Direction = HIGH; // go away from origin;
}
else {
fretterStepper1Direction = LOW;
}
int stepsToMove = stepsFromOrigin - fretterStepper1BPosition;
moveStepper (fretterStepper1, abs (stepsToMove), fretterStepper1Direction);
fretterStepper1APosition += stepsToMove;
fretterStepper1BPosition += stepsToMove;
// fretNote();
}
else {
int stepsFromOrigin = fretter2APositions[note - 47 ];
Serial.print (" Steps: " );
Serial.println (stepsFromOrigin);
if (fretterStepper2APosition < stepsFromOrigin) {
fretterStepper2Direction = HIGH; // go away from origin;
}
else {
fretterStepper2Direction = LOW;
}
int stepsToMove = stepsFromOrigin - fretterStepper2APosition;
moveStepper (fretterStepper2, abs (stepsToMove), fretterStepper2Direction);
fretterStepper2APosition += stepsToMove;
// fretNote();
}
// playNote();
}
void loop () {
if (frettingNote && fretterStepper.distanceToGo () == 0 ) {
Serial.println (" reached fret position" );
frettingNote = false ;
Serial.println (" applying fretter" );
applyServoEffector (fretter, 0 , fretterOnPos);
void noteOffHandler (byte channel, byte pitch, byte velocity) {
// Damp in here
}
playNote ();
}
void checkForNote () {
if (Serial.available () > 0 ) {
Serial.println (" moving stepper" );
// USEFUL FOR DEBUGGING
if (playingNote && !frettingNote && pickerStepper.distanceToGo () == 0 ) {
Serial.print (" picker current position: " );
Serial.println (pickerStepper.currentPosition ());
Serial.println (" reached play note position" );
int numberStepsToMove = Serial.parseInt ();
moveStepper (fretterStepper1, numberStepsToMove, fretterStepper1Direction);
dampNote ();
}
}
void moveStepper (StepperMotor stepper, int stepsToMove, int stepperCurrentDirection) {
Serial.println (" removing fretter" );
applyServoEffector (fretter, 0 , fretterOffPos);
digitalWrite (stepper.setDirectionPin , stepperCurrentDirection);
numberNotesPlayed += 1 ;
pickerStepper.setCurrentPosition (0 );
playingNote = false ;
for (int i = 0 ; i < stepsToMove; i++) {
digitalWrite (stepper.stepPin , HIGH);
delayMicroseconds (505 );
digitalWrite (stepper.stepPin , LOW);
delayMicroseconds (505 );
}
}
// midi1.read();
checkForNote ();
fretterStepper.runSpeedToPosition ();
pickerStepper.runSpeedToPosition ();
void loop () {
midi1.read ();
}