Voici quelques Python que j'ai utilisés pour tester la fiabilité des logiciels en série. Le côté entrée est assez trivial. Vous effectuez simplement les appels ouverts série bang bang appropriés en Python ou C. Le côté sortie est plus impliqué car vous devez utiliser des formes d'onde pour construire le flux binaire.
Le code utilise ici des données 7 bits plutôt que 8 bits. Le test a été écrit à peu près au même moment que j'ajoutais la prise en charge de différents bits par octet.
Le code écrit des blocs de données binaires sur un gpio connecté à un ordinateur portable (via un dongle série). L'ordinateur portable renvoie les données série entrantes sur sa ligne série de sortie. Le Pi lit les données série sur un autre gpio.
Le code vérifie les écarts entre les données envoyées et reçues. L'ordinateur portable est supposé être exempt d'erreurs, donc toutes les erreurs sont supposées être dans le coup de bits.
En regardant les journaux, tout ce qui était inférieur à 19,2 kbps était solide. Quelque chose jusqu'à 115,2 kbps était raisonnable (mais nécessiterait une somme de contrôle) et 230,4 kbps donnait un taux d'erreur de 13% octets.
#!/usr/bin/env python
# bb_serial.py
# 2014-12-23
# Public Domain
# bit bang transmit and receive of serial data
#
# tested by connecting the arbitrary RX/TX gpios to a USB
# serial dongle plugged in to a Linux box.
#
# on the Linux box set the baud and data bits (cs5-cs8)
#
# stty -F /dev/ttyUSB0 19200 cs8
# cat </dev/ttyUSB0 >/dev/ttyUSB0
#
# so the Linux box echoes back data received from the Pi.
#
# laptop timings deviations
#
# baud exp us act us
# 50 20000 13310 * 75
# 75 13333 13310
# 110 9091 13310 * 75
# 134 7462 6792 * 150
# 150 6667 6792
# 200 5000 6792 * 150
# 300 3333 3362
#
import sys
import time
import difflib
import pigpio
RX=19
TX=26
MSGLEN=256
if len(sys.argv) > 1:
baud = int(sys.argv[1])
else:
baud = 115200
if len(sys.argv) > 2:
bits = int(sys.argv[2])
else:
bits = 8
if len(sys.argv) > 3:
runtime = int(sys.argv[3])
else:
runtime = 300
ten_char_time = 100.0 / float(baud)
if ten_char_time < 0.1:
ten_char_time = 0.1
MASK=(1<<bits)-1
# initialise test data
msg = [0] * (MSGLEN+256)
for i in range(len(msg)):
msg[i] = i & MASK
first = 0
pi = pigpio.pi()
pi.set_mode(TX, pigpio.OUTPUT)
# fatal exceptions off (so that closing an unopened gpio doesn't error)
pigpio.exceptions = False
pi.bb_serial_read_close(RX)
# fatal exceptions on
pigpio.exceptions = True
# create a waveform representing the serial data
pi.wave_clear()
TEXT=msg[first:first+MSGLEN]
pi.wave_add_serial(TX, baud, TEXT)
wid=pi.wave_create()
# open a gpio to bit bang read the echoed data
pi.bb_serial_read_open(RX, baud, bits)
# zero error counts
bad_char = 0
total_char = 0
# run for fixed time
start=time.time()
while (time.time()-start) < runtime:
pi.wave_send_once(wid) # transmit serial data
pi.wave_delete(wid)
TXTEXT = TEXT
first += 1
if first >= MSGLEN:
first = 0
TEXT=msg[first:first+MSGLEN]
pi.wave_add_serial(TX, baud, TEXT,bb_bits=7)
while pi.wave_tx_busy(): # wait until all data sent
pass
wid=pi.wave_create()
count = 1
text=""
lt = 0
total_char += MSGLEN
while count: # read echoed serial data
(count, data) = pi.bb_serial_read(RX)
if count:
text += data
lt += count
time.sleep(ten_char_time) # enough time to ensure more data
if text != TXTEXT: # Do sent and received match?
if lt == MSGLEN: # No, is message correct length?
for i in range(MSGLEN): # If so compare byte by byte.
if text[i] != TXTEXT[i]:
# print("{:2X} {:2X}".format(text[i], TXTEXT[i]))
bad_char += 1
else: # Wrong message length, find matching blocks.
ok = 0
s=difflib.SequenceMatcher(None, TXTEXT, text)
for frag in s.get_matching_blocks():
ok += frag[2] # More matching bytes found.
# print(frag)
# print(text, MSGLEN, ok)
if ok < MSGLEN: # Sanity check.
bad_char += (MSGLEN - ok)
else:
print("*** ERRONEOUS good={} LEN={} ***".format(ok, MSGLEN))
print("secs={} baud={} bits={} bad={:.3f}%".
format(runtime, baud, bits, float(bad_char)*100.0/float(total_char)))
print("total={} badchar={}".format(total_char, bad_char))
# free resources
pi.wave_delete(wid)
pi.bb_serial_read_close(RX)
pi.stop()
Journaux
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 230400; done
secs=300 baud=230400 bad=12.610%
total=249344 badchar=31443
secs=300 baud=230400 bad=12.580%
total=247296 badchar=31111
secs=300 baud=230400 bad=12.669%
total=246528 badchar=31232
secs=300 baud=230400 bad=12.274%
total=249600 badchar=30635
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 115200; done
secs=300 baud=115200 bad=0.378%
total=246784 badchar=934
secs=300 baud=115200 bad=0.152%
total=241408 badchar=368
secs=300 baud=115200 bad=0.189%
total=249088 badchar=472
secs=300 baud=115200 bad=0.347%
total=242688 badchar=843
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 57600; done
secs=300 baud=57600 bad=0.080%
total=220416 badchar=177
secs=300 baud=57600 bad=0.066%
total=219392 badchar=145
secs=300 baud=57600 bad=0.099%
total=219904 badchar=218
secs=300 baud=57600 bad=0.084%
total=219136 badchar=184
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 38400; done
secs=300 baud=38400 bad=0.019%
total=206336 badchar=39
secs=300 baud=38400 bad=0.021%
total=206848 badchar=43
secs=300 baud=38400 bad=0.015%
total=206592 badchar=30
secs=300 baud=38400 bad=0.030%
total=206592 badchar=61
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 19200; done
secs=300 baud=19200 bad=0.000%
total=175104 badchar=0
secs=300 baud=19200 bad=0.000%
total=175360 badchar=0
secs=300 baud=19200 bad=0.000%
total=175360 badchar=0
secs=300 baud=19200 bad=0.000%
total=174336 badchar=0
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 75; done
secs=300 baud=75 bad=0.000%
total=2048 badchar=0
secs=300 baud=75 bad=0.000%
total=2048 badchar=0
secs=300 baud=75 bad=0.000%
total=2048 badchar=0
secs=300 baud=75 bad=0.000%
total=2048 badchar=0
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 19200; done
secs=300 baud=19200 bad=0.000%
total=174592 badchar=0
secs=300 baud=19200 bad=0.000%
total=174592 badchar=0
secs=300 baud=19200 bad=0.000%
total=174848 badchar=0
secs=300 baud=19200 bad=0.000%
total=174848 badchar=0
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 19200; done
secs=300 baud=19200 bad=0.000%
total=174848 badchar=0
secs=300 baud=19200 bad=0.000%
total=175360 badchar=0
secs=300 baud=19200 bad=0.000%
total=174592 badchar=0
secs=300 baud=19200 bad=0.000%
total=174848 badchar=0
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 19200; done
secs=300 baud=19200 bad=0.000%
total=174592 badchar=0
secs=300 baud=19200 bad=0.000%
total=175104 badchar=0
secs=300 baud=19200 bad=0.000%
total=175104 badchar=0
secs=300 baud=19200 bad=0.000%
total=175360 badchar=0
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 19200; done
secs=300 baud=19200 bad=0.000%
total=175104 badchar=0
secs=300 baud=19200 bad=0.000%
total=174592 badchar=0
secs=300 baud=19200 bad=0.000%
total=174848 badchar=0
secs=300 baud=19200 bad=0.000%
total=175104 badchar=0
harry /ram $ for ((i=0;i<4;i++)); do /code/bb_serial.py 19200; done
secs=300 baud=19200 bad=0.000%
total=174848 badchar=0
secs=300 baud=19200 bad=0.000%
total=174848 badchar=0
secs=300 baud=19200 bad=0.000%
total=174848 badchar=0
secs=300 baud=19200 bad=0.000%
total=175104 badchar=0