1、使用NI MAX创建多路输入的测量任务
本处设置Dev1/ai0:3四路电压输入,采样率均为100,差分连接。
2、代码
// 设置地址
void Widget::on_add_pushButton_clicked()
{address_txt = QFileDialog::getExistingDirectory(this, tr("Open Directory"),"/home",QFileDialog::ShowDirsOnly| QFileDialog::DontResolveSymlinks);ui->begin_pushButton->setEnabled(true);ui->add_pushButton->setEnabled(false);//操作记录QString current_date = ui->textEdit->toPlainText();QDateTime current_date_time =QDateTime::currentDateTime(); //获取当前时间current_date +=current_date_time.toString("hh:mm:ss");current_date += (address_txt);current_date += "\n";ui->textEdit->setText(current_date);
}// 开始采集
void Widget::on_begin_pushButton_clicked()
{//创建文本文档QDateTime current_date_time =QDateTime::currentDateTime(); //获取当前时间QString thename = current_date_time.toString("yyyy-MM-dd-hh-mm-ss");fileName = thename+".txt";fileName = address_txt+"/"+fileName;file.setFileName(fileName);file.open(QFile::WriteOnly);//开始采集数据int32 error = 0;char errBuff[2048] = { '\0' };error += DAQmxCreateTask("",&taskHandle);error += DAQmxCreateAIVoltageChan(taskHandle, "Dev1/ai0:3", "", DAQmx_Val_Cfg_Default, -10.0, 10.0, DAQmx_Val_Volts, NULL);error += DAQmxCfgSampClkTiming(taskHandle, "", rate, DAQmx_Val_Rising, DAQmx_Val_ContSamps, sample);error += DAQmxSetAITermCfg(taskHandle,"Dev1/ai0:3",DAQmx_Val_Diff);error += DAQmxRegisterEveryNSamplesEvent(taskHandle, DAQmx_Val_Acquired_Into_Buffer, sample, 0,EveryNCallback, (void*)this);error += DAQmxRegisterDoneEvent(taskHandle, 0, DoneCallback, NULL);error += DAQmxStartTask(taskHandle);//绘图_pTimerUpdate->start(1000); //1s更新一次// 操作记录QString current_date = ui->textEdit->toPlainText();current_date +=current_date_time.toString("hh:mm:ss");current_date += QString::fromLocal8Bit("开始采集");current_date += "\n";ui->textEdit->setText(current_date);if (error < 0){DAQmxGetExtendedErrorInfo(errBuff, 2048);qDebug() << error;qDebug() << errBuff;on_stop_pushButton_clicked();}else{ui->stop_pushButton->setEnabled(true);ui->begin_pushButton->setEnabled(false);}
}void Widget::on_stop_pushButton_clicked()
{_pTimerUpdate->stop();file.close();DAQmxStopTask(taskHandle);DAQmxClearTask(taskHandle);ui->stop_pushButton->setEnabled(false);ui->begin_pushButton->setEnabled(true);// 操作记录QString current_date = ui->textEdit->toPlainText();QDateTime current_date_time =QDateTime::currentDateTime(); //获取当前时间current_date +=current_date_time.toString("hh:mm:ss");current_date += QString::fromLocal8Bit("停止采集");current_date += "\n";ui->textEdit->setText(current_date);
}void Widget::Voltage_show()
{//声明时间获取变量,实际情况中,获取的是当前时间的总秒数int nowtime = (QTime::currentTime().hour()*60+QTime::currentTime().minute())*60+QTime::currentTime().second();double key = nowtime;static double lastPointKey = 0;if (key-lastPointKey > 0.5) //大于2ms添加一个数据{ui->capwidget->graph(0)->addData(nowtime, cap1);ui->capwidget->graph(1)->addData(nowtime, cap1);ui->capwidget->graph(2)->addData(nowtime, cap2);ui->capwidget->graph(3)->addData(nowtime, cap2);ui->prewidget->graph(0)->addData(nowtime, pre3);ui->prewidget->graph(1)->addData(nowtime, pre3);ui->prewidget->graph(2)->addData(nowtime, pre4);ui->prewidget->graph(3)->addData(nowtime, pre4);lastPointKey = key;}ui->capwidget->xAxis->setRange(nowtime, 10, Qt::AlignRight); //设置x轴范围ui->capwidget->replot(); //画图ui->prewidget->xAxis->setRange(nowtime, 10, Qt::AlignRight); //设置x轴范围ui->prewidget->replot(); //画图
}int32 CVICALLBACK EveryNCallback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void * callbackData)
{Widget * pDAQContAI = (Widget *)callbackData;int32 error=0;char errBuff[2048]={'\0'};static int totalRead=0;int32 read=0;float64 data[400];QString total,Voltage1,Voltage2,Voltage3,Voltage4;qRegisterMetaType<QVector<int>>("QVector<int>");error = DAQmxReadAnalogF64(taskHandle, //任务句柄nSamples, //每个通道要读取的样本数10.0, //等待时间DAQmx_Val_GroupByScanNumber, //指定样本是否交错,这个是按扫描编号分组(交错)data, //将样本读入的数组400, //数组的大小&read, //从每个通道读取的实际样本数NULL);totalRead += read ;QDateTime current_date_time =QDateTime::currentDateTime(); //获取当前时间int thenumber;if(read>0){//曲线作图电压赋值cap1=data[0];cap2=data[1];pre3=data[2];pre4=data[3];//实时存储for(int i=0;i<400;i=i+4){thenumber=i/4+totalRead-100;QString str(current_date_time.toString("hhmmss")+" "+QString("%1").arg(thenumber+1)+" "+QString("%1").arg(data[i])+" "+QString("%1").arg(data[i+1])+" "+QString("%1").arg(data[i+2])+" "+QString("%1").arg(data[i+3])+"\n");pDAQContAI->file.write(str.toStdString().c_str());}//实时显示total = QString("%1").arg(totalRead);Voltage1 = QString("%1").arg(data[0]);Voltage2 = QString("%1").arg(data[1]);Voltage3 = QString("%1").arg(data[2]);Voltage4 = QString("%1").arg(data[3]);QTableWidgetItem *item0 = new QTableWidgetItem();QTableWidgetItem *item1 = new QTableWidgetItem();QTableWidgetItem *item2 = new QTableWidgetItem();QTableWidgetItem *item3 = new QTableWidgetItem();QTableWidgetItem *item4 = new QTableWidgetItem();item0->setText(total);item1->setText(Voltage1);item2->setText(Voltage2);item3->setText(Voltage3);item4->setText(Voltage4);pDAQContAI->ui->tableWidget->setItem(0,1,item0);pDAQContAI->ui->tableWidget->setItem(1,0,item1);pDAQContAI->ui->tableWidget->setItem(2,0,item2);pDAQContAI->ui->tableWidget->setItem(1,1,item3);pDAQContAI->ui->tableWidget->setItem(2,1,item4);pDAQContAI->ui->tableWidget->show();}if (error < 0){DAQmxGetExtendedErrorInfo(errBuff, 2048);qDebug() << error;qDebug() << errBuff;DAQmxStopTask(taskHandle);DAQmxClearTask(taskHandle);}else{pDAQContAI->ui->stop_pushButton->setEnabled(true);}return 1;
}int32 CVICALLBACK DoneCallback(TaskHandle taskHandle, int32 status, void *callbackData)
{int32 error=0;char errBuff[2048]={'\0'};if(DAQmxFailed(error=status)){DAQmxGetExtendedErrorInfo(errBuff,2048);DAQmxClearTask(taskHandle);qDebug()<<"DAQmx Error:";qDebug()<<errBuff<<endl;}return 0;
}
个人觉得需要注意的几个地方:
⑴NI DAQmx会自动创建线程进行数据采集,可以在该线程中增加写文本等操作,主线程专门用来操作主界面,实现绘制曲线等。
如果在回调函数中(NI DAQmx线程)进行曲线绘制,会出现线程冲突的报错。
⑵EveryNCallback函数本处放在类外面进行声明,归在主界面的类下面进行声明会报错,所以回调中使用的部分变量在public下声明,以及需要指针将内外一起连接。
Widget * pDAQContAI = (Widget *)callbackData;
⑶在之前一直没明白交错是什么意思,在考虑存储数据时发现,非交错就是通道0的100个数存完了再存通道1的100个数,以此类推。交错则是通道0一个数、通道1一个数,按顺序一轮之后再是下一轮,这种更方便存储和后续处理。
3、显示以及存储效果
4、下载地址
NI采集卡多路输入数据的同时采集、显示、曲线绘制及文本存储 工程文件