Possible serial buffer overflow?

I am working on a project where i am going to control 14 servo motors from an interface made in MaxMsp. The communication between the two software work pretty well, but i am running into a problem I have not been able to solve. For instance if i am running 4 of the motors continuously for a half a minute , they start behaving irrational and i loose connection with arduino. If i turn of the motor they keep on moving. I suspect this has to do with some kind of serial buffer overflow, but what can i do to avoid this problem. Here is my code:

#include <Servo.h>

Servo servo1; Servo servo2; Servo servo3; Servo servo4; Servo servo5; Servo servo6; Servo servo7; Servo servo8; Servo servo9; Servo servo10; Servo servo11; Servo servo12;  Servo servo13; Servo servo14; Servo servo15; Servo servo16;

void setup() {
  servo1.attach(22); //analog pin 0
  servo2.attach(24); //analog pin 1
  servo3.attach(26); //analog pin 0
  servo4.attach(28); //analog pin 1
  servo5.attach(30); //analog pin 0
  servo6.attach(32); //analog pin 1
  servo7.attach(34); //analog pin 0
  servo8.attach(36); //analog pin 1
  servo9.attach(38); //analog pin 1
  servo10.attach(40); //analog pin 0
  servo11.attach(42); //analog pin 1
  servo12.attach(44); //analog pin 0
  servo13.attach(46); //analog pin 1
  servo14.attach(48); //analog pin 0
  servo15.attach(50); //analog pin 1
  servo16.attach(52); //analog pin 0
  Serial.begin(9600);
}

void loop() 
{
  static int v = 0; //v - which position servo shall move to
   char m = 0;

  if ( Serial.available()) {
    char ch = Serial.read();
    
    switch(ch) 
    {     
      case '0'...'9':   //if serial receive a number btw 0 and 9
        v = v * 10 + ch - '0'; //convert from  ASCII to number
        break;
      case 65:   //A-P tells arduino which motor to run.
        servo1.write(v);
        v = 0;
        break;
      case 66:
        servo2.write(v);        
        v = 0;
        break;
      case 67:
        servo3.write(v);
        v = 0;
        break;
      case 68:
        servo4.write(v);
        v = 0;
        break;
        case 69:
        servo5.write(v);
        v = 0;
        break;
      case 70:
        servo6.write(v);
        v = 0;
        break;
      case 71:
        servo7.write(v);
        v = 0;
        break;
      case 72:
        servo8.write(v);
        v = 0;
        break;
      case 73:
        servo9.write(v);
        v = 0;
        break;
      case 74:
        servo10.write(v);
        v = 0;
        break;
      case 75:
        servo11.write(v);
        v = 0;
        break;
      case 76:
        servo12.write(v);
        v = 0;
        break;
      case 77:
        servo13.write(v);
        v = 0;
        break;
      case 78:
        servo14.write(v);
        v = 0;
        break;
      case 79:
        servo15.write(v);
        v = 0;
        break;
      case 80:
        servo16.write(v);
        v = 0;
        break;
     
    }
  }
  delay(5);
}

At the moment i only tell the motor which position they shall move to, but i originally wanted to send every value between current position and the position where i want the servo to move (like the sweep example). This would enable me to also control the speed of the servo. The problem is that i reach the point of “overflow” extremely fast when trying to do this. Anyone have an idea how to solve this?

The code looks reasonable - I suspect you have server-side issues, not client-side.

BTW you can use an array of servo objects if you want to make the code more concise, and character values as case-labels:

  case 'A':
    ...

What do you mean by turn off the motor and it keeps moving, motors don't work so well without power.

Sounds more like a power related issue. Classic sign of overheating is that it works fine then it won't work at all, then it works fine a few min later. Something is probably affecting the voltage to the arduino or over drawing a pin or something, which causes the arduino to go into a reset mode where the pin voltages float (usually high) and that would obviously make it impossible to hold a com port connection.

