ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I am working on a small bash script, which involves going through devices on several serial ports, sending them a message and listening for their response. What I am using so far is:
The device on the serial port responds with an affirmative message if it receives "id" (terminated either by newline or \0), or a negative message if it receives anything else.
Unfortunately, when I launch the script, it seems like nothing is returned from the device - the "testing /dev/ttyUSB0" gets echoed, but after that, I just get an empty line, and get thrown back to the prompt. When I try to execute the same commands manually - namely the (read -n32 -t5 resp < /dev/ttyUSB0 ; echo $resp)& and then echo "id" > /dev/ttyUSB0, I do get a response, however, it is not always the affirmative one. So far it seems like the first attempt gets an affirmative, then the next one doesn't unless I echo anything else to the serial port before running read.
Some help in getting the script to work would be appreciated.
There are a bunch of syntax errors in your script.
I am not a big fan of using bash for serial communications but I found something that works fairly well using file descriptors for a simple test.
Untested...
There are a bunch of syntax errors in your script.
I am not a big fan of using bash for serial communications but I found something that works fairly well using file descriptors for a simple test.
Untested...
"bunch of syntax errors" is putting it gently, I'd expect the script to be packed to the brim with them - it is my first attepmt, after all . I tried this, and it seems not to work - nothing gets echoed. I'm a bit puzzled by the read -d '' part - does that imply reading until encountering a \0 terminator? Also, what would you use instead of bash? I did not have any specific motivation for picking bash. Minicom is capable of running scripts, but I had very limited success with that - when running the script by the -S parameter, I get no response. Running it afterwards from the menu works, but that's not very helpful. Thank you for the help so far, though.
I do suspect there might be some problems with the termination of what gets sent, TBF, since sending the chars manually from a serial monitor works just fine (i, d, enter - the device on the other end will consider either \n, \r or \0 to signify an end of a message)
Any language that has a serial port library like c or python. In this case it does not matter but the d '' change the end of line character from a newline to nothing.
try:
Code:
echo -e "id\n\r" >&5
I do have a serial port with a loopback adapter but it can not simulate a real device. I assume your devices all use 9600,8,n,1 for serial port settings?
I don't know exactly what you are doing. I looked at your script and don't have any of those device nodes. I also don't want to change speeds. Here is a nothing example.
Code:
for d in $(ls /dev | grep 'tty'); do
echo "testing "$d""
stty -F /dev/tty1 -a | head -n 1
device="hello "$d""
read -n20 -t5 resp <<< "$device"
echo -e ""$resp"\n"
sleep .5
done
testing tty
speed 38400 baud; rows 67; columns 240; line = 0;
hello tty
testing tty0
speed 38400 baud; rows 67; columns 240; line = 0;
hello tty0
testing tty1
speed 38400 baud; rows 67; columns 240; line = 0;
hello tty1
testing tty10
speed 38400 baud; rows 67; columns 240; line = 0;
hello tty10
...
By the way you can echo/redirect to a variable if it is a file or a character device etc.
Code:
var=test.txt
echo "hello" > $var
The OP is trying to send a command to a device connect by serial port (RS-232) and receive a response. /dev/ttyUSBX or /dev/ttyACMX are device IDs from some device connected to a USB port like a USB serial port adapter. To communicate successfully the serial port speed (baud rate), number of bits. number of stop bits and parity must be the same as the connected device or all you get is garbage.
Ok, so I managed to cobble something together, shamelessly stealing from several examples and possibly following every bad practice under the sun.
This is what I managed:
find_thing.sh (run as . find_thing.sh):
Code:
#!/bin/bash
target="thing"
baudrate=9600
if [ -f ~/minicom.out ]; then rm ~/minicom.out; fi;
for device in $(ls /dev/tty* | grep -E "ttyUSB|ttyACM");
do
if [ -f ~/minicom.out ]; then rm ~/minicom.out; fi;
touch minicom.out
nohup bash -c "minicom -b $baudrate -D $device -S minicom_script.txt -C minicom.out" & > nohup.txt ;
wait
lastline=$(tail ~/minicom.out)
echo $lastline
if [ "$lastline" = "$target" ]
then
echo "match"
export THING="$device"
fi
done;
minicom_script.txt:
Code:
send "" # didn't work if I removed either of these
sleep 1.5 # I understand the sleep, but what the empty send does, no idea
send "id"
expect {
"thing" ! killall minicom
timeout 3 ! killall minicom
}
I suppose I could've explained my situation better: I have a system with several devices connected over USB serial, and the OS tends to assign the device files on bootup at random, even going as far as registering the same device as ttyUSB* or ttyACM* at different times. The device works either way, but the programs running on the system assume a known location for each device. The idea is that I will create a single script for each device, and that script will put the location of said device in an environment variable. Kind of messy, but works, and also solves the problem with the one device that has a different baudrate. Sure, a generalised approach would be much nicer, but perfectionism is the worst enemy of completion. This works.
I do suppose though that I could at least implement some kind of checking for accepted outputs - maybe in the minicom script, although that was...interesting to work with.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.