Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Re: Sending USB commands with Python

Reply
Thread Tools

Re: Sending USB commands with Python

 
 
Dennis Lee Bieber
Guest
Posts: n/a
 
      08-29-2012
On Thu, 30 Aug 2012 08:29:32 +1000, Cameron Simpson <(E-Mail Removed)>
declaimed the following in gmane.comp.python.general:

> On 29Aug2012 17:57, Dennis Lee Bieber <(E-Mail Removed)> wrote:
> | On Wed, 29 Aug 2012 14:21:30 -0700 (PDT), "Adam W."
> | <(E-Mail Removed)> declaimed the following in
> | gmane.comp.python.general:
> | > You are correct about the 2 being the number of bytes written. However when I issue a read command I get:
> | >
> | > >>> ep.write('\x1BA')
> | > 4
> |
> | That's interesting -- as if each byte you send is expanding into a
> | pair of bytes.
>
> UTF-16? ISTR that Windows often uses big endian UTF-16 for filenames and
> text data; could there be some default encoding in ep.write getting in
> your way?
>
> Disclaimer: I'm really not a Windows guy.


I know W9x has both "normal" and "wide" entry points in the system,
and I think WinXP and later default to the "wide" points, but I'd expect
any third party DLL would document what it expects to receive for a
device write operation.

BUT you do give a possible clue. Is the OP using a 3.x Python where
strings are Unicode -- in which case the above may need to be explicitly
declared as a "byte string" rather than text (unicode) string.

I've only recently upgraded my desktop to Python 2.7 (and had to
make sure that copying the old "CherryTemplate" from 2.5 was still
functional -- I don't have time to rework a program that builds a set of
static web pages from database information), so can't really check on
sizes.
--
Wulfraed Dennis Lee Bieber AF6VN
http://www.velocityreviews.com/forums/(E-Mail Removed) HTTP://wlfraed.home.netcom.com/

 
Reply With Quote
 
 
 
 
Adam W.
Guest
Posts: n/a
 
      08-29-2012
On Wednesday, August 29, 2012 6:56:16 PM UTC-4, Dennis Lee Bieber wrote:
>
> BUT you do give a possible clue. Is the OP using a 3.x Python where
>
> strings are Unicode -- in which case the above may need to be explicitly
>
> declared as a "byte string" rather than text (unicode) string.
>


Huzzah! I am indeed using 3.x, and slapping on an .encode('utf-8') made my printer try to spit paper at me! Progress.

Also, astute observation about the endpoint needing to be an input, with the following modification I get:

>>> ep.write('\x1BA'.encode('utf-8'))

2
>>> ep = usb.util.find_descriptor(

intf,
custom_match = \
lambda e: \
usb.util.endpoint_direction(e.bEndpointAddress) == \
usb.util.ENDPOINT_IN
)
>>> ep.read(1)

array('B', [163])
>>>


Anyone want to venture a guess on how I should interpret that? It seems the [163] is the byte data the manual is talking about, but why is there a 'B' there? If I put paper in it and try again I get: array('B', [3])

Thanks for all your help guys, just about ready to stared coding the fun part!
 
Reply With Quote
 
 
 
 
MRAB
Guest
Posts: n/a
 
      08-30-2012
On 30/08/2012 00:45, Adam W. wrote:
> On Wednesday, August 29, 2012 6:56:16 PM UTC-4, Dennis Lee Bieber wrote:
>>
>> BUT you do give a possible clue. Is the OP using a 3.x Python where
>>
>> strings are Unicode -- in which case the above may need to be explicitly
>>
>> declared as a "byte string" rather than text (unicode) string.
>>

>
> Huzzah! I am indeed using 3.x, and slapping on an .encode('utf-8') made my printer try to spit paper at me! Progress.
>
> Also, astute observation about the endpoint needing to be an input, with the following modification I get:
>
>>>> ep.write('\x1BA'.encode('utf-8'))

> 2
>>>> ep = usb.util.find_descriptor(

> intf,
> custom_match = \
> lambda e: \
> usb.util.endpoint_direction(e.bEndpointAddress) == \
> usb.util.ENDPOINT_IN
> )
>>>> ep.read(1)

