Serial Transmition Stopping?

Below are two programs, one for a rover, the other a processing sketch. The rover takes in a int from serial to control movement and the horn, and the processing sketch sends the commands, but also receives serial data from sensors coming in from the rover.

The problem is that after about 30 seconds, the transmission from the rover stops. The numbers no longer change in the processing sketch, and in the serial monitor you have to send a command to it to get the values back (which I'm not %100 sure why) so by repeatedly sending the value 4 (the stop command) I found the numbers that came back eventually stop changing as well.

What is the world could be causing this? Because as best I can tell, it's just stops sending data :confused:

Thank-you.

P.S. I added this to my code:

  if (sonicData < 4)
  {
    tone(tonePin, 1000);
  }

and it would seem that it only works when the processing sketch is open, or it's getting a command from the serial monitor. I encountered this before when I was trying to get my code to not have a huge delay in between pressing w and the rover actually moving. Is my code only working when it's receiving from serial?

//////////////////////////////////////////////////////////////////////////

Arduino Sketch:

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 Sketch:

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)
  {
  
    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');
}

Try:
unsigned long lastSample = 0;

if (millis() >= lastSample + 50)

This is not the correct way to use millis() because it won't work when millis() eventually goes back to 0.

The correct way is to use subtraction as in

if (millis() - lastSample >= 50)

...R

  while( Serial.available() == 0);

The above code has you sit in a loop doing nothing until something comes in on serial.

Mark

Ok thank you for the millis() tip it seems to b e working. However my other problem is that there is a like a ~5 sec delay between when I press w and when the rover moves. I used to think it was due to the while(Serial.available == 0); being left out but now with it in again it was working immediately and now it's slowed down...
Sigh.....

You haven't posted your revised code so its difficult (impossible?) to help.

...R

Same code. Just the millis() thing changed.

Here it is anyway:

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);
}
  string = String(leftLight) + ", " + String(rightLight) + ", " + String(leftTemp) + ", " + String(rightTemp) + ", " + String(leftEmf) + ", " + String(rightEmf) + ", " + String(sonicData);

There is NO benefit in using one Serial.print() statement over using 13 Serial.print() statements. In fact, pissing away resources on all those String instances costs more time and memory.

    lastSample = millis();

The last sample is not anything derived from millis(). The lastSampleTime is. Meaningful names are important.

  sonic();

Good function names consist of a noun and a verb. digitalRead(), for instance. Crappy names consist of random letters. There is nothing in the name of this function that tells me what it does. The same holds true for datas() and movement().

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

There is no excuse for this function not returning a value. Get off the dependence on global variables. digitalRead() doesn't store data in a global variable. Your function shouldn't, either. digitalRead() doesn't presume to know what pin to use. Your function shouldn't either.

Good function names consist of a noun and a verb. digitalRead(), for instance. Crappy names consist of random letters. There is nothing in the name of this function that tells me what it does. The same holds true for datas() and movement().

My functions are for clean code, so when I'm in my main loop I'm not troubled by seeing all that code. It's just nicely tucked away.
But thank you, I do try when it is important to.

This is small enough code. And I know what the meanings are, and look at the code really quick you will see too.
I'd rather call a quick simple sonic() or datas() than functionForCleanCodeForGettingTheMeasurmentFromTheUltrasonicSensor() or functionForCleanCodeForAquirringTheDataIntoVariablesFromTheSensors(). Pardon my sarcasm.

And also it does. datas() ? collecting data from the sensors. sonic ? doing the calculations for the ultrasonic sensor. movement ? makes and controls the movement of the rover.

The last sample is not anything derived from millis(). The lastSampleTime is. Meaningful names are important.

I like lastSample. I use last sample. Just like in an array, I use res (resolution) for the amount of variables in the array. And again, it's shorter.

There is no excuse for this function not returning a value.

Please elaborate why it would need to return anything? And why any of it is a problem. I do not know what you mean. Why is returning it any better than just putting the value into the varible directly in the function.

digitalRead() doesn't store data in a global variable. Your function shouldn't, either. digitalRead() doesn't presume to know what pin to use. Your function shouldn't either.

Explain here too please. I thought (and see) globalVariableExample = digitalRead(meaningfulNamePin); store it into the global variable. Why is storing data into global variables inside functions bad? And what do mean "Your function shouldn't either."
Please elaborate and be clear otherwise your advise has very little meaning to me...

There is NO benefit in using one Serial.print() statement over using 13 Serial.print() statements. In fact, pissing away resources on all those String instances costs more time and memory.

And I add them all in one because that's the only way I know to determine what is what in processing, because in processing I will split it every ", " into a separate variable in an array.
If you know a better way please tell me as I do not know how, to determine one incoming value from another.

I thought (and see) globalVariableExample = digitalRead(meaningfulNamePin); store it into the global variable.

You are storing the value returned by digitalRead() into a variable that MIGHT be global. The digitalRead() function does not. It returns a value. Your functions should, too.

And I add them all in one because that's the only way I know to determine what is what in processing,

Processing has no idea that you used one Serial.print() statement.

because in processing I will split it every ", "

You can send a value in one print statement, and a comma in another. Processing will treat the stream however you define.

I don't agree with @PaulS about global variables. I like using global variables in the small Arduino environment as I can see how I am using my memory. I would use local variables within a function but life is too short to bother with passing parameters and receiving return values. I do use return values for small helper functions that, for example, work out the allowed limits for a value.

I don't think Paul was commenting on your use of functions - only on how you name them and how you name variables. It can be argued that you can use any names you like in your own program. But my personal experience is that Paul's is excellent advice - especially when your code gets a bit more complicated or if you are trying to remember what it does after an absence of 6 months. The other great advantage of carefully chosen names is that they become self-documenting. Remember that long names don't consume any program space - they are just for the information of you and the compiler.

The other important reason for using descriptive names is when you come looking for advice here. It makes your code many many times easier for us to follow. If I can't quickly see what somebody's code does I usually just pass on to another query on the basis "if s/he can't be bothered, why should I?"

The C String functions are not really suitable for the limited memory in an Arduino.

...R

The discussion has become side tracked by style issues.

Is your program now working as you want it to, and if not can you describe in detail what is happening?

...R

Im gonna repost this problem because its different from the title.

Don't start another Thread - that will just confuse everyone.

If you go back to your original post you can modify the title.

...R