Major Lag when adding Sensor programming to loop????

hello,
I am sure this is an age old question, however, I am having problems with lag in my servos when I try to add programming to the main program loop. Is it possible I am asking to much from the arduino or is there a fix for this?

See code:

// =============== Loads Libraries =========================
#include <Wire.h>
#include "I2Cdev.h"
#include <BMP085.h>
#include "HMC5883L.h"
#include <Servo.h>
#include <LiquidCrystal.h>

//================ Configure Hardware ======================
// ==== For Servo Control ======
Servo svr1;Servo svr2;Servo svr3;
Servo svr4;Servo svr5;Servo svr6;
int s1=90;int s2=90;int s3=90;
int s4=90;int s5=90;int s6=90;
// ==== for Serial input =======================
int index;int index_1;
String inputString = "";String outputString = "";
String data = "";String data_1 = "";
String temp_1="";String temp_2="";
boolean stringComplete = false;

//======== For BMP085 ===========================
BMP085 dps = BMP085();
long Pressure = 0, Altitude = 0;
unsigned long time1=0;
float ft = 0;
String alt = "100";
int other = 0;
int sensorValue;
// ====== Main Setup Function ================================
void setup(){
  inputString.reserve(200);
  outputString.reserve(200);
  Serial.begin(115200);
  delay(100);
  svr1.attach(38);svr2.attach(39);svr3.attach(40);
  svr4.attach(41);svr5.attach(42);svr6.attach(43);
  // Used for testing only.
  outputString = ("100.00,200.00,300.00,400.00,500.00,600.00");
  //====== For BMP-085 ========================================
  dps.init(MODE_STANDARD, 24170, true); //Altitude at home.
  
  
}
// ===== Main Program Loop ====================================
void loop(){
  //===== Write data to Servos ===============
  svr1.write(s1);svr2.write(s2);svr3.write(s3);
  svr4.write(s4);svr5.write(s5);svr6.write(s6);

  // When I add this the program slows to a crawl and servos respond slowly.
  /*
  getAlt();
  */
 
}
// =============== End of Loop ==========================


void serialEvent(){
  while (Serial.available()) {
    char inChar = (char)Serial.read(); 
    inputString += inChar;
    if (inChar == '\n') {
      stringComplete = true;
    } 
  }
  if (stringComplete) {
    data = inputString.substring(0, inputString.length() -1);
    index = data.indexOf(",");
    temp_1 = data.substring(0, index);    
    // Sends data to servo 1
    s1 = temp_1.toInt();
    data_1 = data.substring(index+1, data.length());
    index_1 = data_1.indexOf(",");
    temp_2 = data.substring(index +1, index+index_1+1);
    s2 = temp_2.toInt();
    data = data_1.substring(index_1+1, data.length());
    index = data.indexOf(",");
    temp_1 = data.substring(0, index);    
    s3 = temp_1.toInt();
    data_1 = data.substring(index+1, data.length());
    index_1 = data_1.indexOf(",");
    temp_2 = data.substring(index +1, index+index_1+1);
    s4 = temp_2.toInt();
    data = data_1.substring(index_1+1, data.length());
    index = data.indexOf(",");
    temp_1 = data.substring(0, index);    
    s5 = temp_1.toInt();
    data_1 = data.substring(index+1, data.length());
    index_1 = data_1.indexOf(",");
    temp_2 = data.substring(index +1, index+index_1+1);
    s6 = temp_2.toInt();
    // clear the string:
    inputString = "";
    stringComplete = false;    
  }
  Serial.println(outputString);  
}


void getAlt() {
  
  if (((millis() - time1)/1000.0) >= 1.0) {     
     dps.calcTrueTemperature();
     time1 = millis();      
  }
  dps.getPressure(&Pressure);
  dps.getAltitude(&Altitude);
  ft = Altitude / 30.4;  
}

Do you know how long the getAlt() takes ?
You could Serial.print() the millis() before and after that.
The fastest updates for servo motors is about 100Hz.

  // untested example
  Serial.print(F("millis before: "));
  Serial.println( millis());
  getAlt();
  Serial.print(F("millis after: "));
  Serial.println( millis());

How big a lag are you talking about?

