2 servos (or any functions) operating simultaneously?

Thank you for the tip,

Upon examining ‘blink wo delay’, it appears that every time the defined interval is reached and the led blinks, the previousmillis is redefined to be currentmillis so that the iteration gets continually restarted, thus creating a kind of loop that apparently runs in the background. (if that makes any sense)

So I gather that any function that can be set up without a delay won’t interrupt other functions. I’ll have to think about this a bit.

I found a routine here http://scolton.blogspot.com/2010/07/arduino-interrupt-driven-servo-routine.html that uses PWM, resets one of the board’s timers, and uses interrupts to control the servos. The concept seems to make sense but I don’t really understand the code so I’ll have to experiment to see what it does.

I also want the servos to operate in sync with each other so as to produce what appears a ‘single’ movement of the leg.

I found a routine here http://scolton.blogspot.com/2010/07/arduino-interrupt-driven-servo-routine.html that uses PWM, resets one of the board’s timers, and uses interrupts to control the servos

That’s exactly what the Servo library does.
No need to reinvent that particular wheel.

So, is it that i need to map the variable values (degrees) of one servo to the other so that the position of one is dependent on the position of the other ~one would basically 'follow' the other using a conversion between ranges?

What are you using to control the servo's ? If you are running a full 18 or more you may want to look at a dedicated Servo controller which will give you much more flexibility in managing your servos. The Lynxmotion one allows for group moves others have servo speed control etc.

I also want the servos to operate in sync with each other so as to produce what appears a ‘single’ movement of the leg.

I think you fail to understand that any ‘coordination’ between the servos motion will always strictly be a task your software has to perform. Servos move fairly slow relative to program execution and any ‘simultaneous movement’ will be the result of your the ‘step size’ you issue each servo to move and how quick you issue the next step size movement to each servo. The smaller your servo step size commands are the more smooth the apparent ‘coordinated movement’ will be. Any coordination between your servos movement is a software burden on you, there is no hardware assistance you can use.

Lefty

I guess my specific project here may be beside the point, in that, it probably doesn’t matter what the functions are, but just how to make any two (or more) of them run at the same time, not one after the other. ~2 servos moving at the same time using completely different parameters.

//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 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
    }
  }
}

rgallant:
I’m using an UNO r3 with an ardumoto shield (just using 2 pinouts for 2 servos on a homegrown proto leg ~very simplistic). I just got a seeed studio motor sheild but haven’t tried to hook it up yet. I have a couple of different plans to use a total of only 6 to 8 servos to control 6 legs. I don’t really know what I’m doing but I’m determined to figure it out.

retrolefty:
I’m beginning to understand that the arduino only runs one command at a time. But it’s the speed at which it sends incremental pulses to the motors, switching back and forth between them that will produce an impression of simultaneous operation. The coordinated ‘x’ and ‘y’ motor movements, which are basically linear, will appear as a diagonal or curved path ~sort of like a digital representation of an analog wave.

zoomkat:
Thank you for the code example, although I’m not sure that I understand what it’s doing. Please correct me if I’m wrong, but it appears that the serial function is being used to produce the bit information that gets redefined and sent out to the servos. And the serial function is quick enough to supply the info in time for each pulse to a servo which is happening within microsecond intervals.
Does this particular routine only control 4 servos? Can more servos be added?
Does the ‘n’ variable need to be defined as an integer value? or is the code doing this on its own as it continually loops?

Does this particular routine only control 4 servos?

Yes.

Can more servos be added?

Yes, though I'd advise using an array of Servos, rather than individual named instances. With a regular Arduino, you ought to be able to control up to twelve, more with a Mega.

Does the 'n' variable need to be defined as an integer value?

It needs to be an integer datatype, because that is what the Servo write methods expect.

or is the code doing this on its own as it continually loops?

Sorry, don't understand the question

Quote or is the code doing this on its own as it continually loops? Sorry, don't understand the question

I'm not sure if I understand it either.

So the integers n are the microsecond values given by the readString.index?

I am working now to adapt this routine to my prototype setup and see if it works.

zoomkat:

I’m having some trouble understanding what/how I need to input parameter values into the code to produce a desired result.
For the ‘expect single strings’ example, I assume the lettered values represent microseconds and then degrees per each defined servo.

