On my new Dell XPS laptop, I've just started loading all of my goodies on -- and I'm embarrassed to say that I can't get pyserial to work properly in Python 2.7. I ask it to do the following:
import serial
s = serial.Serial(0)
s.write("Hello world!")
s.close()
...and the darn thing gives me the following (code simplified to the real problem so you don't have to scrub through forests of my poorly written Python):
SerialException: could not open port COM1:
[Error 2] The system cannot find the file specified.
I've tried asking for a port explicitly (s = serial.Serial(port="COM1", baudrate=9600) but to no avail. I've also tried COM2, COM3, COM4, etc... But I'm not sure how high it's really worth going if they all return the same SerialException, ya dig?
The reason I mention my laptop model is because I've heard rumors that Dell is slowly killing off its serial connectivity, but quite frankly, I don't know nearly enough about serial-ness to even pretend to know what I'm talking about here. So I hereby bequeath this mission upon you experts.
Thanks for any help you can give!
Are you sure you have a serial port? Your description of the problem suggests that you don't. I'd be quite surprised if a laptop built within the last ten years would actually have one.
I could be wrong though (I'm trying to find it in the specs of the XPS as I write this). At any rate, if you're running Windows you can look in the Device Manager under Ports (COM & LPT)... although beware, some PCs will show a couple of serial ports here that are actually used for purely internal purposes.
If you don't have a serial port, you need to get a USB-to-serial adapter. Look in the Device Manager to find the name of the port.
You can get USB/serial adapters from some electronic stores or office supply stores, and off eBay.
Related
Goal
I have made a website using the Flask framework and am fairly comfortable with HTML, CSS, JS, Python. My goal is to connect an arduino to the client's PC's usb port and use serial.write() to send a number to it.
Notes
I have a working example of interfacing with python if arduino was connected to the server.
import serial
ser = serial.Serial('COM4', 9600)
ser.write('5')
Now I want to run these exact 3 lines on the client side.
Is this even doable? I have researched a lot and it seems that this is not doable due to security reasons? (I'm hoping somebody proves me wrong here.) That is why I'm looking for a workaround. But before that I must mention, I don't need any of the data (numbers) to come from the server. Once the webpage is loaded all serial communication that I need is on the client side.
Client side python: I have looked into writing python on the client side and read about skulpt and PyPyjs but am not sure how I could run the mentioned 3 lines with them on client side(neither seems to support pyserial needed for import serial or at least I have not had any luck finding documentation)
I also looked into arduino documentation for interfacing with software but it seems that all the languages mentioned are server side. If you know of any possible direction languages that could help, I'd be happy to know and go learn them. I saw many forums mentioning Node.js but my understanding is that would also only do the job on the server side.
I'd appreciate any help on where else/other topics I should look into. Thanks in advance.
Is this even doable? I have researched a lot and it seems that this is not doable due to security reasons?
You are correct. There is no ability for browsers to access a COM port. It doesn't matter what language or framework you pick, a browser isn't going to give you that access.
You would need to make a standalone desktop application. You can use HTML and JavaScript to access serial ports, just not in a browser. Chrome Apps (which are actually going away) can do it, as well as an App that uses Electron.
I have an old Raman spectrometer (one of these - http://www.camo.com/downloads/partners/deltanu/Inspector_Raman_Datasheet.pdf) and I'd like to write code, ideally in Python, that can provide it with input parameters, operate it and receive data from it.
The spectrometer connects to a PC via a USB, although it is assigned to a virtual COM port. I currently control it using an .exe file provided by the company that used to sell it, that I believe was produced using LabVIEW.
Is it possible to write my own code to control this sort of hardware? How can I pass parameters and commands to hardware? What information would I need to know to do this?
Although I'm a fairly proficient Python coder, this is a brand new area for me, so any advice on where to start would be super appreciated. I'm open to coding in another language if that would be more appropriate. And let me know if I need to provide any more info.
Cheers, Liam
A google search for the device model name and "programming manual" is usually where I start with something like this. Those keywords hopefully turn up something from the manufacturer that tells you how to do exactly what you're trying to do, and a lot of them include code samples. Unfortunately, with the little information I have on your device, I couldn't find anything. That's going to make it much, much harder.
Everything beyond this point is a guess based on what I've seen before. Typically, if a LabVIEW program interacts with a device over a virtual COM port, the program sends an ASCII command to the device using the protocol defined in the manual, and then receives ASCII data in return. You can try sniffing that data with the NI I/O Trace tool (http://www.ni.com/download/ni-io-trace-14.0.1/4914/en/) while running the manufacturer's application, and then trying to make sense of the flood of data that you see on that port.
It could also be a Modbus device, which may help you figure out the structure of the communication.
In short, this'll be tough without a programming manual, but there is some hope. Good luck!
I'm new to this kind of things so I need help from you guys. When playing around with serial ports, I figured why not echo from one terminal and cat/listen from the other using one of the /dev/ttyS* serial ports on my ubuntu 15.04 laptop. When i do cat /dev/ttyS0 it gives me input output error. then i tried doing it using pyserial on python. when i do
import serial
ser = serial.Serial('/dev/ttyS0')
it gives me SerialException: Could not configure port: (5, 'Input/output error')
After looking around on stack overflow, I found this related post Pyserial: could not configure port: (5, 'Input/output error)
where one of the guy said you need a physical connection to make this happen. I'm guessing that is to create some kind of loop. So my question is what kind of physical connection is required? Who a usb stick do it, or do i need something dedicated to work with the serial port. And if someone would provide good explanation on how serial port programming works, that would be great.
Feel free to edit the question where you see fit. Guys please no need to complain about how dumb this question sounds and all that. After all lots of people come here to learn, and that is what i am doing
You need to have one or two physical com or serial ports on your pc to achieve this. if you have one port you can create a loopback plug by connecting the Rx and Tx pins together.
If you don't have a physical serial port and want to test it you can use socat to create a virtual serial port.
Physically you need a cable that swaps the transmit and receive pins. This is known as a "null-modem cable" because it can connect two computers together without a modem in between.
You probably also need to add yourself to the "dialout" group in order to use the serial ports.
putty is a really good program for testing with serial ports -- you can have two putty instances talking to each other, and then try to connect putty on one side with Python on the other side.
Finally, sometimes there is a modem daemon that will run and think that it should own all the serial ports. It usually gives up and lets them go after awhile, but you might have to find it and kill it if you don't want random processes polling for modems on your serial connection.
I would like to know how to have a Python script determine how a computer is connected to a network. The reason for this is because the script becomes buggy if the connection speed is too slow, so I would like to show a warning if the user is connected via WiFi.
The actual Python executable being run is located on my company's LAN, so this is why the connection speed matters. Additionally, since this executable cannot be run without a connection, I am not concerned with checking that the user is online.
I know nothing about how Python interacts with things like this (or even if its possible), so please let me know if there's anything I can clarify. Thanks in advance
I am using Python 2.7.6 32-bit on Windows 7 64-bit (different bits because pyEnchant)
On Windows, this information is made available via WMI's Network Adapter Classes.
In .NET (e.g., with IronPython), this is easy to use:
ni = Windows.Networking.Connectivity.NetworkInformation
profile = ni.GetInternetConnectionProfile()
if profile:
interface = profile.NetworkAdapter.IanaInterfaceType
if interface == 71:
do WiFi stuff
elif interface == 6:
do Ethernet stuff
else:
do wtf stuff
The IanaInterfaceType is a number from this IANA list. (I you want to parse SNMP MIBs, you can download it that way.) Note that Windows may lump some less common/obsolete adapter types in with Ethernet, but you probably don't care about that.
For older versions of Windows—I'm not sure whether Windows 7 counts as "older" or not—you want Win32_NetworkAdapter and friends, not MSFT_NetworkAdapter/NetworkAdapter as linked above, so the code will be different.
In particular, getting the adapter that's supplying the default internet connection is harder, but more flexible, while getting its type is easier, but less informative. IIRC, at least in XP, even though Windows had some notion of "the internet connection", you couldn't access it through WMI—but you could access all internet connections, or search/iterate for the one you care about. Which is actually better if you've got a VPN, or are sitting on a DMZ, or have multiple NIC cards active at once, etc.
So, what you do is to search or iterate Win32_IP4RouteTable to find which connection route handles the IP address you actually want to connect to, or use Win32_NetworkAdapaterConfiguration to find which NIC handles the address you want to connect from. Either way, you will get an InterfaceIndex, and you can look up the Win32_NetworkAdapter with that InterfaceIndex. Then its AdapterType is a nice string that you can just check != "Wireless". (I believe I figured all of this out from a VBscript example at TechNet Script Center and then ported it to IronPython myself, but it was a long time ago, so I may be remembering wrong. Anyway, the docs seem more complete than they did back then, so that shouldn't be necessary.)
Without .NET (e.g., with standard CPython), you have to use either the web services interface, or talk to the native Win32 COM interface.
In theory, you could talk to the COM interface directly via ctypes, but that's a horrible idea; you almost certainly want pywin32 for that.
And, even better, I would suggest looking around on PyPI for wrappers, like this one, rather than building it yourself. Then, the code should be nearly as simple as with .NET.
Here's some pseudcode using the WMI library linked above and the XP-compatible source-address method described above:
import wmi
MY_IP = '10.1.2.3'
w = wmi.WMI()
for nac in w.Win32_NetworkAdapterConfiguration():
if MY_IP in nac.IPAddress:
idx = nac.InterfaceIndex
break
else:
oops, do something, no NIC has that address
na = w.Win32_NetworkAdapter(InterfaceIndex=idx)
if not na:
oops, unlikely race condition, NIC disabled right before we checked it
if na[0].AdapterType == 'Wireless':
do WiFi stuff
elif na[0].AdapterType.startswith('Ethernet'):
do Ethernet stuff
else:
who's using LocalTalk in 2013?
It should be possible to search the NetworkAddressConfiguration, but I have no idea how to search for "IPAddress contains MY_IP" in the wmi library. Using = might work there, who knows; read through the tutorial to find out.
Searching by target address, on the other hand, should be like this:
TARGET_IP = '10.10.10.10'
w = wmi.WMI()
rt = w.Win32_IP4RouteTable(Destination=TARGET_IP)
if not rt:
oops, no route to host
idx = rt[0].InterfaceIndex
# same as above
Using WMI you can determine the connection without needing the local machine IP.
Use NetConnectionID instead of AdapterType for comparing seems to work.
Works on Windows 10.
import wmi
w = wmi.WMI()
for nac in w.Win32_NetworkAdapterConfiguration():
if nac.IPEnabled:
idx = nac.InterfaceIndex
break
else:
print("oops, do something, no NIC has that address")
na = w.Win32_NetworkAdapter(InterfaceIndex=idx)
if not na:
print("oops, unlikely race condition, NIC disabled right before we checked it")
if 'Wi' in na[0].NetConnectionID:
print("do WiFi stuff")
elif 'Ethernet' in na[0].NetConnectionID:
print("do Ethernet stuff")
else:
print("who's using LocalTalk in 2013?")
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