LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-16-2009, 01:56 PM   #1
caduser1
LQ Newbie
 
Registered: Mar 2009
Posts: 4

Rep: Reputation: 0
Read Non Printable characters from serial port


Can someone please shed some light on the following issue. I am trying to write a shell script to read and send data over a serial port. I could successfully send and receive data, but I need to find a way to detect when an ACK or ENQ or NAK (non-printable characters) has been sent by the device at the end the serial connection.

Any help is appreciated.
 
Old 03-16-2009, 04:23 PM   #2
David1357
Senior Member
 
Registered: Aug 2007
Location: South Carolina, U.S.A.
Distribution: Ubuntu, Fedora Core, Red Hat, SUSE, Gentoo, DSL, coLinux, uClinux
Posts: 1,302
Blog Entries: 1

Rep: Reputation: 107Reputation: 107
Quote:
Originally Posted by caduser1 View Post
Any help is appreciated.
Have you tried using "read" with "-r -s -n 1"? That should let you read one character at a time. You can create variables with the special characters using printf:
Code:
# Create variables for the special characters
ACK=$(printf "\x6")
ENQ=$(printf "\x5")
NAK=$(printf "\x19")
# Open /dev/ttyS0 for reading and writing as file descriptor 5
5<>/dev/ttyS0
while true ;
do
    # Read one character from file descriptor 5
    read -u 5 -r -s -n 1 CHAR
    case $CHAR in
        $ACK)
            # Handle an ACK
        $ENQ)
            # Handle an ENQ
        $NAK)
            # Handle an NAK
        *)
            # Handle other characters
    esac
    ;;
done
I hope you are using bash, and I wish I had an easy way of testing this.
 
Old 03-17-2009, 11:22 PM   #3
damien_d
LQ Newbie
 
Registered: Dec 2008
Posts: 17

Rep: Reputation: 0
Quote:
Originally Posted by caduser1 View Post
Can someone please shed some light on the following issue. I am trying to write a shell script to read and send data over a serial port. I could successfully send and receive data, but I need to find a way to detect when an ACK or ENQ or NAK (non-printable characters) has been sent by the device at the end the serial connection.
Is the serial port in raw mode? i.e. ?
Code:
stty -F /dev/ttyS0 115200 raw
 
Old 03-18-2009, 08:47 PM   #4
caduser1
LQ Newbie
 
Registered: Mar 2009
Posts: 4

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by David1357 View Post
Have you tried using "read" with "-r -s -n 1"? That should let you read one character at a time. You can create variables with the special characters using printf:
Code:
# Create variables for the special characters
ACK=$(printf "\x6")
ENQ=$(printf "\x5")
NAK=$(printf "\x19")
# Open /dev/ttyS0 for reading and writing as file descriptor 5
5<>/dev/ttyS0
while true ;
do
    # Read one character from file descriptor 5
    read -u 5 -r -s -n 1 CHAR
    case $CHAR in
        $ACK)
            # Handle an ACK
        $ENQ)
            # Handle an ENQ
        $NAK)
            # Handle an NAK
        *)
            # Handle other characters
    esac
    ;;
done
I hope you are using bash, and I wish I had an easy way of testing this.


Thanks. I am using bash. In my system if I tried to set the file descriptor to any value higher than 3, the read statement returns an invalid file descriptor error. With values of 1,2, or 3, it doesn't read from the port. But if I use read -r -s -n 1 CHAR < /dev/ttyS0 I could read from the port, but still cannot detect the non-printable charater.

Thanks
 
Old 03-19-2009, 01:55 PM   #5
David1357
Senior Member
 
Registered: Aug 2007
Location: South Carolina, U.S.A.
Distribution: Ubuntu, Fedora Core, Red Hat, SUSE, Gentoo, DSL, coLinux, uClinux
Posts: 1,302
Blog Entries: 1

Rep: Reputation: 107Reputation: 107
Quote:
Originally Posted by caduser1 View Post
TBut if I use read -r -s -n 1 CHAR < /dev/ttyS0 I could read from the port, but still cannot detect the non-printable charater.
You may need to combine that with the "raw" mode mentioned by damien_d
 
Old 03-19-2009, 02:14 PM   #6
caduser1
LQ Newbie
 
Registered: Mar 2009
Posts: 4

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by David1357 View Post
You may need to combine that with the "raw" mode mentioned by damien_d

