[Arduino Qt/C++] Comminucatie probleem Arduino Qt?

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • Xerohumoris
  • Registratie: Augustus 2010
  • Laatst online: 13:22
TL;DR: Wat doe ik in mijn code verkeert waardoor Qt niet wacht op een 'newline'?

Mijn vraag
Voor een project wil ik digitaal een moment meten. Hiervoor gebruik ik een load cell die via een Arduino verbonden is met de computer.

Aan beide kanten heb ik software geschreven die individueel goed lijkt te werken. De Arduino meet goed de waarde en kan dit naar de pc sturen. De software in de computer kan goed de waarde weergeven en eventueel verwerken.

Als ik echter de load cell aan de Arduino hang gaat het fout in de communicatie via Qt. De communicatie met SDK van Arduino gaat goed.

In Qt klopt de reeks met getallen niet meer die ik krijg. Hier zijn soms zeer afwijkende waarden bij. Via de Arduino SDK heb ik deze afwijkende waarden niet.

Voorbeeld
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
"1759100\r\n"
"1751600\r\n"
"1747000\r\n"
"1746100\r\n"
"174670"  << Vanaf hier gaat het fout
"0\r\n"
"1745"
"900\r\n"
"17"
"45000\r\n"
"1741300\r\n" << Dit is weer de eerste goede.
"1742100\r\n"
"1744200\r\n"
"1749300\r\n"


Ongeveer 10% van alle antwoorden bevat een fout.

Via de SDK loopt de reeks door en zit die rare onderbreking er niet in. Als de load cell niet gekoppeld is ook niet. Dan is de waarde die terug komt altijd -2000.

Wat maakt mijn code nu anders dan de manier waarop de SDK de waarden geeft? Is er in Qt een functie die wel echt wacht op de 'newline' zoals deze verzonden wordt?

Nu de code zoals ik die gebruik.

De code in de Arduino:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <HX711.h>

#define DOUT  2
#define CLK  3
HX711 scale;

long tara = 2000;
int units = 1;
void setup() {
  Serial.begin(57600);
  scale.begin(DOUT, CLK);
}

void loop() {
  char input = Serial.read();
    if (input == 'z')
      tara = scale.read_average(15);
    long output = (scale.read() - tara) / units;
    //Serial.print("Output: ");
    Serial.println(output);
}


De code voor communicatie aan de pc kant
C++:
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
//Header
#ifndef SERIALCONNECT_H
#define SERIALCONNECT_H

#include <QObject>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QString>
#include <QByteArray>

class SerialConnect : public QObject
{
    Q_OBJECT

public:
    SerialConnect(QString portName, qint32 baudRate);
    ~SerialConnect();

public slots:
    void processData();

signals:
    void gotData(QByteArray data);

private:
    QSerialPort Device;
    bool DoLoop = false;
};

#endif // SERIALCONNECT_H


//CPP
SerialConnect::SerialConnect(QString portName, qint32 baudRate)
{
    Device.setPortName(portName);
    Device.setBaudRate(baudRate);
    Device.setDataBits(QSerialPort::Data8);
    Device.setParity(QSerialPort::NoParity);
    Device.setStopBits(QSerialPort::OneStop);
    Device.setFlowControl(QSerialPort::NoFlowControl);
    //Device.open(QIODevice::ReadWrite);
}

void SerialConnect::processData()
{
    Device.open(QIODevice::ReadWrite);

    while (DoLoop) {
        Device.waitForReadyRead(-1);
        //QByteArray lineData = Device.readLine(1024);
        char buf[1024];
        qint64 lineLength = Device.readLine(buf, sizeof(buf));
        if (lineLength != -1){
            QByteArray lineData = buf;
            qDebug() << lineData;
            emit gotData(lineData);
        }

    }
    Device.close();
}


Relevante software en hardware die ik gebruik
Qt: laatste stabiele versie

Wat ik al gevonden of geprobeerd heb:

Zoals in de code nu te zien is maak ik gebruik van LONG. Daarvoor maakte in gebruik van DOUBLE. Dit omdat ik even in de veronderstelling dat dit problemen gaf.
Heb de manier waarop de data verwerkt wordt al aangepast. Maakte eerst gebruik van readLine(int maxSize). Ik ben nu overgestapt naar de meer betrouwbare readLine(char *buf, int maxSize). Het effect blijft gelijk. Nu met de logische test van lineLength krijg ik geen SIGMENT ERROR's meer.

Beste antwoord (via Xerohumoris op 29-01-2020 13:23)


  • jeroen3
  • Registratie: Mei 2010
  • Laatst online: 13:19
Er gaat niet zoveel fout.
Je verwacht gewoon per "Device.readLine(buf, sizeof(buf));" een hele lijn te krijgen. Maar doordat je systemen niet synchroon lopen hoeft dat helemaal niet zo te zijn.
Data is read until either of the following conditions are met:

The first '\n' character is read.
maxSize - 1 bytes are read.
The end of the device data is detected.
Als je het aan elkaar knoopt...
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"1759100\r\n"
"1751600\r\n"
"1747000\r\n"
"1746100\r\n"

