[Python3] problemen met encode() bij serial port

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • Mich
  • Registratie: December 2000
  • Laatst online: 06:14
Ik ben bezig om mijn duco box via de seriele port uit te lezen. Op github zijn een aantal voorbeeld scripts te vinden. Ik ben bezig met dit script: https://github.com/SteinH...aster/src/duco/ducobox.py Nu ben ik hier vanaf regel 703 aan het kopiëren geweest om de execute command te kopieren naar mijn eigen nieuwe (en lege) script. Ik loop alleen tegen een probleem aan dat het scipt (vermoedelijk) in python2 is geschreven en ik nu in 3 zit.

Als ik via putty een commando "fanspeed" geef krijg ik als output "FanSpeed: Actual 1929 [rpm] - Filtered 1942 [rpm]".


In mijn code stuur ik ook dit commando "fanspeed"maar kreeg toen de melding

TypeError: unicode strings are not supported, please encode to bytes: 'fanspeed'

Ik heb hierop gezocht en kwam tegen dat je .encode() moet toevoegen. Nu heb ik echter een probleem met mijn output

b'fansp\r ^\r Unknown Cmd\r\r> '


Dat begin stukje met b' komt omdat je encode toevoegd (wak ik ook weer via google achter). Maar ik heb geen idee hoe ik dit weg krijg en of ik wel de juiste encode gebruik. Ik heb tot op heden nog niet met python gewerkt.


Ik werk met Thonny in python3 op mijn raspbian op mijn pi2

Dit is mijn code

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import serial
import time

serial = serial.Serial(
 port='/dev/ttyUSB0',
 baudrate = 115200,
 timeout=0.1
)


serial.flushInput()
serial.flushOutput()


def execute_command(command):
    print(command)
    reply = ''
    if serial:
        serial.write('\r'.encode())
        time.sleep(0.5)
        serial.readline()
        cmd = command.encode("utf-8", "ignore")
        #for c in cmd:
        time.sleep(0.5)
        serial.write(cmd)
        time.sleep(0.5)
        serial.write('\r'.encode())
        time.sleep(0.5)
        reply = str(serial.readline()).replace('\r', '\n')
    else:
        print("No serial device")
    return reply

reply1 = execute_command('fanspeed')
print (reply1)


en de output, waarbij unknown cmd een normale response is op een verkeerde commando. De communicatie werkt in ieder geval wel

code:
1
2
3
4
5
========================= RESTART =========================
>>> %Run test.py
fanspeed
b'fanspd\r       ^\r  Unknown Cmd\r\r> '
>>>

Alle reacties


Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 06-10 17:29

Matis

Rubber Rocket

Volgens mij print je nu letterlijk \r en niet 0x0D.
Daarnaast is de \r een carriage return en niet line feed \n (0x0A).

Daarnaast moet je je string cmd nog omzetten naar een byte array, of de loop gebruiken die je nu uitgecommentarieerd hebt.
Als ik de documentatie van Python goed interpreteer.

[ Voor 45% gewijzigd door Matis op 29-12-2018 18:06 ]

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 27-09 13:03
Python:
1
2
3
4
5
6
7
8
9
10
11
>>> cmd="fanspeed\r\n".encode("ascii")
>>> cmd[8]
13
>>> cmd[9]
10
>>> cmd=b"fanspeed\r\n"
>>> cmd[8]
13
>>> cmd[9]
10
>>>

Lijkt me in beide gevallen te functioneren...

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Mich
  • Registratie: December 2000
  • Laatst online: 06:14
Matis schreef op zaterdag 29 december 2018 @ 18:00:
Volgens mij print je nu letterlijk \r en niet 0x0D.
Daarnaast is de \r een carriage return en niet line feed \n (0x0A).

Daarnaast moet je je string cmd nog omzetten naar een byte array, of de loop gebruiken die je nu uitgecommentarieerd hebt.
Als ik de documentatie van Python goed interpreteer.
die string naar byte gebeurd met .encode() al dan niet met utf-8 erin.

Die loop is denk ik wel cruciaal ja, maar als ik hem gebruik zoals hij in de code stond dan krijg ik weer een andere foutmelding.