Here's my code. Please feel free to comment.

#!/bin/bash

#Port Initialization
stty -F /dev/ttyS000 ispeed 9600 ospeed 9600 sane cs8 -parodd -cstopb ixon

#Port Variable Definition
PORT="/dev/ttyS000"

#Control Characters Definition
STX=$(printf "\x02")
ETX=$(printf "\x03")
ENQ=$(printf "\x05")
ACK=$(printf "\x06")
NACK=$(printf "\x15")

LINETEST=$STX"AREYUTHERE"$ETX

#Some Timers
ENQTIMER=2
PMSTIMER=5
AREYUTHERETIMER=5

RESP="GRS"
RESP2="CHK"

SUCCESS=1
FAILURE=0

DATAFILE="/usr/bin/dgrp/pmsdata.txt"
LOGFILE="/usr/bin/dgrp/log.txt"

Init ()
{
echo -en $ENQ > $PORT
read -r -s -t $ENQTIMER -n 1 DATA1 < $PORT

case $DATA1 in
$ACK)
echo -en $LINETEST > $PORT
read -r -s -t $ENQTIMER -n 1 DATA2 < $PORT
case $DATA2 in
$ACK)
RCODE=$SUCCESS
;;
*)
RCODE=$FAILURE
;;
esac
;;

$ENQ)
echo -en $ACK > $PORT
read -r -s -t $ENQTIMER DATA3 < $PORT

case $DATA3 in
AREYUTHERE)
echo -en $ACK > $PORT
RCODE=$SUCCESS
;;
*)
echo -en $NACK > $PORT
RCODE=$FAILURE
;;
esac
;;

*)
RCODE=$FAILURE
;;

esac
}

NormalOp ()
{
while true
do
read -u 1 -r -s -t $PMSTIMER -n 1 DATA3

case $DATA3 in
$ENQ)
echo -en $ACK > $PORT
read -u 1 -r -s -t $PMSTIMER DATA4
LEN=${#DATA4[*]}

STARTOFDATA=${DATE4:0:3}
ENDOFDATA=${DATA4:-3}
MESSAGE=${DATA4:1:3}

if [ "$STARTOFDATA" = "STX" -a "$ENDOFDATA" = "ETX" ]; then

if [ "$MESSAGE" = "CHK" -o "$MESSAGE" = "EDT" -o "$MESSAGE" = "RST" -o "$MESSAGE" = "STS" -o "$MESSAGE" = "MW " ]; then
echo -e $ACK > $PORT
echo $DATA4 >> $DATAFILE
echo $DATA4 >> $LOGFILE
elif
[ "${MESSAGE:1:10}" = "AREYUTHERE" -o "${MESSAGE:1:8}" = "LINETEST" -o "${MESSAGE:1:3}" = "GRS" -o "${MESSAGE:1:5}" = "RQINZ" ]; then
echo -e $ACK > $PORT
else
echo -e $NACK > $PORT
echo $DATA >> $LOGFILE
fi
else
echo -en $NACK > $PORT
fi
;;
esac
done
}
while true
do
Init

if [ "$RCODE" -eq 1 ]; then
echo "Link success..."
break
else
echo "Link not initialized..."
sleep 2
fi

done

NormalOp

exit 0
 
Old 03-19-2009, 02:18 PM   #7
caduser1
LQ Newbie
 
Registered: Mar 2009
Posts: 4

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by caduser1 View Post
Here's my code. Please feel free to comment.

#!/bin/bash

#Port Initialization
stty -F /dev/ttyS000 ispeed 9600 ospeed 9600 sane cs8 -parodd -cstopb ixon

#Port Variable Definition
PORT="/dev/ttyS000"

#Control Characters Definition
STX=$(printf "\x02")
ETX=$(printf "\x03")
ENQ=$(printf "\x05")
ACK=$(printf "\x06")
NACK=$(printf "\x15")

LINETEST=$STX"AREYUTHERE"$ETX

#Some Timers
ENQTIMER=2
PMSTIMER=5
AREYUTHERETIMER=5

RESP="GRS"
RESP2="CHK"

SUCCESS=1
FAILURE=0

DATAFILE="/usr/bin/dgrp/pmsdata.txt"
LOGFILE="/usr/bin/dgrp/log.txt"

