freeze when receiving multi values on serial data, overflow issue?

but the problem is that all things VERY WELL and respond INSTANT when i just exchange data between the 2 arduino (and the 2 XBee mounted over) in this way <value1,value2,values3> but the problem start when the third values exceeds a threshold
for exampe, all work fine when i send

<45,26,96>

but it start like to freeze when the third value being of 3 digits:

<45,26,166>

it seems to be like an buffer problem not?

jonnys90:
it seems to be like an buffer problem not?

My demo code sets the buffer size at 32 bytes. You can easily change that.

...R

Yeah sure, but i've already tried that many times.. even 64,128,256
By then i don't sleep so much cause just thinking about to solve this problem...
And i don't think arduino have a problem just to send and receive 3 values over wireless serial.. with all the projects i've seen much more complex 100 times than mine that

jonnys90:
Yeah sure, but i've already tried that many times.. even 64,128,256

Post the latest version of your two programs.

...R

I've removed the almost all unused things

Tx

/*
 Example sketch for the PS3 Bluetooth library - developed by Kristian Lauszus
 For more information visit my blog: http://blog.tkjelectronics.dk/ or
 send me an e-mail:  kristianl@tkjelectronics.com
 */

#include <PS3BT.h>
#include <usbhub.h>

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif

USB Usb;
//USBHub Hub1(&Usb); // Some dongles have a hub inside

BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so

PS3BT PS3(&Btd); // This will just create the instance

bool printTemperature;
bool printAngle;
const uint8_t LED_tx = 2;

char dataPacket[64];

int Servo1 = 90; // 2 char
int Servo2 = 0; // 3 char
int Servo3 = 0;
int led1 = 0;
int led2 = 0;


const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use by strtok() function
char messageFromPC[numChars] = {0};
int servo = 90;
int integerFromPC = 0;
float floatFromPC = 0.0;
int shock = 0;

boolean newData = false;

void setup() {
 pinMode(LED_tx, OUTPUT);
 Serial.begin(57600);

#if !defined(__MIPSEL__)
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
  if (Usb.Init() == -1) {
    Serial.print(F("\r\nOSC did not start"));
    while (1); //halt
  }
 Serial.print(F("\r\nPS3 Bluetooth Library Started"));

    Serial.println("This demo expects 3 pieces of data - text, an integer a floating point and an integer value");
    Serial.println("Enter data in this style <text,12,24.7,55>  ");
    Serial.println();
  
}
void loop() {
  Usb.Task();

  if(PS3.PS3Connected || PS3.PS3NavigationConnected) {
 servo = map(PS3.getAnalogHat(LeftHatX), 0, 255, 0, 180);
      if (PS3.getButtonClick(TRIANGLE)) {
          led1 = 1;
      } else {
          led1 = 0;
        }
      if (PS3.getButtonPress(CIRCLE)) {
          led2 = 1;
      } else {
          led2 = 0;
        }
 }

  Serial.print("<");
  Serial.print("hello CAR");
  Serial.print(",");
  Serial.print("1");
  Serial.print(",");
  Serial.print("2.3");
  Serial.print(",");
  Serial.print(servo);
  Serial.print(",");
  Serial.print(led1);
  Serial.print(",");
  Serial.print(led2);
  Serial.println(">");

    recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() replaces the commas with \0
        parseData();

        newData = false;
    }


  if (PS3.PS3Connected || PS3.PS3NavigationConnected) {

    if (PS3.getButtonClick(PS)) {
      Serial.print(F("\r\nPS"));
      PS3.disconnect();
    }
    else {
//      if (PS3.getButtonClick(TRIANGLE))
//        Serial.print("\r\nH");
//      if (PS3.getButtonPress(CIRCLE))
//        Serial.print(F("\r\nH"));
        
      if (PS3.PS3Connected)
        digitalWrite(LED_tx, PS3.getButtonPress(CROSS));
      else
        digitalWrite(LED_tx, LOW);
    }
  }
}

//============

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

//============

void parseData() {

      // split the data into its parts
    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars,",");      // get the first part - the string
    strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
 
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    integerFromPC = atoi(strtokIndx);     // convert this part to an integer

    strtokIndx = strtok(NULL, ",");
    floatFromPC = atof(strtokIndx);     // convert this part to a float

    strtokIndx = strtok(NULL, ",");
    shock = atoi(strtokIndx);

}

Rx

#include <Servo.h>

const int ledPin = 12;                      // the pin that the LED is attached to
int incomingByte;                           // a variable to read incoming serial data into
int val = 0;
int grado = 99;

Servo myservo;

// Receive with start- and end-markers combined with parsing

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use by strtok() function

      // variables to hold the parsed data
