Page 1 of 1

sending commands to serial port

Posted: Fri Jun 28, 2013 7:44 pm
by Hades
Hello,

I have a problems sending commands to my AV-Receiver (Denon AVR-2807) which ist connected to my Pi via USB --> serial adapter (PL2303). I only have very basic knwoledge in Linux and been now searching for 2 days...

The parameters, my Denon requires are:

Code: Select all

Synchronous system :          Tone step synchronization
Communication system :        A half duplex
Communication speed :         9600bps
Character length :            8 bits
Parity control :              None
Start bit :                   1 bit
Stop bit :                    1 bit
Communication procedure :     Non procedural
Communication data length :   135 bytes (maximum) 
Specifications of the Denon-protocol can be found here: http://www.denon.de/DocumentMaster/DE/2 ... ver4_7.pdf

What I want to do (but doesn't work) is:

Code: Select all

echo -e "MUON\r" >> /dev/ttyUSB0
where "MUON<CR>" is the command to mute the Denon (as example). I want to use it from other scripts (siriproxy) and devices (e.g. fritzbox callmonitor).

I CAN connect to the AV-Receiver using

Code: Select all

screen /dev/ttyUSB0 9600
It flawlessly shows me the output of the Denon (i.e. e.g. if I change volume, mute etc.) as well as I can send commands. Minicom also works after I actived CR (Crtl-A w).

I also CAN forward the output of the Denon to a file using

Code: Select all

cat /dev/ttyUSB0 >> anyfile
However, I cannot do anything else in the meanwhile (no command prompt until Ctrl-C).

My settings for stty are the following:

Code: Select all

speed 9600 baud; rows 50; columns 130; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = M-^?; eol2 = M-^?; 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
I also tried to

Code: Select all

cat testfile >> /dev/ttyUSB0
where testfile contains the echo-command as well as

Code: Select all

printf "MUON\" >> /dev/ttyUSB0
. Nothing works.

I thought (i.e. I read it somewhere) that maybe the serial port closes to fast after sending the echo command to get the whole command.

Maybe anyone can help?!

Hades.

Re: sending commands to serial port

Posted: Sat Jun 29, 2013 8:14 pm
by danjperron
if you put a led on pin 3 does it change intensity when you send the data?

Are you using a null modem cable. Did you disable the hardware handshake?

Put 2 leds head to toe one red and the other one with an other color.

If you are usin only rx and tx, you could disable the hardware handshake by connecting pin 1,4 and 6 together, 7 and 8 together.

Daniel

Re: sending commands to serial port

Posted: Sat Jun 29, 2013 9:23 pm
by Hades
sorry. I do not have leds. I do not use a null modem cable. I cannot change the Pins in the cable as it's a ready-bought-adapter.

However, the connection seems to be working because with screen everything works fine, i.e. i can receive and send commands correctly.

I now have a workaround-skript which also works, however only is a workaround:

Code: Select all

screen -dmS AVR2807 /dev/ttyUSB0 9600
screen -S AVR2807 -X stuff "$1\r"
screen -S AVR2807 -X kill
Now if I call this script with e.g. the argument "MUON" the Denon mutes.

Alex.

Re: sending commands to serial port

Posted: Tue Jul 02, 2013 5:27 am
by PiGraham
However, I cannot do anything else in the meanwhile (no command prompt until Ctrl-C).
That's how it works.

If a program doesn't require user interaction, such as piping to a file, you run it as a background task by appending '&' on the end of the command. The program will start and you will be returned to the command prompt.

So if you had a program count that counts slowly then exits:
>count
1,2,3,4,5,6,7,8,9 Done
>

Run in background:
>count &
>

The output will be lost. You probably want the output, so redirect it to a file:
> count >log.txt &
>

log.txt will eventually contain the output "1,2,3,4,5,6,7,8,9 Done"

If you want to interact with more than one process at a time you can run more than one console.
If you run X (>startx) you can launch multiple terminal windows and run different commands in each.

Without X you can press Ctrl-Alt-F2
This will switch you to a new console with a login prompt.
Your original terminal session is still there and you can switch back to it with Ctrl-Alt-F1

This also switches to X. If you ran "startx" from terminal 1 then Ctrl-Alt-F1 will switch to X (whatever is running on terminal 1).

You can also also log in from more than one ssh terminal session on your PC / Mac.

Re: sending commands to serial port

Posted: Tue Jul 02, 2013 8:19 am
by Hades
@PiGraham: thank's a lot. Didn't know that.

Re: sending commands to serial port

Posted: Sat Nov 02, 2013 12:04 am
by armyofme
So pleased to find this page as I was having problems controlling my denon amp via serial and now I can control it via SSH with your script. I'm trying to integrate the script into my home control webpage but I have little scripting knowledge...could you explain what this part of the script does?

Code: Select all

stuff "$1\r"
Thanks!

Re: sending commands to serial port

Posted: Sat Nov 02, 2013 9:00 pm
by Hades
stuff "XYZ" tells the specified screen session to execute XYZ.
in my case I tell the screen session to execute the command "$1\r", where
$1 is the first parameter given to the script and
\r is the linefeed the denon avr needs to know the end of the command.

My script is named avrcom.sh, so if I call "avrcom MUON" from the shell, $1=MUON and the script tells the screen session to execute "MUON\r" and the denon avr mutes.

I have rewritten my script "avrcom":

Code: Select all

#! /bin/sh
# /etc/init.d/avrcom

#touch /var/lock/avr2807

case "$1" in
  start)
    if [ "$2" = "log" ]; then
      echo "Starting serial connection to AVR-2807 with logging... "
      /usr/bin/screen -dmS AVR2807 /dev/ttyUSB2 9600
    else 
      echo "Starting serial connection to AVR-2807 without logging... "
      /usr/bin/screen -dmS AVR2807 /dev/ttyUSB2 9600
    fi
  ;;
  stop)
    echo "Stopping serial connection to AVR-2807 ..."
    /usr/bin/screen -S AVR2807 -X kill
  ;;
  restart)
     echo "Restarting serial connection to AVR-2807 ..."
    /usr/bin/screen -S AVR2807 -X kill
    /usr/bin/screen -dmS AVR2807 /dev/ttyUSB2 9600
  ;;
  send)
    if [ -n "$2" ]; then
      /usr/bin/screen -S AVR2807 -X stuff "$2\r"
    else 
      echo "Usage: $0 $1 {command}"
    fi
  ;;
  cmd)
    if [ -n "$2" ]; then
      /usr/bin/screen -dmS AVR2807 /dev/ttyUSB2 9600
      /usr/bin/screen -S AVR2807 -X stuff "$2\r"
      /usr/bin/screen -S AVR2807 -X kill
    else 
      echo "Usage: $0 $1 {command}"
    fi
  ;;
  *)
    echo "Usage: $0 {start (log) | stop | restart | send|cmd command}"
    exit 1
  ;;
