Better Serial library? & Why we have to make delay after sending info. in Serial

I'm working on the project need to use RS-485 network. Each time I send ASCII code through Serial port, I have to make a delay() for the communication. The delay time depends on the length of the info. If I have many code to send & Receive, It become a really though time for me. Is there some one know a better Serial port library, or any tips for this problem?
Thanks!

Gfast:
I'm working on the project need to use RS-485 network. Each time I send ASCII code through Serial port, I have to make a delay() for the communication. The delay time depends on the length of the info. If I have many code to send & Receive, It become a really though time for me. Is there some one know a better Serial port library, or any tips for this problem?
Thanks!

What version of the IDE are you using? I believe this was fixed/improved with the latest IDE version.

Lefty

On my MAC and Windows are all 1.0.4. Cause the project that I'm working on is for me too huge now. I'm using actually Atmel Studio 6.1 + Visual Micro (Plug-in) to program the code and They call the compiler of Arduino IDE I think to do the compiling work and upload.

Each time I send ASCII code through Serial port, I have to make a delay() for the communication.

Why? Why do you need to delay? What happens if you don't? Are you just assuming that a delay will eliminate the need to read and deal with any response?

Why? Why do you need to delay? What happens if you don't? Are you just assuming that a delay will eliminate the need to read and deal with any response?

Ye, some kinda of. For instance, some commands are used to set a "question" for motor. If I send the command without delay(), motors will not answer this command or they just do not do the thing that the command asked. With the help out my oscilloscope, I "fine tune" all the questions with a "proper" delay(), in order to let the command have enough time to be sent, than I write "If (Serial2.available()) {}...".

Show your code? You don't need to delay at all, however sending data takes time.

Let's put it like this: if you put on a roast beef in the oven, it takes time to cook. You can "delay" and wait for it to finish, or you can do something else. Either way, it still takes time to cook.

