Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re^3: RS232 and Tk with threads

by Marshall (Canon)
on Jan 05, 2022 at 00:38 UTC ( [id://11140147]=note: print w/replies, xml ) Need Help??


in reply to Re^2: RS232 and Tk with threads
in thread RS232 and Tk with threads

Yes, these simple USB to pseudo RS-232 devices can work well. It depends upon what you are talking to. The typical limitation is that voltage swing is only +-5 volts where "real" RS-232 requires +-12 volts. Sometimes cheap devices don't go sufficiently negative (<-3V) for a valid "mark" level and some devices allow invalid voltage ranges to be "counted". I have seen cases where that wasn't good enough, but usually it is. There can be other issues between manufacturer's in how close the device comes to actually performing like a "real" RS-232 I/F chip would, but I think at this stage, you are just trying to get the basics working and that your particular USB->serial gizmo is "good enough".

Update: The incompatibility issue with voltage levels is complicated. see next post for more discussion of this.

I haven't ever used Perl to talk to a RS-232 device on Windows, but have done it in other languages and other O/S'es.
Yes, you are correct that the documentation does leave a lot to be desired! I hope that further explaining things on the conceptual level will be helpful to you and enable you to experiment further.

The reason to use non-blocking calls is that you don't want your GUI to "freeze" and become unresponsive to mouse clicks. If the processor is off in serial port la-la land, then it won't be processing GUI events. I will allow that perhaps you get a version working with blocking calls and then come back later and refine that so that the GUI doesn't "Freeze". However a lot of applications have some kind of "Stop", "Restart", "Abort" button and you want that button to "work" when needed!

I presume that you got the timed routine to display something every 1/2 second? $receive_T->repeat(5000,\&Receive2); While the processor is running Receive2(), it is not processing GUI events. As long as Receive2() runs fast enough, the user won't notice any difference in the GUI at all. In this case, Receive2() does some simple job and then returns way faster than a human is even physically capable of fully pushing a mouse button. We want the same thing (really fast return to GUI business) to happen with the serial port polling routine.

From the documentation:

$gotit = $PortObj->streamline; # poll until data ready $gotit = $PortObj->streamline($count);# block until $count chars recei +ved # fast alternatives to lookfor with no character processing
If you use the 2nd call which specifies a $count, the processor will stay inside of the streamline() method until that number of characters are received. If the thing you are talking to is not particularly chatty, that could be an entire day! 9600 baud is about 1 char/ms. By comparison it takes maybe 50ms for you to blink your eyes. If I am stitching together voice prompts and there is more than about a 20ms variation between segments, you can hear the difference quite easily. So if your application is a stimulus/response situation, say you send a 6 byte command and get back a 10 byte fixed length response, the blocking I/F could still work out ok, because xmit,rcv and processing is less than 20ms and that is so fast the human won't know that the GUI wasn't working during that 20ms interval. Note: there does appear to be a mechanism to abort blocking calls after a specified timeout.

Now if you are listening to be asked to do some command, you might wait for days before a 6 byte command shows up. The user will definitely know that the GUI has gone "bye-bye" while it is waiting for this command to arrive via the serial port.

The first of these reading methods, $gotit = $PortObj->streamline; works differently. The documentation is poor, but my guess is that you either get: undef, "" (null string) or some number of characters in the string, "abc". In this case, streamline() will return its result right away without any "waiting". I suspect (without any documentation) that undef means that some kind of error occurred. I presume most of the time you will get "", null string, no character received and then there is nothing to do. If you are polling every second, there could be 1,000 characters there.

So for Receive3(), untested of course,

at the top of your code, put: $|=1: # turns off buffering for print() sub Receive3 { my $gotit = $ob->streamline; die "got undef from streamline! $!" if (!defined ($gotit)); return if ($gotit eq ""); # nothing to do - no chars received print "$gotit"; # blocking call, but "fast enough" # actual code would do something with $ +gotit # put it in a buffer and decide if it i +s enough for # a complete command or whatever... }
So when using non-blocking I/O polling, there will not be any while(1){} loop. That is an infinite loop and you could be in there for a long time! I think undef means an error that shouldn't be ignored? This code will find out whether that is true or not. I just printed to the console. You know how to update the GUI and I leave that part to you with the guidance that updating the GUI is a very "expensive" operation - meaning consumes lots of MIPS. Maybe you don't want to update the GUI on a per character basis? However, here it could very well be that it is just fine to do an update per character. Just making you aware that the GUI is "expensive". I've seen programs that spend fully 1/2 of the computer power updating a progress bar too often. When updating the display only when it will change dramatically increases performance.

Ok, now call Receive3() at some interval (which I think you know how to do now) and see what happens.

The serial port package has all sorts of tricky "wait for X to happen" features. Those are blocking calls. You may wind up having to do some of these functions yourself. I have no idea what my ($found, $end, $obattern, $instead) = $ob->lastlook; does.

Update: I don't think that you need to use threads. If you used a separate thread for the serial port, then you could put in blocking calls because even if that thread "blocked", it would not freeze the main GUI thread. But you would still need the paradigm of a non-blocking call to ask the serial port thread whether it had some result to report or not. I think you will be fine with a single thread as long as you don't have any while(1){} loops.

Update2: I am not sure what your moniker of "Marjacktablet" means, but I suggest that you register as Monk - that process is free and non-fattening. There are a lot of advantages to being a "registered user". When you post as just "anonymous Monk", it is hard for me to see perhaps other perhaps related questions and responses that you have had. When I post a direct response to your question, you will be able to see that you have a new reply without having to find the exact thread from x days ago. So there are advantages and I recommend you do it.

Replies are listed 'Best First'.
Re^4: RS232 and Tk with threads
by afoken (Chancellor) on Jan 05, 2022 at 14:53 UTC
    The typical limitation is that voltage swing is only +-5 volts where "real" RS-232 requires +-12 volts.

    Um, no.

    RS232 is specified as +3..15 V for 0 ("space") and -3..-15V for 1 ("mark"), and allows for open circuit voltages of up to ±25 V. The voltage range from -3 V to +3 V is unspecified (neither 0 nor 1). See RS232.

    PC hardware originally used MC1488/MC1489 level converters supplied by ±12 V from the PSU, and so had ±12 V levels. Some old laptops are rumored to have used ±5 V levels instead. Modern level converters (like the MAX232 or MAX3232) often use charge pumps powered by the logic supply voltage, resulting in RS232 levels of about ±10 V for a logic supply of +5 V, and ±5 V for a logic supply of +3.3 V. When receiving, PCs usually read any voltage above +3 V as 0 ("space") and anything close to 0 V and below that as 1 ("mark").

    All of these variants are expected to interoperate flawlessly, and they do.

    Some PC peripherals, especially all serial port mice, and serial port LIRC receivers and simple transmitters, abuse some of the RS232 lines as a power supply. RS232 was never designed for that, and while almost PC serial ports could deliver tens of mA per pin, this is not guaranteed. RS232 is defined by voltages, not current.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
      All of these variants are expected to interoperate flawlessly, and they do.
      Unfortunately, I have seen cases where some of these claimed USB-RS232 devices didn't work. While others did. So obviously the failing devices aren't meeting spec. Exactly why, I am not sure. Sometimes communication was ok with box X but not box Y. The answer was throw unreliable one away and get different one made by somebody else. Somewhere I have a list of "known good" manufacturer's. There is a lot of chatter about this on hobbyist sites.

      Update: from Hardware specific problems

      RS232 ports which are physically mounted in a computer are often powered by three power sources: +5 Volt for the UART logic, and -12 Volt and +12 Volt for the output drivers. USB however only provides a +5 Volt power source. Some USB to RS232 converters use integrated DC/DC converters to create the appropriate voltage levels for the RS232 signals, but in very cheap implementations, the +5 Volt voltage is directly used to drive the output. This may sound strange, but many RS232 ports recognize a voltage above 2 Volt as a space signal, where a voltage of 0 Volt or less is recognized as a mark signal. This is not according to the original standard, because in the original RS232 standard, all voltages between -3 Volt and +3 Volt result in an undefined signal state. The well known Maxim MAX232 series of RS232 driver chips have this non-standard behavior for example. Although the outputs of these drivers swings between -10 Volt and +10 Volt, the inputs recognize all signals swinging below 0 Volt and above 2 Volt as valid signals.

      This non-standard behavior of RS232 inputs makes it even more difficult to select the right RS232 to USB converter. If you connect and test an RS232 to USB converter over a serial line with another device, it might work with some devices, but not with others. This can particularly become a problem with industrial applications. Low-cost computers are often equipped with cheap RS232 drivers and when you test the RS232 to USB converter with such a computer, it might work. But the same converter may fail if you try it in an industrial environment. The chances that RS232 ports from low-cost computers accept signals in the 0..5 Volt range are higher than with industrial equipment which is often specifically designed to be immune for noise.

Re^4: RS232 and Tk with threads
by MarSkv267 (Novice) on Jan 07, 2022 at 13:54 UTC

    Ex anonymus Marjacktablet

    With my first posts I've tried to sign in but I never received any mail - it seems that the mail server blocked mails. Then I signed in with gmail and it worked.

    I implemented your code within my script and IT WORKS!!!

    In module where GUI is defined there's the following widget where read characters from COM port are sent:

    $receive_T = $receive_Tk->ROText(-relief=>'groove',-width=>72,-height=>20,-font=>'Courier 8 bold')->pack();

    In the same module there's the widget which repeats the module for reading COM port:

    $receive_T->repeat(100,\&Receive3);

    Thank you very much for your help!

    I also have to finish the part for sending characters to the COM port, but it seems easier than reading the COM port and I will try to do it myself ... otherwise now I know where I can get advice.

    The next step is communication with SAS. One of my coworkers wrote a script in Python few years ago, maybe I will be able to figure out from Python sources how to poll SAS commands. The coworker has no clue about GUI and I wrote many programs (executables) with GUI this one will be my first project that deals with COM port.

      I am very happy to hear about your success!
      Hooray!

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (8)
As of 2024-04-23 17:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found