How to send data through parallel port in Python? - python

I need to send some data via parallel port using Python. And for this I am using psychopy.parallel module.
I have two Windows 7 x64 machines connected via parallel port. This connection is tested and working because it is used by another software to send data via LPT1 port.
I have installed the necessary libraries for psychopy.parallel as described here.
Here is my naive intuition:
Machine 1 (Sending data):
from psychopy import parallel
port = parallel.ParallelPort(address="0xC010")
port.setData(3) # sets just pin 2, 3 high
Checking on Machine 1
port.readData()
> 3
Checking on Machine 2 (Receiving data):
from psychopy import prallel
port = parallel.ParallelPort(address="0xEC00")
port.readData()
> 0
I see that although I can set the pins correctly on Machine 1 and read the result, Machine 2 just gives me a 0.
How to send and receive a signal via parallel port correctly?

There are a few options:
Maybe you haven't got the right driver for pyparallel/psychopy to talk to. You'll need a 32bit parallel port driver if you're using the Standalone PsychoPy (which includes 32bit python). The answer in the link below tells you how to download another test utility that will insert the correct version of both 32bit and 64bit drivers, which you need to do on both machines obviously
your script sending the pules will finish immediately and conceivably the pins are all being set back to low when the script ends? (I think this isn't usually the case but worth checking)
have you set the right address for the parallel port? Your code currently uses the default address but there are various options.
Lastly, the link below tells you how to do it using inpout32.dll directly but I think the drivers are the first thing to get fixed
PsychoPy sending triggers on 64bit OS

Related

How to send raw string to a dotmatrix printer using python in ubuntu?

I have a dot-matrix printer LX-300 connected to my computer through the network. How do I send a raw string with ESCP characters directly to my printer in Python?
The computer is connected to the printer through another computer. I need to send a raw string because LX-300 image printing result is blurry.
The Problem
To send data down this route:
Client computer ---> Server (Windows machine) ---> printer (dot-matrix)
...and to not let Windows mess with the data; instead to send the raw data, including printer control codes, straight from the client computer.
My Solution
Here's how I solved a near-identical problem for a small in-house database application:
Step 1) Make the printer network-accessible without Windows getting its fingers in the data routed to it. I accomplished this by installing the printer using the "Generic/Text Only" driver, then installing
RawPrintServer on the Windows machine connected to the printer.
Step 2) Send raw data over the network to the TCP/IP port specified when you set up RawPrintServer (default is 9100). There are various ways to do that, here's what I did:
data = b"\x1B#A String To Print\x1B#" # be sure to use the right codes for your printer
ip_addr = 123.123.123.123 # address of the machine with the printer
port = 9100 # or whatever you set it to
s = socket.socket()
try:
s.connect((ip_addr, port))
s.send(data)
except:
# deal with the error
finally:
s.close()
Background
I thought about the problem in two parts:
Client machine: spitting out the data I need from Python with the correct formatting/control codes for my printer, and sending it across the network
Print server machine: transmitting the data to the locally connected printer
Number 1 is the easy part. There are actually some libraries in PyPI that may help with all the printer codes, but I found most of them are aimed at the little point-of-sale label printers, and were of limited use to me. So I just hard-coded what I needed into my Python program.
Of course, the way you choose to solve number 2 will effect how you send the data from Python. I chose the TCP/IP route to avoid dealing with Samba and Windows print issues.
As you probably discovered, Windows normally tries very hard to convert whatever you want to print to a bitmap and run the printer in graphics mode. We can use the generic driver and dump the data straight into the (local) printer port in order to prevent this.
The missing link, then, is getting from the network to the local printer port on the machine connected to the printer. Again, there are various ways to solve this. You could attempt to access the Windows printer share in some way. If you go the TCP/IP route like I did, you could write your own print server in Python. In my case, the RawPrintServer program "just worked" so I didn't investigate any further. Apparently all it does is grab incoming data from TCP port 9100 and shove it into the local printer port. Obviously you'll have to be sure the firewall isn't blocking the incoming connections on the print server machine. This method does not require the printer to be "shared" as far as Windows is concerned.
Depending on your situation (if you use DHCP), you might need to do some extra work to get the server's IP address in Python. In my case, I got the IP for free because of the peculiarity of my application.
This solution seems to be working out very well for me. I've got an old Panasonic printer running in Epson ESC/P compatibility mode connected to a Windows 7 machine, which I can print to from any other computer on the local network. Incidentally, this general idea should work regardless of what OS the client computer is running.
Ultimately, you will need and want to write your own wrapper/script to do this. And since you are using a distribution of Linux, this is relatively easy.
On a Linux OS, the simplest way to issue a print job is to open a subprocess to the lpr. Generally, using lpr lets you access the printer without the need to be logged in as root (being a superuser), which is desirable considering the amount of damage that can be done while logged in as a "superuser".
Code like the following:
import subprocess
lpr = subprocess.Popen("/usr/bin/lpr", stdin=subprocess.PIPE)
lpr.stdin.write(data_to_send_to_printer)
Should be a good jumping off point for you. Essentially, this code should allow you to accomplish what you need.
Be careful though; depending on your privilege levels, a call to open a subprocess might need root level/Superuser permissions.
Subprocesses generally inherit the User IDs and access rights by the user that is running the command. For example, if the subprocess is created by a root user, then you will need root user/Superuser rights to access that subprocess.
For more information, check out the hyperlinks I've included in the post.
Good luck!

