Javascript->Serial Port, Serial Line Freezing

Hi everyone! I’m working on a project that involves passing commands from JavaScript → USB/Serial → Arduino Uno. Commands are being sent from JavaScript in the following format: <059> <359> <480>. When I send commands 1000ms apart, everything works fine. I need to send them much faster than that, and when I do, the serial connection locks up and the connection has to be re-initialized to continue. The less time between commands, the faster the connection locks up.

I’ve verified that the command are being sent properly from the JavaScript side and that they actually make it to the Arduino, however the Arduino isn’t parsing them in this format. If I break the commands down to individual bytes – so “<” “0” “5” “9” “>” – they get parsed ok and the Arduino responds as expected, however that significantly limits performance of my application. Thus, the decision to receive three commands + delimiters at a time.

I tried to emulate Nick Gammon’s phenomenal resource on serial communications (Gammon Forum : Electronics : Microprocessors : How to process incoming serial data without blocking), but, while I coded the core functionality of the sketch, I’m not the best programmer and quickly found myself in over my head. A friend helped pull together the buffer and delimiters part below. It works ok when I’m just inputting commands to the serial monitor or from Windows cmd prompt, but it doesn’t respond to the application we’re building at all.

I suspect the timing issue Nick mentioned is the problem, but I’m not sure. Is there a better way to implement the buffer & delimiters that might make the code respond properly, or does anyone have any suggestions we maybe haven’t thought of?

Thank you 8)

Commands are being sent from JavaScript

Does the JavaScript open the serial port, send the data, then close the serial port? If so, then the arduino may be resetting each time data is sent.

        switchThis(inSerial);             // process serial data

void switchThis (String inStr)

You are passing a non-NULL-terminated array of chars to a function that expects something else. Until you correct that problem, there is no sense looking for other problems.

Wrapping a char array in a String so that you can pick out the individual characters strikes me as stupid. The function should expect a pointer to a char array (char *).

zoomkat:

Commands are being sent from JavaScript

Does the JavaScript open the serial port, send the data, then close the serial port? If so, then the arduino may be resetting each time data is sent.

No, the connection remains open, but good suggestion.

PaulS:

        switchThis(inSerial);             // process serial data

void switchThis (String inStr)



Wrapping a char array in a String so that you can pick out the individual characters strikes me as stupid. The function should expect a pointer to a char array (char *).

Agreed. Didn't catch that that had been changed. It's corrected and that fixed the problem of the arduino not responding at all. Thanks a ton.

Seems like the Arduino's read performance could still stand to be optimized -- any suggestions for a better way to parse the incoming packets?

any suggestions for a better way to parse the incoming packets?

Parsing requires delimiters. You don't have any.

Given what you seem to be sending, I don't see a way to improve the interpretation of the data. Using that data, now that's a different story. You do nearly identical things with each digit, except for which pin it applies to. A function call would reduce the amount of code you need.

Servo control test code that uses a comma , as a delimiter. As you use < and > as delimiters, you could drop the < from the sending (I see no use for the start of packet delimiter), and just use the > as the end of packet delimiter if desired.

//zoomkat 3-5-12 simple delimited ',' string parce 
//from serial port input (via serial monitor)
//and print result out serial port
// CR/LF could also be a delimiter

String readString;
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);

  myservo.writeMicroseconds(1500); //set initial servo position if desired
  myservo.attach(7);  //the pin for the servo control 
  Serial.println("servo-delomit-test-22-dual-input"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like 700, or 1500, or 2000,
  //or like 30, or 90, or 180,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      if (readString.length() >0) {
        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);
          myservo.writeMicroseconds(n);
        }
        else
        {   
          Serial.print("writing Angle: ");
          Serial.println(n);
          myservo.write(n);
        }

        //do stuff with the captured readString 
        readString=""; //clears variable for new input
      }
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

PaulS:

any suggestions for a better way to parse the incoming packets?

Parsing requires delimiters. You don’t have any.

Given what you seem to be sending, I don’t see a way to improve the interpretation of the data. Using that data, now that’s a different story. You do nearly identical things with each digit, except for which pin it applies to. A function call would reduce the amount of code you need.

Do the < & > count as delimiters?

It makes sense that using function calls could help, but I’m unfortunately not really a programmer. How would you recommend we use them to speed things up?

The method you’re using to process characters as they arrive only works if the code is in sync with the incoming stream and characters arrive before you try to read them. This is not a good strategy.

Given that you have got explicit start and end markers, it seems to me that the most obvious way would be to discard incoming characters until you get the start marker and then buffer characters until you found the end marker. This is a trivial change from common techniques based on looking for end-of-line markers to denote the end of each message. I mean something like this:

if(Serial.available())
{
	char c = Serial.read();
	if(receiving)
	{
		if(c == '>')
		{
			// end of message
			// TODO: handle the current message content
			// TODO: clear the current message
			receiving == false;
		}
		else
		{
			// TODO: add the received character to the current message
		}
	}
	else
	{
		if(c == '<')
		{
			receiving == true;
		}
	}
}

You could buffer the received characters in a char array and then use strtol() or similar to parse that into a number, but if you know that the message is just going to contain a decimal string then it would IMO be cleaner to parse each character to a decimal digit and add that to a numerical accumulator (i.e. multiply the accumulator by ten and add the new digit).