Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much

RS232, parity, program flow

by MarSkv267 (Novice)
on Jan 18, 2022 at 13:49 UTC ( #11140561=perlquestion: print w/replies, xml ) Need Help??

MarSkv267 has asked for the wisdom of the Perl Monks concerning the following question:

I have questions about parity, how to send codes in correct format and about the program flow.

Configration file is $CONF and $PORT is the connected USB RS232 adapter found by mode.

When I change parity later in the script (to either odd, even, mark or space of course) it doesn't change unless I (a) change it, (b) write settings and (c) save it into $CONF. Is there any simpler way to do it ?

$ob = Win32::SerialPort->new($PORT) ; $ob->baudrate(19200); $ob->databits(8); $ob->stopbits(1); $ob->buffers(4096, 4096); $ob->parity("none"); $ob->write_settings; $ob->save($CONF);

My next question is about sending codes to COM port. I've found the line ser.write(b'\xa1\xa2') online (which is probably in Python or Java) and I'd like to send them to the COM port to be recevied in the same format as they were sent:

$send="0xa10xa2"; # "0xa10xa2" $send="\x{a1}\x{a2}"; # "กข" $send=hex("a1a2"); # 41378 $send=hex("a1").hex("a2"); # 161162 $ob->write($send);

I assume that the program flow itself below is correct: the "receiving from COM port" functioned in my RS232 terminal already. I still don't receive anything yet on COM part; if parity is changed correctly and when sent codes are in correct format then it should start working?

# read from array foreach $array(@array){ $ob->parity($parity1); # change parity $ob->write_settings; $ob->save($CONF); $send=$char1.$char2.$char3.$char4.; # sending hexadecimal c +haracters $ob->write($send); # receiving from COM port $gotit = $ob->streamline; die "got undef from streamline! $!" if (!defined ($gotit)); return if ($gotit eq ""); if($gotit eq $char5){ # + is $char5 received? $ob->parity($parity2); # change + parity $ob->write_settings; $ob->save($CONF); $ob->write($array); # send +from array } }

Thanks in advance for your help!

Replies are listed 'Best First'.
Re: RS232, parity, program flow
by Marshall (Canon) on Jan 19, 2022 at 11:17 UTC
    From the docs "The write_settings method writes a new Device Control Block to the driver. The write_settings method will return true if the port is ready for access or undef on failure. Ports are opened for binary transfers. A separate binmode is not needed. The USER must release the object if write_settings does not succeed.

    I doubt that you need to save the configuration to the $CONF file. But this: write_settings() or die "port fail! $!"; looks important. That would be a normal paradigm, (1)change a bunch of stuff then (2)say, I'm done, make all of those changes effective. I would imagine that you have to make sure that the serial port is in an "idle state" no characters pending to be send when you fiddle with it's configuration settings. How to do that I don't know, but look carefully at docs. Basically don't screw with the serial port's brain while it is busy.

    I would suppose that $obj->write("\xa1\xa2"); would work? Port is already open for binmode.

    Your code appears to be deviating from my previous advice about async I/O and "not freezing the GUI". Not sure what is going on there. Remember that in the computer's time frame, it will be a very long time before a buffer of chars are actually sent by the port.

Re: RS232, parity, program flow
by MarSkv267 (Novice) on Jan 21, 2022 at 13:49 UTC

    You were correct, when parity is altered it's enough to write it without saving it into conf file.

    I'm still working on my RS232 script, I've downgraded it removing the GUI part to avoid messing with non-blocking (which I can include later when basic problems are solved).

    On another laptop I have program Termite where the auto-reply is set for 303132 (hex) and the respond is 33 (hex). When my script sends 303132 (hex) Termite should respond with 33 (hex) in its GUI.

    $ob->write("\x30\x31\x32"); while(1){ $gotit=$ob->lookfor(); if ($gotit) { print "RX> ".$gotit."\n"; if($gotit eq "\x33"){ print "\t(a)\t".$gotit." eq \\x33\n"; } if($gotit eq "33"){ print "\t(b)\t".$gotit." eq 33\n"; } if($gotit eq "3"){ print "\t(c)\t".$gotit." qe 3\n"; } $nnn=hex($gotit); if($nnn eq "3"){ print "\t(d)\t".$gotit." eq hex(\$gotit)\n"; } if($gotit == 3){ print "\t(e)\t".$gotit." == 3\n"; } } $ob->lookclear; # needed to prevent blocking sleep (0.2); }

    When I start my script Termite writes receives the code sent from my script and sends back code 33 (hex):

    30 31 32 012 33 3

    Unfortunatelly my script doesn't receive the code 33 (hex) sent by Termite.

    If I send 33 manually from Termite it writes 33 0a and my script responds as:

    RX> 3 (a) 3 eq \x33 (c) 3 qe 3 (d) 3 eq hex($gotit) (e) 3 == 3

    The Airlogger (sniffer) shows the following:

    [RX]123 [TX]3

    Polling in Termite is set to 200ms and the sleep in my script is set to 200ms as well. I set different polling in both Termite and my script and it doesn't solve anything.

    I have no idea why code 33 (hex) (or any code sent, 33 is just for an example) sent from Termite is not recognized.

    Thanks in advance for your help!

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11140561]
Approved by philipbailey
Front-paged by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (2)
As of 2022-05-21 00:47 GMT
Find Nodes?
    Voting Booth?
    Do you prefer to work remotely?

    Results (76 votes). Check out past polls.