esac
exit 0
If you call avrcom with the following parameter
start/stop/restart: starts/stops/restarts a screen session in the background
send XYZ: sends the command XYZ to the existing screen session
cmd XYZ: opens screen session, sends command XYZ and closes the session.

logging doesn't work yet.

Hopes that helps. Feel free to copy/modify the script.

Hades.

Re: sending commands to serial port

Posted: Sun Nov 03, 2013 3:09 pm
by armyofme
Thanks for your reply Hades - that's helped me understand better what is happening inside the script.

May be you could help me a bit further. Your scripts work great for me from SSH and I'm trying to implement them in my home webpage. Basically my webpage calls a CGI script which sends a command (tellstick) and a parameter to switch on my living room lights. This works great so I thought I could apply this to your script. Only thing is because your script uses screen it needs to be called from my main user not the www-data user that is used on the webpage. So after a bit of research I read how to use a php script to execute the script with my main user. It looks like this:

Code: Select all

<?php
exec("sudo -u armyofme /usr/lib/cgi-bin/denon_cgi");
?>
This calls the CGI script:

Code: Select all

#!/bin/bash
echo "Content-type: text/plain"
echo "" 
screen -dmS 3012CI /dev/ttyUSB0 9600
screen -S 3012CI -X stuff "$1\r"
screen -S 3012CI -X kill
This works but it is obviously not calling the parameter at this stage. This is where I am stuck. I need the php script to call the CGI script plus parameter. So after reading your above post I thought may be I could include the parameters in the webpage like with the tellstick situation. This is what my webpage looks like:

Code: Select all

<html>
<head>
<title>Home Control Page</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<body style="text-align:center" bgcolor="lavender">
</head>

    <script language="javascript">
    var m_XML = false;

    function ProcessResponse()
    {
            if (m_XML.readyState == 4)
            {
                    if (m_XML.status == 200)
                    {
                    }
            }
    }

    function Doxml(act,chan)
    {
            try
            {
                    if (! m_XML)
                    {
                            if (window.XMLHttpRequest)
                            {
                                    m_XML = new XMLHttpRequest();
                            }
                            else if (window.ActiveXObject)
                            {
                                    m_XML = new ActiveXObject("Microsoft.XMLHTTP");
                            }
                    }

                    if (m_XML)
                    {
                            m_XML.open("GET","/cgi-bin/tdtool_cgi?"+act+"&"+chan);
                            m_XML.onreadystatechange = ProcessResponse ;
                            m_XML.send(null);
                    }
            }
            catch (e)
            {
            }
    }
function Doxml4()
    {
            try
            {
                    if (! m_XML)
                    {
                            if (window.XMLHttpRequest)
                            {
                                    m_XML = new XMLHttpRequest();
                            }
                            else if (window.ActiveXObject)
                            {
                                    m_XML = new ActiveXObject("Microsoft.XMLHTTP");
                            }
                    }

                    if (m_XML)
                    {
                            m_XML.open("GET","/cgi-bin/party_cgi");
                            m_XML.onreadystatechange = ProcessResponse ;
                            m_XML.send(null);
                    }
            }
            catch (e)
            {
            }
    }
function Doxml5()
    {
            try
            {
                    if (! m_XML)
                    {
                            if (window.XMLHttpRequest)
                            {
                                    m_XML = new XMLHttpRequest();
                            }
                            else if (window.ActiveXObject)
                            {
                                    m_XML = new ActiveXObject("Microsoft.XMLHTTP");
                            }
                    }

                    if (m_XML)
                    {
                            m_XML.open("GET","/cgi-bin/capital_cgi");
                            m_XML.onreadystatechange = ProcessResponse ;
                            m_XML.send(null);
                    }
            }
            catch (e)
            {
            }
    }	