char messageFromPC[numChars] = {0};
int servo = 8;
int led1 = 0;
int led2 = 0;
int integerFromPC = 0;
float floatFromPC = 0.0;
int shock = 77;

boolean newData = false;

void setup() {
  Serial.begin(57600);                      // initialize serial communication

  Serial.println( "Serial Start" );
  pinMode(ledPin, OUTPUT);                  // initialize the LED pin as an output
  myservo.attach(7);

    Serial.println("This demo expects 3 pieces of data - text, an integer, a floating point, and 3 other integer values");
   
    Serial.println();

  }

void loop() {

  Serial.print("<");
  Serial.print("hello PS3");
  Serial.print(",");
  Serial.print("3");
  Serial.print(",");
  Serial.print("2.1");
  Serial.print(",");
  Serial.print(shock);
  Serial.println(">");


    recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() replaces the commas with \0
        parseData();

        newData = false;
    }


    val = servo;
       myservo.write(val);

    if (led1 == 1) {
       digitalWrite(ledPin, HIGH);      
      } else {
        digitalWrite(ledPin, LOW);
        }
    if (led2 == 1) {
       digitalWrite(ledPin, HIGH);      
      } else {
        digitalWrite(ledPin, LOW);
        }
 
}

//============

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

//============

void parseData() {

      // split the data into its parts
    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars,",");      // get the first part - the string
    strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    integerFromPC = atoi(strtokIndx);     // convert this part to an integer

    strtokIndx = strtok(NULL, ",");
    floatFromPC = atof(strtokIndx);     // convert this part to a float
 
    strtokIndx = strtok(NULL, ",");
    servo = atoi(strtokIndx); 
 
    strtokIndx = strtok(NULL, ",");
    led1 = atoi(strtokIndx);
 
    strtokIndx = strtok(NULL, ",");
    led2 = atoi(strtokIndx);
 
}

As I mentioned already, you don't seem to have any means to get dubugging information and without that it is rather difficult to debug the problem.

I suggest you simplify the system to start with. Put aside the XBees and the USB Host shield and write a program to send the necessary data using SoftwareSerial to send and receive the data over a wired connection between the two Arduinos. That will leave HardwareSerial on both Arduinos free for debug messages.

When you can get that to work I suggest you add in the USB Host shield and get that working. If all of that works properly you could then switch the references to SofwareSerial to Serial and try the XBee shields.

I am concerned that I don't see any control over the freqency at which new data is transmitted. My guess is that you are sending data much too frequently. How about deliberately reducing it to (say) 5 times per second.

The code you posted sends messages in both directions - is that necessary? Should there be some coordination between the two devices? For example only send a reply after a message is received?

...R

i've just passed another day of change, upload reset and restart again and now i can't even send a default values
I made as you suggest to me, i removed the xbee shields and i used only the 2 arduinos naked with your functions, and
My configuration now use SoftwareSerial to send and the HardwareSerial for debug but i receive only 0 for my added value:

Message hello CAR
Integer 1
Float 2.30
Servo 0
Led1 0
Led2 0

and

Message hello PS3
Integer 3
Float 2.10
Shock 0

:frowning:

Please can you provide me 2 simple sketches with your functions for Tx and Rx with 2-3 more INT values? maybe i done something wrong when i add my custom value.

jonnys90:
i've just passed another day of change, upload reset and restart again and now i can't even send a default values
I made as you suggest to me, i removed the xbee shields and i used only the 2 arduinos naked with your functions, and
My configuration now use SoftwareSerial to send and the HardwareSerial for debug but i receive only 0 for my added value:

I had hoped that by now you would know to post your code without having to be reminded.

Please can you provide me 2 simple sketches with your functions for Tx and Rx with 2-3 more INT values? maybe i done something wrong when i add my custom value.

I will see if I have time tomorrow morning. It would be much easier for me if I can see your latest code first.

...R

Yeah, i've ri writed the 2 sketches just with your functions and a added some default values to be sent, using SoftwareSerial for sending and the HardwareSerial for debuggin.
It seems to work fine in this way, but with a delay of 500ms..

So now i will start to add the controller config and after to test it without SoftwareSerial and removing the delay or can leave a little minimum delay, cause anyway as i need to control the RC car and receive the force feedback back i need an instant communication.

As you ask me, this the the currently code, please check it if need to correct something in this first part:

TX

#include <SoftwareSerial.h>
SoftwareSerial XSerial(9, 8); // TX, RX

const byte numChars = 32;
char receivedChars[numChars];

// char endMarker = '>';
boolean newData = false;

