How to Continuously acquire signal



  • Hello guys I am getting a signal continuously from a USB device. I want to store or display it on screen the whole time untill my program is stopped or someone pushes the stop button how i can do that. I have install the drivers for the device and i can read the signal also but, the problem is when i run my code it read the signal value at that particular time and not for the whole time till the program is stopped. Should i use the while loop and read the signal in this while loop till the program is stopped. Please help. Thanks in advance.



  • @rockon209 said in How to Continuously acquire signal:

    Should i use the while loop and read the signal in this while loop till the program is stopped.

    No.

    Do the reading in a qobject and move that qobject in another thread

    Can you show your current code?



  • @VRonin
    for example following is the code and i am getting 1000 sample (data) points but i want to all the sample till the program is running

    #include <QApplication>
    #include <QWidget>
    #include <QDebug>
    
    #include <NIDAQmx.h>
    
    int main(int argc, char **argv)
    {
        // Initialize a usual Qt application
        QApplication app(argc, argv);
        QWidget w;
    
        // Initialize DAQmx and read analog input (Copied and simplified from
        // http://www.ni.com/tutorial/5409/en/#toc3 )
        TaskHandle taskHandle = 0;
        int32 samplesReceived = 0;
        float64 data[1000];
    
        DAQmxCreateTask("MyTask", &taskHandle);
        DAQmxCreateAIVoltageChan(taskHandle, "Dev1/ai0", "", DAQmx_Val_Cfg_Default, -10.0, 10.0, DAQmx_Val_Volts, NULL);
        DAQmxCfgSampClkTiming(taskHandle, "", 10000.0, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, 1000);
        DAQmxStartTask(taskHandle);
        DAQmxReadAnalogF64(taskHandle, 1000, 10.0, DAQmx_Val_GroupByChannel, data, 1000, &samplesReceived, NULL);
        DAQmxStopTask(taskHandle);
        DAQmxClearTask(taskHandle);
    
        // Print results
        qDebug() << "Received" << samplesReceived << "points";
        for (int i = 0; i < samplesReceived; ++i)
            qDebug() << data[i];
    
        // Run Qt event loop
        w.show();
        return app.exec();
    }
    

  • Lifetime Qt Champion

    Hi,

    Like suggested by @VRonin, encapsulate the DAQmx calls and then you can either use a QTimer to trigger the read at regular interval or a separate thread.



  • You can use the DAQmx API callback to acquire signals, in that way you collect signals every time your data is ready from the DAQ. I wrote a DAQ class to encapsulate all the NI functionality a while back



  • @SGaist @Irshad @VRonin
    Actually I am new to Qt. Could you please explain it with an example so that I can understand. I have written DAQmx read/write function in one .cpp file.and will call them when i want to read/write the data. But i dont know how I can read it all the time till the program is running.



  • I do not know how DAQmx works, does it need to call DAQmxCreateTask every time you read or do you create it once and just call DAQmxReadAnalogF64 repeatedly?



  • Hello @VRonin

    DAQmxCreateTask has to be call everytime to read the data



  • #include <QObject>
    #include <QThread>
    #include <QCoreApplication>
    #include <atomic>
    #include <array>
    
    class DAQmxWorker : public QObject{
        Q_OBJECT
        Q_DISABLE_COPY(DAQmxWorker)
    public:
        explicit DAQmxWorker(QObject* parent=Q_NULLPTR)
            :QObject(parent)
        {
            m_continueLoop.store(false);
        }
        Q_SIGNAL void sampleReceived(int32 samplesReceived, const std::array<float64,1000>& data);
        Q_SIGNAL void finished();
        Q_SLOT void execute(){
            m_continueLoop.store(true);
            while(m_continueLoop.load()){
                TaskHandle taskHandle = 0;
                int32 samplesReceived = 0;
                std::array<float64,1000> data;
            
                DAQmxCreateTask("MyTask", &taskHandle);
                DAQmxCreateAIVoltageChan(taskHandle, "Dev1/ai0", "", DAQmx_Val_Cfg_Default, -10.0, 10.0, DAQmx_Val_Volts, NULL);
                DAQmxCfgSampClkTiming(taskHandle, "", 10000.0, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, 1000);
                DAQmxStartTask(taskHandle);
                DAQmxReadAnalogF64(taskHandle, 1000, 10.0, DAQmx_Val_GroupByChannel, data.data(), 1000, &samplesReceived, NULL);
                DAQmxStopTask(taskHandle);
                DAQmxClearTask(taskHandle);
                sampleReceived(samplesReceived,data); 
                QCoreApplication::processEvents();
            }
            finished();
        }
        Q_SLOT void stop(){
            m_continueLoop.store(false);
        }
    private:
        std::atomic_bool m_continueLoop;
    };
    

    now you can use it as suggested in the post linked above:

    QThread* thread = new QThread;
    DAQmxWorker* worker = new DAQmxWorker();
    worker->moveToThread(thread);
    connect(thread, SIGNAL(started()), worker, SLOT(execute()));
    connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
    connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    thread->start();
    

    when new data gets read the sampleReceived signal will be emitted and you can connect to it from whatever thread you like.
    to stop it just call worker->stop(); from the main thread



  • Hello @VRonin
    please have a look at this code i have just entered a while loop and it works fine just to read the data continuously. Is this the right way to do it.?

    #include <QApplication>
    #include <QWidget>
    #include <QDebug>

    #include <NIDAQmx.h>

    int main(int argc, char **argv)
    {
    // Initialize a usual Qt application
    QApplication app(argc, argv);
    QWidget w;
    while(true)
    {
    // Initialize DAQmx and read analog input (Copied and simplified from
    // http://www.ni.com/tutorial/5409/en/#toc3 )
    TaskHandle taskHandle = 0;
    int32 samplesReceived = 0;
    float64 data[1000];

    DAQmxCreateTask("MyTask", &taskHandle);
    DAQmxCreateAIVoltageChan(taskHandle, "Dev1/ai0", "", DAQmx_Val_Cfg_Default, -10.0, 10.0, DAQmx_Val_Volts, NULL);
    DAQmxCfgSampClkTiming(taskHandle, "", 10000.0, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, 1000);
    DAQmxStartTask(taskHandle);
    DAQmxReadAnalogF64(taskHandle, 1000, 10.0, DAQmx_Val_GroupByChannel, data, 1000, &samplesReceived, NULL);
    DAQmxStopTask(taskHandle);
    DAQmxClearTask(taskHandle);
    
    // Print results
    qDebug() << "Received" << samplesReceived << "points";
    for (int i = 0; i < samplesReceived; ++i)
        qDebug() << data[i];
    

    }
    // Run Qt event loop
    w.show();
    return app.exec();
    }



  • if you try it you'll see your widget will not show up at all.

    I gave you the solution above...

    Otherwise (and probably better) see if DAQmx allows to pass a callback function to execute when data is available (something like QIODevice does with the readyRead() signal)



  • @VRonin ya you are right
    But I am not able to understand how your logic of QThread is working. Suppose i have a start button and if i press it ,the code(your code) will store the data in an array. Means let say that i have a analog input (room temperature measuring device connected) to the NI device. And I want to check the the temp every one second. So how I can make the logic so that i can measure and display it in the widget.



  • @rockon209 said in How to Continuously acquire signal:

    And I want to check the the temp every one second.

    This is not continuously acquire data. this is reading every once in a while. You can use a QTimer for that, either in the main thread or the worker object

    QTimer updateTimer(1000);
    connect(&updateTimer,&QTimer::timeout,[]()->void{
    // Initialize DAQmx and read analog input (Copied and simplified from
        // http://www.ni.com/tutorial/5409/en/#toc3 )
        TaskHandle taskHandle = 0;
        int32 samplesReceived = 0;
        float64 data[1000];
    
        DAQmxCreateTask("MyTask", &taskHandle);
        DAQmxCreateAIVoltageChan(taskHandle, "Dev1/ai0", "", DAQmx_Val_Cfg_Default, -10.0, 10.0, DAQmx_Val_Volts, NULL);
        DAQmxCfgSampClkTiming(taskHandle, "", 10000.0, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, 1000);
        DAQmxStartTask(taskHandle);
        DAQmxReadAnalogF64(taskHandle, 1000, 10.0, DAQmx_Val_GroupByChannel, data, 1000, &samplesReceived, NULL);
        DAQmxStopTask(taskHandle);
        DAQmxClearTask(taskHandle);
    
        // Print results
        qDebug() << "Received" << samplesReceived << "points";
        for (int i = 0; i < samplesReceived; ++i)
            qDebug() << data[i];
    };)
    updateTimer.start();

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.