Stazione meteo con NI USB-6008 e NI-DAQmx®


Come allestire una semplice stazione meteo per la misura della temperatura interna, temperatura esterna, umidità relativa, usando una scheda di acquisizione National Instruments USB-6008 e le API NI-DAQmx® per Visual C++
a cura di Francesco Parisi (fparisi [at] gmail [dot] com) - Versione 1.0 - Ultima revisione: 07 Aprile 2007

[Indice] [La scheda NI USB-6008] [Misura della temperatura interna] [Misura della temperatura esterna] [Il software di gestione]

Software di gestione

Il software di gestione usa la libreria NI-DAQmx e l'ambiente Microsoft Visual C++ 6.0. Sono state sviluppate due applicazioni: la prima in modalità console e la seconda in modalita grafica (sfruttando le MFC).

Applicazione console Win32 | Applicazione MFC

Il metodo di risoluzione è classico. Viene usato un timer, azionato dal bottone "Leggi valori", che ogni secondo legge i dati e aggiorna conseguentemente i controlli. Premendo il pulsante "Esci", o comunque chiudendo il dialogo, viene "killato" il timer e liberate le risorse hardware e software impegnate da NI-DAQmx.


Output del programma

Di seguito il sorgente del file RilevazioneMeteo2Dlg.cpp :

// 
//	  Rilevazione meteo con NI-DAQmx	  
//	  Versione 1.0 (applicazione MFC)  
//	  
//	  http://telpar.altervista.org/ni-daqmx/meteo/
//
//        Autore: Francesco Parisi <fparisi@gmail.com>
//	  Ultima revisione: 07/Aprile/2007
//
//	  Hardware: NI 6008-USB  -- Software: NI-DAQmx C API 7.5
//		
//	  Oggetto:
//	  Acquisizione di tre segnali lentamente variabili, ad intervalli regolari,
//	  mediante temporizzazione software interna, governata da un ciclo while
//
//	  CANALE1 (Dev1/ai0): Sensore LM35 (Temperatura interna)
//	  CANALE2 (Dev1/ai1): Sensore AD590 (Temperatura esterna)	  
//	  CANALE3 (Dev1/ai2): Sensore 2322 (Umidità relativa esterna)
//
//

// RilevazioneMeteo2Dlg.cpp : implementation file
//

#include "stdafx.h"
#include "RilevazioneMeteo2.h"
#include "RilevazioneMeteo2Dlg.h"
// header di NI-DAQ mx //
#include "C:\Programmi\National Instruments\NI-DAQ\DAQmx ANSI C Dev\include\NIDAQmx.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


//////////////// NI-DAQmx ///////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////


#define CAL_INTERNA  +0.4   /* Calibrazione sensore temp. interna */
#define CAL_ESTERNA  -2.0   /* Calibrazione sensore temp. esterna */
#define CAL_UMIDITA  -3.0   /* Calibrazione sensore umidità relativa */


TaskHandle taskHandle=0;         /* ID del task che verrà assegnato da DAQmxCreateTask */	
float64 vet[3];	                 /* Vettore che contiene i campioni letti */    
char input[] = "Dev1/ai0:2";	 /* Gli ingressi usati sono AI0, AI1 e AI2 */
char nomeTask[] ="TaskAI";		 /* Nome del task */
float64 minVal=0, maxVal=2.5;    /* Gli ingressi sono condizionati al range 0..2.5V */           
int32 configInput=DAQmx_Val_RSE; /* Gli ingressi sono configurati come single-ended */		  
int32 totale=0;					 /* Totale dei campioni acquisiti */

/////////////// NI-DAQmx ////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////



	
/////////////////////////////////////////////////////////////////////////////
// CRilevazioneMeteo2Dlg dialog

