1

I have the following code, used on an RPi2:

import serial
import time

# Set up serial port
ser = serial.Serial(
    port='/dev/ttyAMA0',
    baudrate=921600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS,
    #inter_byte_timeout=0.1,
    timeout=0
)

text = raw_input("prompt") #just a stop

start = time.time()

ser.write('\x00')

buf=[]
while True:
    reader=ser.read(1)
    if len(reader)>=1:
        buf.append(reader)
        j=''.join(buf)
        print buf
        break

print(time.time()-start)

This is used to test the time between sending and receiving a byte to another RPi2 with a similar code to receive and send a byte. This prints the following value: 0.00970196723938

My question is, why is this soo slow, and how can I make this faster? I mean, with this, it feels like using 921600 baud is an overkill when you exchange information through this port.

EDIT:

As I meantioned in the comments, I had this implemented as an ARQ system of some sort. Basically the idea is that a packet is sent containing a header+packet (where header tells the serial what is the packet size for it to read), then a response is gotten from the other side.

I have tried to transfer a file of 15476 B with 236-sized packets. The result was an astonishing 18.537263 sec. I have singled out and timed the major parts of the code whilst file transferring, and this is the result (outputted):

Read header: 0.020258
Read packet: 0.246363
Correct msg: 0.002918
Append msg: 0.000208

Basically read packet is the black sheep here. Having 15476/236=~66 packets and the time to just read packets from the serial line is 0.246*66=16,2 sec. Bear in mind that "Read packet" is simply the time between the read header and the processing of this packet, so there is no processing involved in this time.

This is my function to read packets:

def pread(val):
    start = time.time()
    while time.time() - start < TOUT_recv:
        if ser.inWaiting() >= val:
            return ser.read(val)

    ser.flushInput
    return None

val is given by the header that was sent attached to the packet. It reads one byte, gets the size to be read, then proceeds to read the packet. How can I improve this timing?

  • 1
    Your methodology appears seriously flawed. Send a statistically significant number of characters and time that from first to last. – joan Jan 7 '18 at 13:02
  • The idea behind this was to create an ARQ system, where a packet would be sent, then ACK received, then next packet, etc.. However, I have tested this and it was extremely slow. I thought this script would be enough to show. When I get back home, I'll edit the post with those results. – Berd Jan 7 '18 at 13:11
  • The bit time on the line will be swamped by all the other processing going on. – joan Jan 7 '18 at 13:16
  • Ditton joan. This is a poor test of the baud rate, even if it is a better approximation of your real scenario. I've done pretty thorough tests with pis vs. an FPGA and the UART is fine up to at least 1 Mbaud. But keep in mind that sending a large amount is of course going to be more efficient per byte than sending one at a time, which probably has more overhead in userspace and kernel handling than the actual hardware transmission time, esp. if you are using a pseudo-interpreted language like python. I.e., if this is what you are going to do, don't expect to be sending 100k+ bytes/sec. – goldilocks Jan 7 '18 at 16:22
  • I have editted the answer as requested. Please tell me if there is anything missing. – Berd Jan 7 '18 at 20:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.