You are not logged in.

Dear visitor, welcome to QtForum.org. If this is your first visit here, please read the Help. It explains in detail how this page works. To use all features of this page, you should consider registering. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

simonb

Beginner

  • "simonb" is male
  • "simonb" started this thread

Posts: 28

Location: Jerusalem,Israel

  • Send private message

1

Monday, March 19th 2012, 12:12pm

Missing lines on Qextserialport

Hi all,

I'm using QextSerial port to read data from RS-232 at 400hz rate, most of the time I got currected data but sometimes I got invalid data (missing lines from the packet).

I checked the device with realTerm and the data is currect so it's not a hardware bug.

what can cose this missing line error? some suggestions?
Thanks.

More info:

The algo:
If (start recording)
1. clear buffer
2. read data and sync on the packet header
3. check sum
4. save data to files
if (stop recording)
1. read data (clear buffer)

My setup
QT 4.7
QextSerialPort 1.2.0
Win xp sp3
using sea-level (rs-232 to usb)

Open port function:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 this->setState(STOP_RECORDING);
    port = new QextSerialPort(portName,QextSerialPort::EventDriven);
    if(port->open(QIODevice::ReadWrite )) {
          connect( port, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
    }
    else {
            return -1;
    }

    port->setBaudRate(BAUD691200);
    port->setDataBits(DATA_8);
    port->setParity(PAR_NONE);
    port->setStopBits(STOP_2);
    port->setFlowControl(FLOW_OFF);
    port->setRts( true );
    port->setDtr( true );

    connect(&timer, SIGNAL(timeout()), this, SLOT(procTimerOut()));
    this->timer.setInterval(50);
    return 0;


Reading from port:

Source 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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#define PACKET_SIZE 40

void Driver::onReadyRead()
{/* Read data from port */
    if (this->state() == STOP_RECORDING) {
        this->port->read(port->bytesAvailable());
        return;
    }

    if (this->rxBuffer.isEmpty()) {
        this->timer.start();
    }
    QByteArray data = this->port->read(port->bytesAvailable());
    this->rxBuffer.append(data);
}
void Driver::procTimerOut()
{
    this->timer.stop();
    /* Print raw data to file */
    files_data.rawData.write(rxBuffer.toHex());
    if (!this->last_line.isEmpty()){
        rxBuffer.prepend(this->last_line);
    }
    if (rxBuffer.size() < PACKET_SIZE) {
        qDebug("buffer is small [%d]",rxBuffer.size());
        return;
    }
    if (this->sync(rxBuffer) != SUCCESS) {
        emit actionDone(EINVAL,"Cannot sync on packet");
        return;
    }

    while (rxBuffer.size() > PACKET_SIZE) {
        const QByteArray sample = rxBuffer.mid(0, PACKET_SIZE);
        rxBuffer.remove(0, PACKET_SIZE);
        if (this->addSample(sample) == INVALID_CHECKSUM)  {
                QString errMsg = this->portID + ": Invalid checksum at ["
                                 + QString::number(this->sampleCounter) + "]\n"
                                 + QString(sample.toHex());
                emit actionDone(INVALID_LINE,errMsg);
                rxBuffer.clear();
                return;
            }
        }
    }
    if (!rxBuffer.isEmpty()) {
        this->last_line = rxBuffer;   //read all data that left
        rxBuffer.clear();             //remove all data that left
    }
    else {
        this->last_line.clear();
    }
}
int Driver::sync(QByteArray &rxBuffer)
{
    if (!rxBuffer.startsWith(this->key)){//Note: Sync on packet
        int prefix_offset = rxBuffer.indexOf(this->key);
        if (prefix_offset == -1){
            return EINVAL;
        }
        rxBuffer.remove(0,prefix_offset);
        if (!rxBuffer.startsWith(this->key)) {
            return EINVAL;
        }
    }
    return SUCCESS;
}
inline int Driver::addSample(const QByteArray & sample)
{
    const struct packet *pkt;
    pkt = (const struct packet *)sample.constData();
    int checksum_bytes = sizeof(struct packet) - sizeof(pkt->checksum);
    u16 crc = checksum((const unsigned char *)pkt, checksum_bytes);
    if ( crc != pkt->checksum ) {
        return INVALID_CHECKSUM;
    }
    this->print_analyzed_sample(pkt);
    this->sampleCounter++;
    return SUCCESS;
}
}

void Driver::startRecording()
{
    this->prepareForRecord();
    this->setState(START_RECORDING);
}
void Driver::stopRecording()
{
    this->setState(STOP_RECORDING);
    this->closeFiles();
}

void Driver::prepareForRecord()
{
    this->genetate_output_Files(); //creat output files, and open to write data
    //reset data
    QByteArray buf;
    do {
        buf = port->readAll();
    } while (buf.size() > 0);
    this->rxBuffer.clear();
}

simonb

Beginner

  • "simonb" is male
  • "simonb" started this thread

Posts: 28

Location: Jerusalem,Israel

  • Send private message

2

Wednesday, March 28th 2012, 2:36pm

Need help please...

3

Wednesday, March 28th 2012, 4:05pm

at least, in Driver::procTimerOut()

Source code

1
2
3
4
5
6
7
8
if( ! last_line.isEmpty() )
{
    rxBuffer.prepend( last_line );
}
if( rxBuffer.size() < PACKET_SIZE )
{
    return;
}

seems strange
what if (! last_line.isEmpty()) and (rxBuffer.size() < PACKET_SIZE) ???
probably lastLine will be prepended two times

simonb

Beginner

  • "simonb" is male
  • "simonb" started this thread

Posts: 28

Location: Jerusalem,Israel

  • Send private message

4

Thursday, March 29th 2012, 9:13am

Thanks alot Nicolas it's realy bug and i fixed it by adding

Source code

1
    this->last_line.clear();


Here the new code

Source code

1
2
3
4
5
6
7
8
9
if (!this->last_line.isEmpty())
{
        rxBuffer.prepend(this->last_line);
        this->last_line.clear();
 }
if( rxBuffer.size() < PACKET_SIZE )
{
    return;
}


But still got the same problem... :huh:

5

Thursday, March 29th 2012, 1:43pm

with asynchroneous mechanism, all read from serial port should be done in the same slot

try to simplify, eg:
- removing timeout and last_line which seems me unusefull

Source 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
36
37
38
39
void Driver::onReadyRead()
{
    // if not registering, read to trash, return

    if( state() == STOP_RECORDING )
    {
        port->readAll();
        return;
    }

    // read available data in receive buffer

    rxBuffer.append( port->readAll() );

    // if not enough to sync return, keeping data for later

    int keyPos;
    if( (keyPos = rxBuffer.indexOf( key )) < 0 ) return;

    // synchronize

    rxBuffer.remove( 0, keyPos );

    //  treat all complete packets

    while( rxBuffer.size() >= PACKET_SIZE )
    {
        const QByteArray sample = rxBuffer.left( PACKET_SIZE );
        rxBuffer.remove( 0, PACKET_SIZE );
        if( addSample( sample ) == INVALID_CHECKSUM )
        {
            // treat error
        }
        else
        {
            // ???
        }
    }
}

Source code

1
2
3
4
5
void Driver::startRecording()
{
    genetate_output_Files();
    setState( START_RECORDING );
}

Source code

1
2
3
4
5
6
void Driver::stopRecording()
{
    setState( STOP_RECORDING );
    closeFiles();
    rxBuffer.clear();
}

This post has been edited 11 times, last edit by "Nicolas SOUCHON" (Mar 30th 2012, 4:05pm)