@@ -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();
}