problem with hardware serial, not with altsoftserial

Hi to everyone,

I'm trying to write some code to control a gprs module (with arduino pro). During a day I was getting crazy because the gprs module did not reply to AT commands.
Today I tried to change the code (just change Serial. to altsoft in the print command, nothing more) to use altsoftserial to program the gprs module and everything is goes ok. What is the problem hardware serial? I tried it with small pieces of code, so here is one:

        timeout = millis() + REPLY_TIMEOUT;
	Serial.flush();
        Serial.println("AT+QPOWD=1\r\n");
	while (timeout > millis()){
                if (Serial.find("NORMAL POWER DOWN")){
			nss.println ("Module AT off");
			break;
		}
		
	timeout = millis () + POWER_ON_OFF_DELAY;
	while (timeout > millis ()){
		if (digitalRead (STATUSPIN) == LOW){
			success= 0;
			nss.println ("Module off");
			break;
		}
	}

With that code the GPRS module appears to not receive or not respond to the At command.

I suppose that an option would be use altsofserial instead of hardware serial but this is a small of a project including a gps and others sensors. Now I’m trying each part with arduino pro but the plan is to integrate all the code in a sanguino running at 8 mhz. The gps will use altsoftserial and the gprs module hardware serial because it will transfer a small file to a ftp server.

Thanks in advance for your help and sorry for my limited english

Useful

Code snippets here don't work. You need to post all of your code, and describe how the hardware is connected. If you simply changed Serial for AltSoftSerial, without changing any hardware, nothing is going to work.

Using AltSoftSerial, or any software serial, on the hardware serial pins does not make sense.

	Serial.flush();

What is this doing, and why are you using it? I'd hazard a guess that 99.99% of all uses of the flush() method are wrong or unnecessary.

Sorry, here are the code:

#include <AltSoftSerial.h>

#define NETWORK_SEARCH_DELAY 10000
#define POWER_ON_OFF_DELAY 15000
#define FTP_DELAY 10000
#define	REPLY_TIMEOUT 3000
#define ON_OFF 2
#define STATUSPIN 3

boolean STATUS;
AltSoftSerial nss;

void setup (){
  
  nss.begin (9600);
  byte success;
  delay (5000);
  nss.println ("vamos");
  delay(5000);
  nss.println ("on push");
  
  if (powerOn ()){
    nss.println ("power on");
    success = 0;
    unsigned long timeout;
    timeout = millis() + POWER_ON_OFF_DELAY;
    Serial.flush();
    while (timeout > millis()){
    if (Serial.find("Call Ready")){
      success = 1;
      nss.println ("Module ready");
      break;
    }
    else {
      nss.println ("No call ready found");	
    }
    }
  }
    
  if (success == 1) {
        nss.println ("success =1");
    	timeout = millis() + REPLY_TIMEOUT;
	Serial.flush();
        Serial.print("AT+QPOWD=1\r\n");
	while (timeout > millis()){
                if (Serial.find("NORMAL POWER DOWN")){
			nss.println ("Module AT off");
			break;
		}
	}
	
	timeout = millis () + POWER_ON_OFF_DELAY;
	while (timeout > millis ()){
		if (digitalRead (STATUSPIN) == LOW){
			success= 0;
			nss.println ("Module off");
			break;
		}
	}
  }
 
} // final setup


void loop (){
  
  
}


boolean powerOn(){
bool	success = false;
	pinMode (ON_OFF, OUTPUT);
//set on/off pin
	pinMode (STATUSPIN, INPUT);  //set status pin
	
	digitalWrite (ON_OFF, LOW); // power on M95
	delay (1500); // min high to power on 1000
	digitalWrite (ON_OFF, HIGH);
	if (digitalRead (STATUSPIN) == HIGH){
		
		success = true;
		nss.println ("on a la primera");
	}
	
	else{
		digitalWrite (ON_OFF, LOW); // power on M95
		delay (1500); // min high to power on 1000
		digitalWrite (ON_OFF, HIGH);
		if (digitalRead (STATUSPIN) == HIGH){
			STATUS = true;
			success = true;
			nss.println ("on a la segunda");
		}
	}
	
	return (success);
}

When altsoftserial is used to communicate with the gprs (quectel m95 evb kit), I directly attach arduino altsoftserial rx and tx pins with tx and rx pins of the module. An sparkfun ftdi basic is connected to the arduino and the outcome of the serial port is displayed in the serial monitor. With this configuration all goes ok.
When I use the harware serial port to connect with the gprs, hardware serial rx and tx pins are connected to the tx and rx pins of the module and I connect the ftdi rx and tx pins to the tx and rx pins of the arduino altsoftwareSerial and also the positive and negative output of the ftdi to the arduino to power it. And of course I change the Serial instances to nss (altsoftserial) and viceversa. I use serial monitor to see the outcome of the program. In this case the module power on without problems and the serial harware "detects" it because I can see in the serial monitor "Module ready". Afterwards the module do not switch off instead I know the program enters in the ( if (success == 1)).
I'm a newbie in programming. I use the Serial.flush to "clean" the serial buffer,in this programs pehaps it is not neccesary baut in other functions with the gprs module I think is neccesary because different AT commands have the same response ("ok"). I suppose I'm wrong with it use.
Thank you very much!!

Can you confirm which pins you are using for AltSoftSerial? It requires the use of specific pins, depending on board type.

Now, in the arduino pro 328, pin are rx 8 and tx 9.

pipeSG,
I'm assuming you are wanting to clear RX buffers and are using Serial.flush() to do it.
The problem is that the Arduino team changed what "flush" does in HardwareSerial
when they went to TX buffering and interrupt driven output in the newer versions of the
Arduino core code.
HardwareSerial no longer purges out the RX buffer data like it still does in the Softserial libraries.
In HardwareSerial flush() now waits to push all the character in the software buffers
out the USART but can return before the last 2 characters fully exit the USART.
The HardwareSerial code does not account for
1 character that can be in the USART FIFO and 1 in the USART transmit buffer,
so IMO, the new flush() is even useless for trying to ensure that all the characters have exited
the USART.

My view is that in the grand scheme of things this issue around the term "flush"
is caused by a big terminology disconnect
as the serial i/o guys from decades ago defined it to mean empty/eliminate but in the newer
C++ stream i/o speak "flush" means to push out the buffered data and force it to be written
to the stream.

Unfortunately because of this change,
there is now no way to toss all the RX buffered characters, using
the current HardwareSerial API, which is what I assume you are needing.

While you could go in and update HardwareSerial to give back the old functionality,
or even play games with a class wrapper that re-defines flush() to make it work like
it used to, my suggestion is to write your own code snippet to flush/purge/empty out the RX buffers when you
need to ensure that you are starting with a clean/empty RX buffer.

While not as efficient as what could be done in the actual library,
it will work on either SoftSerial or HardwareSerial no matter which
version of the IDE you use.

Instead of Serial.flush() do something like:

    while(Serial.read() >= 0){}; // flush out RX buffer

--- bill

Thank you very much Bill!!
I'll include your suggestion in the program or modify hardware serial flush function with old flush.
I think my main problem is not related with flush of the buffer. I think the gprs not receive correctly the AT command, although arduino send it or at least connecting directly the serial port to the ftdi it appears in the serial monitor. Using the another uart in the gprs module evaluation kit I can see the responses of the module and in the moment in which the arduino should send the power down command no response appears.

pipesg,
After looking closer at your code, I think I see a potential issue.

If you look at this code fragment:

        Serial.print("AT+QPOWD=1\r\n");
	while (timeout > millis()){
                if (Serial.find("NORMAL POWER DOWN")){
			nss.println ("Module AT off");
			break;
		}

This has a different behavior on softserial vs HardwareSerial particularly with Arduino 1.x and beyond.
With a softserial library, when Serial.print() returns, ALL of the characters, (every single bit) will have been sent
out the TX line. With HardwareSerial NONE of the characters will have been fully sent out the
TX line. They have been buffered up and the 'A' will still be in the process of transmitting.
Serial.find() will now start looking for characters. In the case of HardwareSerial, the receiving device
will not even see the AT string for another 10-12 ms much less have responded to anything.

I also think the while timeout loop you are using may not be doing what you think.
While it will provide a timeout, it won't give you a 3 second timeout to find the string.
The while loop will abort if it sees 3 seconds has passed, but that is after the call to Serial.find()
which has its own inter character timeout to search for the target string.
The issue with calling Serial.find() in a loop is that as it looks for the string it is swallowing
each character and throwing it away.
Depending on timing, it may be possible that you never see the target string
even though you call Serial.find() in a loop.

Without knowing the response timing of the target device or seeing the AltSoftSerial code
it is hard to say exactly what is happening or if this is even an issue.
(Maybe AltSoftSerial.read() waits forever for received characters vs buffering them in the background?)

You could bump the stream timeout and eliminate the while/timeout loop you have.
For example:

        Serial.print("AT+QPOWD=1\r\n");
	Serial.setTimeout(3000); // max delay for each character
        if (Serial.find("NORMAL POWER DOWN")){
		nss.println ("Module AT off");
	}

Do you have a link for AltSoftSerial?
And what version of the IDE are you using?
--- bill

Thank you very much Bill!!
I'll include your suggestion in the program and I'll try it. Yesterday I modified the flush function and also the buffer size as in 0023 version (when I finish the whole program with gps and gprs I'll use a 644PA so I have lot of memory available). I tryed it and the flush function acts as it is expected.
Due to the strange behaviour of the arduino (gprs did not detect the at command but if I connect TX directly to FTDI it is detected in serial monitor), I decided to try it in a breadboard 644PA 8mhz and...it works very good!!!! The gprs module respond to all at commands. I can understand it. How is that possible? Could it malfunction the tx pin of my mini?
Thanks for your help, although arduino is relatively easy, sometimes it's frustrating for a newbie!!!!