function Doxml6([color=#FF0000]$1[/color])
    {
            try
            {
                    if (! m_XML)
                    {
                            if (window.XMLHttpRequest)
                            {
                                    m_XML = new XMLHttpRequest();
                            }
                            else if (window.ActiveXObject)
                            {
                                    m_XML = new ActiveXObject("Microsoft.XMLHTTP");
                            }
                    }

                    if (m_XML)
                    {
                            m_XML.open("GET","/cgi-bin/denon.php?"+[color=#FF0000]$1[/color]);
                            m_XML.onreadystatechange = ProcessResponse ;
                            m_XML.send(null);
                    }
            }
            catch (e)
            {
            }
    }	
</script>

    <body>
    <table>
    <tr>
    <td>Living Room Main Light</td>
    <td><button type="button" onclick="Doxml('-f','1')">OFF</button></td>
    <td><button type="button" onclick="Doxml('-v60','-d1')">LOW</button></td>
    <td><button type="button" onclick="Doxml('-v120','-d1')">MID</button></td>
    <td><button type="button" onclick="Doxml('-n','1')">ON</button></td>
    </tr>
    <tr>
    [color=#FF0000]<td>Dining Room Amplifier</td>
    <td><button type="button" onclick="Doxml6('ST02OFF')">OFF</button></td>
    <td><button type="button" onclick="Doxml6('')">VOL-</button></td>
    <td><button type="button" onclick="Doxml6('')">VOL+</button></td>
    <td><button type="button" onclick="Doxml6('ST02ASIG')">ON</button></td>
    </tr>[/color]
    <tr>
    <td>Top Bedroom Main Light</td>
    <td><button type="button" onclick="Doxml('-f','5')">OFF</button></td>
    <td><button type="button" onclick="Doxml('-v60','-d5')">LOW</button></td>
    <td><button type="button" onclick="Doxml('-v90','-d5')">MID</button></td>
    <td><button type="button" onclick="Doxml('-n','5')">ON</button></td>
    </tr>
    <tr> 
    <td>Party Mode</td>
    <td><button type="button" onclick="Doxml4()">Play</button></td>
    </tr> 
    <tr> 
    <td>Capital Radio</td>
    <td><button type="button" onclick="Doxml5()">Play</button></td>
    </tr> 
    </table>
    </html>
Any ideas?

Re: sending commands to serial port

Posted: Sun Nov 03, 2013 6:02 pm
by Hades
sorry i can't help you with that.

Re: sending commands to serial port

Posted: Sun Nov 03, 2013 6:55 pm
by armyofme
No problem, your help so far has been great, thank you.

Anyone else out there with any ideas?

Re: sending commands to serial port

Posted: Wed Nov 06, 2013 5:05 am
by Kendall Bennett
Try this.

echo "This is a test message" /dev/ttyS0

Not sure about what you are running but looks like a linux build of some type. If the serial port is Com1 then ttyS0 should be that port. Think about it like hard drives Etc.

:) :D :geek:

Re: sending commands to serial port

Posted: Fri Mar 28, 2014 11:59 pm
by bruce_miranda
I am doing this too but for a NAD.

If I try and use the echo command I always get

Code: Select all

-bash: /dev/ttyUSB0: Device or resource busy
how do I send data to the serial port.

If I use your workaround of using the screen commands then I can send data to the NAD. But the problem is I don't know how to read the serial port using the screen command. The NAD allows you to query the settings of the amplifier by passing command. But I have not been able to get that to work.

Re: sending commands to serial port

Posted: Sat Mar 29, 2014 5:02 am
by Richard-TX
There is a difference between *nix and dos/windows when you hit the enter key. DOS/Win sends a newline and carriage return. where *nix sends only a newline.

Try this command

echo "This is a test message\r\n" > /dev/ttyS0
or
echo -n "This is a test message\r" > /dev/ttyS0

My feeling is that Denon is expecting a CR at EOL. I have seen some devices error when it sees a nl.

As far as your busy resource error goes, try running fuser against the device. Maybe there is a getty running on it.

Code: Select all

# fuser /dev/ttyAMA0
/dev/ttyAMA0:         2618
# ps -ef | grep 2618
root      2618     1  0 Mar28 ttyAMA0  00:00:00 /sbin/getty -L ttyAMA0 115200 vt100

Re: sending commands to serial port

Posted: Sat Mar 29, 2014 5:13 am
by Richard-TX
One more thing regarding serial ports.

if the default speed of the serial port is not what you need, then you have to change the speed in your script.

Code: Select all

#!/bin/sh
stty 19200  < /dev/ttyAMA0
echo "some command\r" > /dev/ttyAMA0

Re: sending commands to serial port

Posted: Sat Mar 29, 2014 5:02 pm
by bruce_miranda
I am not doing this on the Denon, but on a NAD. But I don't think that is the issue here. The issue is I can't talk directly to the serial port for some reason. Could it be permissions?

I'm trying this on a Raspbmc installation that has root disabled.

Code: Select all

[email protected]:~$ stty 115200  < /dev/ttyUSB0
-bash: /dev/ttyUSB0: Device or resource busy
whatever I try and do with the serial port directly I get the same message. But with screen command in a script I can send data to the serial port without a problem.

Re: sending commands to serial port

Posted: Sun Mar 30, 2014 1:14 am
by Richard-TX
try running your commands when logged in as root.

Re: sending commands to serial port

Posted: Sun Mar 30, 2014 9:36 pm
by bruce_miranda
root is disabled on raspbmc. What else can I try?

Re: sending commands to serial port

Posted: Mon Mar 31, 2014 6:51 pm
by bruce_miranda
Even with root I cannot send a command to the serial port via echo.

Code: Select all

[email protected]:/home/pi# stty
speed 115200 baud; line = 0;
eol = M-^?; eol2 = M-^?;
-brkint ixany
-echok
[email protected]:/home/pi# echo "\rMain.Power=On\r" > /dev/ttyUSB0
I get no errors but the amplifier does not turn on.

But if I run the following commands, it works fine.

Code: Select all

/usr/bin/screen -dmS NADC390DD /dev/ttyUSB0 115200
      /usr/bin/screen -S NADC390DD -X stuff "\rMain.Power=On\r"
      /usr/bin/screen -S NADC390DD -X kill
what else can I try.

Re: sending commands to serial port

Posted: Tue Apr 01, 2014 9:46 pm
by bruce_miranda
OK so only screen is able to send the commands to the Serial port. That is OK for any command I need to send the amplifier.

However the amplifier is also able to send me back the status if I send it certain commands. e.g. "Main.Balance.Leveltrim?" should Read the Balance Level trim and return it back via the serial port.

Given that I am sending this command via the screen stuff command, how do I catch what is coming back?

Re: sending commands to serial port

Posted: Sun Jun 30, 2019 9:53 am
by jayedgar
Hades wrote:
Sat Jun 29, 2013 9:23 pm
sorry. I do not have leds. I do not use a null modem cable. I cannot change the Pins in the cable as it's a ready-bought-adapter.

However, the connection seems to be working because with screen everything works fine, i.e. i can receive and send commands correctly.

I now have a workaround-skript which also works, however only is a workaround:

Code: Select all

screen -dmS AVR2807 /dev/ttyUSB0 9600
screen -S AVR2807 -X stuff "$1\r"
screen -S AVR2807 -X kill
Now if I call this script with e.g. the argument "MUON" the Denon mutes.

Alex.
I had this configuration successfully in use with my Denon AVR for years. After upgrading the kernel to version 4.19.42 v7+ this weekend it seems to be broken. The serial commands are getting stuck. I tried to connect to the serial interface using minicom for a first check and I could not send any commands manually. However, the last command I had issued before via screen was finally sent to the AVR after some time. I guess this is when the serial gets reset by minicom. I was not able to find out more yet. Is anyone facing the same trouble?

Re: sending commands to serial port

Posted: Mon Jul 01, 2019 6:29 pm
by moviebrain
jayedgar wrote: [quote=Hades post_id=379038 time=<a href="tel:1372541036">1372541036</a> user_id=75030]
sorry. I do not have leds. I do not use a null modem cable. I cannot change the Pins in the cable as it's a ready-bought-adapter.

However, the connection seems to be working because with screen everything works fine, i.e. i can receive and send commands correctly.

I now have a workaround-skript which also works, however only is a workaround:

Code: Select all

screen -dmS AVR2807 /dev/ttyUSB0 9600
screen -S AVR2807 -X stuff "$1\r"
screen -S AVR2807 -X kill
Now if I call this script with e.g. the argument "MUON" the Denon mutes.

Alex.
I had this configuration successfully in use with my Denon AVR for years. After upgrading the kernel to version 4.19.42 v7+ this weekend it seems to be broken. The serial commands are getting stuck. I tried to connect to the serial interface using minicom for a first check and I could not send any commands manually. However, the last command I had issued before via screen was finally sent to the AVR after some time. I guess this is when the serial gets reset by minicom. I was not able to find out more yet. Is anyone facing the same trouble?
[/quote]

Sorry I stumbled on your post. I don't know what process you used to update the kernel but assuming you are now on raspbian Buster have you updated your sources to point to the new buster repos? Try that and see if there is an update to screen, I doubt the Jessie or Stretch binary for screen works in Buster.