Go Down

Topic: Servo control midi (Read 635 times) previous topic - next topic

eptheca

I'm trying to sync a servo to sweep 0-180-0 deg. and loop, controlled and synced to a MIDI signal from Ableton Live
For now I can start the sweep with midi and get it to stay in a set tempo with turning the servo 1 deg. at a time with a delay
this code:
Code: [Select]
// Midi controlled servo sweep
// eptheca 2012

#include <Servo.h>

Servo myservo;  // create servo object to control a servo
                // a maximum of eight servo objects can be created

int pos = 0;    // variable to store the servo position

byte midi_start = 0xfa;
byte midi_stop = 0xfc;
byte midi_clock = 0xf8;
byte midi_continue = 0xfb;
int play_flag = 0;
byte data;

void setup() {
Serial.begin(31250);  // midi baud rate
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  myservo.write(0);
}


void loop() {
if(Serial.available() > 0) {
data = Serial.read();
  //Serial.print(data, BYTE);
if(data == midi_start || data == midi_continue) {
   play_flag = 1;
}

while(play_flag = 1)
      for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees
  {                                  // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(11.11);                       // waits 15ms for the servo to reach the position
  }
  for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees
  {                               
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(11.11);                       // waits 15ms for the servo to reach the position
  }
}

else if(data == midi_stop) {
play_flag = 0;
  myservo.write(0);

}
else if((data == midi_clock) && (play_flag == 1)) {
   Sync();
}
}


void Sync() {
  // do something for every MIDI Clock pulse when the sequencer is running
}

 


This doesn't really work as the delay makes it not listen to other incoming MIDI messages, and it's not accurate.

MIDI sync messages sends 24 ticks per. 1/4 note,  so in a 4/4 beat it would be 96 ticks per bar.
I would like the servo to move from 0 to 180 deg. in that tempo, and wonder if anybody has a suggestion for how to scale the 180 deg. to the 96 ticks?

For now I have tried this:
Code: [Select]
// Midi controlled servo sweep
// eptheca 2012

#include <Servo.h>

Servo myservo;  // create servo object to control a servo
                // a maximum of eight servo objects can be created

int pos = 0;// variable to store the servo position
int counter = 0;

byte midi_start = 0xfa;
byte midi_stop = 0xfc;
byte midi_clock = 0xf8;
byte midi_continue = 0xfb;
int play_flag = 0;
byte data;

void setup() {
Serial.begin(31250);  // midi baud rate
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  myservo.write(0);
}


void loop() {
if(Serial.available() > 0) {
data = Serial.read();
   //Serial.print(data, BYTE);
if(data == midi_start || data == midi_continue) {
  play_flag = 1;
}

else if(data == midi_stop) {
play_flag = 0;
counter = 0;
  myservo.write(0);

}
else if((data == midi_clock) && (play_flag == 1)) {
   Sync();
}
}
}


void Sync(){                  // do something for every MIDI Clock pulse when the sequencer is running

if(counter < 192) {
counter = counter + 1;
  else if(counter <= 96){
    if(pos == 0);
    pos +=1;
    myservo.write(pos);
}
else if(counter >= 96) {
if(pos == 180);
pos -=1;
  myservo.write(pos);
}
else{
counter = 0;
}
}
}



I am not sure about the counting
Does it make sense?
My idea was to get it to count the ticks, up to 192, then reset count to 0 and loop that
For every tick it should move 1 deg. until 180 deg. then 1 deg. until 0 and loop that

With this code it works once, up to 180 deg. then it stops, and starting and stopping midi messages does not help

Also 1 deg per tick is not what I'm after, I would like it to move 180 deg. in 96 ticks, which is 1.875 deg per tick
Anybody have an idea on how to do that?

Grateful for any suggestions

Cheers

RPCoyle


Code: [Select]

if(counter < 192) {
counter = counter + 1;
  else if(counter <= 96){  //change to just "if"
    if(pos == 0);
    pos +=1;
    myservo.write(pos);
}
else if(counter >= 96) { // change to just "if"
if(pos == 180);
pos -=1;
  myservo.write(pos);
}


You might look at the else if in your code... it looks like it may never get called. Try changing it to just an if statement.   The bracketing in void Sync() is kind of funny, I'm not sure what the compiler would make of it.


Go Up