It looks as if the servo movements are triggered by serial input - how frequently do you expect to receive commands over the serial port?

Where do these commands come from, and what controls the frequency of the commands?

Do you mean to get pressure and altitude every time you call getAlt (each time thru loop)?

First off thanks for all the replies. The actual hadware hooked to the Arduino when project is done will be a BPM085 for altitude data, a MPU6050 Gyro for Attitude data, and a HMC5883L compass along with up to nine servos and GPS. I hope to use a Xbee pro to transmit and receive data when the project is done but for testing I am hooked to a serial port.

It seems I can get either the data from the sensors back to the computer just fine (Another sketch entirely.) or the servo control. But not both. The test platform I am using at the moment is a Processing Sketch (See Below) I got the servos working great with the sketch I posted. Its getting all the other data processed is where I am having the issue. So to answer your questions:

  1. Do you know how long the getAlt() takes ?
    No, I basically modified the example sketch that was with the library.

  2. How big a lag are you talking about?
    Basicly when I run the sketch without the "getAlt()" routine the servos work smooth and are very responsive. After adding the "getAlt()" routine the servos become choppy at best and sometimes just stop working.

  3. How frequently do you expect to receive commands over the serial port?
    The main goal is to control servos and get real time data back to a processing sketch for my RC airplane.

4.Do you mean to get pressure and altitude every time you call getAlt (each time thru loop)?
Not really sure...

Processing Sketch used for testing:

// For GamePort control=============>
import procontroll.*;
import net.java.games.input.*;
import java.io.*;
// For Serial Function=============>
import processing.serial.*;

Serial port;
String input = "";
String output = "";
int lf = 10; // ASCII linefeed

// Config for Game Controller application.
ControllIO controll;
ControllDevice device;
ControllStick stick0, stick1, stick2;
//Variables for Game controller
float x0;
float y0;
float x1;
float y1;
float x2;
float y2;
String sx0 = "";
String sy0 = "";
String sx1 = "";
String sy1 = "";
String sx2 = "";
String sy2 = "";

String serialOut = "";


void setup() {
  // Setup the screen for output.
  textFont(createFont("Verdana", 18));
  size(500, 130);
  noStroke();
  background(0);
  // List all the available serial ports:
  println(Serial.list());
  // The first serial port on my mac is the Arduino so I just open that.
  // Consult the output of println(Serial.list()); to figure out which you
  // should be using.
  port = new Serial(this, Serial.list()[3], 115200);
  // Fire a serialEvent() when when a linefeed comes in to the serial port.
  port.bufferUntil(lf);
  port.write(lf);
  delay(10000); // Give serial port time to hook up.

  //NEW
    // Used for Gameport...
  controll = ControllIO.getInstance(this);
  device = controll.getDevice("PPM");
  device.printSticks();  
  stick0 = device.getStick(0);stick0.setTolerance(0.05f);
  stick1 = device.getStick(1);stick1.setTolerance(0.05f);
  stick2 = device.getStick(2);stick2.setTolerance(0.05f);

}

// Process a line of text from the serial port.
void serialEvent(Serial p) {
  input = (port.readString());
  print("received: " + input);
}

// Draw the input and ouput buffers and a little help.
void draw() {
  background(0);
  fill(204, 102, 0);
  text("Results of :", 10, 20);
  fill(255, 255, 255);
  rect(10, 75, 480, 5);
  text(output, 10, 55);  
  text(input, 10, 110);

  // Gets gameport data and converts it for 180 degree servo (0-180).
  x0 = stick0.getX()*180/2+90; //+ width/2;
  y0 = stick0.getY()*180/2+90; //+ height/2;
  x1 = stick1.getX()*180/2+90; //+ width/2;
  y1 = stick1.getY()*180/2+90; //+ height/2;
  x2 = stick2.getX()*180/2+90; //+ width/2;
  y2 = stick2.getY()*180/2+90; //+ height/2;
  // converts Servo data to string for serial transmission.
  sx0 = Float.toString(x0);
  sy0 = Float.toString(y0);
  sx1 = Float.toString(x1);
  sy1 = Float.toString(y1);
  sx2 = Float.toString(x2);
  sy2 = Float.toString(y2);

  output="";
  output += sx0;
  output += (",");
  output += sy0;
  output += (",");
  output += sx1;
  output += (",");
  output += sy1;
  output += (",");
  output += sx2;
  output += (",");
  output += sy2;
  output += (",");
  output += ('\n');
  
  print("sending: " + output);
  port.write(output);
  delay(5);    
      

  

     
      
  
  
  fill(255, 255, 255);
  rect(10, 75, 480, 5);
  text("                                        ", 10, 55);
  text(output, 10, 55);  
  text(input, 10, 110);
  


}