> array('B', [163])
>>>>

>
> Anyone want to venture a guess on how I should interpret that? It seems the [163] is the byte data the manual is talking about, but why is there a 'B' there? If I put paper in it and try again I get: array('B', [3])
>
> Thanks for all your help guys, just about ready to stared coding the fun part!
>

The result is an array of bytes ('B'). I think the value means:

0b10100011
^Ready
^Top of form
^No paper
^Printer error

The error is that it's out of paper.
 
Reply With Quote
 
Dennis Lee Bieber
Guest
Posts: n/a
 
      08-30-2012
On Wed, 29 Aug 2012 16:45:10 -0700 (PDT), "Adam W."
<(E-Mail Removed)> declaimed the following in
gmane.comp.python.general:

>
> Huzzah! I am indeed using 3.x, and slapping on an .encode('utf-8') made my printer try to spit paper at me! Progress.
>
> Also, astute observation about the endpoint needing to be an input, with the following modification I get:
>
> >>> ep.write('\x1BA'.encode('utf-8'))

> 2


I'm a tad curious if using the notation

b'\x1bA'

without the .encode() would work.

My concern is that you may encounter some "string" of data for
printing which the .encode() ends up /changing/ (don't UTF-8 strings use
a high-bit to signal a multi-byte encoding of what had been a single
character?). A pure byte string shouldn't have that problem.

> >>> ep = usb.util.find_descriptor(

> intf,
> custom_match = \
> lambda e: \
> usb.util.endpoint_direction(e.bEndpointAddress) == \
> usb.util.ENDPOINT_IN
> )


Seems tedious to keep swapping -- does USB support bidirectional
connections?

> >>> ep.read(1)

> array('B', [163])
> >>>

>
> Anyone want to venture a guess on how I should interpret that? It seems the [163] is the byte data the manual is talking about, but why is there a 'B' there? If I put paper in it and try again I get: array('B', [3])


Per documentation (section 8.6 in Python 2.7.2 library) of "array"
module:

'b' signed char int 1
'B' unsigned char int 1


>>> import array
>>> array.array("B", "\x1bB")

array('B', [27, 66])
>>>

--
Wulfraed Dennis Lee Bieber AF6VN
(E-Mail Removed) HTTP://wlfraed.home.netcom.com/

 
Reply With Quote
 
Adam W.
Guest
Posts: n/a
 
      08-30-2012
On Wednesday, August 29, 2012 10:07:54 PM UTC-4, Dennis Lee Bieber wrote:
> On Wed, 29 Aug 2012 16:45:10 -0700 (PDT), "Adam W."
>
> I'm a tad curious if using the notation
>
>
>
> b'\x1bA'
>
>
>
> without the .encode() would work.
>
>
>
> My concern is that you may encounter some "string" of data for
>
> printing which the .encode() ends up /changing/ (don't UTF-8 strings use
>
> a high-bit to signal a multi-byte encoding of what had been a single
>
> character?). A pure byte string shouldn't have that problem.
>


Your notation does work, and I was just coming around to reevaluating the use of the encode because I am getting really odd results when trying to print lines.

For example I set the byte length to 10 and sent this 500 times or so expecting to get a solid black bar:
ep.write('\x16FFFFFFFFFF'.encode('utf-8'))

But what I got was a weird stripped pattern... I feel like a lot of my commands are working by chance, I can't explain to myself why the A in \x1bA isn't being treated as part of the hex. This stuff always confuses me.


>
> > >>> ep = usb.util.find_descriptor(

>
> > intf,

>
> > custom_match = \

>
> > lambda e: \

>
> > usb.util.endpoint_direction(e.bEndpointAddress) == \

>
> > usb.util.ENDPOINT_IN

>
> > )

>
>
>
> Seems tedious to keep swapping -- does USB support bidirectional
>
> connections?
>


I assigned the input to ep2 to resolve the switching issue.
 
Reply With Quote
 
Dennis Lee Bieber
Guest
Posts: n/a
 
      08-30-2012
On Wed, 29 Aug 2012 20:53:48 -0700 (PDT), "Adam W."
<(E-Mail Removed)> declaimed the following in
gmane.comp.python.general:

> Your notation does work, and I was just coming around to reevaluating the use of the encode because I am getting really odd results when trying to print lines.
>
> For example I set the byte length to 10 and sent this 500 times or so expecting to get a solid black bar:
> ep.write('\x16FFFFFFFFFF'.encode('utf-8'))


How many bytes did it claim to send?
>
> But what I got was a weird stripped pattern... I feel like a lot of my commands are working by chance, I can't explain to myself why the A in \x1bA isn't being treated as part of the hex. This stuff always confuses me.
>

That's the easy one -- \x in a string introduces an 8-bit byte value
-- so only two hex digits well be read. The "A" is interpreted as
regular text.
--
Wulfraed Dennis Lee Bieber AF6VN
(E-Mail Removed) HTTP://wlfraed.home.netcom.com/

 
Reply With Quote
 
Adam W.
Guest
Posts: n/a
 
      08-30-2012
On Thursday, August 30, 2012 12:55:14 AM UTC-4, Dennis Lee Bieber wrote:
>
> How many bytes did it claim to send?
>

11, which is what I expected. But I changed the byte value to 16 (because I was having trouble getting single digit hex values working in the command) and sent this command:
>>> for x in range(0,500):

ep.write(b'\x16\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xF F\xFF\xFF\xFF\xFF\xFF\xFF\xFF')

it respond with 500 17's and prints a black bar! So it looks like whatever concern you had with using encode was coming to fruition.

>
> That's the easy one -- \x in a string introduces an 8-bit byte value
>
> -- so only two hex digits well be read. The "A" is interpreted as
>
> regular text.


Interesting, so what if I only wanted to send 4bits as a hex value? Also can I somehow throw in some binary alongside of hex? At some point in my program I'm going to need to send some commands preferably in hex along with the binary image data.
 
Reply With Quote
 
Dennis Lee Bieber
Guest
Posts: n/a
 
      08-30-2012
On Thu, 30 Aug 2012 05:51:56 -0700 (PDT), "Adam W."
<(E-Mail Removed)> declaimed the following in
gmane.comp.python.general:


>
> Interesting, so what if I only wanted to send 4bits as a hex value? Also can I somehow throw in some binary alongside of hex? At some point in my program I'm going to need to send some commands preferably in hex along with the binary image data.


You will never be able to send something less than 8-bits. I suspect
the printer treats each byte as one column of dots, so you'd probably be
sending \xF0 or \x0F depending on which bit is "top" or "bottom" -- this
would give a half column of ink and the other half would be blank.

\x?? is the Python notation to represent a binary value in a
string/byte LITERAL.

Your previous attempt with the "F" was sending ASCII F characters,
hex value 46 (01000110) [was your striped layout one skinny stripe, and
three widths lower a double-width stripe?].

As long as your image data is in on/off (B/W) bytes (unsigned, or to
simplify, integers in the range 0..255), it should be no problem.

>>> import random
>>> data = [random.randint(0, 255) for i in range(32)]
>>> data

[25, 134, 166, 159, 253, 121, 114, 110, 18, 122, 197, 233, 127, 216,
188, 89, 10, 201, 250, 32, 231, 32, 99, 7, 227, 122, 166, 172, 21, 78,
17, 166]
>>> bar = bytearray(data)
>>> bar

