QSerialport readyRead() for measuring revolutions
-
Hello all,
I am trying to measure the revolutions of a motor sent from my ARDUINO to QSerialPort by using the readyRead-Signal. ARDUINO sends just one byte (val '1') at a time per revolution.
I connected the readyRead-Signal to my receive-method:QObject::connect(port, SIGNAL(readyRead()), this, SLOT(dataRx()));
In that method I measure (a.o.) the time between SIGNALS and store them in a list:
now = std::chrono::system_clock::now(); rxTimepoints->push_back(now.time_since_epoch().count());
Looking at this list I find that dataRx seems to be called twice per byte sent by the ARDUINO (the values in the list should continually decrease as the motor is speeding up, but between two correct values of 180000-40000 microseconds there is always a value of 12000-4000 µs.
How can that happen? How can I get rid of that doubling?Thank you for helping...
@herrgross said in QSerialport readyRead() for measuring revolutions:
Looking at this list I find that dataRx seems to be called twice per byte sent by the ARDUINO
Can you show a minimal example? For example, you realize that if you execute that
connect()
statement twice in your code, somewhere, your slot would get called twice? Are you saying that the sender sends different values each time and you see the same bytes twice as pairs (like1,1,10,10,100,100,...
)? Ah, no, it's1
every time: suggest you change that (e.g. just increment each time) so you see different values. Does yourdataRx()
read whatever has been received? What isbytesAvailable()
reporting each time? I am starting by trying to discover whether you are seeing twice as many bytes actually sent from Arduino vsreadyRead()
signal being fired twice vs your slot being called twice. -
@Ronel_qtmaster thank you for the nice idea ... but it did not solve the problem..... anyhow I tried to control what's actually arriving with readall() into a QByteArray and the checking the size of the array and reading the data. There was nothing arriving than the '1' sent by arduino, no endline character or other
I still assume the signals are coming in delayed (due to serialPort or signal event queue) and because of that your slot restarts the timer and therefore you have significantly shorter timespans in between.
Just a guess without analysing your code. -
@herrgross said in QSerialport readyRead() for measuring revolutions:
Looking at this list I find that dataRx seems to be called twice per byte sent by the ARDUINO
Can you show a minimal example? For example, you realize that if you execute that
connect()
statement twice in your code, somewhere, your slot would get called twice? Are you saying that the sender sends different values each time and you see the same bytes twice as pairs (like1,1,10,10,100,100,...
)? Ah, no, it's1
every time: suggest you change that (e.g. just increment each time) so you see different values. Does yourdataRx()
read whatever has been received? What isbytesAvailable()
reporting each time? I am starting by trying to discover whether you are seeing twice as many bytes actually sent from Arduino vsreadyRead()
signal being fired twice vs your slot being called twice.@JonB I allready searched if I connected twice... could not find that.
here's some of the list I get:
and here's the code of my dataRx:
void Sirene::dataRx() { if (port->bytesAvailable() > 0) { QByteArray data = port->readAll(); QString value; value = QString::number(data[0]); statusBar()->showMessage(value); data.clear(); } now = std::chrono::system_clock::now(); rxTimepoints->push_back(now.time_since_epoch().count()); }
-
@JonB I allready searched if I connected twice... could not find that.
here's some of the list I get:
and here's the code of my dataRx:
void Sirene::dataRx() { if (port->bytesAvailable() > 0) { QByteArray data = port->readAll(); QString value; value = QString::number(data[0]); statusBar()->showMessage(value); data.clear(); } now = std::chrono::system_clock::now(); rxTimepoints->push_back(now.time_since_epoch().count()); }
@herrgross
That's a lot of code; if you want to debug I would suggest a much smaller example.You haven't shown whether the
port->bytesAvailable() > 0
is followed every timedataRx()
is called. You haven't shown the value you receive which I thought you were changing from always being1
--- you send it to the statusbar, which isn't very helpful.I don't understand your timing numbers (
now
,now-before
), I don't see how that helps you tell whetherreadyRead()
is being emitted twice per byte input.I suggest you reduce this to simple code illustrating what is going on.
-
@herrgross
That's a lot of code; if you want to debug I would suggest a much smaller example.You haven't shown whether the
port->bytesAvailable() > 0
is followed every timedataRx()
is called. You haven't shown the value you receive which I thought you were changing from always being1
--- you send it to the statusbar, which isn't very helpful.I don't understand your timing numbers (
now
,now-before
), I don't see how that helps you tell whetherreadyRead()
is being emitted twice per byte input.I suggest you reduce this to simple code illustrating what is going on.
@JonB ok, I reduced the code to what is necessary... (edited above)
the now and now - before in the list are :
now = std::chrono::system_clock::now();
and that value minus the previous now-value (which is the timespan between these two time_points)
So when the motor speeds up these values should continuously decrease, as the timespan between each call shoud be getting smaller.
I changed now the arduino, so it sends each time an increased value,
and in my statusbar (althoug not very pretty) I can see, that the value of QByteArray[0] is raising by 2 every call (so I get 2,4,6,8,10...)
that should not happen I guess... -
I still assume the signals are coming in delayed (due to serialPort or signal event queue) and because of that your slot restarts the timer and therefore you have significantly shorter timespans in between.
Just a guess without analysing your code. -
Hello all,
I am trying to measure the revolutions of a motor sent from my ARDUINO to QSerialPort by using the readyRead-Signal. ARDUINO sends just one byte (val '1') at a time per revolution.
I connected the readyRead-Signal to my receive-method:QObject::connect(port, SIGNAL(readyRead()), this, SLOT(dataRx()));
In that method I measure (a.o.) the time between SIGNALS and store them in a list:
now = std::chrono::system_clock::now(); rxTimepoints->push_back(now.time_since_epoch().count());
Looking at this list I find that dataRx seems to be called twice per byte sent by the ARDUINO (the values in the list should continually decrease as the motor is speeding up, but between two correct values of 180000-40000 microseconds there is always a value of 12000-4000 µs.
How can that happen? How can I get rid of that doubling?Thank you for helping...
@herrgross said in QSerialport readyRead() for measuring revolutions:
Originally you said:Looking at this list I find that dataRx seems to be called twice per byte sent by the ARDUINO
Now you say:
I can see, that the value of QByteArray[0] is raising by 2 every call (so I get 2,4,6,8,10...)
which sounds more like "dataRx seems to be called only once per 2 bytes sent by the ARDUINO".
As I've said, you need to find out what the actual case is. Get that sorted out before you concentrate on your timings.
-
@herrgross said in QSerialport readyRead() for measuring revolutions:
Originally you said:Looking at this list I find that dataRx seems to be called twice per byte sent by the ARDUINO
Now you say:
I can see, that the value of QByteArray[0] is raising by 2 every call (so I get 2,4,6,8,10...)
which sounds more like "dataRx seems to be called only once per 2 bytes sent by the ARDUINO".
As I've said, you need to find out what the actual case is. Get that sorted out before you concentrate on your timings.
-
@JonB what would you suggest how I can find out? I'm stuck in this since yesterday and run out of ideas...
@herrgross
I don't know what your problem is. I have not seen convincing evidence thatreadyRead()
is being emitted any more (or less) than it should be. You could write simpler code to verify that if you wish, or not. Only you know what your timing figures mean, I do not. I don't know thatreadyRead()
signal is a reliable means of measuring timings in real time. I don't understand hardware and have no idea what an Arduino is :) -
@herrgross
I don't know what your problem is. I have not seen convincing evidence thatreadyRead()
is being emitted any more (or less) than it should be. You could write simpler code to verify that if you wish, or not. Only you know what your timing figures mean, I do not. I don't know thatreadyRead()
signal is a reliable means of measuring timings in real time. I don't understand hardware and have no idea what an Arduino is :) -
@herrgross got it!!!!
in the arduino code the interrupt must be set to RISING instead of HIGH, so it's only sending when the state of the interruptpin c h a n g e s to HIGHattachInterrupt(digitalPinToInterrupt(interruptPin), impuls, RISING);
thank you all!!
-