"1746700\r\n"  << Vanaf hier gaat het fout

"1745900\r\n"

"1745000\r\n"

"1741300\r\n" << Dit is weer de eerste goede.
"1742100\r\n"
"1744200\r\n"
"1749300\r\n"

Valt wel mee dus. Geen data kwijt. Puur fragmentatie.

Simpele fix: QIODevice::canReadLine()

Ik zou echter ook wel een oogje houden op QSerialPort::bytesAvailable(), immers kan het zo zijn dat als je nooit een '\n' krijg je buffer gewoon vol zit. Als je frames die je verstuurt allemaal 9 bytes zijn, dan is bytesAvailable() van 15 sowieso fout.

[ Voor 13% gewijzigd door jeroen3 op 28-01-2020 23:03 ]

Alle reacties


Acties:
  • Beste antwoord
  • 0 Henk 'm!

  • jeroen3
  • Registratie: Mei 2010
  • Laatst online: 13:19
Er gaat niet zoveel fout.
Je verwacht gewoon per "Device.readLine(buf, sizeof(buf));" een hele lijn te krijgen. Maar doordat je systemen niet synchroon lopen hoeft dat helemaal niet zo te zijn.
Data is read until either of the following conditions are met:

The first '\n' character is read.
maxSize - 1 bytes are read.
The end of the device data is detected.
Als je het aan elkaar knoopt...
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"1759100\r\n"
"1751600\r\n"
"1747000\r\n"
"1746100\r\n"

"1746700\r\n"  << Vanaf hier gaat het fout

"1745900\r\n"

"1745000\r\n"

"1741300\r\n" << Dit is weer de eerste goede.
"1742100\r\n"
"1744200\r\n"
"1749300\r\n"

Valt wel mee dus. Geen data kwijt. Puur fragmentatie.

Simpele fix: QIODevice::canReadLine()

Ik zou echter ook wel een oogje houden op QSerialPort::bytesAvailable(), immers kan het zo zijn dat als je nooit een '\n' krijg je buffer gewoon vol zit. Als je frames die je verstuurt allemaal 9 bytes zijn, dan is bytesAvailable() van 15 sowieso fout.

[ Voor 13% gewijzigd door jeroen3 op 28-01-2020 23:03 ]


Acties:
  • 0 Henk 'm!

  • Xerohumoris
  • Registratie: Augustus 2010
  • Laatst online: 13:22
Dank dit ga ik morgen met een frisse blik goed bekijken en verwerken. Ik laat het weten als het niet werkt.
jeroen3 schreef op dinsdag 28 januari 2020 @ 23:00:
Ik zou echter ook wel een oogje houden op QSerialPort::bytesAvailable(), immers kan het zo zijn dat als je nooit een '\n' krijg je buffer gewoon vol zit. Als je frames die je verstuurt allemaal 9 bytes zijn, dan is bytesAvailable() van 15 sowieso fout.
Dit probleem wordt ondervangen op de Arduino als het goed is. Serial.println() geeft altijd een newline mee. Met Serial.print() doe je dit niet. Dit heb ik bewust gedaan. Dit gezien de in Qt hierop gewacht wordt en automatisch wordt afgebroken.

Acties:
  • 0 Henk 'm!

  • YakuzA
  • Registratie: Maart 2001
  • Niet online

YakuzA

Wat denk je nou zelluf hey :X

Xerohumoris schreef op dinsdag 28 januari 2020 @ 23:27:
Dank dit ga ik morgen met een frisse blik goed bekijken en verwerken. Ik laat het weten als het niet werkt.


[...]


Dit probleem wordt ondervangen op de Arduino als het goed is. Serial.println() geeft altijd een newline mee. Met Serial.print() doe je dit niet. Dit heb ik bewust gedaan. Dit gezien de in Qt hierop gewacht wordt en automatisch wordt afgebroken.
Zoals hierboven aangegeven door @jeroen3 klopt de aanname dat readline op een \n wacht niet.
Het probleem komt alleen uit je eigen read loop, vandaar dat de sdk het wel goed uitleest, die plakt waarschijnlijk de readlines aan elkaar tot hij een \n tegen komt oid.

Death smiles at us all, all a man can do is smile back.
PSN


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 27-09 13:03
Xerohumoris schreef op dinsdag 28 januari 2020 @ 23:27:
Dank dit ga ik morgen met een frisse blik goed bekijken en verwerken. Ik laat het weten als het niet werkt.


[...]


Dit probleem wordt ondervangen op de Arduino als het goed is. Serial.println() geeft altijd een newline mee. Met Serial.print() doe je dit niet. Dit heb ik bewust gedaan. Dit gezien de in Qt hierop gewacht wordt en automatisch wordt afgebroken.
Aan de ontvangende kant wil je normaal gesproken altijd een timeout hebben die aangeeft dat het niet meer goed gaat komen en opnieuw begint met een transactie.

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.