Using pySerial with Python 3.3 - python

I've seen many code samples using the serial port and people say they are working codes too. The thing is, when I try the code it doesn't work.
import serial
ser = serial.Serial(
port=0,
baudrate=9600
# parity=serial.PARITY_ODD,
# stopbits=serial.STOPBITS_TWO,
# bytesize=serial.SEVENBITS
)
ser.open()
ser.isOpen()
print(ser.write(0xAA))
The error it gives me is : "SerialException: Port is already opened".
Is it me using python3.3 the problem or is there something additional I need to instal ? Is there any other way to use COM ports with Python3.3 ?

So the moral of the story is.. the port is opened when initialized. ser.open() fails because the serial port is already opened by the ser = serial.Serial(.....). And that is one thing.
The other problem up there is ser.write(0xAA) - I expected this to mean "send one byte 0xAA", what it actually did was send 170(0xAA) zeros. In function write, I saw the following :
data = bytes(data) where data is the argument you pass. it seems the function bytes() doesn't take strings as arguments so one cannot send strings directly with: serial.write(), but ser.write(bytearray(TheString,'ascii')) does the job.
Although I am considering adding:
if(type(data) == type('String')):
data = bytearray(data,'ascii')
in ser.write(), although that would make my code not work on other PCs.

Related

ser.inWaiting() always returns 0 when reading a virtual port

I'm having difficulties getting pyserial to play nicely with a virtual port. I know this is an area which a few others have written about, but I couldn't find anything which solved my problem in those answers. Forgive me if I'm just being dense, and the solution exists ready-made elsewhere.
This is what I'm trying to achieve: I want to set up a virtual port, to which I can write data in one .py file, and from which I can then read data in another .py file. This is for the purposes of development and testing; I don't always have access to the device around which my current project is built.
This is my code so far:
dummy_serial.py
import os, pty, serial, time
master, slave = pty.openpty()
m_name = os.ttyname(master)
s_name = os.ttyname(slave)
# This tells us which ports "openpty" has happened to choose.
print("master: "+m_name)
print("slave: "+s_name)
ser = serial.Serial(s_name, 9600)
message = "Hello, world!"
encoded = message.encode("ascii")
while True:
ser.write(encoded)
time.sleep(1)
reader.py
import serial, time
# The port will change, depending on what port "openpty" (in the other file)
# happens to choose.
ser = serial.Serial("/dev/pts/1", 9600)
while True:
time.sleep(1)
incoming_bytes = ser.inWaiting()
# This print statement gives us an idea of what's going on.
print(incoming_bytes)
if incoming_bytes != 0:
data = ser.read(incoming_bytes)
print(data)
At present, dummy_serial.py seems to run okay. However, reader.py just keeps saying that there are no bytes waiting to be read, and hence reads no data.
What I would like:
An explanation of why ser.inWaiting() keeps returning 0, and a solution which makes ser.read(x) actually spit out "Hello, world!"
Or an explanation of why what I'm trying to do is fundamentally silly, and a better means of creating a writeable/readable virtual port.

pyserial: how to receive rs232 answers from power supply correctly

I'm currently trying to set up a communication with a power supply (RND 320-KA3005P) through RS232 with pyserial.
The Problem is that after sending "*DIN?", which should return manufacturer, model name and software version, the connection seems to receive nothing. Also no other command was successful. Using the included software, after connecting, a LabView program opens and the device is remote controllable, so I think the problem is in my code.
Code Example:
Connection parameters as described in the manual.
As end-of-line characters I tried "\r\n","\r","\n" which seems to solve many other problems, but here with no success.
import io
import serial
import time
import sys
ser = serial.Serial('COM4',
baudrate = 9600,
bytesize=8,
timeout=1,
stopbits = serial.STOPBITS_ONE,
parity = serial.PARITY_NONE,
xonxoff = False)
eol_char = '\r\n'
sio = io.TextIOWrapper(io.BufferedReader(ser),newline=eol_char)
while True:
sending = input("type:\n")
ser.write((sending + eol_char).encode('utf-8'))
time.sleep(0.2)
ans = sio.read()
sys.stdout.write('received: ' + str(ans))
print('\ntry again\n')
Which after entering the command gives:
type:
*DIN?
received:
try again
type:
Also when I run the script on the loopback
ser = serial.serial_for_url('loop://',timeout=1)
...
output:
type:
*DIN?
received: *DIN?
try again
type:
it seems to work fine. I'm using Windows 10 and a USB to RS232 converter. Does anyone have an idea about what I'm missing here?
Thanks in advance.
The solution I figured out is rather disappointing. Turns out that with a USB to RS232 converter cable, instead of the USB connection I used before, the commands to set and get values work as expected. The command '*DIN?', which I tried initially, which I got from the manual:), still gives no reaction - probably just not supported.
I believe the *DIN? command, found under "Functionality check" which should return: "Manufacturer, model name, software version.", is actually a typo. When all commands are later listed in the manual, number 11 says *IDN? and should return the KA3005P identification.
It is also ironic that the example they give under number 11 says: "* IDN?"...

Python Run Shell Without Enter [duplicate]

This question already has answers here:
How to read a single character from the user?
(26 answers)
Closed 6 years ago.
This is my first post to stackoverflow, so please let me know if I don't follow the correct etiquette.
I am also new to Python and would like to incorporate it into a project. I currently have a Emotiv EEG headset and would like to run a homebuilt 3-D Printer from brain signals. To do so, the EEG headset is read by EmoKey 2.0.0.20 (see attached photo), EmoKey will then send keystrokes to the Python Shell, Python interprets this and sends commands to my Arduino run printer through a COM PORT.
This may seem to be an indirect way of doing things, but it works except for one hitch. Lets pretend I think left, this is sent to EmoKey which types 'L' and the keystroke Enter into the Python Shell. In theory this would then move the printer head left. However, when EmoKey sends Enter it only creates a new line in the Shell, it doesn't actually execute. I then have to press enter by hand, which defeats the whole point.
.getch() hasn't worked because I don't think there is an actual key stroke for it to read. The link below also seems like it would be useful, but It hasn't worked thus far.
How to run a shell script without having to press enter/confirm s.th. inbetween
My question is: How can I get Python to execute what is written in the shell when only something like L or R is written? I don't think I can have it wait for a keystroke, Python would have to wait and automatically execute when it sees a specific command.
I understand that this may seem like a duplicate of the link below. However, .getch hasn't worked with EmoKey so far (maybe it's just a mistake on my part). Also, I wan't to find a way for my Python script to read what is put into the shell. Although I've started this project with just the "L" and "R" commands for simplicity and prototyping, I will move into using G-code so I can communicate with other printers or CNC equipment. That is another reason why .getch won't work in my case since it only grabs a single character (A single G-code command will be a few characters long).
Python read a single character from the user
I'm using Windows 10 and Python 2.7.11.
import serial
ser = 0
def init_serial():
COMNUM = 3 #Enter Your COM Port Number Here.
global ser #Must be declared in Each Function
ser = serial.Serial()
ser.baudrate = 9600
ser.port = COMNUM - 1 #COM Port Name Start from 0
#ser.port = '/dev/ttyUSB0'
#Specify the TimeOut in seconds, so that SerialPort
#Doesn't hangs
ser.timeout = 10
ser.open() #Opens SerialPort
# print port open or closed
if ser.isOpen():
print 'Open:' + ser.portstr
init_serial()
while 1:
temp = raw_input('Send command + Enter:\r\n')
ser.write(temp) #Writes to the SerialPort
#bytes = ser.readline() #Read from Serial Port
#print 'Response: ' + bytes #Print What is Read from Port
EmoKey Interface
I think you are looking for something like readchar:
import readchar
ch = readchar.readkey()
This definition is kind of clunky and unsatisfying, but I think it solves your problem without having to install any new packages. If I create a module defined in this link (I put it in a file called "getch.py"), we can check if the input key matches anything in a list of strings.
from getch import getch
while True:
if getch() in ['l', 'r', 'L', 'R']:
print('This was the key I was looking for!')
Technically you only need the section of the class I linked to that is relevant to your OS, but this example getch() function that I linked to is nice in that it is cross platform.

pySerial very strange behaviour ... Code works when executed in shell but not in a script

I'm struggling with pySerial. To be brief ... The code below works great when executed in the Python Shell ...
>>> import serial
>>> s=serial.Serial("COM5", 9600)
>>> while(1):
s.write("#")
s.readline()
Produces the output below in the shell:
1L
'56.73\r\n'
1L
'56.73\r\n'
When the same code is written in a script say "readSerial.py" the script will either not transmit the hashtag that triggers the serial device to transmit the data, or will not receive the replied data.
I'm using pySerial 3, but have noticed the same behavior with 2.7. Using Python 2.7.10 64 bit on Win10. But also noticed this behavior on Raspberry Pi with /dev/ttyACM0. I would really like to have this solved. I'm not that experienced in Python so this might be an oversight.
Hardware is checked and double checked.
Thanks,
KK
Thanks, but I really know how to print data from Python. The problem is really with pySerial. Here is the complete code, please don't discus errors in commented out code. These are of no concern here.
#from numpy import array
#import matplotlib.animation as animation
import time
import serial as s
#data = array([])
Arduino = s.Serial("COM5", 9600)
i = 0
while (1):
try:
Arduino.write("#")
time.sleep(.1)
inString = Arduino.readline()
data = float(inString)
print i, ":", data
i += 1
time.sleep(1)
except KeyboardInterrupt:
break
Arduino.close()
But like said this doesn't work. As far as I can tell the readline() function does not return. And ... there 's really no point in making it return by setting the tx timeout. To add to the mistery; When the code is debugged (i.e. stepped trough) it does work.
Thanks in advance,
KK
From the FAQ :
Example works in serial.tools.miniterm but not in script.
The RTS and DTR lines are switched when the port is opened. This may
cause some processing or reset on the connected device. In such a
cases an immediately following call to write() may not be received by
the device.
A delay after opening the port, before the first write(), is
recommended in this situation. E.g. a time.sleep(1)

Port already in use

I am on a Windows 7 computer, trying to use Python to run a simple program on my Arduino to make it blink.
For some reason, whenever I attempt to run the script in PowerShell, I receive an error that the port is already open. I have tried restarting my computer, changing Arduinos, changing the USB port that I have plugged into, running a different program that I am quite sure closes the computers connection to the port. However, I am still getting the same error.
I am quite new to Python and Arduino, so there might be something stupidly easy that I am forgetting. I have asked a friend who is more experienced and he spoke of it being a problem with Windows.
Here is the relevant code. The class I used in Python is as follows.
import serial
import socket
import glob
import pickle
from time import sleep,time
class Ardustat():
def __init__(self):
self.port = ""
self.ser = serial.Serial()
self.mode = "serial"
self.debug = False
def findPorts(self):
"""A commands to find possible ardustat ports with no Arguments, """
return glob.glob("COM*")
def connect(self,port):
if self.mode == "serial":
self.ser = serial.Serial(port,57600)
self.ser.timeout = 1 # what does this do?
self.ser.open()
return "connected to serial"
And the Python code is
from ardustat_library_simple_dan import Ardustat
import time
serial_port = 'COM6'
ard = Ardustat()
#Connect to the irritating ardustat
ard.connect(serial_port)
for a in range(0,5):
ard.blink(serial_port)
time.sleep(.2)
The Arduino code is long, but in the setup there is the following code.
void setup()
{
//Startup Serial
Serial.begin(57600);
// Serial.println("Hi Dan!");
Is there anything wrong?
I can see a few reasons why this is not working:
You have your serial monitor running while you're running your script:
The serial port can only be open once on a given host, if you try to open it twice, the second program to open it will report it as already opened.
You did not open the serial connection on the Arduino side:
You say you run a blink sketch. If that's the default blink.ino, it does not open the serial port and your system may report the serial port is not openable (and I don't know Windows, but I wouldn't be surprised to see an inconsistent error happening)
You wrote your own blink sketch, but you did not put Serial.begin(115200); in the setup() of your sketch file.
You open the port twice (or more) in the Python code.
You shall have only one serial.open() statement in your code.
So first, check your code to be sure you do actually use the serial port from within the Arduino sketch. You can paste your code in your question so we can check that out.
Then, check your Python code to be sure you do actually open the serial port once and only once within your script.
Finally, be sure to not have another program opening the serial port while you're running your script, usually one tend to test the connection with Arduino's serial monitor, let it open and try to open the port using a script, which does not work. I saw that very often from beginners.
And I vote for... problem #3 \o/
class Ardustat():
def __init__(self):
self.port = ""
self.ser = serial.Serial() # Here you open the port once
self.mode = "serial"
self.debug = False
def findPorts(self):
"""A commands to find possible ardustat ports with no Arguments, """
return glob.glob("COM*")
def connect(self,port):
if self.mode == "serial":
self.ser = serial.Serial(port,57600) # Here you open the port twice
I did not check pySerial's source code, but I'm pretty sure serial.Serial() opens up the first serial port it finds available at its default speed. Therefore, as you don't close the connection from the first instance of self.ser, the second instance gets crazy saying "dude, it's already opened!".
That's why you'd better not add an abstraction (Artustat) over a correct abstraction (pyserial.Serial), but just use correctly the tools and do something like:
with serial.Serial(port, speed) as ser:
do_blink(ser)
where do_blink() is a function where you do your stuff. The with statement over serial.Serial will take care of the life of the serial port object (opening it when you enter the block, closing it as you exit the block).

Categories

Resources