Unfortunally i do not think it is the maxpatch that cause the trouble. It is a basic and simple patch sending position and which motor to move at a set speed. Thanks for improvement tips!

What i mean by turning off is that i stop sending position commands, not that i turn off power. The motors keeps on moving without receiving commands and the movements seems random. To fix it i have to unplug the arduino from usb port... What happens if max keeps sending commands even if the motor has not finished moving to new position? Will serial buffer overflow?

Again having absolutely no information it sounds unlikely like a code issue, and more likely a wiring or power issue.

You have to do troubleshooting, make simpler test program. See if it happens while only driving 1 motor, then 2 then 3..... make sure all the servo's work the same way on the same program. Test each part then start adding them up till the problem occurs and then the issue will likely be obvious.

Here’s the maxpatch by the way if anyone want to have a look. Thanks for the help!

ITW_Servo 3_eks.maxpat (23.5 KB)

Here's the maxpatch by the way if anyone want to have a look. Thanks for the help!

How are you powering your servos? Most servo issues are due to an inadequate power supply, or trying to power the servos from the arduino.

i use a 5v power adapter for every two motors.

harddrive123: i did some testing earlier running 4 motors. the faster i sent the change position commands, the faster the problems occured. i also tried different motors with no luck.

zangpa: i use a 5v power adapter for every two motors.

What current do these supplies give? Budget at least 1A per servo if they are moving simultaneously. If you supplies are USB 5V supplies, they will be 0.5A or perhaps a bit more, inadequate for a single servo.

You need something like a 15A to 20A supply.

You are connecting the grounds from all the servo's to your arduino right? ^_^

In general take the total current and add 20%, this gives headroom for current spikes and thermal. On wall adapters because of poor thermal and made in china specials, you might want to be in the 30-50%.

Does it happen when you only run 1 ? If it works on 1 then it really does suggest its a supply issue or a perhaps a defective servo?

I know i am a bit on the lower side with current. Most power supplies i use give 2A, some of them 1.7. I will do some testing with a 1-2 servoes and see what happens. And yes, grounds are connected.

I know i am a bit on the lower side with current.

That is at least one of the problems, and it accounts for about 95% of forum posts reporting unexpected behavior of servos.

Servo test code that can send commands to one to four servos at the same time. You might try one servo then four servos and see if there is a difference between one servo moving and four servos moving at the same time.

//zoomkat 11-22-12 simple delimited ',' string parse 
//from serial port input (via serial monitor)
//and print result out serial port
//multi servos added 
// Powering a servo from the arduino usually *DOES NOT WORK*.

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 for suggestions and code. I will do some real testing of motors/power. But one last question before testing: Could the problems occur after a certain amount of time and depending on motor speed if the powering was the problem? I don't know that much about it myself, but that fact was the reason for me thinking this had something to do with buffer….

It unfortunally does not look like it is caused by power issue. I ran 1 servo of a 5v 2A supply, sending 20 commands pr sec, and it ran for 3 min before starting to act out! The servo was only drawing 0.7 a so should not be lack of current. Anyone have another idea what could be wrong.

sending 20 commands pr sec,

Maybe you should elaborate more on the source of the commands and just how fast the commands are being sent. I would think a serial buffer might overflow if subjected to a command spew from a micro controller or pc.

I know this is a bit fast, but i did this on purpose since it is almost similar to sending to 14 motors once pr sec. Is it impossible to control this many motors from one arduino board?

I know I said earlier that the code looked reasonable, but I must have been blind.

You have a call to delay(5) in loop() - lose it!! Lose all calls to delay if you need to keep up with incoming serial!

At 9600 baud each character takes 1.04ms, so a delay of 5ms will mean about 5 characters are coming in for each iteration of loop(), yet you only process 1 character each time round.

Thanks MarkT!! This is starting to make sense!! I had this idea that servos needed a delay, so i kept the delay, even if i found that the programing was way more stable when i took down the delay time.