Using Python, How do I make a virtual serial port on Linux?

I have two python programs that need to read from the same serial port via pySerial API.
From what I understand, you can not have two programs reading from the same serial port. So what I plan on doing is have one python program read from a physical serial port, and then have it copy the EXACT data it received from the serial port to the virtual serial ports, where the other python programs can read it via pySerial API.
Of the two python progarms that will be using pySerial, only one of them will respond back with anything.
Any ideas how to do this?
Creating virtual serial port may be trivial or complicated depending on your requirements.
If you only need to propagate data from real port to virtual port (and vice versa), you can use tools like socat, remserial, or conserver. See usage examples here: 1, 2, 3.
Such tools create a pty (pseudo-tty) and transfer data between real port and pty in both directions. However, they do not propagate other APIs, includig various termios and ioctl() calls specific to serial port.
If it's not enough, you need more advanced tools like tty0tty or ser2net andsercd (based on RFC 2217) and others. See this post.

Python Pyserial Windows No Port Found

I have just tried to connect to usb mobile to send sms through it using AT commands. But when i use pyserial to connect to it in a windows os, i get error could not open port, the file specified cannot be found.
>>> import serial
>>> ser = serial.Serial(0) # open first serial port
>>> print ser.name # check which port was really used
>>> ser.write("hello") # write a string
>>> ser.close()
even if i replace the 0 with any other value, like 0 -10 or 'com0','com1' etc, i still get error file specified not found, port cannot be open.
There is a command listed in pyserial documentation which lists ports or allows you to open a port
python -m serial.tools.miniterm
This command is supposed to list all serial ports. But it shows none.
I have 3 usb ports on my system. What is causing this issue.
Pyserial is not guaranteed to detect all ports. This depends on how the device and the OS communicate and if pyserial is designed to pick up on this. For Example, pyserial could not detect a LabJack U3-LV or a EPSOM-POS receipt printer I plugged in in a Win8 session (both could be detected using a linux session).
Try serial.tools.list_ports.comports() and see what it gives you.
You could also look at the pyusb module for usb connections.
Also: I recommend being careful when using numbers for ports, as the mapping may not be "common-sense" logical (i.e. 0 may not map to COM0). Use explicit string names instead.
I found the solution myself. Its pretty simple and uses the same code in the question.. I was getting blocked error because there was no modem(nokia phone) in my device manager. although i had plugged in my phone into the usb, there was no nokia pc suite installed. Once you install nokia pc suite and connect your nokia phone, in device manager -> modems your phone will appear. Just check its properties->modem and you will find the com5 or whichever number. Then use that id to connect. If you dont know this, just iterate till you find the right one.
Thanks everyone who tried to help