All Code can be find here: Software Serial used on Arduino UNO R3 convert to Mega 2560 Hardware Serial - Networking, Protocols, and Devices - Arduino Forum
the really Tricky Part is in here (in the main code's "manualDrive.ino")

Serial2.println("#1p5"); //Set the motor's mode to "Rotate and speed changeable mode".
Serial2.println("#1d0"); //Set the motor's rotate direction to "left".
Serial2.println("#1pA"); //Let the motor start to execute the movement.

Theses command should be at one time sent to set the motor in a certain "modi" and do the specified thing. If I don't add a 8ms delay() between them, the effect is that the motor start to rotate but the direction is the opposite one.
BTW, the motor is Nanotec P4D (working on 24V)

If I don't add a 8ms delay() between them, the effect is that the motor start to rotate but the direction is the opposite one.

The problem is not the serial data, then. There is something about the motor and it's handling of serial data. You need to investigate that, not blame the HardwareSerial class.

The problem is not the serial data, then. There is something about the motor and it's handling of serial data. You need to investigate that, not blame the HardwareSerial class.

Pauls, thanks! I thought the problem is from the Arduino side. Yeh, It seems not. And I discover, the Serial communication of the Motor is pretty tricky. I've to investigate more time on them!

BTW: I discovered today, the .flush() for Serial2 don't works at all!?

Gfast:
I'm working on the project need to use RS-485 network.

This is close to becoming a cross-post. Your other thread also talks about serial problems. How about, next time, actually providing a link to "the project" rather than making us guess, or possibly solve the same problem twice?

Gfast:
All Code can be find here: Software Serial used on Arduino UNO R3 convert to Mega 2560 Hardware Serial - Networking, Protocols, and Devices - Arduino Forum
the really Tricky Part is in here (in the main code's "manualDrive.ino")

Is this it?

int chipDriver = 8; //This PIN drives the RS-485 chip's mode. HIGH=="send" LOW=="Recieve" 

void setup()
{
	Serial.begin(19200);
	Serial1.begin(19200); //This is the Serial port connected to the weight transmitter.
	pinMode(chipDriver,OUTPUT);
	digitalWrite(chipDriver,LOW);
}

void loop()
{
	digitalWrite(chipDriver, HIGH); //Set RS-485 chip's mode to "send"
	//'

BTW: I discovered today, the .flush() for Serial2 don't works at all!?

I don't see Serial2.flush there.

Please don't play these guessing games. If you want help, post the relevant code, and then describe what "don't works at all!" means for you.-Start of the message, "01"-weight transmitter's address,
//"ZERO"-command to set transmitter to Zero, "03" the XOR result from
//"01ZERO", "\r"-Carriadge return to end the command.
Serial1.write("$01ZERO03\r"); //send command through Serial1 port
digitalWrite(chipDriver, LOW); //Set RS-485 chip's mode to "receive"

//if some thing is available from Serial1, write it on Serial port.
while(Serial1.available() > 0){
	Serial.write(Serial1.read());
}

}


---

> BTW: I discovered today, the .flush() for Serial2 don't works at all!?

I don't see Serial2.flush there.

Please don't play these guessing games. If you want help, post the relevant code, and then describe what "don't works at all!" means for you.

Hi Nick, Thanks for your patient answer and the tipps! Next time I'll try my best to describe my project better!

Is this it?

Yes, this is it. But I'm sorry the attached code isn't up to date. I put here this time a new one.

Today I've tried again if the "Serial2.flush();" works. And it not at all.
Detail: in the setup(), I send a bunch of commands to the motor, in order to let it surely work at the proper state:

        sendToMotor("#1S"); //motor stop
	sendToMotor("#1g32"); //Schrittmodus einstellen (Vollschritt etc.)
	sendToMotor("#1:ramp_mode=0"); //Trapez-Rampe(0), Sinusrampe(1), Jerkfreerampe(2) Seite37
	sendToMotor("#1p5"); // '5' - Drehzahlmodus, '2' - "Absolute Positionierung" Seite47
	sendToMotor("#1u100"); //Minimalfrequenz Seite49
	sendToMotor("#1o8000"); //Maximalfrequenz Seite50
	sendToMotor("#1b41649"); //equal to 3Hz/ms, set acceleration Seite51
	sendToMotor("#1d1");//'0' - links, '1' - rechts	
	sendToMotor("#1I"); //Drehgeber auslesen
	sendToMotor("1#U0");//'0' - aus, '1' - Korrektur nach einer Fahrt, '2' - Kor. waehrend einr Fahrt Seite23

Then, I should get the right answer from each command, And I did it with:

        while(Serial2.available())
		Serial.write(Serial2.read());
	while(Serial2.read()>0); //".flush();" don't work for Serial2

Question 1: I can get the answer from the motor, and even I write a "flush()" before this snippet, I can still get the answer from motor. I write like this:

        Serial2.flush();
	while(Serial2.available())
		Serial.write(Serial2.read());
	while(Serial2.read()>0); //".flush();" don't work for Serial2

Question 2: This should be the real tricky problem happening all through my communication with motors!
the funciton "sendToMotor()" is pretty simple:

/*****
* Purpose: send a String to motor's rs485 port
* Argument: String message
* return: void
* input: string message
* output: send message through Serial port direct to motors.
*****/
void sendToMotor(String message) {
	Serial2.print(message);
	Serial2.print('\r');
	delay(10); //the delay time should be even smaller to speed up the system update speed
}

If I send commands through this command, and the delay() in it is only be set as 5ms, I can't get all the expected answers. If it's 10ms, I can get the correct amount of answers. (I attach the screen shoots of the serial monitor in these two situations).
My thought: I send command too fast, that the serial port of some side or even both sides of the serial communication overload.

Juni25a_TwoSoftwareSerial.rar (22.8 KB)

delay(5) send command.png

delay(10) send command.png

This is close to becoming a cross-post. Your other thread also talks about serial problems. How about, next time, actually providing a link to "the project" rather than making us guess, or possibly solve the same problem twice?

Nick, cause I'm a new bie, I'm not sure what you mean. Should I put the total project description on somewhere here?
The other post is for the rs-485 network (half duplex) of the weight transmitters. This one is for the even trickier rs-485 for motors (full duplex).
This is the link of the step motor that I use:

What are you expecting the flush() call to do? It's function is different depending on the IDE version.

@Nick:

Let's put it like this: if you put on a roast beef in the oven, it takes time to cook. You can "delay" and wait for it to finish, or you can do something else. Either way, it still takes time to cook.

You forgot the most common cooking mistake here. You can put the roast in the oven, don't wait for it to cook, then remove it immediately and eat it raw. :smiley:

It's function is different depending on the IDE version.

Thank you really so much! You help me at this very point! Great!

And then comes the new problem!!
On theory, we can wait for all the Serial communication done through the help of "Serial.flush();" in a very "smart" way. But even so, I still can't get the right answer from the motor? I mean like different delay time have different answer from the motor. I don't set delay, but Serial.flush(); between each command to let the code wait for the Serial communication. But still can't got all the answers!

What a tricky & expensive motor!

Serial data transmission is generally bidirectional. Asynchronous, yes, but bidirectional. I don't see anywhere in your code where you care what the motor might be saying in response to your commands, if it responds at all.

The command pages I looked at indicate that each command causes a reply. Why aren't you concerned about the responses?

The command pages I looked at indicate that each command causes a reply. Why aren't you concerned about the responses?

Yeh, Pauls. You are almost right. I don't need much bidirectional communication between arduino and step motor. 99% command is "single directional". I'm not sure in really professional area how many motor will be controlled by his own build-in microcontroller and in my motor (Nanotec PD4-N) there is even a "shaft encoder" that can record the absolutely position of the motor. In my project I have to read the value through Serial port. So I have to do care about if the command is correctly be gotten by motors. And I think my still works not great function that read this value should be enhanced.

/*****
* Purpose: get the actual drehzahl of the motor. (Right-rotation add the Drehzahl, left reduce it)
* Argument: void
* Return: void
* input: void
* output: the position value "drehWert" read from the integrated circuit of the motor
*****/
void Drehgeber() {
	char signAscii;
	int sign; //Here can not be "byte", that can't save negative value.
	int  length;
	
	Serial2.println("#1I"); //"ask" motor for the position value.
	if (Serial2.available()) {
		length = Serial2.available(); //if a bit is readed, than it doesn't exist in the serial buffer anymore.
		if (Serial2.read() == 49){ //wenn erste Stelle eine '1' ist (Motoradresse),(this part should be refactoringed to let the other motor also work)
			if (Serial2.read() == 73){ //wenn nächste Stelle ein 'I' ist (Drehgeberposition)
				drehwert = 0;
				signAscii = Serial2.read(); //Ascii '+' or '-'
				if (signAscii == '+') //wenn Ascii Wert = 43 dann positiv
				sign = 1; //store the polarity of the absolute position value from shaft encoder.
				else if (signAscii == '-') //wenn Ascii Wert = 45 dann negativ
				sign = -1;
				for (int i=(length-5); i>=0; i--){
					int Wert = Serial2.read();
					drehwert = drehwert + ((Wert - 48) * pow(10,i)); //calculate the read value
				}
				drehwert = drehwert * sign; //here set the direction of the absolute positioin value.
			}
			Serial.print(" position:");
			Serial.println(drehwert);
		}
		else Serial.println("ERROR, Drehgeber crashed!");
		while(Serial2.read()>0); //clear the Serial2's buffer
	}
}

Protocol:
Ask command format:
"#1I\r" -- '#'-command start, '1'-motor address,'I'-command asking for shaft encoder read value, '\r'-CR end symbol
Answer command format:
"1I00000000\r" -- '1'-motor address, 'I"-command asking for shaft encoder read value, "00000000"-read value,'\r'-CR end symbol
The read value don't have fixed bits. I thought the parsing method is very poor... And I can't make it better any further.

BTW: In 2011, Pauls you helped me this year to build a perfect working Xbee communication. I appreciate your kindly help. Here I'd like to thank you once more. :slight_smile:

I don't need much bidirectional communication between arduino and step motor.

Once it's working, you probably don't need any. Until then, it's a good idea to understand what the stepper motor is getting and what it is accepting or rejecting, in case some input you are giving it is not quite right.

	if (Serial2.available()) {
		length = Serial2.available(); //if a bit is readed, than it doesn't exist in the serial buffer anymore.
		if (Serial2.read() == 49){ //wenn erste Stelle eine '1' ist (Motoradresse),(this part should be refactoringed to let the other motor also work)
			if (Serial2.read() == 73){ //wenn nächste Stelle ein 'I' ist (Drehgeberposition)
				drehwert = 0;
				signAscii = Serial2.read(); //Ascii '+' or '-'
				if (signAscii == '+') //wenn Ascii Wert = 43 dann positiv
				sign = 1; //store the polarity of the absolute position value from shaft encoder.
				else if (signAscii == '-') //wenn Ascii Wert = 45 dann negativ
				sign = -1;
				for (int i=(length-5); i>=0; i--){
					int Wert = Serial2.read();

If there is at least one byte available to read, that does not mean that you can then read as many as you want.

Gfast:
And I did it with:

        while(Serial2.available())
	Serial.write(Serial2.read());
while(Serial2.read()>0); //".flush();" don't work for Serial2


...
My thought: I send command too fast, that the serial port of some side or even both sides of the serial communication overload.

I don't see what that code usefully achieves. Rather than explaining at great length, read this:

Gammon, It works!
I used your last example to parse from Serial coming Data. Bravo!

But I do did a tiny modification on it:
in the "void loop(){}" I changed "if (Serial.available())" to "while (Serial.available())". If I don't, the Serial buffer will be overflowed (But I'm not pretty clear about this point.)

Thank you again!

P.S. The function that works perfectly now is:

const char startOfNumberDelimiter = 'I';
const char endOfNumberDelimiter   = '\r';

void shaftEncoder(){
	Serial2.print("#1I\r");
	while (Serial2.available())
		processInput();
}

void processNumber (const long n)
{
	Serial.println (n);
}  // end of processNumber

void processInput ()
{
	static long receivedNumber = 0;
	static boolean negative = false;
	
	byte c = Serial2.read ();
	
	switch (c)
	{
		case endOfNumberDelimiter:
		if (negative)
		processNumber (- receivedNumber);
		else
		processNumber (receivedNumber);
		
		// fall through to start a new number
		case startOfNumberDelimiter:
		receivedNumber = 0;
		negative = false;
		break;
		
		case '0' ... '9':
		receivedNumber *= 10;
		receivedNumber += c - '0';
		break;
		
		case '-':
		negative = true;
		break;
		
		case '+':
		negative = false;
		break;
		
		default:
		Serial.println("!");
		break;
		
	} // end of switch
}  // end of processInput