CRilevazioneMeteo2Dlg::CRilevazioneMeteo2Dlg(CWnd* pParent /*=NULL*/)
	: CDialog(CRilevazioneMeteo2Dlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CRilevazioneMeteo2Dlg)
	m_StrTempEst = _T("");
	m_StrRH = _T("");
	m_StrTempInt = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CRilevazioneMeteo2Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CRilevazioneMeteo2Dlg)
	DDX_Control(pDX, IDLEGGI, m_cAvviaLettura);
	DDX_Text(pDX, IDC_STATIC_TEMP_EST, m_StrTempEst);
	DDX_Text(pDX, IDC_STATIC_RH, m_StrRH);
	DDX_Text(pDX, IDC_STATIC_TEMP_INT, m_StrTempInt);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CRilevazioneMeteo2Dlg, CDialog)
	//{{AFX_MSG_MAP(CRilevazioneMeteo2Dlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDOK, OnLeggi)
	ON_BN_CLICKED(IDCANCEL, OnEsci)
	ON_BN_CLICKED(IDESCI, OnEsci)
	ON_BN_CLICKED(IDLEGGI, OnLeggi)
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CRilevazioneMeteo2Dlg message handlers

BOOL CRilevazioneMeteo2Dlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here


	
    /*********************************************/
	/* CREAZIONE DEL TASK                        */
	/*********************************************/

	  DAQmxCreateTask(nomeTask,&taskHandle);	
 

    /*********************************************/
	/* CONFIGURAZIONE DEL TASK                   */
	/*********************************************/

	  DAQmxCreateAIVoltageChan(
		         taskHandle,
				 input,				
				 "",                
				 configInput,
				 minVal,
				 maxVal,
				 DAQmx_Val_Volts,
				 ""              
				 );
	

	/*********************************************/
	/* AVVIO DEL TASK                            */
	/*********************************************/
	
	  DAQmxStartTask(taskHandle) ;


	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CRilevazioneMeteo2Dlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CRilevazioneMeteo2Dlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CRilevazioneMeteo2Dlg::OnLeggi() 
{

  // Disabilita il bottone "Leggi valori"
  m_cAvviaLettura.EnableWindow(FALSE);

  // Imposta il timer, leggi ogni secondo (1000 ms)
  SetTimer(ID_TIMER, 1000, NULL);
	
}

void CRilevazioneMeteo2Dlg::OnEsci() 
{
    /*********************************************/
	/* STOP E CLEARING DEL TASK                  */
	/*********************************************/
	 
	if(taskHandle!=0)   {            /* ... se è stato creato il task */	
	    DAQmxStopTask(taskHandle);   /* fermalo */
		DAQmxClearTask(taskHandle);  /* libera le risorse impegnate per il task */
	}
		

	// killa il Timer...
    KillTimer(ID_TIMER); 

	// esci...
	OnOK();  
}


// Di seguito, il codice da eseguire ogni 1000 ms

void CRilevazioneMeteo2Dlg::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	
	   DAQmxReadAnalogF64(
		     taskHandle,      /* Leggi i campioni dal task identificato da taskHandle */
			 1,				  /* Quanti campioni per canale?  */
			 10,              /* Aspetta al piu` 10sec */
			 DAQmx_Val_GroupByScanNumber,	  /* Lettura a priorita' di canale */
			 vet,			  /* Indirizzo del vettore */
			 3,		    	  /* Dimensione del vettore vet */
			 &totale,         /* Numero di campioni letti */
			 NULL             /* -- non utilizzato -- */
			 );

  // vengono letti i valori da vet quindi convertiti secondo le rispettive scale
  // e infine formattati come stringhe associate alle variabili dei controlli testo
  
  m_StrTempInt.Format("%.1f", vet[0] * 20 + CAL_INTERNA);  		   
  m_StrTempEst.Format("%.1f", vet[1] * 29.2 + 250 - 273 + CAL_ESTERNA);	    		
  m_StrRH.Format("%.0f", vet[2] * 32 + 10 + CAL_UMIDITA);	

  // aggiorna i controlli con le nuove variabili
  UpdateData(FALSE);		   	   
	 
   // FINE CODICE	
  CDialog::OnTimer(nIDEvent);

}


Appendice


NI-DAQmx®, LabVIEW®, LabWindows/CVI® sono marchi registrati di National Instruments Corporation. Visual C++ è un marchio registrato di Microsoft Corporation. E' consentito l'utilizzo del materiale presente in queste pagine esclusivamente per scopi hobbistici, attività educative curriculari e comunque non di lucro. E' gradita la citazione della fonte. Questa pagina è visualizzabile con qualsiasi browser.