Do these get input to 'if (c == ‘,’), or after any of the comparison operators (>,<, etc.), or manually replace ‘n’ anywhere? and should they look the same, with a value (100a) followed by a letter? Or, where do motor position parameters get input?
How many changes of direction will this routine handle as is without repeating any of the ‘if’ statements?(maybe I shouldn’t try to ask this last question yet, until I see a result)

Thank you for posting this example, at least I have a direction to work in.

I'm having some trouble understanding what/how I need to input parameter values into the code to produce a desired result. For the 'expect single strings' example, I assume the lettered values represent microseconds and then degrees per each defined servo.

You should be testing the code to see the results. Using the posted code, sending the first line below from the serial monitor to the arduino will position myservoc at 30 deg., myservob at 180 deg., myservoa at 70 deg., and myservod at 120 deg. The second line will send 700us to myservoa, 1500us to myservoc, and 2000us to myservod.

30c,180b,70a,120d,
700a,1500c,2000d,

Sweet, I have some movement of the motors although I’m still not clear on how to input the values correctly.
I’ll keep experimenting and see what happens.

Cool, it works. this is a whole new level of programming for me, it's hard to describe how I feel about it. I had some problems with my com ports that I don't understand, I've never had a problem with them before but it seems to have sorted itself out.

So now I need to figure out how to run a few short, looped series of strings (walking patterns for each leg ~they should all be the same, half with an opposite order of operation) in a function similar to 'Serial.printIn(readString)' that will be stored on the arduino so that the 'string loops' can be incorporated into sensor iterations that will determine travel direction. I think I have most of my sensor iteration figured out, except for the directional radio signal receiver, but that'll come later.

Thanks for the guidance everyone, I will gladly accept more help with my project.

I just started working on this and have a ‘ways to go’ ~gotta sleep at some point, though. I’ve decided to drop the idea of a smooth gait until more important things are taken care of first. I haven’t gone all the way through it or compiled it to see where the disjunctions are yet. For the time being this will only be for one leg with 2 servos, it will gradually expand from there. I will edit this post as I work on it and ask for advice accordingly - unless anyone is able to see any obvious, needed restructuring.

/*
'zoomkat 11-22-12 simple delimited ',' string parse' is combined with 'PROGMEM string demo' 
inside of a while loop that gets started with a bumper sensor used as a manual switch.
Moves one leg prototyped for a hexapod ~to be further expanded...
                              ********************************
         *Testing this gave me alphabet characters in the serial monitor instead
          of the indexed numbers I defined (degree values for servos), this tells me 
          I must be close.  A simple change of datatypes only gives disassembler messages
          I don't understand(strcpy_P). Some help with this would be great.*  
                              ********************************
 zoomkat 11-22-12 simple delimited ',' string parse
         from serial port input (via serial monitor)
         and print result out serial port
         multi servos added
         
 PROGMEM string demo
        -How to store a table of strings in program memory (flash), and retrieve them.
           Information summarized from:
        http://www.nongnu.org/avr-libc/user-manual/pgmspace.html
               -Here is a good template to follow for setting up a 
                table (array) of strings in program memory. 
        -Setting up the strings is a two-step process.               */

  //define strings
#include <avr/pgmspace.h>
prog_char string_0[] PROGMEM = {'60a, 90b'};   //positions leg at ready(may have no use)
prog_char string_1[] PROGMEM = {'25a, 170b'};  //gait for one leg (2 motors(a,b))
prog_char string_2[] PROGMEM = {'160a'};       //
prog_char string_3[] PROGMEM = {'5b'};         //
prog_char string_4[] PROGMEM = {'25a'};        // 
//prog_uint16_t string_5[] PROGMEM = ;
//prog_uint16_t string_6[] PROGMEM = ;
//prog_uint16_t string_7[] PROGMEM = ;
//prog_uint16_t string_8[] PROGMEM = ;
//prog_uint16_t string_9[] PROGMEM = ;

  // Then set up a table to refer to strings.
PROGMEM const char *string_table[] =  //change "string_table" name to suit
{   
  string_0,
  string_1,
  string_2,
  string_3,
  string_4,
//  string_5
//  string_6,
//  string_7,
//  string_8,
//  string_9, 
};
char buffer[32];  //needs to be large enough for the largest string it must hold
                  //may eventually hold up to 240 characters for all servos  
