Serial Transmission Suddenly Gets Delay

I no longer know if this is a Arduino problem, or a Processing problem, so I will be posting this on both sites.

My problem is here in this video:

As you can see some time in the video after some time the serial transmission or receiving just slows down and gets a delay!
I really don`t know what is causing this and would appreciate help.
Computer specs:

Codes:

Arduino:

const int S1 = 6; //D1 Speed Control
const int S2 = 5; //D2 Speed Control
const int D1 = 8; //D1 Direction Control
const int D2 = 7; //D2 Direction Control

const int rightEncoderPin = A0; // (If you and the rover are pointing the same direction)
const int leftEncoderPin = A1;

const int tonePin = 4;
const int leftLightPin = A3;
const int rightLightPin = A2;
const int leftTempPin = A4;
const int rightTempPin = A5;
const int rightEmfPin = A7;
const int leftEmfPin = A6;

const int trigPin = 3;
const int echoPin = 2;

int direct = 0;

int leftspeed = 255; 
int rightspeed = 255;

int leftLight = 0;
int rightLight = 0;
int leftTemp = 0;
int rightTemp = 0;
int leftEmf = 0;
int rightEmf = 0;
int sonicData = 0;

String string = "";
int lastSample = 0;

void setup() 
{
  pinMode(D1, OUTPUT);
  pinMode(D2, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(rightEncoderPin, INPUT);
  pinMode(leftEncoderPin, INPUT);
  pinMode(rightLightPin, INPUT);
  pinMode(leftLightPin, INPUT);
  pinMode(rightTempPin, INPUT);
  pinMode(leftTempPin, INPUT);
  pinMode(rightEmfPin, INPUT);
  pinMode(leftEmfPin, INPUT);
  pinMode(tonePin, INPUT);
 
  Serial.begin(9600);
}

void loop() 
{ 
  while( Serial.available() == 0);
  direct = Serial.read() -'0'; 

  string = String(leftLight) + ", " + String(rightLight) + ", " + String(leftTemp) + ", " + String(rightTemp) + ", " + String(leftEmf) + ", " + String(rightEmf) + ", " + String(sonicData);
  
  if (millis() - lastSample >= 50) // We can't be overloading our computers serial buffer now can we?
  {
    Serial.println(string);
    lastSample = millis();
  }
  
  //Serial.println(direct);
  
  sonic();
  datas();
  movement(); 
}

void datas()
{
  leftLight = analogRead(leftLightPin);
  leftTemp = analogRead(leftTempPin);
  leftEmf = analogRead(leftEmfPin);
  rightLight = analogRead(rightLightPin);
  rightTemp = analogRead(rightTempPin);
  rightEmf = analogRead(rightEmfPin);
}

void sonic()
{
  int duration, distance;
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(1000);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  sonicData = distance;
}

void movement()
{
  switch(direct) 
  {
  case 0://Move Forward
    forward (leftspeed,rightspeed);
    break;
  case 1://Move Backwards
    reverse (leftspeed,rightspeed);
    break;
  case 2://Turn Left
    left (leftspeed,rightspeed);
    break;
  case 3://Turn Right
    right (leftspeed,rightspeed);
    break;
  case 4:
    stop();
    noTone(tonePin);
    break;
  case 5:
    tone(tonePin, 500);
    break;
  default:
    stop();
    break;
  } 
}


void stop(void) //Stop
{
  digitalWrite(S1,LOW);
  digitalWrite(S2,LOW);
}
void forward(char a,char b)
{
  analogWrite (S1,a);
  digitalWrite(D1,LOW);
  analogWrite (S2,b);
  digitalWrite(D2,LOW);
}
void reverse (char a,char b)
{
  analogWrite (S1,a);
  digitalWrite(D1,HIGH);
  analogWrite (S2,b);
  digitalWrite(D2,HIGH);
}
void left (char a,char b)
{
  analogWrite (S1,a);
  digitalWrite(D1,HIGH);
  analogWrite (S2,b);
  digitalWrite(D2,LOW);
}
void right (char a,char b)
{
  analogWrite (S1,a);
  digitalWrite(D1,LOW);
  analogWrite (S2,b);
  digitalWrite(D2,HIGH);
}

Processing:

import processing.serial.*;
Serial port;

String data = "";

void setup() 
{
    size(800, 165);
    smooth();
    background(0);
    fill(255, 50, 0);
    textAlign(CENTER, CENTER);
    
    port = new Serial(this, "COM5", 9600);
    port.bufferUntil('\n');
}

void draw() 
{
  background(0);
  textSize(75);
  text("PROGRAM RUNNING", width/2, 59);
  textSize(15);
  text("Use WASD keys to navigate RoboRat-V1", width/2, 104);
  text("Incoming Serial Data: " + data, width/2, 140);
  
  if (keyPressed)
  {
    textSize(25);
    text(key, width/2, 16);
  }
  
  if (keyPressed)
  {
  
    if (key == 'w') {port.write('0');};
    if (key == 's') {port.write('1');};
    if (key == 'a') {port.write('2');};
    if (key == 'd') {port.write('3');};
    if (key == 'h') {port.write('5');};
  
  }
  else
  {
   port.write('4'); 
  }
  
  
}

void serialEvent (Serial port)
{
  data = port.readStringUntil('\n');
}

THANK YOU!

The first thing that comes to mind is maybe your serial buffer is filling up.

Forgot to mention, thought of that. But because the problem is information is going out, the in information probably won’t affect it. Also, I have it only sending every 50 milliseconds specifically so that does not happen :confused:

That would be my guess too - there's nothing to control how fast the Processing application writes characters to the Arduino so it could easily exceed the speed of the (very slow) serial link you are using. You need to control the transmission frequency to ensure that the serial connection doesn't ever get congested.

Also, I strongly suggest you stop using the problematic String class in your Arduino sketch. It isn't making your life any easier here, and means that you're hammering the Arduino's heap for no good reason. Just use c-strings (null-terminated char arrays) instead.

Finally, I suggest you only format the Arduino's output string when you are about to send it - at the moment you format it regardless of whether it's time to send it.

This is strange looking.

  while( Serial.available() == 0);
  direct = Serial.read() -'0';

So is:

  string = String(leftLight) + ", " + String(rightLight) + ", " + String(leftTemp) + ", " + String(rightTemp) + ", " + String(leftEmf) + ", " + String(rightEmf) + ", " + String(sonicData);
  
  if (millis() - lastSample >= 50) // We can't be overloading our computers serial buffer now can we?
  {
    Serial.println(string);

The app on the other end of the serial port can't tell whether you used 13 Serial.print() statements to send the data, or if you pissed time and resources away using the String class. 7 calls to the constructor plus 12 calls to allocate and copy data and several more calls to the destructor take time. You don't need to waste that time.

The app on the other end of the serial port can't tell whether you used 13 Serial.print() statements to send the data, or if you pissed time and resources away using the String class. 7 calls to the constructor plus 12 calls to allocate and copy data and several more calls to the destructor take time. You don't need to waste that time.

PaulS,
Can you please link a tutorial or something that explain what the constructor and destructor are ?

Any C++ book dealing with object oriented programming (and that would be most of them) will explain what a constructor and destructor are.

I think the problem @PaulS is referring to in his inimitable style is the baggage (extensive assembler code and complex RAM manipulation) associated with the use of the C String class (with a big S) which would be avoided completely by a series of separate Serial.print() statements that have the exact same effect.

...R

[...]
String string = "";
int lastSample = 0;

[...]
void loop() 
{ 
  [...]
  if (millis() - lastSample >= 50) // We can't be overloading our computers serial buffer now can we?
  {
    Serial.println(string);
    lastSample = millis();
  }
[...]
}

I believe that lastSample should be unsigned long.

Regards,

Brad
KF7FER

Well pressing spacebar brought me back to the last page and everything I just wrote disappeared.

Long story short:

It wasn't the String.
Processing did know the difference.
It can tell.
When something prints on the arduino, the serial port is not available and then the printed value goes into a variable.
See the table below.
Printing one at a time, make it unreadable on the other end.
You can't tell one value from another.
Is that 604 from the rightTemp, rightLight, leftEmf WHO KNOWS!
I would have to attach a char to each one or send it before hand so that I know that that value is for that sensor.
That is more complicated than I know how to deal with in processing.
The null character thing is a good idea if it will act exactly as a string to processing. Please add links.
I implemented the 'only make the string when it prints', and that may or may not have help :confused:
I realized you's guys meant the serial buffer on the arduino, and I changed the framerate in processing from 60 (sending every ~16ms) to 20 (every 50ms).
It didn't work.
Then it worked.
And then the result was repeatable!
It still works so that must have been it!
Thanks for the other suggestions too!

Tables:
Assuming the values from the sensors stay the same for the half a second:
112, 123, 234, 1020, 40, 41, 23
Data will be printed and received every fifty ms.

Using a String:
Time ms --- What shows up on screen every fifty ms
050 --- 112, 123, 234, 1020, 40, 41, 23
100 --- 112, 123, 234, 1020, 40, 41, 23
150 --- 112, 123, 234, 1020, 40, 41, 23
200 --- 112, 123, 234, 1020, 40, 41, 23
250 --- 112, 123, 234, 1020, 40, 41, 23
300 --- 112, 123, 234, 1020, 40, 41, 23
350 --- 112, 123, 234, 1020, 40, 41, 23
400 --- 112, 123, 234, 1020, 40, 41, 23
450 --- 112, 123, 234, 1020, 40, 41, 23
500 --- 112, 123, 234, 1020, 40, 41, 23
Which every 50ms I can read that data into their respective variables, knowing that the first one is lightRight, the second is.....

Printing every variable on a separate line:
Time ms --- What shows up on screen every fifty ms
050 --- 112
100 --- 123,
150 --- 234
200 --- 1020
250 --- 40
300 --- 41
350 --- 23
400 --- 112
450 --- 123
500 --- 234
It's slower. How do I know what values what? I would have to add to attach a char to each one or send it before hand so that I know that that value is for that sensor.
That is more complicated than I know how to deal with in processing.

Printing every variable on a separate line outcome 2:
Time ms --- What shows up on screen every fifty ms
050 --- 23
100 --- 23,
150 --- 23
200 --- 23
250 --- 23
300 --- 23
350 --- 23
400 --- 23
450 --- 23
500 --- 23
It only reads one value, then flushes the rest. I've seen both cases happen.
So as far as I'm concerned, unless strings are really this bad they would have taken them out and I'm keeping the strings.

you pissed time and resources away using the String class

This is a tiny sketch, and I'm sure it can handle it, because it is, and they would have taken Strings out if they can't.
PaulS, please do not reply on my post any longer. I do not appreciate your text simulated attitude. You seem upset/frustrated at the code I put up. No thanks.

Processing did know the difference.

No, it most certainly does not!

It can tell.

No, it can not.

When something prints on the arduino, the serial port is not available and then the printed value goes into a variable.

What are you talking about? The serial port on the Arduino doesn't go away because it wrote to it. If the serial port on the Processing side goes away, you are doing something wrong.

Printing one at a time, make it unreadable on the other end.

You haven't shown any code where you try, so all we can assume is that you are doing it wrong.

You can't tell one value from another.

You haven't shown any code where you try, so all we can assume is that you are doing it wrong.

Is that 604 from the rightTemp, rightLight, leftEmf WHO KNOWS!

Anyone would, if you were doing it right,

I would have to attach a char to each one or send it before hand so that I know that that value is for that sensor.

Wrong again.

That is more complicated than I know how to deal with in processing.

No argument there.

PaulS, please do not reply on my post any longer. I do not appreciate your text simulated attitude.

Get your Arduino code right, and I won't need to. Frankly, I don't care if you appreciate being told you are doing it wrong. You are, so get over it.

madscience2728:
Data will be printed and received every fifty ms.

But unless you changed the data type for lastSample, after 30 seconds or so (or whenever millis() first returns a value larger than an integer) the Arduino will NOT consistently be sending every 50 millis.

I can't see how that wouldn't have an effect.

Just trying to help,

Brad
KF7FER

PaulS am I to assume then that when you were still learning programming you did every single thing right, never making a mistake!

When something prints on the arduino, the serial port is not available and then the printed value goes into a variable.

What are you talking about? The serial port on the Arduino doesn’t go away because it wrote to it. If the serial port on the Processing side goes away, you are doing something wrong.

The while(serial.available == 0); part PaulS. If nothing is printed, nothing gets written to a variable. It waits for the serial port to not be available, meaning something was printed, then writes that into a variable.

Printing one at a time, make it unreadable on the other end.

You haven’t shown any code where you try, so all we can assume is that you are doing it wrong.

You can’t tell one value from another.

You haven’t shown any code where you try, so all we can assume is that you are doing it wrong.

Code change as suggested:

  if (millis() - lastSample >= 50) // We can't be overloading our computers serial buffer now can we?
  {
    //string = String(leftLight) + ", " + String(rightLight) + ", " + String(leftTemp) + ", " + String(rightTemp) + ", " + String(leftEmf) + ", " + String(rightEmf) + ", " + String(sonicData);
    Serial.println(leftLight);
    Serial.println(rightLight);
    Serial.println(leftTemp);
    Serial.println(rightTemp);
    Serial.println(leftEmf);
    Serial.println(rightEmf);
    Serial.println(sonicData);
    lastSample = millis();
  }

Notice the title.
This is at 60fps (jumbled mess).

And this one at 20fps (only from the ulsy).

Is that 604 from the rightTemp, rightLight, leftEmf WHO KNOWS!

Anyone would, if you were doing it right,

How smartass. In the way you want it to send the data, it only get the value from the ultrasonic sensor anyway. And if not, TELL ME THEN how in that mess of incoming data can I tell one value from another. How do I do it right. Since you’ve made it so clear that I am doing it wrong. HOW do I do it right. Tell ME. Don’t just say I’m doing it wrong. That helps no one.

Get your Arduino code right, and I won’t need to

Nice way to treat people on the forum, looking for help, and aide in where they went wrong to better themselves. Again, were you perfect at every single thing you codded from the beginning. I doubt it.
Nice way to treat people on the forum, looking for help, and aide in where they went wrong to better themselves. Sorry I just had to write that again!

lastSample is now an unsigned long.

Code change as suggested:

NOT as suggested. I suggested the you print() a variable (NOT println() it), then print() a separator, repeating that for all variables, and THEN print the carriage return/line feed.

Nobody here advised you to print each of your values on a separate line.

All that was suggested was to achieve EXACTLY the same as you are doing but without using String functions.

So, Serial.print(value);
Serial.print(" , ");
Serial.print(value2);
etc etc etc, all on the same line

Processing won't know the difference.

...R