Thanks for the response.
I didn't connect a potentiometer, but I did set the motor to move up for 250mS, and down for 250mS.
The motor is moving back and forth correctly with this. This is the first bit of PID coding that I've used in the project so far.
const byte pin_a = 9; //for encoder pulse A
const byte pin_b = 10; //for encoder pulse B
const byte pin_fwd = 5; //for H-bridge: run motor forward
const byte pin_bwd = 6; //for H-bridge: run motor backward
const byte pin_pwm = 3; //for H-bridge: motor speed
int encoder = 11;
int m_direction = 0;
int sv_speed = 100; //this value is 0~255
double pv_speed = 0;
int timer1_counter; //for timer
void setup() {
pinMode(pin_a,INPUT_PULLUP);
pinMode(pin_b,INPUT_PULLUP);
pinMode(pin_fwd,OUTPUT);
pinMode(pin_bwd,OUTPUT);
pinMode(pin_pwm,OUTPUT);
attachInterrupt(digitalPinToInterrupt(pin_a), detect_a, RISING);
// start serial port at 9600 bps:
Serial.begin(9600);
//--------------------------timer setup
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
timer1_counter = 34286; // preload timer 65536-16MHz/256/2Hz
TCNT1 = timer1_counter; // preload timer
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt
interrupts(); // enable all interrupts
//--------------------------timer setup
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
}
void loop() {
digitalWrite(pin_fwd,0); //run motor backward
digitalWrite(pin_bwd,1); //run motor backward
analogWrite(pin_pwm,sv_speed); //set motor speed
Serial.print("speed (rpm) is : ");
Serial.print(pv_speed); //Print speed value to Computer
Serial.print(" -- ");
Serial.print("Direction = ");
Serial.println(m_direction);
delay(200);
digitalWrite(pin_bwd,0); //run motor backward
digitalWrite(pin_fwd,1); //run motor backward
analogWrite(pin_pwm,sv_speed); //set motor speed
Serial.print("speed (rpm) is : ");
Serial.print(pv_speed); //Print speed value to Computer
Serial.print(" -- ");
Serial.print("Direction = ");
Serial.println(m_direction);
delay(200);
}
void detect_a() {
encoder+=1;
m_direction = digitalRead(pin_b);
}
ISR(TIMER1_OVF_vect) // interrupt service routine - tick every 0.5sec
{
TCNT1 = timer1_counter; // set timer
pv_speed = 60*(encoder/200.0)/0.5;
encoder=0;
}
Haven't done any tuning of PID parameters whatsoever.
I'll dig into PID functionality today. Thanks for providing me with some direction!
I've updated the code a few times over and switched from an Arduino UNO to a Nano (had to, as a power outage messed up my UNO during an upload /: )
As it stands now, it will follow the incoming data from Ableton at very slow speeds only. Anytime there is a somewhat quick automation, the fader stops moving, and starts jumping around once every second or two. It wasn't like this with my UNO.
Here's an updated version of the code. I still haven't found a PID library that I like much - what are some decent ones?
#include <SoftwareSerial.h>
#include <CapacitiveSensor.h>
#include <MIDI.h>
#define rxPin 4
#define txPin 1
SoftwareSerial midiSerial (rxPin, txPin);
const byte motorDown = 5;
const byte motorUp = 6;
const byte motorPWM = 3;
const byte wiper = 7; //Position of fader relative to GND (Analog 0)
const byte touchSend = 2;//Send pin for Capacitance Sensing Circuit (Digital 7)
const byte touchReceive = 7; //Receive pin for Capacitance Sensing Circuit (Digital 8)
int faderValue = analogRead(wiper);
int velocityIn;
byte motorSpeed = 75; // Raise if the fader is too slow (0-255)
byte minimumCp = 200; // Raise if the fader is too sensitive (0-1023)
byte tolerance = 10; // Raise if the fader is too shaky (0-1023)
double faderMax = 0; //Value read by fader's maximum position (0-1023)
double faderMin = 0; //Value read by fader's minimum position (0-1023)
bool touched = false; //Is the fader currently being touched?
CapacitiveSensor cs_7_2 = CapacitiveSensor(touchReceive, touchSend);
MIDI_CREATE_DEFAULT_INSTANCE();
void setup() {
cs_7_2.set_CS_AutocaL_Millis(0xFFFFFFFF);
midiSerial.begin(31250);
MIDI.begin(MIDI_CHANNEL_OMNI);
while (!Serial);
pinMode(motorDown, OUTPUT);
pinMode(motorUp, OUTPUT);
pinMode(motorPWM, OUTPUT);
pinMode(rxPin, INPUT );
pinMode(txPin, OUTPUT);
analogRead(faderValue);
analogWrite(motorPWM, motorSpeed);
calibrateFader(); }
void calibrateFader() {
digitalWrite(motorUp, HIGH);
analogWrite(motorPWM, 100);
delay(300);
digitalWrite(motorUp, LOW);
faderMax = analogRead(wiper) - tolerance;
digitalWrite(motorDown, HIGH);
analogWrite(motorPWM, 100);
delay(300);
digitalWrite(motorDown, LOW);
faderMin = analogRead(wiper) + tolerance; }
void loop() {
int faderPos = analogRead(wiper);
int lastfaderValue;
int faderMIDI = faderPos / 8;
int faderState = digitalRead(7);
while ( midiSerial.available() > 0 ) { // try swapping the '0' with a '2' if it gets too buggy
long commandByte = midiSerial.read();
long noteByte = midiSerial.read();
long velocityByte = midiSerial.read();
midiSerial.write( commandByte);
midiSerial.write( noteByte);
midiSerial.write( velocityByte);
velocityIn = velocityByte; }
{ long totalCp = cs_7_2.capacitiveSensor(30);
if (totalCp <= minimumCp) { updateFader(velocityIn*8); } // Not Touching Fader
else {
MIDI.sendControlChange(36, faderMIDI, 16); // Pitch: 36, Data: Controlled by fader Channel: 16)
digitalWrite(motorDown, LOW);
digitalWrite(motorUp, LOW); }
lastfaderValue = faderPos; } }
void updateFader(int position) { //Function to move fader to a specific position between 0-1023 if it's not already there
if (position < analogRead(wiper) - tolerance && position > faderMin && !touched) {
digitalWrite(motorDown, HIGH);
while (position < analogRead(wiper) - tolerance && !touched) {}; //Loops until motor is done moving
digitalWrite(motorDown, LOW); }
else if (position > analogRead(wiper) + tolerance && position < faderMax && !touched) {
digitalWrite(motorUp, HIGH);
while (position > analogRead(wiper) + tolerance && !touched) {}; //Loops until motor is done moving
digitalWrite(motorUp, LOW); } }
If anyone notices anything that looks bad/redundencies or whatever please let me know.
Thanks
Here's the latest version of the code - Added the touch sensor functionality. I've got the code sending a MIDI message on note 37, channel 16. In Ableton, I've got this mapped so that it selects my track when receiving a message from that note. For some reason though, I have to move my fader all the way down to the bottom in order to get my track to select. Weird
#include <SoftwareSerial.h>
#include <CapacitiveSensor.h>
#include <MIDI.h>
#define rxPin 4
#define txPin 1
SoftwareSerial midiSerial (rxPin, txPin);
const byte motorDown = 5;
const byte motorUp = 6;
const byte motorPWM = 3;
const byte wiper = 7; //Position of fader relative to GND (Analog 0)
const byte touchSend = 2;//Send pin for Capacitance Sensing Circuit (Digital 7)
const byte touchReceive = 7; //Receive pin for Capacitance Sensing Circuit (Digital 8)
int velocityIn;
byte motorSpeed = 75; // Raise if the fader is too slow (0-255)
byte minimumCp = 75; // Raise if the fader is too sensitive (0-16838)
byte tolerance = 10; // Raise if the fader is too shaky (0-1023)
double faderMax = 0; //Value read by fader's maximum position (0-1023)
double faderMin = 0; //Value read by fader's minimum position (0-1023)
bool touched = false; //Is the fader currently being touched?
CapacitiveSensor cs_7_2 = CapacitiveSensor(touchReceive, touchSend);
MIDI_CREATE_DEFAULT_INSTANCE();
void setup() {
cs_7_2.set_CS_AutocaL_Millis(0xFFFFFFFF);
midiSerial.begin(31250);
MIDI.begin(MIDI_CHANNEL_OMNI);
while (!Serial);
pinMode(motorDown, OUTPUT);
pinMode(motorUp, OUTPUT);
pinMode(motorPWM, OUTPUT);
pinMode(rxPin, INPUT );
pinMode(txPin, OUTPUT);
analogWrite(motorPWM, motorSpeed);
calibrateFader(); }
void calibrateFader() {
digitalWrite(motorUp, HIGH);
analogWrite(motorPWM, 100);
delay(300);
digitalWrite(motorUp, LOW);
faderMax = analogRead(wiper) - tolerance;
digitalWrite(motorDown, HIGH);
analogWrite(motorPWM, 100);
delay(300);
digitalWrite(motorDown, LOW);
faderMin = analogRead(wiper) + tolerance; }
void loop() {
int faderPos = analogRead(wiper);
int lastfaderValue;
int faderMIDI = faderPos / 8;
while ( midiSerial.available() > 0 ) {
int commandByte = midiSerial.read();
int noteByte = midiSerial.read();
byte velocityByte = midiSerial.read();
midiSerial.write( commandByte);
midiSerial.write( noteByte);
midiSerial.write( velocityByte);
velocityIn = velocityByte; }
{ int totalCp = cs_7_2.capacitiveSensor(30);
if (totalCp <= minimumCp) { touched = false; updateFader(velocityIn*8); }// Not Touching Fader
if ((faderPos == lastfaderValue) && (totalCp > minimumCp)) { touched = true; // Touching Fader
MIDI.sendNoteOn(37, 127, 16);
digitalWrite(motorDown, LOW);
digitalWrite(motorUp, LOW); }
if ((faderPos != lastfaderValue) && (totalCp > minimumCp)) { touched = true; // Moving Fader
MIDI.sendControlChange(36, faderMIDI, 16);
digitalWrite(motorDown, LOW);
digitalWrite(motorUp, LOW); }
lastfaderValue = faderPos; } }
void updateFader(int position) { //Function to move fader to a specific position between 0-1023 if it's not already there
if (position < analogRead(wiper) - tolerance && position > faderMin && !touched) {
digitalWrite(motorDown, HIGH);
while (position < analogRead(wiper) - tolerance && !touched) {}; //Loops until motor is done moving
digitalWrite(motorDown, LOW); }
else if (position > analogRead(wiper) + tolerance && position < faderMax && !touched) {
digitalWrite(motorUp, HIGH);
while (position > analogRead(wiper) + tolerance && !touched) {}; //Loops until motor is done moving
digitalWrite(motorUp, LOW); } }
Going to start a new topic dedicated to getting the capacitive touch sensor to work.
Thanks for the help`