Reputation: 7
I have a problem. I have 2 pieces of hardware (similar to pi) and I'm trying to test communication over serial cable between them. Both are linux based but have limited tools. I have wrote a script to send and receive files. When I send a txt file with some text on it, everything works fine. When i try to send a binary file, the data it's not the same, sometimes i get bigger file, sometimes smaller and sometimes just some bytes are changed. I'm wondering for hours why this happens, I set the devices to raw
mode (for binary file)...
Here's the scrpit I wrote:
#!/bin/bash
FILE=$2
send()
{
if [ ! -f $FILE ]; then
echo "File $2 doesn not exist, please introduce a valid file"
fi
content=`cat "$FILE"` #Dump the file content into variable
echo -E "$content" > /dev/ttyO5 #send the whole content to the other device
}
receive()
{
if [ -f $FILE ]; then
echo "The file already exists. Do you want to overwrite it? (y/n
read opc
if [ "$opc" == "n" ]; then
exit 1
fi
rm "$FILE"
fi
while read -t 5 -r -n 1 c; do # read char by char -r to avoid backslashes to be scaped
echo -E -n "$c" >> $FILE # append char on file -n(to avoid creation of new lines and -E to avoid interpretation of backslashes.
done < /dev/ttyO5
}
case $1 in
's')
send
;;
'r')
receive
;;
*)
echo "Usage $0 [s | r] [FILE]"
;;
esac
To put the devices on raw
mode, I use stty -F /dev/ttyO5 raw
and this are the options of the device:
speed 9600 baud;stty: /dev/ttyO5
line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon
-ixoff -iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0
ff0
-isig -icanon iexten -echo -echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke
My mind tells me that there's a problem when interpretating some chars and that it might be fixed changing some of the options above. I try several, but i cant make it work. If somebody sees something I dont, i would highly appreciate it.
Regards
EDIT: Problem found but not solved. Read and cat dont like the characters NULL
and \n
. How could i read those 2 chars?
Upvotes: 0
Views: 596
Reputation: 19315
Add IFS=
before read to allow to read space, tab characters
while IFS= read -t 5 -r -n 1 c; do
EDIT: '\n' and '\0' still can't be read.
Compare the two following outputs
for i in {{0..9},a,b,c,d,e,f}{{0..9},a,b,c,d,e,f};do printf '\x'"$i"; done | od -c
for i in {{0..9},a,b,c,d,e,f}{{0..9},a,b,c,d,e,f};do printf '\x'"$i"; done | { while IFS= read -r -n1 c; do echo -E -n "$c";done;} | od -c
EDIT: to read a newline add the option -d ''
while IFS= read -t 5 -r -n 1 -d '' c; do
If [[ $c = '' ]]
; so it's the '\0' character in this case, use printf '\0' for example to write it
Following command proves that all character can be copied
for i in {{0..9},a,b,c,d,e,f}{{0..9},a,b,c,d,e,f};do printf '\x'"$i"; done | { while IFS= read -r -n1 -d '' c; do if [[ $c = '' ]]; then printf '\0'; else echo -E -n "$c";fi;done;} | od -c
EDIT:
considering performance read
is slow, consider using another unix tool : perl
perl -e '
# $/ end of line of input, special variable
# read one byte at time
$/=\1;
my $outfilename=shift;
open $outfile,">>",$outfilename or die $!;
while (<>) {
# do something on output (for example print ascii number)
print ord($_),"\n";
# write to out file
print $outfile "$_";
}
' "$FILE" < /dev/ttyO5
Upvotes: 1