Canbus. Cant received frame after write frame
-
Hello everybody! I need your help. I cant received frame after write frame;
pseudocode:
writeFrame(myFrame); // I will write new frame to can, after..
auto answerFrame = getFrame(int id); // but, the frame does not have time to arrive before this code is executedWho-How to get the frame, without QCanBusDevice::framesReceived signal
-
@Eugene5_11 Welcome to the forum.
If you must use synchronous methods then you need to look at:
-
@Eugene5_11 Post your actual code and explain what "don't work" is supposed to mean.
-
@ChrisW67
can_test.h#pragma once #include <qcanbusdeviceinfo.h> #include <qmessagebox.h> #include <qcanbus.h> #include <qobject.h> #include <qthread.h> #include <qdebug.h> #include <Windows.h> enum class CanStatus { connected, connecting, unconnected }; class CanTest : public QObject { Q_OBJECT private: QCanBusDevice* m_device; CanStatus canStatus = CanStatus::unconnected; QVector<QCanBusFrame> framescash; public: CanTest(); ~CanTest(); CanStatus getCanStatus(); QCanBusFrame readData(); void writeData(QCanBusFrame frame); signals: void sig_changeCanState(); public slots: void changeCanState(); void framesReceived(); };
can_test.cpp
#include "can.h" CanTest::CanTest() { QString error_str; m_device = QCanBus::instance() ->createDevice(QStringLiteral("passthrucan"), QStringLiteral("SM2 USB"), &error_str); if (!m_device) { QMessageBox::critical(nullptr, "Error", "Error, " + error_str); return; } if (!m_device->connectDevice()) { QMessageBox::critical(nullptr, "Error", "Error, " + error_str); return; } connect(m_device, &QCanBusDevice::framesReceived, this, &CanTest::framesReceived); connect(m_device, &QCanBusDevice::stateChanged, this, &CanTest::changeCanState); } QCanBusFrame CanTest::readData() { if (framescash.size() > 0) { return framescash.at(0); } return QCanBusFrame(1, 0x0); } void CanTest::framesReceived() { QVector<QCanBusFrame> frames = m_device->readAllFrames(); for (const auto& _t : frames) { if (_t.frameId() == 0x7CE) { framescash.append(_t); qDebug() << "Frame from QCanBusDevice::framesReceived(): " << _t.toString(); } } } void CanTest::writeData(QCanBusFrame frame) { if (!m_device) return; m_device->writeFrame(frame); } CanStatus CanTest::getCanStatus() { return canStatus; } void CanTest::changeCanState() { switch (m_device->state()) { case QCanBusDevice::ConnectedState: canStatus = CanStatus::connected; break; case QCanBusDevice::ConnectingState: canStatus = CanStatus::connecting; break; case QCanBusDevice::UnconnectedState: canStatus = CanStatus::unconnected; break; } qDebug() << "can status: " << m_device->state(); emit sig_changeCanState(); } CanTest::~CanTest() { if (!m_device) return; if (m_device->state() == QCanBusDevice::ConnectedState) { m_device->disconnectDevice(); } delete m_device; }
widgetclass:
....
void QtWidgetsClass::sendMsg() { //for (int i = 0; i < 100; i++) { can->writeData(newFrame); // here I need got a frame auto answerFrame = can->readData(); qDebug() << "Frame before writeFrame function(): " << answerFrame.toString(); } }
-
@Eugene5_11 You claim that waitForFramesReceived() "dont work" but your code does not use the function.
You first need to decide if your code is supposed to operate synchronously (i.e use the wait* functions) or asynchronously (i.e. using signals to determine when stuff is received). Your current code is asynchronous but is expecting synchronous behaviour.
can->writeData(newFrame); // ^^^ This frame will not be written until the Qt event loop is reached // ^^^ Responses will not be received until the Qt event loop is reached // vvv so here it has not been sent and a response cannot have been received. // here I need got a frame auto answerFrame = can->readData(); // ^^^ this returns something regardless of whether there is anything in your QVector cache
-
@ChrisW67 I do
QCanBusFrame CanTest::readData(int id) { /*if (framescash.size() > 0) { return framescash.at(0); } return QCanBusFrame(1, 0x0);*/ while (m_device->waitForFramesReceived(1000)) { QVector<QCanBusFrame> frames = m_device->readAllFrames(); for (const auto& _t : frames) { if (_t.frameId() == 0x7CE) { return _t; } } } }
This is work! But, I think that not correctly
-
@Eugene5_11 We do not know your entire requirement but this is the general flow using standard Qt async processing:
- Sending
- Clear the response queue
- Send a request frame
- Return to the Qt event loop
- Receiving
- Receive all CAN frames (You have no control over this).
- Queue any frame with frameID 0x7CE.
- Discard any other frame
- If queue not empty then signal response received. The slot attached to this signal should process the queue.
- Return to Qt event loop
- Receive all CAN frames (You have no control over this).
If you are only interested in the first 0x7CE received after sending the request frame, then the queue could be a single QCanBusFrame.
For more complex flows a simple state machine could be implemented.
- Sending
-