Klaus Holst Jacobsen
Klaus Holst Jacobsen

Reputation: 41

Use perl to send AT commands to modem

I have a embedded Linux box with perl 5.10 and a GSM modem attached. I have written a simple perl script to read/write AT commands through the modems device file (/dev/ttyACM0).

If I write a simple command like ATZ\r to the modem and wait for a response I receive very odd data like \n\n\nATZ\n\n0\n\nOK\n\n\n\n\nATZ\n\n\n\n... and the data keeps coming in. It almost seems like the response is garbled up with other data.

I would expect something like ATZ\nOK\n (if echo is enabled).

If I send the ATZ command manually with e.g. minicom everything works as expected.

This leads me to think it might be some kind of perl buffering issue, but that's only guessing.

I open the device in perl like this (I do not have Device::Serialport on my embedded Linux perl installation):

open(FH, "+<", "/dev/ttyACM0") or die "Failed to open com port $comport";

and read the response one byte at a time with:

while(1) {
    my $response;
    read(FH, $response, 1);
    printf("hex response '0x%02X'\n", ord $response);
}

Am I missing some initialization or something else to get this right?

Upvotes: 3

Views: 2344

Answers (3)

Klaus Holst Jacobsen
Klaus Holst Jacobsen

Reputation: 41

Thanks for your answer. Although not the explicit answer to my question it certainly brought me on the right track.

As noted by mti2935 this was indeed not a perl problem, but a mere tty configuration problem.

Using the stty command with the following parameters set my serial port in the "expected" mode:

  • -opost: Disable all output postprocessing
  • -crnl: Do not translate CR to NL
  • -onlcr: Do not translate NL to CR NL
  • -echo: Do not echo input (having this echo enabled and echo on the modem itself gave me double echoes resulting in odd behaviour in my script)

It is also possible to use the combination setting "raw" to set all these parameters the correct way.

Upvotes: 1

Mark Setchell
Mark Setchell

Reputation: 207465

It may be something to do with truncation. Try changing "+>" into "+<".

Or it may be something to do with buffering, try unbuffering output after your open():

select((select(FH), $| = 1)[0]);

Upvotes: 3

mti2935
mti2935

Reputation: 12027

I don't think you need the while loop. This code should send the ATZ command, wait for the response, then print the response:

 open(FH, "+>", "/dev/ttyACM0") or die "Failed to open com port $comport";
 print FH ("ATZ\n");
 $R = <FH>;
 print $R;
 close(FH);

Upvotes: 3

Related Questions