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.
Greetings all,
I am attempting to write a script to communicate with a photovoltaic inverter via a serial port on a Damn Small Linux PC. The inverter reads/writes binary data, and I've figured out how to handle that via od and awk, but I can't seem to actually communicate with the inverter. I know it works 'cause if I reboot my DSL PC to WinXP, I have a VBScript that works just fine... so communication and hardware is not the issue. Please take a look at the following and let me know if you have any suggestions. Right now, whenever I try to read from /dev/ttyS0, the script just hangs. The lines below that start with ####### are all my attempts so far, and they all hang. The last ###### is what I expect to get back from the inverter.
I am not really familiar with reading and writing thru /dev/ttyS0, but I assume you simple echo to it and read from it and everything else is handled on a lower level by the device driver.
First question is of course if the serial port is configured correctly at works at all. You can connect pin 2 and 3 of the serial connector on the PC as to make a loopback plug. Everything you write to the port should be echoed and read again by your script.
If this does not happen, it is useless to try to talk to the inverter.
If this works, are you sure that there is no additional protocol being used to talk to the inverter? Often it is something like STX at the beginning, some DLE's and EOT's at the end of the transmission, often with checksums etc.
Also a great help is a device called break-out box or Interfaker which has LED's for all important serial signals, and you can force signals like DTR and DSR active or inactive. With the LED's you can see if anything is transmitted ar all and if the status of the handshake lines is satisfactory.
I've made some progress. I'm getting data back from the inverter now. Turns out that one of my \x01 needed to be \x00. This caused a problem with null characters, but printf solved that.... I think. The problem I'm having now is that I appear to be getting 'random' responses from the inverter. I get different length responses (anywhere between 1 and 5 bytes) and almost never the same response twice. The fact that I'm getting anything at all indicates that my message TO the inverter is working. If I change it to a badly formatted message (such as changing the last byte to a incorrect checksum) I get nothing. So, here's what I have (the commented line is what I expect):
Code:
#!/bin/bash
stty -F /dev/ttyS0 raw ispeed 2400 ospeed 2400 cs8 -ignpar -cstopb eol 255 eof 255
#Get total watt-hours generated
printf "\x80\x80\x80\x00\x01\x01\x11\x13" > /dev/ttyS0
eol=0
ff=$'\xff'
until [ $eol -eq 1 ]; do
echo -n .
read -r -d $ff -n 1 -t 2 OneByte < /dev/ttyS0
eol=$?
InStr=$InStr$OneByte
done
echo $InStr
######InStr=$'\x80\x80\x80\x03\x01\x01\x11\x01\x02\x03\x18'
InStrLen=${#InStr}
for ((x=0;x<$InStrLen;x++)); do
let z=0x$(echo -n ${InStr:x:1} | od -h | awk '{ print $2 }')
echo -n $z...
done
if [ $InStrLen -gt 8 ]; then
if [ ${InStr:0:7} = $'\x80\x80\x80\x03\x01\x01\x11' ]; then
let a=0x$(echo -n ${InStr:7:1} | od -h | awk '{ print $2 }')
let b=0x$(echo -n ${InStr:8:1} | od -h | awk '{ print $2 }')
let c=0x$(echo -n ${InStr:9:1} | od -h | awk '{ print $2 }')
let WattsTotal=$[ (($a*256)+$b)*10**$c ]
fi
fi
echo TOTAL: $WattsTotal
If I understand your code (I'm not a bash scripter),you stop when there's nothing to read (eol=$? and test $eol).
This however does not mean that you have received a complete message (you might be reading to early). So if you know that a message has a fixed length or a specific terminator, I would read till you have the full message (count bytes or set n to 8 or OneByte equals whatever) and ignore $eol for that purpose.
What probably happens now:
the second time you run the program, you still receive data from the previous run.
Hope this helps
Last edited by Wim Sturkenboom; 06-05-2009 at 10:42 AM.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.