Datahead:

  1. Do you know how long the getAlt() takes ?
    No, I basically modified the example sketch that was with the library.

Let me repfrase that: Tell me how long the getAlt() takes ! :wink:

Servo uses TIMER2 do any of the other libs you are using make use of it?

Mark

Erdin:
Let me repfrase that: Tell me how long the getAlt() takes ! :wink:

To be honest I started this project to learn how to code. So I am not sure how one would get that information. I will however look into it.

holmes4:
Servo uses TIMER2 do any of the other libs you are using make use of it?
Mark

Here again I am not sure what is using what. I wish I could give better answers here.

This may sound silly but I am considering piggy backing a second Arduino one for control and one the sensors. Due to the fact that the control board only needs to accept data and the sensor board only needs to send data I could use the secondary port of the Mega and pass the control data to the second Arduino via the first one. ( I am just brainstorming here)

Ron

The code snippet in Reply #1 was for measuring the time of the getAlt() function.

The function millis() returns the number of milliseconds since startup.
Displaying them before and after, and the difference is the number of milliseconds the getAlt() takes.

I took a glance at the libraries. I think the others don't use hardware timers. I'm 80% sure of it.

Erdin,
First off thanks for the help. After using your snippet of code. There doesn't seem to be that much of a delay. So perhaps it is in how I am configuring the servos. Or perhaps I am looking in the wrong direction. What I do know is once the "getAlt" is added the the servos jerk and behave erratic. Not to mention the servo power supply gets warm. (A series of six LM7805 Voltage regulators with caps hooked to a separate Power Source with all grounds hooked to a common bus with the Arduino.)

Never the less here is the results of the test. It looks like were around 30 milliseconds for a delay time. Considering this is the first of four sensors on the board I am not sure about the time factor.

Thanks
Ron

PS: Very handy little snippet of code,,, Thank you.

ending: 0.0,0.88990784,70.14328,90.0,180.0,83.9176,
received: millis before: 39814millis after: 39842
sending: 0.0,0.0,70.14328,90.0,180.0,83.9176,
received: millis before: 39846millis after: 39875
sending: 0.0,0.88990784,68.82216,90.0,180.0,83.9176,
sending: 0.0,0.88990784,68.82216,90.0,180.0,83.9176,
received: millis before: 39879millis after: 39907
sending: 0.0,0.88990784,70.14328,90.0,180.0,83.9176,
sending: 0.0,0.0,68.82216,90.0,180.0,83.9176,
received: millis before: 39911millis after: 39940
sending: 0.0,0.0,68.82216,90.0,180.0,83.9176,
received: millis before: 39944millis after: 39971
sending: 0.0,0.88990784,68.82216,90.0,180.0,83.9176,
sending: 0.0,0.88990784,70.14328,90.0,180.0,83.9176,
received: millis before: 39975millis after: 40004
sending: 0.0,0.88990784,70.14328,90.0,180.0,83.9176,
sending: 0.0,0.0,68.82216,90.0,180.0,83.9176,
received: millis before: 40008millis after: 40036
sending: 0.0,0.88990784,68.82216,90.0,180.0,83.9176,
sending: 0.0,0.88990784,70.14328,90.0,180.0,83.9176,
received: millis before: 40040millis after: 40069
sending: 0.0,0.0,70.14328,90.0,180.0,83.9176,
sending: 0.0,0.0,70.14328,90.0,180.0,83.9176,
received: millis before: 40073millis after: 40100
sending: 0.0,0.88990784,70.14328,90.0,180.0,83.9176,
sending: 0.0,0.88990784,70.14328,90.0,180.0,83.9176,
received: millis before: 40104millis after: 40133
sending: 0.0,0.0,70.14328,90.0,180.0,83.9176,
sending: 0.0,0.88990784,68.82216,90.0,180.0,83.9176,
received: millis before: 40137millis after: 40165
sending: 0.0,0.88990784,70.14328,90.0,180.0,83.9176,
sending: 0.0,0.0,68.82216,90.0,180.0,83.9176,
received: millis before: 40169millis after: 40198
sending: 0.0,0.0,68.82216,90.0,180.0,83.9176,
sending: 0.0,0.0,68.82216,90.0,180.0,83.9176,
sending: 0.0,0.88990784,68.82216,90.0,180.0,83.9176,
received: millis before: 40202millis after: 40229
sending: 0.0,0.88990784,70.14328,90.0,180.0,83.9176,
received: millis before: 40233millis after: 40262

Datahead:
3. How frequently do you expect to receive commands over the serial port?
The main goal is to control servos and get real time data back to a processing sketch for my RC airplane.

That doesn't really answer the question. How frequently do you expect to receive commands? Where do these commands come from, and what controls the frequency of the commands?

PeterH:
That doesn't really answer the question. How frequently do you expect to receive commands? Where do these commands come from, and what controls the frequency of the commands?

At the moment I am sending the commands via serial from the Processing sketch I posted. As to my expectation of receiving the command I am open to suggestions. I essence I want the servos to have a smooth transition with little or no delay from moving the control sticks hooked to the computer that is running the Processing sketch. At the moment the frequency of the command is based on how fast the serial data is sent to the arduino which at this point I am running the interface at 115200 baud and data is sent every draw cycle of the Processing sketch. I hope that answered your question...

Ron

Datahead:
data is sent every draw cycle of the Processing sketch. I hope that answered your question...

Sigh.

No, it doesn't. I have no idea how frequently your Processing sketch performs draw cycles. How many commands do you expect to receive per second?

If they are only limited by the speed of the serial connection then this is a bad idea because the serial buffers at both sides of the link will add latency. You need to control the transmission frequency so that the serial link does not ever get congested, and then design your sketch to ensure that it can always process the incoming messages when they arrive at this frequency.

PeterH:
You need to control the transmission frequency so that the serial link does not ever get congested, and then design your sketch to ensure that it can always process the incoming messages when they arrive at this frequency.

Peter,
First off thank you for your patience. I am somewhat new to coding and your help is greatly appreciated. The above statement makes perfect sense. Would there happen to be an example somewhere that I can use to accomplish this goal?

On another note, after messing around with the arduino sketch a little more I went ahead and loaded the configuration and sketch commands for the HMC5883L compass and the MPU6050 Gyro. Once that was done I ran the sketch and had no problems with the servos acting erratic, and the data from these devices transferred back to the processing sketch without an issue. It seems to be that when a sketch command for the BMP085 is introduced to the sketch is when the servo problem starts. Any thoughts on this???

Thanks,
Ron

It seems to be that when a sketch command for the BMP085 is introduced to the sketch is when the servo problem starts.

How long does it take to get data from the BMP085? A relatively long time, I'm guessing.

During that time, are interrupts being processed? If not, that would explain the servo issues.

Look at the library you are using. Or post a link to it.

PaulS:
How long does it take to get data from the BMP085? A relatively long time, I'm guessing.
During that time, are interrupts being processed? If not, that would explain the servo issues.

Look at the library you are using. Or post a link to it.

Paul,
I figured out it takes about 30ms to process the data. If I trim down the sketch I got it down to 15ms. As to the interupts I am not sure if they are being processed or not. As to the library I am using the one below, however I tried the Adafruit library as well with the same results.

After messing with the sketch and adding the compass and gyro the serial data is being transferred quite quickly with no problem to processing and the servos work great. So it is my guess there is a conflict somewhere between the servo library and the BMP085 library. I am going to keep working on this, however I may start looking for alternate devices for the Altimeter as in a flight control system it is kind important... LOL... I am open to suggestions. In the mean time I am going to get the GPS hooked up and working. (I hope...)

Here is the link to the library files: