User avatar
rin67630
Posts: 285
Joined: Fri Mar 04, 2016 10:15 am

Solved: Formatting an integer to be passed to Serial as a single char.

Sat Mar 23, 2019 8:45 pm

I am currently struggling with the correct way to format a variable that should be passed to the Serial library in order to be issued as a single character.

Here is my python3 code excerpt:

Code: Select all

import os, pty, serial
import tkinter
import sys
import usb.core
import sched, time
from decimal import *
from threading import Timer
from tkinter import *
from serial import Serial
import threading

dev = usb.core.find(idVendor=0x16c0, idProduct=0x5dc)
root = Tk()
dB = 0
labelText = StringVar()
labelText.set("0")
getcontext().prec = 2

print ("Starting dB Meter by Mikael Bendiksen")


master,slave = pty.openpty() #open the pseudoterminal
s_name = os.ttyname(slave) #translate the slave fd to a filename

print ("Pseudo serial name is: ")
print (s_name)
ser = Serial(s_name, 2400, timeout=1)


def update():
  ret = dev.ctrl_transfer(0xC0, 4, 0, 0, 200)
  global dB
  dB = (ret[0] + ((ret[1] & 3) * 256)) / 10 + 30
  AK = int(0 + (2*dB))
 #ser.write(b'test2\r\n')
  ser.write(AK)
  labelText.set(dB);
  root.update_idletasks() 
  t = Timer(1.0, update)
  t.start();
The (original, commented out) instruction ser.write(b'test2\r\n') works
My instruction ser.write(AK) produces following error:

Pseudo serial name is:
/dev/pts/2
Traceback (most recent call last):
File "devdB.py", line 45, in <module>
update()
File "devdB.py", line 39, in update
ser.write(AK)
File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 558, in write
return len(data)
TypeError: object of type 'int' has no len()

The Serial library clearly expects a text.
AK is an integer which value is changing between 50 and 255. It should be converted into a single text byte.

Who can tell me how to do that magic?
Thank you!
Last edited by rin67630 on Sun Mar 24, 2019 9:03 pm, edited 1 time in total.

Andyroo
Posts: 3310
Joined: Sat Jun 16, 2018 12:49 am
Location: Lincs U.K.

Re: Formatting an integer to be passed to Serial as a single char.

Sat Mar 23, 2019 8:59 pm

Could you use the chr() function in Python?

This returns a Unicode character but for the range you are using I think you only get a single character.
Need Pi spray - these things are breeding in my house...

User avatar
rin67630
Posts: 285
Joined: Fri Mar 04, 2016 10:15 am

Re: Formatting an integer to be passed to Serial as a single char.

Sat Mar 23, 2019 9:27 pm

Andyroo wrote:
Sat Mar 23, 2019 8:59 pm
Could you use the chr() function in Python?

This returns a Unicode character but for the range you are using I think you only get a single character.
Yes, thanks.
I tried, but got an error:

Traceback (most recent call last):
File "devdB.py", line 46, in <module>
update()
File "devdB.py", line 40, in update
ser.write(chr(AK))
File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 518, in write
d = to_bytes(data)
File "/usr/lib/python3/dist-packages/serial/serialutil.py", line 63, in to_bytes
raise TypeError('unicode strings are not supported, please encode to bytes: {!r}'.format(seq))
TypeError: unicode strings are not supported, please encode to bytes: 'Z'

This error text is imho not helpful to find the correct instruction...

danjperron
Posts: 3331
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: Formatting an integer to be passed to Serial as a single char.

Sat Mar 23, 2019 9:40 pm

maybe

ser.write(AK.to_bytes(1,byteorder='big'))

hippy
Posts: 5350
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: Formatting an integer to be passed to Serial as a single char.

Sat Mar 23, 2019 10:03 pm

Code similar to 'ser.write(chr(AK))' has always worked for me but I tend to use Python 2.7

I thought that also worked for Python 3 but cannot put hand on heart and say it does.

Has what the PySerial library uses or what chr() produces changed in Python 3 or is it simply that your AK is out of the 0-255 range ?

I have no idea; but you can search Google as easily as I can, and can add a 'print' to show the value of AK before the write.

Andyroo
Posts: 3310
Joined: Sat Jun 16, 2018 12:49 am
Location: Lincs U.K.

Re: Formatting an integer to be passed to Serial as a single char.

Sat Mar 23, 2019 10:14 pm

Going by the 3.5 notes:
chr(i)
Return the string representing a character whose Unicode code point is the integer i. For example, chr(97) returns the string 'a', while chr(8364) returns the string '€'. This is the inverse of ord().

The valid range for the argument is from 0 through 1,114,111 (0x10FFFF in base 16). ValueError will be raised if i is outside that range.
Taken from https://docs.python.org/3.5/library/functions.html#chr
Need Pi spray - these things are breeding in my house...

User avatar
rin67630
Posts: 285
Joined: Fri Mar 04, 2016 10:15 am

Re: Formatting an integer to be passed to Serial as a single char.

Sun Mar 24, 2019 2:33 am

danjperron wrote:
Sat Mar 23, 2019 9:40 pm
maybe
ser.write(AK.to_bytes(1,byteorder='big'))
That works!
Thank you so much.

User avatar
rin67630
Posts: 285
Joined: Fri Mar 04, 2016 10:15 am

Re: Formatting an integer to be passed to Serial as a single char.

Sun Mar 24, 2019 3:01 am

Andyroo wrote:
Sat Mar 23, 2019 10:14 pm
Going by the 3.5 notes:
chr(i)
Return the string representing a character whose Unicode code point is the integer i. For example, chr(97) returns the string 'a', while chr(8364) returns the string '€'. This is the inverse of ord().

The valid range for the argument is from 0 through 1,114,111 (0x10FFFF in base 16). ValueError will be raised if i is outside that range.
Taken from https://docs.python.org/3.5/library/functions.html#chr
sure, but
-print (chr(AK)) returns Z, which seems to be a word
-whereas print (AK.to_bytes(1,byteorder='big')) returns b'Z' which is a byte.
that last one is accepted by serial().

Return to “Python”