How to interface with a Nintendo WiiMote through Python 3.3?

I am trying to read the button states and accelerometer and IR camera values with Python 3.3 but none of the ways that I have tried work. The first way is through Bluetooth sockets with this code:
import socket
if __name__ == '__main__':
MAC = '00:1F:C5:35:91:5A'
blue = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
wm = blue.connect((MAC,1))
But this always generates errors. When the computer is already paired to the WiiMote I get No route to host, when I'm not connected but visible I get Operation now in progress and when I'm not visible I get Connection reset by peer.
I'm able to read the button states with pygame.joystick and cat /dev/input/js0 but this leaves me unable to send requests to the WiiMote which allow me to read the accelerometer and IR camera values.
The are also modules such as CWiiD and PyWiiUse but are only compatable with Python 2.x. I have also tried using the HID to send these requests but the modules install for Python 2.7 even though I don't have that version of Python installed.
Is there any way that this task can be accomplished? I'm running Ubuntu 13.10 on a 64 bit Intel i5 and the solution doesn't need to platform independent.

Half-duplex serial communications in Python

I have a device with a built-in USB/Serial adapter (shows up as a Prolific PL2303). The device documentation provides full details on how to communicate with it, and provides a sample Windows app. However, I need to use it on Linux - ideally with Python but I'm not too precious about that.
The device docs state the device runs at 9600, 8N1 with half duplex. The Windows app works fine - device works fine (so I know it's not a device problem). However, I can't communicate with it using Python on Linux. I'm using pySerial, and I've tried a similar (full duplex, also PL2303) device which works fine.
I've tried several combinations of setting xonxoff, rtscts etc. I've also tried RTS toggling using setRTS(True) and checking for CTS and DSR etc - gets all return False. I can successfully open the device using pySerial (I can see activity light flashing - simple but effective test) and pySerial complains if you unplug it during reads/writes.
Doesn't seem to matter what flags/lines I set or what data I send, always get the same result.
>>> s=serial.Serial()
>>> s.port('/dev/ttyUSB1')
>>> s.open()
>>> s
Serial<id=0x7fe94b533b50, open=True>(port='/dev/ttyUSB1', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=3, xonxoff=0, rtscts=0, dsrdtr=0)
>>> s.write('\2CMD2292\r')
>>> s.inWaiting()
0
>>> s.setRTS(True)
>>> s.getCTS()
False
(several iterations of above with different flags).
Ignore the data in the write command - that's just a status check command. Doesn't matter what goes there, the device should either respond with an answer or an error.
I've even resorted to closing and re-opening the device in between setting various ctsrts flags etc., and unplugging / replugging it to force resets. As above it continues to work fine using the Windows test app. I can't use Portmon etc. to sniff the Windows port traffic as it's a 64bit Win7 install and I don't currently have time to build an XP machine.
Any thoughts?
UPDATE: I've also tried all of the above using Python on the same Windows box that the demo app works on. It definitely opens the port and communicates, but again no info back regardless of what's written.
UPDATE2: It looks like it might be device-driver related. Some additional background research suggests that some PL2303 chips have functionality to support half-duplex, but this isn't supported by the Linux drivers. The Windows demo app comes with a dedicated device driver and the app doesn't work on a clean test machine using default Windows drivers. This makes me think that while I can connect to it successfully through Python, I can't control the duplex comms (e.g. even in an STX/ETX way) and therefore this might be a hopeless case. sigh.
UPDATE3: Thanks for the comments below. However, I couldn't find any way round this. I tried a USB protocol analyser, and I tried disassembling the driver but it just became rather time-consuming, so in the end I took the device apart and after some tinkering I managed to replace the existing usb-serial adapter with a proper PL2303 part - on the device side, it was just a basic 2-wire serial interface so it didn't care what was talking to it. I can't seem to close this question so I'll leave it as-is.
Try
s.flush()
just after your s.write call

Categories