UART'ı Bitirmek için PiGPIO Kütüphanesi Örneği


11

PiGPIO kütüphanesi http://abyz.me.uk/rpi/pigpio/index.html , özelliklerinden birinin "herhangi bir kullanıcı gpio'sunu kullanan yazılım seri bağlantıları" olduğunu belirtmektedir.

Bunu, herhangi bir 2 ücretsiz GPIO piminde bir yazılım UART oluşturmak için kullanabileceğiniz anlamına gelir.

Projelerin örnekler sayfasında, bu özellik için örnek yok ve Google'da hiçbir şey bulamadım.

Bunu yapan var mı? Öyleyse lütfen beni örneğe yönlendirin.

Değilse, bir UART'ı bitirmek için alternatif kütüphaneler var mı?

Teşekkürler,


Ayrıca bakınız: raspberrypi.stackexchange.com/questions/3475/… ve raspberrypi.stackexchange.com/questions/24019/… İkincisi @joan pigpio'yu işaret ederek cevaplanır, bu yüzden belki daha fazla fikir verebilir.
Ghanima

Pi'den bir dizüstü bilgisayara göndererek ve dizüstü bilgisayarın Pi'ye yankılanmasını sağlayarak birkaç gün pigpio yazılım serisini test ettim. Onu yazmak istedim ama olaylar bu egzersizi geçti. Ne bulabileceğimi göreceğim.
joan

Yanıtlar:


13

İşte yazılım serisinin güvenilirliğini test etmek için kullandığım bazı Python. Giriş tarafı oldukça önemsizdir. Python veya C'de uygun bit patlama seri açık çağrılarını yaparsınız. Bit akışını oluşturmak için dalga formlarını kullanmak zorunda olduğunuz için çıkış tarafı daha fazla dahil olur.

Buradaki kod, 8 bit veri yerine 7 bit kullanıyor. Test, bayt başına farklı bitler için destek eklediğim sırada yazıldı.

Kod, ikili veri bloklarını bir dizüstü bilgisayara bağlı bir gpio'ya yazar (seri dongle üzerinden). Dizüstü bilgisayar, gelen seri verileri çıkış seri hattına yansıtır. Pi başka bir gpio'daki seri verileri okur.

Kod, gönderilen ve alınan veriler arasındaki tutarsızlıkları kontrol eder. Dizüstü bilgisayarın hatasız olduğu varsayılır, bu nedenle herhangi bir hatanın biraz beceriyor olduğu varsayılır.

Günlüklere 19.2kbps'den daha az bir şey bakmak sağlamdı. 115,2 kbps'ye kadar olan her şey makul (ancak sağlama toplamı gerektirir) ve 230,4 kbps,% 13 bayt hata oranı verdi.

#!/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()

Kütükler

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

Hangi seri donanım kilidini kullandınız? Büyük olanlar bazen oldukça güvenilmez olabilir ...
not2qubit

Testler için bir PL2303HX USB To RS232 TTL 5V 3.3V Çıkış modülü kullandım. EBay'den 1.53 £.
joan

Donanım kilidinin güvenilirliğini kolayca test edebilirsiniz; kendi
Tx'i Rx'e bağlayın

0

Dongle gibi hata ekleyecek herhangi bir şeyi test etmek için Tx'i doğrudan Rx'e bağladığınızda, kütüphanenin gerçekten ne kadar iyi performans gösterdiğini söyler.

Raspberry Pi 3b + üzerinde GPIO 23'ü Tx ve GPIO 24'ü Rx veya diğer ücretsiz GPIO olarak kullanın. Bu, yerleşik UART ile aynı sırayla iyi görünüyor ve pratik olarak yanında, sadece 3 pim sağda ve Rx'in sağında bir GND pimi var.

Sonuçlar:

Until 19200bps no errors.
- 38400 and 57600 bps less 1% error sometimes
- 115200bps was 10-20% error or so
- 230400bps over 80% error or so

Checksum karmaları veya SPI / I2C - UART dönüştürücüleri kullanmanıza gerek kalmadan 19200 veya daha azıyla yaşayabiliyorsanız - iyi olmalıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.