sending/parsing serial data from Max->Arduino to control multiple servos

Hello,

I am interested in using Max messages to control multiple servo motors, each independently.

I was able to successfully get a system (hardware, programming using the arduino's Servo library) to control multiple motors from the same Max slider value send over serial (usb).

However, I am a relatively inexperienced programmer, and am having trouble coming up with a protocol to parse the serial data in the Arduino code to send one value to one motor, and a second value to another.

I have done a little bit of research and know that the solution probably calls for an index or address character that I would assign to each position value in Max, and that would be parsed and sent to the various motor positions in Arduino. However, I am struggling to figure out how to format this address character (ASCII vs Integer, etc) and how to code in Arduino to read this address and send it to the particular motor it addresses.

Below I've attached an abridged Arduino 2 code of my general motor set up, and a sample Max patch assigning possible address labels.

Any hints/advice/suggestions would be greatly appreciated!

Thanks!
JCR

//concept sketch in Arduino 2 code for controlling 2 independent motors,

#include <Servo.h> //load servo library

Servo servo1; // create servo object to control a servo (part of servo library protocol)
Servo servo2;

unsigned char temp_data = 0; //value for the entire serial read -some combo of address and position values
unsigned char address = 0; //the address value indicating which servo to send position data (1, 2, 3, etc.)
unsigned char pos = 0; //the motor position value, which follows the address (0-179)

unsigned char Max1; // value for servo1 position
unsigned char Max2; // value for servo2 position

//HERE IS WHERE I WOULD DEFINE SOME FUNCTION TO PARSE THE ADDRESS AND POSITION DATA

void setup()
{
servo1.attach(3); // attaches the output on pin 3 to the servo1
servo2.attach(4); // attaches the output on pin 4 to the servo2

Serial.begin(9600);
}

void loop()
{
if (Serial.available()) { //check if data sent from cpu

temp_data = Serial.read(); //assign value for entire serial read

}

if (address = 1) //is for servo1 position -HERE WILL BE THE IF STATEMENT READING THE ADDRESS

{
pos = Max1;
servo1.write(Max1); // sets the servo1 position according to value
}

if (address = 2) //is for servo2 position

{
pos = Max2;
servo2.write(Max2); // sets the servo2 position according to value
}

delay(15); // waits for the servo to get there
}


----------begin_max5_patcher----------
1155.3oc2Y0zaiaCD8r8uBBcoI.dMHoDsjJJZQOt2JPO1rXAiDiM2UlTPj1I
sK1+6keIamrRdcxRgj1KRlTTRy6wYdyLxeY9rjakOvTIfeF7WfYy9x7YybSY
mXVX7rjszGpZnJ2xRpja2xD5jE9qoYOncyqXLvdZyNF3NY2V5gEzvErJ4Nga
U3vjhca4hFl18HQGmTtS2OKLLaKUWsgKV+wNVk1annzzkvEfrUEKIK.4H6Q6
TfODtGdsyjj29o2gx6Mj6jBsftk4tzu2woMGtR25acuxkvSVqh+Ot0hvKg1Y
+5741CKtPdZKSonqYeCOU0HUGl8Q7.dPd.cFdnDa4ABI2dJszdDULLOfQW.O
7DTGl1aL5+tk4esIIfODQBoU1oAz3vHXTliQRQNGDz4XDT4qMiHX2aLjAhjr
l.fBJWAgIWdDC9LdJPmyAovwHENRBCGgWHwiW3VghWJ8LlRy6Azs.gTCT65X
f62P0AIGfdCCDby.bQUytZCM.nB.sttyLO3JszbC7pM.CIuWds4Z0FhtUp3Z
tTDDvTaj6ZpAZ5mYK.JI38+z99mGytbibVaCCHuCHas2lZPst7nn0QfP2lkK
DGQbCPvw15xdkD6FaqZKe8FMPvrzlphy+k28qURwdVmxPa+1Dlhf3UCwkvS3
sQyQfeknsQD.3Z4v5goOW8vrbhiFJv9DlmMtGF239nFy+m1vU.F7G8QpWAMo
1KuNIJdKXihHIDWcvaYLdpLFNK81hQUx.WpEROxdHV6A6zoggCS.ehlH9Lib
4zY9aLIq6cZ+q46CkypLJW2H5SfnZoU8045+s84PAWwVtdow+LuDr35A00Ri
Byll6z0RW4p.FU5hnyxGlZSmdO0TeEEXe9oIwU87aHd5+zsE+VAxzXP4TtSf
vtsfTxJmut2Ierch2XIXnZIOpIXRQWPBlxr3kfogqzQsnaZaKyTK3M2r3YHA
dFhIEQNIP02g1nDS5qcmHpFdMqKRHOn9mVziYyfQg9ghNZocFfqYcejIn21v
NM7610UxFYm+4CWVlUBwKF7GGeICwLgKcfGKfwLppk9YSF.Xb5js2+A6ab6r
oPKdq1IaaG+nf9OXIZPWIZ85MmsC1hUOe9Hlfl4jRPQSKIz8dvWXUwYKmp7+
SZIAjiBcycdsjbx+A0RZoBVSTq5F6Ok4+hAiUQxgbwOgOJrHOybit69EVJWD
AUeqYWFpJFAUYK7P6Hp9NMfUBsuNB1dbvpZcOAWckO4qm6vfc9GyOJ4ttpd2
m9j9fiFRMSo4BmcbxhreKtSVzFdcMSbJiskW2JMhrAiHEm4saejBp3vniuHt
xFR33rgcXuTDXkZ9wQP7rG6m3N5LJF596EH44N+u.iZGMALJpbJPfoQEqMSx
NEA1QS.BJtDD7DW+ozmvVe420dbFM5YDkQ7eUsUqd8hqr037b7BB66YD2ov+
ShazTf.xEffm.yI0KHcBXzfV6KgQ8IOLsbF9R3Ny2Z7lznexm0Z0B2PtvOzk
2Loism2udWGEIzNSBSsIu0tNegdOXfwb664qy+WPrFhN5
-----------end_max5_patcher-----------

You might try something like below.

//zoomkat 11-22-12 simple delimited ',' string parse 
//from serial port input (via serial monitor)
//and print result out serial port
//multi servos added 

String readString;
#include <Servo.h> 
Servo myservoa, myservob, myservoc, myservod;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);

  //myservoa.writeMicroseconds(1500); //set initial servo position if desired

  myservoa.attach(6);  //the pin for the servoa control
  myservob.attach(7);  //the pin for the servob control
  myservoc.attach(8);  //the pin for the servoc control
  myservod.attach(9);  //the pin for the servod control 
  Serial.println("multi-servo-delimit-test-dual-input-11-22-12"); // so I can keep track of what is loaded
}

