Discussions au sujet des autres produits NI

annuler
Affichage des résultats de 
Rechercher plutôt 
Vouliez-vous dire : 

Synchronisation de 2 entrées compteurs (DAQmx et CVI)

viCPT.gifBonjour à 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

0 Compliments
Message 1 sur 6
3 381 Visites

 Salut, 

Vous voulez faire la synchronisation des "clocks".

Vous pouvez utiliser une structure séquentielle par exemple.

 

Sequence structure.jpg

 

Cela répond-t-il à votre question ?

 

Salut,

 

James.

Greetings and Regards,
James
0 Compliments
Message 2 sur 6
3 219 Visites

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

Greetings and Regards,
James
0 Compliments
Message 3 sur 6
3 205 Visites
#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

0 Compliments
Message 4 sur 6
3 170 Visites

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

Greetings and Regards,
James
0 Compliments
Message 5 sur 6
3 159 Visites

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

0 Compliments
Message 6 sur 6
3 146 Visites