le 04-12-2017 02:05 AM
Bonjour à tous,
Je développe sous CVI.
Je dois lire 2 entrées compteurs (de fronts) à~200Khz sur un boitier NI USB 6210, mon pb est que la lecture des 2 entrées n'est pas synchroniser.
Lors de mon test (m^me signal connecté aux 2 compteurs j'ai un décallage des valeus lues et le décallage puet glisser dans un sens comme dans l'autre.
On m'a fourni un VI qui fait cette lecture qui lui me donne un écart constant entre les 2 compteurs ce qui indique bien qu'il n'y a pas de glissement .
Par contre sous cvi (parce que ela entre dans un développemnt plus conséquent , je n'arrive pas à effectuer cette synchronisation de taches.
Bref, le code VI est plus parlant q'une suite de phrases .
Je crée bien les 3 taches, je n'arrive pas à coder les fils de synchronisation du sampleclock.
je ne trouve pas de doc qui explique cela.
Si quelqu'un aurait déjà rencontré ce problème, et aurait une solution , je suis preneur.
Bien cordialement,
Didier
le 05-16-2017 10:07 AM
Salut,
Vous voulez faire la synchronisation des "clocks".
Vous pouvez utiliser une structure séquentielle par exemple.
Cela répond-t-il à votre question ?
Salut,
James.
le 05-17-2017 06:46 AM
Salut,
Récemment je vous ai proposé d’utiliser une structure séquentielle, car j’ai compris que le ‘‘screenshot’’ provient du code où il y a le décalage.
Si je comprends bien, la synchronisation fonctionne normalement sur labVIEW mais pas sur CVI ?
Dans ce cas, pourriez-vous poster votre code CVI ?
Merci,
James
le 05-22-2017 12:29 AM
#include "windows.h" #include <utility.h> #include <ansi_c.h> #include <formatio.h> #include <cvirte.h> #include <userint.h> #include <stdlib.h> #include <NIDAQmx.h> #include <DAQmxIOctrl.h> #include "TestCompteur.h" #define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else #define F_OPEN 1 #define F_WRITE 2 #define F_CLOSE 3 static int panelHandle; static TaskHandle gCt0TaskHandle=0, gCt1TaskHandle=0, gAITaskHandle=0; static int32 gSampsToRead=1; static uInt32 gNumAIchannels=1; static float64 *gAIdata=NULL; static uInt32 *gData=NULL; static int gFic=0; int32 CVICALLBACK EveryCallback (TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData); int32 CVICALLBACK DoneCallback (TaskHandle taskHandle, int32 status, void *callbackData); int32 CVICALLBACK EveryCpt0Callback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData); int32 CVICALLBACK EveryCpt1Callback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData); int32 CVICALLBACK EveryNCallback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData); int f_Fic (int what, uInt32 c0, uInt32 c1); char *Ndate_fr (void); char *FrTimeStr (char (sep)); char *Ndate_fr (void); int main(int argc, char *argv[]) { if( InitCVIRTE(0,argv,0)==0 ) return -1; /* out of memory */ if( (panelHandle=LoadPanel(0,"TestCompteur.uir",PANEL))<0 ) return -1; NIDAQmx_NewPhysChanCICtrl(panelHandle,PANEL_CHAN0,0); NIDAQmx_NewPhysChanCICtrl(panelHandle,PANEL_CHAN1,0); NIDAQmx_NewTerminalCtrl(panelHandle,PANEL_CLKSRC,0); DAQmxResetDevice ("Dev2"); DisplayPanel(panelHandle); RunUserInterface(); if (gAITaskHandle) DAQmxClearTask(gAITaskHandle); if (gCt0TaskHandle) DAQmxClearTask(gCt0TaskHandle); if (gCt1TaskHandle) DAQmxClearTask(gCt1TaskHandle); DiscardPanel(panelHandle); return 0; } int CVICALLBACK PanelCallback(int panel, int event, void *callbackData, int eventData1, int eventData2) { if( event==EVENT_CLOSE ) QuitUserInterface(0); return 0; } int CVICALLBACK StartCallback(int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { int error=0; char AIChan[256], Cpt0Chan[256], Cpt1Chan[256]; char clockSource[256]; uInt32 initialCount; uInt32 nb_AcqAI=10; // uniquement pour création du trigger sur clocksource les valeurs ne sont pas utilisées. char errBuff[2048]={'\0'}; float64 rate=1000; if( event==EVENT_COMMIT ) { GetCtrlVal(panel,PANEL_AICHAN, AIChan); GetCtrlVal (panel,PANEL_CHAN0, Cpt0Chan); GetCtrlVal (panel,PANEL_CHAN1, Cpt1Chan); GetCtrlVal (panel,PANEL_CLKSRC, clockSource); GetCtrlVal (panel,PANEL_INITIAL, &initialCount); GetCtrlVal (panel,PANEL_RATE, &rate); GetCtrlVal (panel,PANEL_CHECKFIC, &gFic); //GetCtrlVal (panel,PANEL_SAMPLES, &gSampsToRead); if( (gData=malloc(gSampsToRead*sizeof(uInt32)))==NULL ) { MessagePopup("Error","Not enough memory"); goto Error; } /*********************************************/ // DAQmx Configure Code /*********************************************/ DAQmxErrChk (DAQmxCreateTask("",&gAITaskHandle)); DAQmxErrChk (DAQmxCreateAIVoltageChan(gAITaskHandle, AIChan, "", DAQmx_Val_Cfg_Default, -10., +10., DAQmx_Val_Volts, NULL)); DAQmxErrChk (DAQmxCfgSampClkTiming(gAITaskHandle, "OnboardClock", rate, DAQmx_Val_Rising, DAQmx_Val_ContSamps, nb_AcqAI)); // lecture 10 valeurs DAQmxErrChk (DAQmxCreateTask("",&gCt0TaskHandle)); DAQmxErrChk (DAQmxCreateCICountEdgesChan(gCt0TaskHandle, Cpt0Chan,"", DAQmx_Val_Rising, 0, DAQmx_Val_CountUp )); DAQmxErrChk (DAQmxCfgSampClkTiming(gCt0TaskHandle, clockSource, rate, DAQmx_Val_Rising, DAQmx_Val_ContSamps, 1)); // lecture 1 valeur DAQmxErrChk (DAQmxCreateTask("",&gCt1TaskHandle)); DAQmxErrChk (DAQmxCreateCICountEdgesChan(gCt1TaskHandle, Cpt1Chan,"", DAQmx_Val_Rising, 0, DAQmx_Val_CountUp)); DAQmxErrChk (DAQmxCfgSampClkTiming(gCt1TaskHandle, clockSource, rate, DAQmx_Val_Rising, DAQmx_Val_ContSamps, 1)); // lecture 1 valeur DAQmxErrChk (DAQmxRegisterDoneEvent(gAITaskHandle, 0, DoneCallback, NULL)); DAQmxErrChk (DAQmxRegisterDoneEvent(gCt0TaskHandle, 0, DoneCallback, NULL)); DAQmxErrChk (DAQmxRegisterDoneEvent(gCt1TaskHandle, 0, DoneCallback, NULL)); DAQmxErrChk (DAQmxRegisterEveryNSamplesEvent(gCt1TaskHandle, DAQmx_Val_Acquired_Into_Buffer, 1, 0, EveryCpt1Callback, NULL)); DAQmxErrChk (DAQmxRegisterEveryNSamplesEvent(gAITaskHandle,DAQmx_Val_Acquired_Into_Buffer,nb_AcqAI,0,EveryNCallback,NULL)); if( (gAIdata=malloc(nb_AcqAI*gNumAIchannels*sizeof(float64)))==NULL) { MessagePopup("Error","Not enough memory"); goto Error; } /*********************************************/ // DAQmx Start Code /*********************************************/ if (gFic) f_Fic(F_OPEN, 0, 0); DAQmxErrChk (DAQmxStartTask(gCt0TaskHandle)); // Tache DCpt0 DAQmxErrChk (DAQmxStartTask(gCt1TaskHandle)); // Tache DCpt1 Sleep (.01); DAQmxErrChk (DAQmxStartTask(gAITaskHandle)); // Tache AI juste pour créer l'horloge de cadencement SetCtrlAttribute(panel,PANEL_START,ATTR_DIMMED,1); } Error: SetWaitCursor(0); if( DAQmxFailed(error) ) { DAQmxGetExtendedErrorInfo(errBuff,2048); if(gAITaskHandle) { DAQmxStopTask(gAITaskHandle); DAQmxClearTask(gAITaskHandle); gAITaskHandle = 0; } if(gCt0TaskHandle) { DAQmxStopTask(gCt0TaskHandle); DAQmxClearTask(gCt0TaskHandle); gCt0TaskHandle = 0; } if(gCt1TaskHandle) { DAQmxStopTask(gCt1TaskHandle); DAQmxClearTask(gCt1TaskHandle); gCt1TaskHandle = 0; } if( gData ) { free(gData); gData = NULL; } SetCtrlAttribute(panel,PANEL_START,ATTR_DIMMED,0); MessagePopup("DAQmx Error",errBuff); } return 0; } int CVICALLBACK StopCallback(int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { if( event==EVENT_COMMIT && gAITaskHandle && gCt0TaskHandle && gCt1TaskHandle) { DAQmxStopTask(gAITaskHandle); DAQmxStopTask(gCt0TaskHandle); DAQmxStopTask(gCt1TaskHandle); DAQmxClearTask(gAITaskHandle); gAITaskHandle = 0; DAQmxClearTask(gCt0TaskHandle); gCt0TaskHandle = 0; DAQmxClearTask(gCt1TaskHandle); gCt1TaskHandle = 0; SetCtrlAttribute(panel,PANEL_START,ATTR_DIMMED,0); if (gFic) f_Fic(F_CLOSE, 0, 0); } return 0; } int32 CVICALLBACK EveryCpt1Callback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData) { int32 error=0; char errBuff[2048]={'\0'}; uInt32 data1=0, data0=0; if(gCt1TaskHandle) DAQmxErrChk (DAQmxReadCounterScalarU32(gCt1TaskHandle, -1, &data1, NULL)); SetCtrlVal(panelHandle, PANEL_DATA1, data1); if(gCt0TaskHandle) DAQmxErrChk (DAQmxReadCounterScalarU32(gCt0TaskHandle, -1, &data0, NULL)); SetCtrlVal(panelHandle, PANEL_DATA0, data0); SetCtrlVal(panelHandle, PANEL_DT, data0-data1); if (gFic) f_Fic(F_WRITE, data0, data1); Error: if( DAQmxFailed(error) ) { DAQmxGetExtendedErrorInfo(errBuff,2048); if (gCt0TaskHandle) { DAQmxStopTask(gCt0TaskHandle); DAQmxClearTask(gCt0TaskHandle); gCt0TaskHandle = 0; } if (gCt1TaskHandle) { DAQmxStopTask(gCt1TaskHandle); DAQmxClearTask(gCt1TaskHandle); gCt1TaskHandle = 0; } MessagePopup("DAQmx Error",errBuff); SetCtrlAttribute(panelHandle,PANEL_START,ATTR_DIMMED,0); } return 0; } int32 CVICALLBACK EveryNCallback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData) { int32 error=0; char errBuff[2048]={'\0'}; if(gAITaskHandle) { DAQmxErrChk (DAQmxReadAnalogF64(gAITaskHandle, nSamples, 10.0, DAQmx_Val_GroupByChannel, gAIdata, nSamples*gNumAIchannels, NULL, NULL)); //if( numReadAI>0 ) PlotStripChart(panelHandle,PANEL_STRIPCHART,gAIdata,numReadAI*gNumAIchannels,0,0,VAL_DOUBLE); } Error: if( DAQmxFailed(error) ) { DAQmxGetExtendedErrorInfo(errBuff,2048); if( gAITaskHandle!=0 ) { DAQmxStopTask(gAITaskHandle); DAQmxClearTask(gAITaskHandle); gAITaskHandle = 0; } if( gAIdata ) { free(gAIdata); gAIdata = NULL; } MessagePopup("DAQmx Error",errBuff); SetCtrlAttribute(panelHandle,PANEL_START,ATTR_DIMMED,0); } return 0; } int32 CVICALLBACK DoneCallback(TaskHandle taskHandle, int32 status, void *callbackData) { int32 error=0; char errBuff[2048]={'\0'}; if (gAITaskHandle) { DAQmxClearTask(gAITaskHandle); gAITaskHandle = 0; } if (gCt0TaskHandle) { DAQmxClearTask(gCt0TaskHandle); gCt0TaskHandle = 0; } if (gCt1TaskHandle) { DAQmxClearTask(gCt1TaskHandle); gCt1TaskHandle = 0; } // Check to see if an error stopped the task. DAQmxErrChk (status); Error: DAQmxGetExtendedErrorInfo(errBuff,2048); if( DAQmxFailed(error) ) MessagePopup("DAQmx Error",errBuff); SetCtrlAttribute(panelHandle,PANEL_START,ATTR_DIMMED,0); return 0; } int f_Fic(int what, uInt32 c0, uInt32 c1) { static FILE *fice; char name [260]; static int Cpt=0; static double Chrono0, Chrono; switch (what) { case F_OPEN: strcpy (name, "SagCpt_"); strcat (name, Ndate_fr()); strcat (name, "_"); strcat (name, FrTimeStr('-')); strcat (name, ".csv"); //strcat (name, ".raw"); //fice = fopen (name, "wb"); fice = fopen (name, "wt"); if (fice==NULL) { MessagePopup ("Saguntocounter Error:", "Create MeasFile "); return-1; } Cpt=0; Chrono0 = Timer (); SetCtrlVal (panelHandle, PANEL_FICNAME, name); break; case F_WRITE: if (fice!=NULL) { Chrono = Timer () - Chrono0; Cpt++; fprintf (fice, "%d; %f; %d; %d; %d\n",Cpt, Chrono, c0, c1, c1-c0); } break; case F_CLOSE: if (fice!=NULL) fclose (fice); break; } return Cpt; } //*====================================================================== //* Module : Ndate_fr //*====================================================================== char* Ndate_fr (void) { int err,mois,jour,annee; static char ddate[11]; err = GetSystemDate (&mois,&jour,&annee); Fmt (ddate,"%s<%i[w2p0]-%i[w2p0]-%i[w4p0]\0",jour,mois,annee); return (ddate); } //*====================================================================== //* Module : FrTimeStr //*====================================================================== char* FrTimeStr (char (sep)) { int hh,mm,ss; static char ftime[13]; GetSystemTime (&hh,&mm,&ss); Fmt (ftime,"%s<%i[w2p0]%c%i[w2p0]%c%i[w2p0]\0",hh,sep,mm,sep,ss); return (ftime); } //*====================================================================== //* Module : FrDateStr //*====================================================================== char* FrDateStr (char (sep)) { int mois,jour,annee; static char fdate[13]; GetSystemDate (&mois,&jour,&annee); Fmt (fdate,"%s<%i[w2p0]%c%i[w2p0]%c%i[w4p0]\0",jour,sep,mois,sep,annee); return (fdate); } //*=============================== End OF Code =========================
Bonjour James,
j'ai avancé sur le sujet, j'arrive maintenant sous CVI à avoir les 2 entrées synchronisées, mais avec une différence constante.
Je pense que cela est du au fait que la l'acquisition de chaque compteur se fait dans deux taches différentes.
Est -il possible d'activer la lecture du second compteur sur un compte bien précis du premier?
Je joins mon code de test. ( je n'ai pour l'instant plus la centrale pour effecteur les tests...)
Merci
Didier AM
le 05-22-2017 08:48 AM
Salut,
Merci d’avoir posté votre code CVI.
Dans votre premier message, vous avez mentionné que vous voulez lire 2 entrées compteurs…
Etant donné que votre code est en partie sous LabView et CVI, je suis un peu confus au sujet de l’objectif de votre code.
Afin de pouvoir répondre correctement à votre question :
Pouvez-vous expliquer à l’aide d’un exemple, ce que vous voulez dire par : activer la lecture du second compteur sur un compte bien précis du premier ? (sur CVI je présume ?)
Une petite description du but de votre code et des taches que vous avez créé serait aussi un coup de pouce bien apprécié.
Je reste confiant, que nous trouverons une solution très rapidement.
Cordialement,
James
le 05-24-2017 04:22 AM
Merci James pour tes réponses.
Je précise, le VI est une solution que l'on m'a proposé mais je ne développe pas sous Labview.
Je suis donc parti du VI et j'ai créé (avec du mal) le pendant CVI.
Dans le code ci dessus, je n'ai plus de glissement entre les 2 entrées compteurs lorsque j'utilise un géné à 200 kHZ.
J'ai juste le décalage lié je pense au fait que chaque compteur soit lu dans un tâche séparée.
Pour aller plus loin, je souhaiterai pouvoir lire la valeur du compteur 2 chaque fois que le compteur 1 a compté un nombre de top prédéfini., par exemple un tour de rouleau. Je précise que le signal peut monter à 300kHz (GI sur un rouleau dépasse 1000m/mn).
Pour l'insant je n'ai rien d'autre que le code envoyé, je devrai théoriquement récupérer la centre USB d'ici une quinzaine de jour.
Bien à toi
Didier