bytearray(b'\x19\x86\xa6\x9f\xfdyrn\x12z\xc5\xe9\x 7f\xd8\xbcY\n\xc9\xfa
\xe7 c\x07\xe3z\xa6\xac\x15N\x11\xa6')
>>> bytes(bar)

'\x19\x86\xa6\x9f\xfdyrn\x12z\xc5\xe9\x7f\xd8\xbcY \n\xc9\xfa \xe7
c\x07\xe3z\xa6\xac\x15N\x11\xa6'
>>>
>>> bbar = bytes(bar)
>>> for b in bbar:

.... print "Decimal: %4.4s:\tHex: \\x%2.2X\t%s" % (ord(b), ord(b), b)
....
Decimal: 25: Hex: \x19 
Decimal: 134: Hex: \x86 ?
Decimal: 166: Hex: \xA6 ?
Decimal: 159: Hex: \x9F ?
Decimal: 253: Hex: \xFD ??
Decimal: 121: Hex: \x79 y
Decimal: 114: Hex: \x72 r
Decimal: 110: Hex: \x6E n
Decimal: 18: Hex: \x12 
Decimal: 122: Hex: \x7A z
Decimal: 197: Hex: \xC5 ?
Decimal: 233: Hex: \xE9 ?
Decimal: 127: Hex: \x7F 
Decimal: 216: Hex: \xD8 ?
Decimal: 188: Hex: \xBC ?
Decimal: 89: Hex: \x59 Y
Decimal: 10: Hex: \x0A

Decimal: 201: Hex: \xC9 ?
Decimal: 250: Hex: \xFA ??
Decimal: 32: Hex: \x20
Decimal: 231: Hex: \xE7 ?
Decimal: 32: Hex: \x20
Decimal: 99: Hex: \x63 c
Decimal: 7: Hex: \x07 
Decimal: 227: Hex: \xE3 ?
Decimal: 122: Hex: \x7A z
Decimal: 166: Hex: \xA6 ?
Decimal: 172: Hex: \xAC
Decimal: 21: Hex: \x15 
Decimal: 78: Hex: \x4E N
Decimal: 17: Hex: \x11 
Decimal: 166: Hex: \xA6 ?
>>>


You might be able to go directly:

bbar = bytes(data)

based on the documentation for Python 3.2.3. I can't even find bytes()
in the 2.7 documentation.

I suspect your biggest problem will be in converting your image
format (at the minimum, it may be row oriented and you need to generate
columns of 8-rows at a time)


Try:

data = [ 22,
0, 1, 3, 7, 15, 31, 63, 127, 255,
127, 63, 31, 15, 7, 3, 1, 0 ]
bbar = bytes(data)

Set data length to 17, and send bbar...

If my guess is right, this should put up an equilateral triangle.


--
Wulfraed Dennis Lee Bieber AF6VN
(E-Mail Removed) HTTP://wlfraed.home.netcom.com/

 
Reply With Quote
 
Cameron Simpson
Guest
Posts: n/a
 
      08-30-2012
On 30Aug2012 05:51, Adam W. <(E-Mail Removed)> wrote:
| On Thursday, August 30, 2012 12:55:14 AM UTC-4, Dennis Lee Bieber wrote:
| > How many bytes did it claim to send?
|
| 11, which is what I expected. But I changed the byte value to 16
| (because I was having trouble getting single digit hex values working
| in the command) and sent this command:
|
| >>> for x in range(0,500):
| ep.write(b'\x16\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xF F\xFF\xFF\xFF\xFF\xFF\xFF\xFF')
|
| it respond with 500 17's and prints a black bar! So it looks like whatever concern you had with using encode was coming to fruition.

Yeah. Try 'iso8859-1' instead of 'utf-8'. You want to be not translating
the byte values at all. UTF-8 encodes character values over 127 as multibyte
sequences. ISO8859-1 is a 256 code set that does no translation -
character codes in go directly to byte values out.

You're speaking a binary protocol, not text, so you want a one to one
mapping. Better still would be to be using a bytes I/O layer instead of
one with a text->byte translation; I do not know if the USB library
you're using offers such. So try 'iso8859-1'; at least the translation
is a no-op.

Cheers,
--
Cameron Simpson <(E-Mail Removed)>

B1FF is an archetype, and all you're showing us is one of the more amusing of
his many instantiations. - Howard E. Motteler <(E-Mail Removed)>
Ah, perhaps Arthur Clarke anticipated this in his celebrated short story,
"The Nine Million Names Of B1FF"? - Nosy <(E-Mail Removed)>
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Sending USB commands with Python Cameron Simpson Python 0 08-29-2012 11:25 PM
Re: Sending USB commands with Python Cameron Simpson Python 0 08-29-2012 10:29 PM
Sending USB commands with Python Adam W. Python 8 08-29-2012 09:57 PM
Need Help Differentiating Bad Commands From Incomplete Commands Tim Stanka Python 1 08-02-2004 02:08 AM
Re: man pages for C commands (GCC commands) Ben Pfaff C Programming 4 06-28-2003 06:21 PM



Advertisments