I don't think you are dealing with a Perl issue here, not directly. But just in case, add this at the start of your script to make your life easier and help us get to the root of the problem:
use strict;
use warnings;
use diagnostics;
You are running this on a Raspberry Pi, right? In my experience, this hardware had a lot of "unexpected features", like messing up SPI timing when a new ethernet packet arrives.
In your case, you seem to transfer more than 16 bytes at one time, but i rather suspect the serial hardware has a 16 byte limited buffer, and that is most likely where your timing gets messed up and you drop some bytes. This happens when the system is busy with other stuff (like dealing with ethernet or other interrupts) and can't get to working on the serial buffer in time.
You have quite a few alternatives here. You could use another hardware or try one of those serial-to-ethernet boxes. You could also try a different Serial-to-USB adapter.
perl -e 'use MIME::Base64; print decode_base64("4pmsIE5ldmVyIGdvbm5hIGdpdmUgeW91IHVwCiAgTmV2ZXIgZ29ubmEgbGV0IHlvdSBkb3duLi4uIOKZqwo=");'
| [reply] [d/l] [select] |
Unfortunately I can't reproduce the issue you describe on my end (at least with a fake serial port). When I've worked with Device::SerialPort, I've had the most success reading a single byte from the port at a time. However, I've had even better experiences on *NIX (including RPi) with IO::Termios, which I wrote about here: Lower-Level Serial Port Access on *NIX
| [reply] |
Hi haukex, looks like I’ll be jumping ship from from Device::Serialport. My programming knowledge is limited, I mainly work from examples I find online. I will try IO::Termios after work with examples from the link you provided. Thank you.
| [reply] |
Hey guys, I've found something that works on the bench. Fingers crossed it works in production. Was a simple matter of adding a sleep().
my $char = $port->lookfor();
sleep(4); # number will be decreased in production
if ($char) {
print "$char\n";
First time posting here, was not disappointed. Thanks heaps!
| [reply] [d/l] |
I've found something that works on the bench.
sleep(4); # number will be decreased in production
That looks quite scary. Seeing delays in code handling serial transmissions is usually an indicator for misconfiguration, i.e. lack of proper handshake. In Serial data delay, you explicitly disable all handshake:
$port->handshake("none")
Check the documentation of the serial device. I would expect to find either handshake lines (RTS/CTS, sometimes DSR/DTR), or some kind of software handshake. XON/XOFF is common for software handshake, but people have been (and still are) very creative in re-inventing the wheel, especially with embedded devices. There are literally hundreds of strange software handshake protocols.
Software handshake using XON/XOFF can be handled by the operating system or some low-level driver library, but you have to enable it. If you find the device sending unexpected 0x13 and 0x11 bytes, especially when writing much data to it, it may implement XON/XOFF. 0x13 = 19 = DC3 is XOFF, meaning that you should stop sending more data. 0x11 = 17 = DC1 is XON, telling you to continue sending data. For non-standard software handshake variants (i.e. everything but XON/XOFF), RTFM.
Hardware handshake is usually easier. Some embedded devices implement only one half of the hardware handshake, a pin to indicate "input buffer is full, stop sending more data". That is usually labelled RTS (according to RS232E, it should be labelled RTR, ready to receive) and should be connected to CTS on the other side. The other pin, CTS, is omitted because they expect their communication partner (i.e. the PC) to be able to handle all incoming data at full speed.
For hardware handshake, a three-wire connection (RxD, TxD, GND) is not sufficient, you need at least one extra wire from device RTS (or DTR) to PC CTS (or DSR). Use at least a five-wire connection (RxD, TxD, GND, RTS, CTS), preferably a cable with all signals connected.
In Serial data delay, I see you using /dev/ttyUSB0. I know there are some USB RS232 converters that DO NOT implement the handshake lines. Make sure you don't have such a troublemaker device. FTDI FT232-based adapters should be fine. FTDI FT230 implements only RTS and CTS, but lacks support for DSR, DTR, DCD, RI. Prolific-based adapters cause a lot of pain on Windows due to crappy drivers, but work ok on Linux.
At work, we have banned everything but FTDI, and we buy them only from major distributors. They costs a few cents more, but it's simply not worth fiddling with some random garbage chip that either crashes the system, stops transmitting data, or damages data in the middle of a 24 hour aerospace test procedure. The costs for supporting crap chips in that environment buy you a truckload of FTDI chips. For debugging, you also do not want a chip that is unreliable. Your development target is sufficiently unreliable to cause lots of trouble. You do not want to waste time debugging your debug tools.
Also in Serial data delay, I see /home/pi. Are you using a Raspberry Pi? Its serial port does support RTS/CTS, but you have to enable it: https://ethertubes.com/raspberry-pi-rts-cts-flow-control/, http://www.deater.net/weave/vmwprod/hardware/pi-rts/. Remember that the Raspi uses 3.3V signals, you have to add a level converter. Using a MAX3232 or similar is quite easy, as they come as ready-to-use adapter boards, including pin headers for the Raspi side and DB9 connector for the RS232 side.
Alexander
--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
| [reply] [d/l] [select] |
Thanks heaps for the replies, I had time to try a couple things before work, with the same result.
Used a laptop (Linux Mint) to receive the serial data serialUSB to SerialUSB.
Used laptop (Linux Mint) to received serial data on onboard serial ttyS0, sent from SerialUSB.
| [reply] |