Init ()
{
echo -en $ENQ > $PORT
read -r -s -t $ENQTIMER -n 1 DATA1 < $PORT

case $DATA1 in
$ACK)
echo -en $LINETEST > $PORT
read -r -s -t $ENQTIMER -n 1 DATA2 < $PORT
case $DATA2 in
$ACK)
RCODE=$SUCCESS
;;
*)
RCODE=$FAILURE
;;
esac
;;

$ENQ)
echo -en $ACK > $PORT
read -r -s -t $ENQTIMER DATA3 < $PORT

case $DATA3 in
AREYUTHERE)
echo -en $ACK > $PORT
RCODE=$SUCCESS
;;
*)
echo -en $NACK > $PORT
RCODE=$FAILURE
;;
esac
;;

*)
RCODE=$FAILURE
;;

esac
}

NormalOp ()
{
while true
do
read -u 1 -r -s -t $PMSTIMER -n 1 DATA3

case $DATA3 in
$ENQ)
echo -en $ACK > $PORT
read -u 1 -r -s -t $PMSTIMER DATA4
LEN=${#DATA4[*]}

STARTOFDATA=${DATE4:0:3}
ENDOFDATA=${DATA4:-3}
MESSAGE=${DATA4:1:3}

if [ "$STARTOFDATA" = "STX" -a "$ENDOFDATA" = "ETX" ]; then

if [ "$MESSAGE" = "CHK" -o "$MESSAGE" = "EDT" -o "$MESSAGE" = "RST" -o "$MESSAGE" = "STS" -o "$MESSAGE" = "MW " ]; then
echo -e $ACK > $PORT
echo $DATA4 >> $DATAFILE
echo $DATA4 >> $LOGFILE
elif
[ "${MESSAGE:1:10}" = "AREYUTHERE" -o "${MESSAGE:1:8}" = "LINETEST" -o "${MESSAGE:1:3}" = "GRS" -o "${MESSAGE:1:5}" = "RQINZ" ]; then
echo -e $ACK > $PORT
else
echo -e $NACK > $PORT
echo $DATA >> $LOGFILE
fi
else
echo -en $NACK > $PORT
fi
;;
esac
done
}
while true
do
Init

if [ "$RCODE" -eq 1 ]; then
echo "Link success..."
break
else
echo "Link not initialized..."
sleep 2
fi

done

NormalOp

exit 0


Here's the log of what happens when I execute it:
2004.12.7: 15:17:24 - Sending ENQ
2004.12.7: 15:17:25 - Received: {ACK}
2004.12.7: 15:17:25 - VMs_Xmit->Sending: {STX}AREYUTHERE{ETX}
2004.12.7: 15:17:29 - Received: {NAK}
2004.12.7: 15:17:29 - Received NAK - Sending again
2004.12.7: 15:17:29 - Sending ENQ
2004.12.7: 15:17:35 - Timed Out - Trying again
2004.12.7: 15:17:35 - Sending ENQ
2004.12.7: 15:17:35 - Received: {ACK}
2004.12.7: 15:17:35 - VMs_Xmit->Sending: {STX}AREYUTHERE{ETX}
2004.12.7: 15:17:39 - Received: {NAK}
2004.12.7: 15:17:39 - Received NAK - Sending again
2004.12.7: 15:17:39 - Sending ENQ
2004.12.7: 15:17:45 - Timed Out - Trying again
2004.12.7: 15:17:45 - Sending ENQ
2004.12.7: 15:17:45 - Received: {ACK}
2004.12.7: 15:17:46 - VMs_Xmit->Sending: {STX}AREYUTHERE{ETX}
2004.12.7: 15:17:49 - Received: {NAK}
2004.12.7: 15:17:49 - Received NAK - Sending again
2004.12.7: 15:17:55 - Received: {ACK}
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Difficult to read serial port omwoyo Programming 3 07-03-2007 06:47 AM
[Perl] Transforming non-printable characters. ////// Programming 3 04-04-2007 04:51 PM
How to read serial port (/dev/ttyS0) seraph-seph Linux - Hardware 4 11-01-2006 06:55 AM
When to read from the serial port? kad_79 Programming 3 06-15-2006 02:39 PM
Serial port Read Write SeanatIL Programming 2 07-14-2004 03:42 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:28 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration