I'm working on a project that uses an Arduino UNO and a motorized fader to send and receive MIDI data from my computer/musical keyboard. I'm trying to set up my motor with PID to control the position and speed of the motor - Been having some difficulty, but after watching a few tutorials I think I'm starting to grasp the idea.
Here's the code that I came up with so far - I'm not sure if this is correct for PID control or not, but it makes my motor respond very strangely to any positioning data that is coming in.
#include <SoftwareSerial.h>
#define rxPin 2
#define txPin 1
SoftwareSerial midiSerial (rxPin, txPin);
const byte wiper = 0; //Position of fader relative to GND (Analog 0)
const byte motorUp = 4;
const byte motorDown = 5;
const byte motorPWM = 6;
double faderMax = 0;
double faderMin = 0;
byte motorSpeed = 150; // Raise if the fader is too slow (0-255)
byte tolerance = 10; // Raise if the fader is too shaky (0-1023)
int incomingCommand;
int incomingNote;
int incomingVelocity;
int currentPosition;
unsigned targetPosition;
unsigned long distanceToTarget;
unsigned PIDspeed;
void setup() {
midiSerial.begin(31250);
Serial.begin(250000);
analogWrite(motorPWM, motorSpeed);
calibrateFader();
}
void calibrateFader() {
digitalWrite(motorUp, HIGH);
analogWrite(motorPWM, motorSpeed);
delay(300);
digitalWrite(motorUp, LOW);
faderMax = analogRead(wiper) - tolerance;
digitalWrite(motorDown, HIGH);
analogWrite(motorPWM, motorSpeed);
delay(300);
digitalWrite(motorDown, LOW);
faderMin = analogRead(wiper) + tolerance;
}
void loop() {
while ( midiSerial.available() > 0) {
incomingCommand = midiSerial.read();
incomingNote = midiSerial.read();
incomingVelocity = midiSerial.read();
midiSerial.write( incomingCommand);
midiSerial.write( incomingNote);
midiSerial.write( incomingVelocity);
targetPosition = incomingVelocity*8.05511811024;
currentPosition = analogRead(A0);
distanceToTarget = targetPosition-currentPosition;
}
PIDspeed = abs(distanceToTarget)/6;
if (distanceToTarget >=0) {
analogWrite(motorPWM, PIDspeed);
digitalWrite(motorUp, HIGH);
digitalWrite(motorDown, LOW);
}
if (distanceToTarget <=0) {
analogWrite(motorPWM, PIDspeed);
digitalWrite(motorDown, HIGH);
digitalWrite(motorUp, LOW);
}
}
Updated code:
#include <SoftwareSerial.h>
#define rxPin 2
#define txPin 1
SoftwareSerial midiSerial(rxPin, txPin);
const byte wiper = 0; //Position of fader relative to GND (Analog 0)
const byte motorUp = 4;
const byte motorDown = 5;
const byte motorPWM = 6;
double faderMax = 1023;
double faderMin = 0;
byte motorSpeed = 150; // Raise if the fader is too slow (0-255)
byte tolerance = 10; // Raise if the fader is too shaky (0-1023)
byte Proportional = 12;
unsigned int incomingCommand;
unsigned int incomingNote;
unsigned int incomingVelocity;
unsigned int PIDspeed;
int currentPosition;
int targetPosition;
int distanceToTarget;
void setup()
{
midiSerial.begin(31250);
Serial.begin(250000);
calibrateFader();
}
void calibrateFader()
{
digitalWrite(motorUp, HIGH);
analogWrite(motorPWM, motorSpeed);
delay(300);
digitalWrite(motorUp, LOW);
faderMax = analogRead(wiper) - tolerance;
digitalWrite(motorDown, HIGH);
analogWrite(motorPWM, motorSpeed);
delay(300);
digitalWrite(motorDown, LOW);
faderMin = analogRead(wiper) + tolerance;
}
void loop()
{
while (midiSerial.available() >= 3)
{
incomingCommand = midiSerial.read();
incomingNote = midiSerial.read();
incomingVelocity = midiSerial.read();
if (targetPosition <= 1023)
{
midiSerial.write(incomingCommand);
midiSerial.write(incomingNote);
midiSerial.write(incomingVelocity);
}
targetPosition = incomingVelocity * 8.05511811024;
}
currentPosition = analogRead(A0);
distanceToTarget = (targetPosition - currentPosition);
PIDspeed = (abs(distanceToTarget) / Proportional) + 90;
analogWrite(motorPWM, PIDspeed);
if (targetPosition <= 1023)
{
if (distanceToTarget > 60)
{
digitalWrite(motorUp, HIGH);
}
if (distanceToTarget < 60)
{
digitalWrite(motorDown, HIGH);
}
if ((distanceToTarget >= -60) && (distanceToTarget <= 60))
{
digitalWrite(motorDown, LOW);
digitalWrite(motorUp, LOW);
}
}
}
In this version, the motor is actually less responsive than before. I think it must have to do with the data that's coming in from my DAW, which isn't consistently a piece of command, note or velocity data. For example, if I select a different track in my DAW, it sends data into my Arduino. When I read anything greater than 0 bytes, the data still comes in, but the note, command and velocity readings are more sporadically located. It was suggested by another that I try using a MIDI parser, but that's a different topic I suppose.