Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Re^4: r/w attached infrared head on /dev/ttyUSB0

by stoerti (Novice)
on May 26, 2019 at 07:36 UTC ( [id://11100548]=note: print w/replies, xml ) Need Help??


in reply to Re^3: r/w attached infrared head on /dev/ttyUSB0
in thread r/w attached infrared head on /dev/ttyUSB0

I tried different versions of Ubuntu. Now I have installed the actual image from volkszaehler.org
It runs on a raspberry pi
The "cat /dev/ttyUSB0&" makes no difference if started before or after the stty settings.

The stty arguments are from a documentation, I tried your style and it seems to be running the same as before.
The meter system giving the commands "/?!" and "000" back, when I send it to him.
Every line ends with "\r\n".

I changed my code:

use Fcntl qw/:DEFAULT/;<br> use IO::Termios ();<br> use IO::Stty ();<br> <br> sysopen my $fh, '/dev/ttyUSB0', O_RDWR or die "sysopen: $!";<br> my $handle = IO::Termios->new($fh) or die "IO::Termios->new: $!";<br> $handle->set_mode('300,7,e,1');<br> IO::Stty::stty($handle, qw/ cs7 parenb -parodd raw -echo /);<br> <br> my $raw = "\x2F\x3F\x21\x0D\x0A";<br> $handle->syswrite($raw) == length($raw) or die "syswrite";<br> my $raw = "\x06\x30\x30\x30\x0D\x0A";<br> $handle->syswrite($raw) == length($raw) or die "syswrite";<br> <br> while(1) {<br> my $toread = 1;<br> $handle->sysread(my $in, $toread) == $toread or die "sysread";<br> print $in;<br> }<br> <br> $handle->close;<br> <br> <br>
And you see in strace my problem: (only last lines of output)
read(4, "/", 1) = 1<br> read(4, "L", 1) = 1<br> read(4, "O", 1) = 1<br> read(4, "G", 1) = 1<br> read(4, "4", 1) = 1<br> read(4, "L", 1) = 1<br> read(4, "K", 1) = 1<br> read(4, "1", 1) = 1<br> read(4, "3", 1) = 1<br> read(4, "B", 1) = 1<br> read(4, "D", 1) = 1<br> read(4, "2", 1) = 1<br> read(4, "0", 1) = 1<br> read(4, "2", 1) = 1<br> read(4, "0", 1) = 1<br> read(4, "1", 1) = 1<br> read(4, "5", 1) = 1<br> read(4, "\r", 1) = 1<br> read(4, "\n", 1) = 1<br> write(1, "/LOG4LK13BD202015\r\n", 19/LOG4LK13BD202015) = 19<br> read(4, <br>

After "read(4," the script waits endless

The only way it works, when I send the sequence (stty setting, then /?!\r\n, then 000\r\n) directly into a shell
So I can not understand what the problem could be.

Replies are listed 'Best First'.
Re^5: r/w attached infrared head on /dev/ttyUSB0
by haukex (Archbishop) on May 26, 2019 at 09:24 UTC

    Thanks for the update - it's strange, and unfortunately I'm running out of ideas at the moment... I use the IO::Termios+IO::Stty combination on a Raspberry Pi myself, running a stock Raspbian, to read multiple FTDI chips and other dataloggers at once, and it works fine. Did you compare the strace results of the shell and the Perl scripts to make sure the same thing gets sent? Are you certain there are no other processes on the system trying to open/read the port? For example, did you make sure to kill all the cat processes you backgrounded, and check for other daemons? For example, I once had trouble with gpsd trying to get to the serial port when I was trying to use it as well, or that website mentions a vzlogger process that is included as part of the image.

      I tried now a complete other raspberry with an older installation of raspbian.
      It is exactly the same situation.

      So I can be sure, there are no other running processes or something other what kills my script.


      I now it can be working.
      Some years ago I had this thing working, but after some years the SD card was crashed.
      And I have a backup - problem is, I don't know where...
      What I remember, I had the same problems but I made it working.

        Sorry I can't be of more assistance, other than all the debugging tips and trying to find the difference between cat+stty and Perl, I'm still out of ideas at the moment. It could possibly be related to whatever kernel driver or USB module this is - in the node I linked to, I mentioned that I discovered that I needed to set -echo for some of the adapters I was working with (specifically, an FTDI USB-COM485-PLUS4 module with a FT4232H chip). Unfortunately, the way I discovered this was with lots of experimenting and banging my head against the wall. I recall using cat+stty, minicom, and screen to talk to the virtual port until I figured out the issue with the -echo option. I can only suspect that the issue with the module you're working with might be similar, some combination of options needed to make it work. Good luck, and let us know if you have more questions or you do figure it out :-)

        Do you remember a vaguely familiar looking guy asking you about it?


        holli

        You can lead your users to water, but alas, you cannot drown them.
Re^5: r/w attached infrared head on /dev/ttyUSB0
by huck (Prior) on May 30, 2019 at 04:25 UTC
      Thanks for your help but that doesn't work too.
      The problem is not the control sequence, the problem is, that the data is not coming back completely, only the first line comes back.
      But why does it work, when I send the sequences from shell and getting it with cat?

        The problem is not the control sequence

        The hints at the link i provided seem to suggest it is in how you are sending the control sequences, that the timeing is very important.

        Try this

        use Fcntl qw/:DEFAULT/; use IO::Termios (); use IO::Stty (); use IO::Handle; # use IO::Socket; use IO::Select; sysopen my $fh, '/dev/ttyUSB0', O_RDWR or die "sysopen: $!"; my $handle = IO::Termios->new($fh) or die "IO::Termios->new: $!"; $handle->set_mode('300,7,e,1'); IO::Stty::stty($handle, qw/ raw -parodd cs7 -cstopb parenb -ixoff -crt +scts -hupcl -ixon -opost -onlcr -isig -icanon -iexten -echo -echoe -e +choctl -echoke/); my $msg1 = "\x2F\x3F\x21\x0D\x0A"; my $msg2 = "\x06\x30\x30\x30\x0D\x0A"; for my $sleep (qw /.1 .2 .3 .4 .5 .6 .7 .8 .9 1.0 1.1 1.2/) { tryit ($msg1,$msg2,$sleep,2); } exit; sub sw{ my $raw=shift; $handle->syswrite($raw) == length($raw) or die "syswrite : $raw"; } sub tryit { my $msg1=shift; my $msg2=shift; my $sleep=shift; my $timeout=shift; my $sel_read = IO::Select->new(); $sel_read-> add($handle); my $didsomething=1; my $buf; print "waiting $sleep between sends\n"; sw($msg1); select (undef,undef,undef,$sleep); sw($msg2); while ($didsomething) { $didsomething=0; my ($rd_ptr,$wr_ptr,$er_ptr)=IO::Select->select($sel_read,undef,un +def,$timeout); for my $fh (@$rd_ptr) { $buf=''; $didsomething=1; my $rv = sysread($fh, $buf, 64*1024, length($buf)); if (!$rv) { if (defined($rv)) { die 'EOF';} else {die 'Connection terminated';} } # bad rv else { print $buf;} } # $fh } # while print "no chars for $timeout secs\n"; } # tryit #for (1..300) { # my $toread = 1; # $handle->sysread(my $in, $toread) # == $toread or die "sysread"; # print $in; #} $handle->close;

        commented out last for loop

        But why does it work, when I send the sequences from shell and getting it with cat?

        One more guess: the two echo commands in the root node may mean the port is opened and closed twice, I think... you might try replicating that in your Perl code.

        (huck's guess was a good one, too bad it didn't work...)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11100548]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (2)
As of 2024-04-20 15:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found