DA 24/7 C Demo 3
The 24/7 Data Acquisition Wildcard™ is a complete analog front end, offering exceptional 24-bit resolution, excellent stability, and remarkable noise rejection for instrumentation applications. Ideal for high resolution, low frequency measurements and data logging, this analog-to-digital converter (ADC) accepts low level signals directly from transducers, amplifies and conditions them, and converts them with 24 bits of resolution with no missing codes performance.
This C language demonstration program shows how to read 4 different channels at a fixed sample rate without performing a calibration before each sample and without using interrupts. A self-calibration is performed only once at the outset, resulting in faster conversion times.
// **************************************************************************************** // FILE NAME: wda247demo3.c // copyright 2009 Mosaic Industries, Inc. All rights reserved. // --------------------------------------------------------------------- // DATE: 4/20/2009 // VERSION: 1.0, for QED/Q-Line (HC-11) and PDQ line (HCS-12) controllers // --------------------------------------------------------------------- // This is the demonstration code for the 24/7 Data Acquisition Wildcard. // Please see its User Guide for more details. // // The final example shows how to read 4 different channels at a // fixed sample rate without performing a calibration before each // sample and without using interrupts. This example performs a // Self Calibration on each channel, reads the calibration // coefficients using Read_FS_Cal() and Read_Zero_Cal(), stores the // calibration coefficients into a structure, loads the 24-Bit A/D // with the stored calibration coefficients using // Start_Conv_With_Values(), periodically samples each channel using // AD24_Sample_NP(), and finally stores the samples into an array. // // MAKE SURE THAT THE DA247_MODULE_NUM CONSTANT MATCHES YOUR HARDWARE JUMPER SETTINGS!! // // --------------------------------------------------------------------- // Disclaimer: THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT // ANY WARRANTIES OR REPRESENTATIONS EXPRESS OR IMPLIED, // INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES // OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. // // ********************************************************************* #include <mosaic/allqed.h> //__GNUC__ is true for Mosaic PDQ IDE #ifdef __GNUC__ #include <wda247.h> #else #include "library.h" #include "library.c" #endif // NOTE: YOU MUST MAKE SURE THAT DA247_MODULE_NUM CONSTANT MATCHES YOUR HARDWARE JUMPERS!! #define DA247_MODULE_NUM 0 // double check your hardware jumper settings!!! #define CH0 0 // Constants for channels 0 - 3 #define CH1 1 #define CH2 2 #define CH3 3 #define SAMPLE_FREQ 320 // Constant corresponding to 60 hz // 19200 / 60 = 320 [See Table 5] #define NUM_SAMPLES 40 // Total number of samples: // 10 samples for 4 channels #define NUM_CHANNELS 4 // Num channels we are sampling // Declare an array for samples & allocate memory for the samples // from 4 sensors; each sample is 4 bytes. ulong ad24_data[NUM_SAMPLES/NUM_CHANNELS][NUM_CHANNELS]; typedef struct // Config options for each channel { ulong ad_zero_cal; // 24-bit zero sacle cal val ulong ad_fs_cal; // 24-bit full scale cal val int ad_freq_int; // Frequency Integer 19 - 4000. char ad_gain; // Gain 1 to 128. char ad_polarity; // Bipolar or Unipolar mode. char ad_res; // Resolution: 16-bit or 24-bit. char ad_bo; // Burn out current on/off char ad_fsync; // Sync on/off. char ad_ch; // Channel. } AD_CHANNEL; typedef struct // Global structure. { AD_CHANNEL ch0; AD_CHANNEL ch1; AD_CHANNEL ch2; AD_CHANNEL ch3; char current_channel; // Current channel being used. int index; // Index into data array } AD_INFO; AD_INFO ad24_struct; // Declare a global instance of the // structure. // Perform a Full Self Calibration on channel 0-1 for bipolar, unity // gain, 60 Hz operation and get calibration coefficients. // Initialize channel 0 of my_struct with calibration coefficients // and settings. int Init_CH0 ( void ) { int flag; flag = Start_Conversion( SELF_CAL, SAMPLE_FREQ, GAIN_1, BIPOLAR, WORD_24BIT, BO_OFF, CH_0_1 ); if( flag == -1 ) { ad24_struct.ch0.ad_freq_int = SAMPLE_FREQ; ad24_struct.ch0.ad_gain = GAIN_1; ad24_struct.ch0.ad_polarity = BIPOLAR; ad24_struct.ch0.ad_res = WORD_24BIT; ad24_struct.ch0.ad_bo = BO_OFF; ad24_struct.ch0.ad_fsync = FSYNC_OFF; ad24_struct.ch0.ad_ch = CH_0_1; ad24_struct.ch0.ad_zero_cal = Read_Zero_Cal(); ad24_struct.ch0.ad_fs_cal = Read_FS_Cal(); } return(flag); } // Perform a Full Self Calibration on channel 2-3 for bipolar, unity // gain, 60 Hz operation and get calibration coefficients. // Initialize channel 1 of my_struct with calibration coefficients // and settings. int Init_CH1 ( void ) { int flag; flag = Start_Conversion( SELF_CAL, SAMPLE_FREQ, GAIN_1, BIPOLAR, WORD_24BIT, BO_OFF, CH_2_3 ); if( flag == -1 ) { ad24_struct.ch1.ad_freq_int = SAMPLE_FREQ; ad24_struct.ch1.ad_gain = GAIN_1; ad24_struct.ch1.ad_polarity = BIPOLAR; ad24_struct.ch1.ad_res = WORD_24BIT; ad24_struct.ch1.ad_bo = BO_OFF; ad24_struct.ch1.ad_fsync = FSYNC_OFF; ad24_struct.ch1.ad_ch = CH_2_3; ad24_struct.ch1.ad_zero_cal = Read_Zero_Cal(); ad24_struct.ch1.ad_fs_cal = Read_FS_Cal(); } return(flag); } // Perform a Full Self Calibration on channel 4-5 for bipolar, unity // gain, 60 Hz operation and get calibration coefficients. // Initialize channel 2 of my_struct with calibration coefficients // and settings. int Init_CH2 ( void ) { int flag; flag = Start_Conversion( SELF_CAL, SAMPLE_FREQ, GAIN_1, BIPOLAR, WORD_24BIT, BO_OFF, CH_4_5 ); if( flag == -1 ) { ad24_struct.ch2.ad_freq_int = SAMPLE_FREQ; ad24_struct.ch2.ad_gain = GAIN_1; ad24_struct.ch2.ad_polarity = BIPOLAR; ad24_struct.ch2.ad_res = WORD_24BIT; ad24_struct.ch2.ad_bo = BO_OFF; ad24_struct.ch2.ad_fsync = FSYNC_OFF; ad24_struct.ch2.ad_ch = CH_4_5; ad24_struct.ch2.ad_zero_cal = Read_Zero_Cal(); ad24_struct.ch2.ad_fs_cal = Read_FS_Cal(); } return(flag); } // Perform a Full Self Calibration on channel 6-7 for bipolar, unity // gain, 60 Hz operation and get calibration coefficients. // Initialize channel 3 of my_struct with calibration coefficients // and settings. int Init_CH3 ( void ) { int flag; flag = Start_Conversion( SELF_CAL, SAMPLE_FREQ, GAIN_1, BIPOLAR, WORD_24BIT, BO_OFF, CH_6_7 ); if( flag == -1 ) { ad24_struct.ch3.ad_freq_int = SAMPLE_FREQ; ad24_struct.ch3.ad_gain = GAIN_1; ad24_struct.ch3.ad_polarity = BIPOLAR; ad24_struct.ch3.ad_res = WORD_24BIT; ad24_struct.ch3.ad_bo = BO_OFF; ad24_struct.ch3.ad_fsync = FSYNC_OFF; ad24_struct.ch3.ad_ch = CH_6_7; ad24_struct.ch3.ad_zero_cal = Read_Zero_Cal(); ad24_struct.ch3.ad_fs_cal = Read_FS_Cal(); } return(flag); } // This routine loads the 24-Bit A/D with the next set of // calibration coefficients without performing a calibration. void Load_Coefficients( int current_ch ) { switch( current_ch ) { case CH0: Start_Conv_With_Values( ad24_struct.ch0.ad_fs_cal, ad24_struct.ch0.ad_zero_cal, ad24_struct.ch0.ad_freq_int, ad24_struct.ch0.ad_gain, ad24_struct.ch0.ad_polarity, ad24_struct.ch0.ad_res, ad24_struct.ch0.ad_bo, ad24_struct.ch0.ad_fsync, ad24_struct.ch0.ad_ch ); break; case CH1: Start_Conv_With_Values( ad24_struct.ch1.ad_fs_cal, ad24_struct.ch1.ad_zero_cal, ad24_struct.ch1.ad_freq_int, ad24_struct.ch1.ad_gain, ad24_struct.ch1.ad_polarity, ad24_struct.ch1.ad_res, ad24_struct.ch1.ad_bo, ad24_struct.ch1.ad_fsync, ad24_struct.ch1.ad_ch ); break; case CH2: Start_Conv_With_Values( ad24_struct.ch2.ad_fs_cal, ad24_struct.ch2.ad_zero_cal, ad24_struct.ch2.ad_freq_int, ad24_struct.ch2.ad_gain, ad24_struct.ch2.ad_polarity, ad24_struct.ch2.ad_res, ad24_struct.ch2.ad_bo, ad24_struct.ch2.ad_fsync, ad24_struct.ch2.ad_ch ); break; case CH3: Start_Conv_With_Values( ad24_struct.ch3.ad_fs_cal, ad24_struct.ch3.ad_zero_cal, ad24_struct.ch3.ad_freq_int, ad24_struct.ch3.ad_gain, ad24_struct.ch3.ad_polarity, ad24_struct.ch3.ad_res, ad24_struct.ch3.ad_bo, ad24_struct.ch3.ad_fsync, ad24_struct.ch3.ad_ch ); break; } } // This routine takes one sample, stores it to an array, then starts // a conversion for the next channel. void Get_Sample ( void ) { // Get sample from the 24-Bit A/D, store to array ad24_data[ad24_struct.index][ad24_struct.current_channel]=AD24_Sample_NP(); // Increment channel number, did we sample all the channels yet? if( ad24_struct.current_channel++ >= NUM_CHANNELS - 1 ) { // Init channel number to 0, we finished sampling all channels. ad24_struct.current_channel = 0; // Set varible to store next group of data ad24_struct.index++; } // Load coefficients for the next channel Load_Coefficients ( ad24_struct.current_channel ); } // This routine repeatedly calls Get_Sample() every timeslice_ticks // * 5ms. Be sure other tasks do not take longer than // timeslice_ticks * 5ms. void Execute_So_Often ( uint num_times, ulong timeslice_ticks ) { ulong sample_time; int i; for( i = 0; i < num_times; i++ ) { sample_time = FetchTSCount(); Get_Sample(); do { Pause(); } while ( FetchTSCount() - sample_time < timeslice_ticks ); } } // This routine takes 10 samples from 4 sensors at 60 Hz. All of // the settings for each channel are stored in a global structure. // All channels must have the same sampling rate! int Sample_Routine3 ( void ) { int flag; flag = Init_AD24( DA247_MODULE_NUM );// 24/7 Data Acquisition Wildcard is // the first Wildcard on the stack Use_Onboard_Ref(); // Use on-board reference ad24_struct.current_channel = CH0;// Set ch0 as current channel ad24_struct.index = 0; // Init array index number // Init structure; Be sure to call Init_CH0 last since it is the // first channel sampled. Init_CH3(); Init_CH2(); Init_CH1(); Init_CH0(); // Get 1 sample every 60 ms. 60 ms is the fastest we can call // Get_Sample() because the sample rate is 60Hz and the 24-Bit A/D // takes 3 clock cycles to obtain a sample when using // Start_Conv_With_Values(). This alone is 3/60 or 50 ms. If a // full Self-Calibration was performed before each conversion, the // fastest rate you could sample one channel would be 10/60 or 167 // ms. This would amount to 666 ms for 4 channels or 1.5 Hz per // channel. Execute_So_Often( NUM_SAMPLES, (ulong)12 ); // 12*5ms = 60ms return(flag); } _Q void print_routine( void ) { int i,j; long val; printf("\n\n channel value\n----------------------\n"); for( i = 0; i < NUM_CHANNELS; i++ ) { for( j = 0; j < NUM_SAMPLES/NUM_CHANNELS; j++ ) { printf(" %d %lx\n", i, ad24_data[j][i]); } } } int main( void ) { Sample_Routine3(); print_routine(); return 0; }
See also →
24/7 Data Acquisition Wildcard Users Guide
24/7 Data Acquisition Wildcard Glossary
DA 24/7 C Demo 1
DA 24/7 C Demo 2
DA 24/7 Forth Demo 1
DA 24/7 Forth Demo 2
DA 24/7 Forth Demo 3