void loop() {

  //expect single strings like 700a, or 1500c, or 2000d,
  //or like 30c, or 90a, or 180d,
  //or combined like 30c,180b,70a,120d,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      if (readString.length() >1) {
        Serial.println(readString); //prints string to serial port out

        int n = readString.toInt();  //convert readString into a number

        // auto select appropriate value, copied from someone elses code.
        if(n >= 500)
        {
          Serial.print("writing Microseconds: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.writeMicroseconds(n);
          if(readString.indexOf('b') >0) myservob.writeMicroseconds(n);
          if(readString.indexOf('c') >0) myservoc.writeMicroseconds(n);
          if(readString.indexOf('d') >0) myservod.writeMicroseconds(n);
        }
        else
        {   
          Serial.print("writing Angle: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.write(n);
          if(readString.indexOf('b') >0) myservob.write(n);
          if(readString.indexOf('c') >0) myservoc.write(n);
          if(readString.indexOf('d') >0) myservod.write(n);
        }
         readString=""; //clears variable for new input
      }
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

Thanks Zoomcat,

I used the little Max patch below to send data to the serial object formatted as: position value, servo designator letter, and a comma (101a,102a,103a,56b,57b,200c,199c, etc).

The serial reader of your Arduino code read the values and sliced the designator and comma off to give me data like:
"92c
writing Angle: 92
95c
writing Angle: 95
100c
writing Angle: 100
112c
writing Angle: 112
116c
writing Angle: 116
120c
..."

However, I'm still not sure how to parse this data to send to various Servo.writes. This may even be included in the Arduino code you sent, but I'm not experienced with this language and am having a hard time conceptualizing how to separate these data based on the letter designation and comma in between them (which I'm not married to, if there is an easier way to format the data to be isolated in a string).

Any further hints/suggestions would be greatly appreciated. Thanks!


----------begin_max5_patcher----------
1116.3oc2ZF0aaBCDG+4jOEVn8vlTVkOiMf2a6avj1iqSSNfWmmHPDP551z9
tOrMIglRZHTGnsujD6Xv28y28myN4uym4sL+NYoG5CnuflM6uymMyzktiYMs
m4sRbWbpnzLLuUxxRwMRuE1uqRdWko+2.wWe8hsc+87rpR0ej5uBHWga5Nay
JUVprxbqH66LeS01dgV2gLwJycv6iEJQ5168ZQU7OTY27sBYbk0zYQ7qXKPD
NtdpP9g5Wgnqvnu1bM1In52qk1Kvya2WoRLSQ9xe9dlmtq+Met9kE8DHw4qV
Iypd.PDkwJ04vicddwMK0swsGVKBgGBgBoVzDwzuQ0l.hfaQnVXHvoXHIAcs
W70dHQVBROJw1wjpxjw4axpZGML4jJfQZEKEZhk786lT.dHn5XoPTNhgQzHD
minzIJUJ.Gpc+l.EfPFXtDPFBZxj+p9heXPTU9YkJ46boEeF0j3D7fDmGfiT
UYU2Hw2kQK.AOgJtAT+VXggGZTB0kZMeVVbaNxG8o7RUkJOC8V76gP96d1nB
yHQZpUmaU+JXo1wTgggPlxTUhrv6wbrtW7WdSbdZdg0LwWwobLYQmeXuwd7r
EfXhNH1vhGOcoy3BxdHVTC2JYw2jYhkox1ne2RYT8DL.XsVjISOCVg6lULLv
CfZ+T6rVO9DPxFE.f4J.Z3t25BENUz3MvxoSyvutFDGTkVPnaIhX5HB.VIfm
JQnudKbkxgdW3Ji59JWW9xoxUJ1u2UtxXtuxUFEwiltJW8YQNoxUVvqiJWaj
acQkqrP2V4ZvT9THN0EUtx3ud0bI0YR8UykdANs.wKGMWvhpdo4RotLKh4iX
.hGNcBt.ocXxvEbovqCA2lp4bgfKk31PkorF2.ZKpL7SJ.bIQhSyKkSFPrxp
btgK7ABDhSAx57hJjXZCQnglR8ovPCQ3NTGoTpMZj.wCv3g7j46yExSPPg4a
TVinmVPQoel5wvCy8m0F446YsQB489r13tmLvyWxXexTu.S3KwCgrYiOO4Cg
jiGiSgbpoUiHCPXOMZExdAclsQZrPaNy1Sbbs1zkddZsCpDeG4TzEVOqONUi
5XO8pn1dkY.lsicveb.yzn6+9tZY9lh3sgNayqP6mmDYYkJSnkJaMnfv6Mne
nRRjYsc9DUoN3xXjcGI0W6QG4dZ6gNZ1yAtd21CiWOH3QrmUpj0400CTt8zw
raNw2nMR8Y6ZsehFYOX7VgOXwqa6odOWOqrm5c7bVqv.X+kps6nffo6ZcAVg
Y8ZEN3DdvHaO.6DqvcmyPs+iPZ3qo0kfn8wAnmWHAqYOl1j9.6NHtTI88xA7
GsbrCRmORNOLZQn8xdNYDp6rGBbAxXfPipytega9tVWf.t9.zwim.+hvSydX
nbVaEHcqK.OOH4zMdPiDz3ng1OOfLvbdaguh0quUVT1bOMlRc07+zVFdvBSS
Ulsoo7cuB4spsi2bNPdhh55wqpKFeSgcK62Eo+YTpmm+M++fzKN82
-----------end_max5_patcher-----------

Good day,

I have tried your approached and found it complexe, I am also not an expert but found a different approach in API mode. Also take in consideration that I am using xbees series 1 but the logic I am applying could be applied to any sketch. I am simply passing analog values across and the sketch could b modified easily.

I am still building this sketch, at the present moment I am only passing 1 analog value from the pot, I am trying to include another signal to the sketch ending up passing analog X&Y and controlling 2 motors independently.

The trick is to parse the information received

http://forum.arduino.cc/index.php?topic=181305.0

Fabiolus

Thanks for all the replies so far, but unfortunately I'm still at a loss as to how to define a system of flags/tags in the Arduino code to separate the value following the tag coming in from the Serial.read (the number preceding the letter designation a, b, c, in my previous example...though it would probably make more sense to have the letter tag come first: a128, rather than 128a, ).

So it would isolate "A138," as the value 138, and I could then define a variable for all values coming in with that have the "A" tag, and set "servo A" to read to those only those values, the "servo B" to read only values with a "B" tag, etc.

Thanks again for all your help!
J

Using the code I posted, when you send the control strings using the serial monitor, your servos do not respond? Perhaps your "Max patch" is causing issues.