//	variable values to be received and to hold the parsed data
char messageFromCAR[32] = {0};
int integerFromCAR = 0;
float floatFromCAR = 0.0;

int shock = 0;

// variable values to be sent
int servo = 55;
int led1 = 0;
int led2 = 1;


void setup() {
    Serial.begin(57600);
    Serial.println("<Arduino Controller is ready>");

	XSerial.begin(57600);
	XSerial.println("Hello, car?");
}

void loop() {
    recvWithStartEndMarkers();
    showNewData();

	parseData();
	showParsedData();

	XSerial.print("<");
	XSerial.print("Hello CAR");
	XSerial.print(",");
	XSerial.print("1");
	XSerial.print(",");
	XSerial.print("2.3");
	XSerial.print(",");
	XSerial.print(servo);
	XSerial.print(",");
	XSerial.print(led1);
	XSerial.print(",");
	XSerial.print(led2);
	XSerial.println(">");

	delay(500);	
}

// #########################	FUNCTIONS	#########################

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;
 
 // if (Serial.available() > 0) {
    while (XSerial.available() > 0 && newData == false) {
        rc = XSerial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0';	// terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

void showNewData() {
    if (newData == true) {
//	Serial.print("Data Recieved :");
//	Serial.println(receivedChars);
        newData = false;
    }
}

void parseData() {

    // split the data into its parts
    
  char * strtokIndx;						// this is used by strtok() as an index
  
  strtokIndx = strtok(receivedChars,",");	// get the first part - the string
  strcpy(messageFromCAR, strtokIndx); 		// copy it to messageFromPC
  
  strtokIndx = strtok(NULL, ",");			// this continues where the previous call left off
  integerFromCAR = atoi(strtokIndx);			// convert this part to an integer
  
  strtokIndx = strtok(NULL, ",");
  floatFromCAR = atof(strtokIndx);			// convert this part to a float

  strtokIndx = strtok(NULL, ",");
  shock = atoi(strtokIndx);

}


void showParsedData() {
 Serial.print("Message ");
 Serial.print("\t");
 Serial.println(messageFromCAR);
 Serial.print("Integer ");
 Serial.print("\t");
 Serial.println(integerFromCAR);
 Serial.print("Float ");
 Serial.print("\t\t");
 Serial.println(floatFromCAR);
 Serial.print("Shock ");
 Serial.print("\t\t");
 Serial.println(shock);
 Serial.println("");
}

RX

#include <SoftwareSerial.h>
SoftwareSerial XSerial(9, 8); // TX, RX

const byte numChars = 32;
char receivedChars[numChars];

// char endMarker = '>';
boolean newData = false;

//	variable values to be received and to hold the parsed data
char messageFromPS3[32] = {0};
int integerFromPS3 = 0;
float floatFromPS3 = 0.0;

int servo = 0;
int led1 = 0;
int led2 = 0;

// variable values to be sent
int shock = 14;


void setup() {
    Serial.begin(57600);
    Serial.println("<Arduino Car is ready>");

	XSerial.begin(57600);
	XSerial.println("Hello, ps3?");
}

void loop() {
    recvWithStartEndMarkers();
    showNewData();

	parseData();
	showParsedData();

	XSerial.print("<");
	XSerial.print("Hello PS3");
	XSerial.print(",");
	XSerial.print("4");
	XSerial.print(",");
	XSerial.print("5.6");
	XSerial.print(",");
	XSerial.print(shock);
	XSerial.println(">");

	delay(500);	
}

// #########################	FUNCTIONS	#########################

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;
 
 // if (Serial.available() > 0) {
    while (XSerial.available() > 0 && newData == false) {
        rc = XSerial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0';	// terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

void showNewData() {
    if (newData == true) {
//	Serial.print("Data Recieved :");
//	Serial.println(receivedChars);
        newData = false;
    }
}

void parseData() {

    // split the data into its parts
    
  char * strtokIndx;						// this is used by strtok() as an index
  
  strtokIndx = strtok(receivedChars,",");	// get the first part - the string
  strcpy(messageFromPS3, strtokIndx); 		// copy it to messageFromPC
  
  strtokIndx = strtok(NULL, ",");			// this continues where the previous call left off
  integerFromPS3 = atoi(strtokIndx);			// convert this part to an integer
  
  strtokIndx = strtok(NULL, ",");
  floatFromPS3 = atof(strtokIndx);			// convert this part to a float

  strtokIndx = strtok(NULL, ",");
  servo = atoi(strtokIndx);

  strtokIndx = strtok(NULL, ",");
  led1 = atoi(strtokIndx);

  strtokIndx = strtok(NULL, ",");
  led2 = atoi(strtokIndx);

}


void showParsedData() {
 Serial.print("Message ");
 Serial.print("\t");
 Serial.println(messageFromPS3);
 Serial.print("Integer ");
 Serial.print("\t");
 Serial.println(integerFromPS3);
 Serial.print("Float ");
 Serial.print("\t\t");
 Serial.println(floatFromPS3);
 Serial.print("Servo ");
 Serial.print("\t\t");
 Serial.println(servo);
 Serial.print("Led1 ");
 Serial.print("\t\t");
 Serial.println(led1);
 Serial.print("Led2 ");
 Serial.print("\t\t");
 Serial.println(led2);
 Serial.println("");
}

Thanks

You can't put in delay(500); like that because it prevents loop() from repeating quickly. loop() should repeat hundreds or thousands of times per second.

Use millis() to manage timing without blocking as illustrated in Several Things at a Time

You should create a function to send your data and ensure that that function is only called every 500 msecs.

...R

1 i just use 500ms as i'm debugging and less than this can freeze/broke the SoftwareSerial
2 I know millis() but what i need here it's NOT to run thigs at same time, infact if i can choose i WOULDN'T even use 1ms of delay, but as i tested before without a minimum delay of 10ms it has freezed (maybe overflowed the buffering) the RX arduino

You can use millis() to manage timing in any way you want.

Can you describe in English (not code) the exact sequence of events you want to happen and then maybe we can figure out how to achieve that.

...R

I do not have any specific sequences requirements but i just would to send some comands to the RX (RC car) in the most fast way possible, and need also that the RX Car sends back instantly some value like from the feedback force sensor that i will mount.

Based on Reply #32 it seems to me the simplest way to organize the 2 programs is for both programs to listen for data continuously using recvWithStartEndMarkers(). The Tx would start by assuming it can send a message and the Rx would start by assuming it can't.

Switch on the Rx first and wait a few seconds to allow it to start listening and then start the Tx. It will send a message and then it will not send another message until it gets a reply from the Rx.

For its part the Rx will stay listening until it receives a message and then it will send its reply and go back to waiting for another message.

Would that sort of system be suitable?

...R

Mmm, but

Robin2:
The Tx would start by assuming it can send a message and the Rx would start by assuming it can't.

Switch on the Rx first and wait a few seconds to allow it to start listening and then start the Tx. It will send a message and then it will not send another message until it gets a reply from the Rx.

For its part the Rx will stay listening until it receives a message and then it will send its reply and go back to waiting for another message.

Are this system will not going to affect the latency of their communication between the 2 arduino?
if not, it can be a good "alternative"..

jonnys90:
Are this system will not going to affect the latency of their communication between the 2 arduino?
if not, it can be a good "alternative"..

What level of latency would be acceptable? (And "zero" is not a practical answer).

If the system I suggested in NOT acceptable you will need to figure a more complex scheme to prevent everything getting tangled up.

You could have an asynchronous system in which each device transmits at specific intervals (say 10 times per second) and each only sends short messages (less then 64 bytes) that fit in the Serial input buffer so there is no risk of overflow. But if you do that you will need to consider very carefully how each program interprets the received data in the context of its other activities, including data it has already sent, or is about to send.

You would also need to ensure that each program could read and deal with 10 messages per second.

In any case I can't see what added value you would get with 10 messages per second done asynchronously compared with doing the same thing synchronously like I suggested.

...R

i don't know, but imho i think that 10 times per second it would be a little bit slowly if we think that we need a fast communication with fast reaction to comand an RC Car/and receive feedback, for the byte it wouldn't be a problem as i just need to send 3-4 value numbers as <xxx,xxx,xxx,xxx>

jonnys90:
i don't know, but imho i think that 10 times per second it would be a little bit slowly

So tell us what you require - at the moment you are just finding problems when you should be focusing on solutions.

Personally I can't respond as fast as 10 times per second.

...R

Yeah infact i already started to make these changes and to test how it would works with that little "delay".

But this part in the loop():

   while (Serial.available() > 0) {
        incomingByte = Serial.read();
 
 if (incomingByte == 'H') {
 digitalWrite(led_rx, HIGH);
 } else digitalWrite(led_rx, LOW);
 }

interferes with this part inside your function

while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

How i can write it without to add my part inside your recvWithStartEndMarkers() function?
because if i rename my incomingByte to rc it ask me to add the variable rc and vice versa if i rename your rc to incomingByte it doesn't work anyway

jonnys90:
Yeah infact i already started to make these changes and to test how it would works with that little "delay".

But this part in the loop():

For goodness sake - you don't use them both. Just use my function.

...R