String readString;
//int string[] = {1,2,3,4,5,6,7,8,9};

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

#include <Wire.h>
 const int bumperPinR = 2;   // the number of the bumper pin
 const int bumperPinL = 4;   // 
  int bumperStateR = 0;      // variable for reading the bumper status
  int bumperStateL = 0;      //

void setup() 
{
  Serial.begin(9600);
          //wrong idea but want to save the values temporarily   
 //String('60a, 90b');  //positions leg at ready(may have no use)
 //String('25a, 170b');  //gait for one leg (2 motors(a,b))
 //String('160a');       //
 //String('5b');         //
 //String('25a');        //
 //String('125a, 140b');  //smoothed motion not in use
 //String('80a, 150b');   //
 //String('45a, 160b');   //
 //String('30a, 170b');   //

  //myservoa.writeMicroseconds(1500);   //set initial servo position if desired?
  //myservob.writeMicroseconds(1500);   //
 myservob.attach(8);   //the pin for the servob control
 myservoa.attach(9);   // 
  //Serial.println("");  //keep track of what is loaded

 pinMode(bumperPinR, INPUT);  //sets the bumper pins as an inputs
 pinMode(bumperPinL, INPUT);  //

 Wire.begin();      //initializes/activates voltage sensing for bumperpins?  
}

void loop() 
{
  bumperStateR = digitalRead(bumperPinR);   //read state of bumper sensors
  //bumperStateL = digitalRead(bumperPinL);   //
 
 while (bumperStateR == LOW)      //begin a loop(one leg walking) with bumper sensor
 {
   for (unsigned int i = 1; i < 8; i++)   //prints successive strings in table?
   {                                                    //'strcpy_P' copies strings from program memory to buffer,
     strcpy_P(buffer, (PGM_P)pgm_read_word(&(string_table[i]))); //necessary casts and dereferencing 
     Serial.println(buffer);                                           //required to gather data from table above.
     delay(500);                  //~line:'strcpy_P' seems to be the problem...~         
   }
   if (Serial.available())  
   {
     char c = Serial.read();  //gets one byte from serial buffer
     if (c == ',')            //where/what is 'char c'?  
     {
       if (readString.length() >1)  //greater than 1 char?
       {
         Serial.println(readString);  //prints string to serial port out

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

          // auto select appropriate value, my servos use 0-180 so 181 should work
         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);
         }
         else
         {   
           Serial.print("writing Angle: ");
           Serial.println(n);
           if(readString.indexOf('a') >0) myservoa.write(n);
           if(readString.indexOf('b') >0) myservob.write(n);
         }
         readString="";  //clears variable for new input
       }
     }  
     else 
     {     
       readString += c;  //makes the string readString
     }
   }
 } 
}
String string1 =  String('25a, 170b');

You haven't even tried to compile this, have you?

AWOL:

No, I didn't try to compile it, I just threw it together after some research and wanted to see what initial responses it would conjure.

I just replaced/modified it (above) with a version that survived the compiler but hasn't yet been tested. I'm gonna do that now and see what happens.

HMMM.... I'm having 'com port' problems again, not sure what's happening with my ports, so the code (above) remains untested until I figure this out.

1-2-13. Upon testing, alphabet characters printed to the serial monitor instead of the indexed number values. I changed datatypes to 'unsigned int' and 'uint16_t', used '#define' for the first line, and tried quite a few combinations of changes with no results. There must be more to it than simply changing datatypes, I don't know. I could use some help with it if anyone has any ideas.

I need help setting up strings in PROGMEM as 'int' or 'unsigned int' instead of 'char' datatypes. I think the routine is really close to doing what I want except it prints alphabet characters only instead of the indexed numbers I have defined in the first few lines of code (refer to my last couple of posts and the code above)

Any suggestions or info about this would be greatly appreciated. Thanx

I think the routine is really close to doing what I want

What routine would that be?

Maybe I'm not using the word 'routine' correctly, but the code I'm referring to is in reply #19 (above). I refined and replaced what I had first posted there but the new code gives me the wrong results. There are a few comments in the code and in subsequent posts.

The code in reply #19 needs to have the single quotes replaced with double quotes where necessary, otherwise chances of success are slim. When you've done that and compiled it, repost your code, and tell us how it behaves.