code:
1
2
3
        for c in cmd:
            time.sleep(0.001)
            serial.write(c)


Geeft deze foutmelding

TypeError: object of type 'int' has no len()

Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 06-10 17:29

Matis

Rubber Rocket

Ik snap ten eerste niet waarom er een sleep in de loop moet, want er wordt toch niet realtime geschreven?
Daarnaast zou ik, als ik jou was, er een debugger aanknopen en kijken wat er in cmd en/of c zit qua waarde.
Want nu lijkt het een int-array te zijn en niet een byte-array zoals de functie verwacht.

@farlane ik weet niet of het cruciale verschil zit in het feit dat er nu double of single quotes gebruikt worden. Daarvoor is mijn Python-kennis niet goed genoeg, maar in C(++) is het wel degelijk een verschil tussen een byte en string.

[ Voor 25% gewijzigd door Matis op 30-12-2018 14:56 ]

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • Mich
  • Registratie: December 2000
  • Laatst online: 06:14
Matis schreef op zondag 30 december 2018 @ 14:54:
Ik snap ten eerste niet waarom er een sleep in de loop moet, want er wordt toch niet realtime geschreven?
Daarnaast zou ik, als ik jou was, er een debugger aanknopen en kijken wat er in cmd en/of c zit qua waarde.
Want nu lijkt het een int-array te zijn en niet een byte-array zoals de functie verwacht.

@farlane ik weet niet of het cruciale verschil zit in het feit dat er nu double of single quotes gebruikt worden. Daarvoor is mijn Python-kennis niet goed genoeg, maar in C(++) is het wel degelijk een verschil tussen een byte en string.
Ik ben in ieder geval een stap verder. Ik liet me in de output misleiden door de b' aan het begin van de zin. Maar dit heeft geen invloed. Het commando help werkt gewoon (zonder for loop). Die for loop is dus (neem ik aan) om een string van langer dan x aantal characters te versturen.

Bij het binnen gaan van de for loop is c 102 en cmd is b'fanspeed'.

Ik heb het serial.write vervangen voor print en nu kan ik goed zien wat er gebeurt.

code:
1
2
3
4
5
6
7
8
102
97
110
115
112
101
101
100



Als ik mijn commando gewoon als string in de for loop laat gaan komt er dit uit.


code:
1
2
3
4
5
6
7
8
f
a
n
s
p
e
e
d


Maar als ik dit wil schrijven via de seriële port klaagt hij wee dat ik het moet encoden naar bytes.


edit:
opgelost

code:
1
2
3
4
        cmd = command
        for c in cmd:
            time.sleep(0.001)
            serial.write(c.encode())


als string de for lus in gaan en daarna omzetten naar byte met encode()

Nu ga ik verder prutsen om de juiste gegevens uit het antwoord te halen.

[ Voor 9% gewijzigd door Mich op 30-12-2018 17:03 ]


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 27-09 13:03
Matis schreef op zondag 30 december 2018 @ 14:54:
@farlane ik weet niet of het cruciale verschil zit in het feit dat er nu double of single quotes gebruikt worden. Daarvoor is mijn Python-kennis niet goed genoeg, maar in C(++) is het wel degelijk een verschil tussen een byte en string.
In Python maakt double of single quotes niet uit, het worden beide str/string objecten. Python 3 strings zijn daarbij per default UTF encoded strings, int Python 2 zijn dat by default 8-bit strings.

Een literal die wordt geprefixed met b wordt daarbij in Python 3 een "bytes" object (een array van bytes / c-string eigenlijk dus), in Python 2 wordt deze prefix genegeerd omdat daar een str object hetzelfde is als een bytes object. Om van de een naar de ander te komen moet je (vanzelfsprekend) een encoding opgeven.

Maargoed, je kunt dus prima een string in 1 keer naar een bytes object converten str.encode(), dat hoeft niet per karakter te gebeuren.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • +1 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 06-10 17:29

Matis

Rubber Rocket

@farlane weer wat geleerd. Thnx :)

If money talks then I'm a mime
If time is money then I'm out of time

Pagina: 1