/* Rev. 24-Dec-2020 This version is to read the HP 3490A DVM in a loop and write the Measurement data to the screen and to a file. Each "measurement" that is displayed on the screen and written to the output file consists of: - the average DC value from N DVM Samples - the AC RMS Noise based on N DVM Samples - the time - the number of errors detected in making this measurement - the Measurement Number starting from 1 The information that is sent to the screen includes details about each Sample that is read from the DVM. Typically many Samples (perhaps 10 to 100) are averaged to make a Measurement. The Output File contains a Header, all of the Measurement Data, and a Trailer. The Serial Number of the ft245r in HP-3490A 1637 is: FTC8MGZF typically used for Current The Serial Number of the ft245r in HP-3490A 1529 is: FTC8MH7K typically used for Voltage Recall that the FTD library is in: /usr/local/lib/libftd2xx.a and we need the header files: ftd2xx.h and WinTypes.h */ #include #include #include #include #include #include #include "ftd2xx.h" #define MAXLINE 80 int main() { /* Declare the variables and structures in this program. */ char ft_dev_SN[20]; // ft245r device USB serial number unsigned char ReadBuffer[256]; DWORD dwRxSize = 0; DWORD dwBytesPerFrame = 8; DWORD dwBytesRead; FT_STATUS ftStatus; FT_HANDLE ftHandle; int queueChecks = 0; int check_for_error = 0; int usb_reset_counts = 0; int dvm_data_frame_errors = 0; int dvm_read_attempts = 0; int wait_between_measurements = 100; // finish one until start next in seconds long int timeout = 5; // timeout in seconds struct timeval run_start_time; // start of this data collection run struct timeval start_time; // start of the Queue Check Timeout struct timeval now_time; struct timeval elapsed_time; int Loops_to_Make = 1; // Number of Measurements to record. int Loop_Index = 1; // Index Number of the Measurement being made now int Sample_Index = 1; // Index of DVM Samples per Measurement int Number_of_Samples_Collected = 0; int Number_of_Samples_per_Measurement = 10; // i.e. DVM Samples per Measurement int Temp_Index = 1; // Temporary Loop Index double This_DVM_Reading = 0.0; double DVM_Reads[50005]; // Maximum number of Samples per Measurement. int SN_of_DVM; // Serial Number of the DVM 1529 or 1637. char output_filename[MAXLINE]; FILE *fpout; // Pointer to the Output File time_t current_time; // arithmetic time type - time since the epoch char* c_time_string; double This_DC_Measurement = 0.0; // The DC value of the current Measurement double This_RMS_Measurement = 0.0; // The RMS value of the current Measurement double *pt_This_DC_Measurement; // Pointer to This_DC_Measurement double *pt_This_RMS_Measurement; // Pointer to This_RMS_Measurement double DC_Measurements_Array[1005]; // The array that holds the DC Measurements double RMS_Measurements_Array[1005]; // The array that holds the RMS Measurements double total_sum = 0.0; // Temporary working double float location double avg_of_sum = 0.0; // Temporary working double float location /* Declare the functions that are called by this program. */ int dumpBuffer(unsigned char *buffer, int elements); double Volts_from_Buffer(unsigned char *buffer); int Check_DVM_Frame(unsigned char *buffer); int min_max_locate(double *DVM_Reads, int Number_of_Samples_per_Measurement); int calc_DC_and_RMSs(double *DVM_Reads, int Number_of_Samples_per_Measurement, double *pt_This_DC_Measurement, double *pt_This_RMS_Measurement); /*==================================================================*/ /* */ /* First do all of the things that we will do only once before */ /* starting the loop over the number of Measurements to be taken. */ /* */ /*==================================================================*/ /* Set the value of the Pointers to the variables that */ /* will hold the Current DC and RMS Measurements */ pt_This_DC_Measurement = &This_DC_Measurement; pt_This_RMS_Measurement = &This_RMS_Measurement; /* Ask the operator Which DVM is this run is going to read */ printf("\n\n"); printf(" Enter the Serial Number of the DVM (1529 or \n"); printf(" 1637) that this run of the program will record: "); scanf( "%d", &SN_of_DVM ); printf("\n"); if (SN_of_DVM == 1529) { ft_dev_SN[0] = 'F'; ft_dev_SN[1] = 'T'; ft_dev_SN[2] = 'C'; ft_dev_SN[3] = '8'; ft_dev_SN[4] = 'M'; ft_dev_SN[5] = 'H'; ft_dev_SN[6] = '7'; ft_dev_SN[7] = 'K'; ft_dev_SN[8] = '\0'; } else if (SN_of_DVM == 1637) { ft_dev_SN[0] = 'F'; ft_dev_SN[1] = 'T'; ft_dev_SN[2] = 'C'; ft_dev_SN[3] = '8'; ft_dev_SN[4] = 'M'; ft_dev_SN[5] = 'G'; ft_dev_SN[6] = 'Z'; ft_dev_SN[7] = 'F'; ft_dev_SN[8] = '\0'; } else { printf("\n This is an unknown DVM Serial Number - Exiting \n"); exit(2); } /* Ask the operator how many Measurements to make and record. */ printf(" Enter the number Measurements \n"); printf(" to make and record in the output file: "); scanf( "%d", &Loops_to_Make ); printf("\n"); /* Ask the operator how many DVM Samples to average per Measurement. */ printf(" Enter the number of DVM Samples \n"); printf(" to average per recorded Measurement. \n"); printf(" 50k is max. Typically 1 Sample per second: "); scanf( "%d", &Number_of_Samples_per_Measurement ); printf("\n"); /* Ask the operator how long to wait between Measurements */ printf(" Enter the number of seconds to wait between \n"); printf(" finishing one Measurement and starting the next: "); scanf( "%d", &wait_between_measurements ); printf("\n"); /* Ask the operator the filename for the Measurement output file */ printf(" Enter the filename for the \n"); printf(" Measurement output text file: "); scanf( "%s", output_filename ); printf("\n"); if ((fpout = fopen(output_filename, "w")) == NULL) { printf("\nERROR: Can't open output file %s\n", output_filename); exit (2); } /* Zero the arrays that holds the DC & RMS Measurements. */ Temp_Index = 0; while (Temp_Index <= 1003) { DC_Measurements_Array[Temp_Index] = 0.0; RMS_Measurements_Array[Temp_Index] = 0.0; ++Temp_Index; } Temp_Index = 0; printf("\n The DC & RMS Measurement Arrays have been zeroed. \n\n"); /* Obtain current time - for screen display and the output file header */ /* The time(NULL) function returns current system time as a time_t value */ current_time = time(NULL); if (current_time == ((time_t)-1)) { (void) fprintf(stderr, "Failure to obtain the current time.\n"); exit(EXIT_FAILURE); } /* Convert to local time format as a character string. */ /* The c_time() function converts a time_t value to a textual representation */ c_time_string = ctime(¤t_time); if (c_time_string == NULL) { (void) fprintf(stderr, "Failure to convert the current time.\n"); exit(EXIT_FAILURE); } /* Print to stdout. ctime() has already added a terminating newline */ /* character and put this time-stamp in the output file. */ printf("\n\n Current time is %s", c_time_string); /* Write a Header into the Output File so that we */ /* know the Conditions under which this Run was taken. */ fprintf(fpout, "\n\n Current time is %s", c_time_string); fprintf(fpout, "\n This is a run of %d Measurements", Loops_to_Make ); fprintf(fpout, "\n Number of Samples per Measurement is %d", Number_of_Samples_per_Measurement ); fprintf(fpout, "\n The number of seconds between Measurements is %d \n\n", wait_between_measurements ); /*================================================================================*/ /* */ /* Now start the loop over the number of Measurements to be made and recorded */ /* */ /*================================================================================*/ Loop_Index = 1; while ( Loop_Index <= Loops_to_Make ) { /* Zero the array that holds the DVM Samples. */ Sample_Index = 0; while (Sample_Index <= 50000) { DVM_Reads[Sample_Index] = 0.0; ++Sample_Index; } Sample_Index = 1; printf("\n The DVM Sample Storage Array has been zeroed. \n\n"); /* Advertize the USB Serial Number of the DVM's ft245r interface. */ printf("\n The USB Serial Number of the DVM's FT245R is - %s\n", ft_dev_SN); /* Open the ft245r device with the serial number = ft_dev_SN. */ /* Note that we will Open the ft245r interface at the */ /* beginning of each Measurement and then Close it after all */ /* of the DVM Samples have been collected for that Measurement. */ if((ftStatus = FT_OpenEx(ft_dev_SN, FT_OPEN_BY_SERIAL_NUMBER, &ftHandle)) != FT_OK){ /* This can fail if the ftdi_sio driver is loaded use lsmod to check this and rmmod ftdi_sio to remove also rmmod usbserial */ printf("Error FT_OpenEx(%d)\n", (int)ftStatus); printf("Use lsmod to check if ftdi_sio (and usbserial) are present.\n"); printf("Unload them using rmmod ftdi_sio as they conflict with ftd2xx.\n"); return 1; } printf(" Opened USB Device - %s\n\n", ft_dev_SN); /* Get the time at the start of this DVM data collection run. */ gettimeofday(&run_start_time, NULL); /* Start the loop that collects the Required Number of DVM Samples */ while (Sample_Index <= Number_of_Samples_per_Measurement) { printf("\n\n Starting Read Sample Number = %d\n\n", Sample_Index); /* Check the ft245 Queue Status and wait for 8 bytes */ /* of read data. Give up if this takes too long. */ Restart_Queue_Check: dwRxSize = 0; gettimeofday(&start_time, NULL); for (queueChecks = 1; dwRxSize < dwBytesPerFrame; queueChecks++) { /* Delay for 100 msec before the First check of the */ /* Queue Status and between checks of Queue Status. */ usleep(100000); ftStatus = FT_GetQueueStatus(ftHandle, &dwRxSize); if (ftStatus != FT_OK) { printf("\nFT_GetQueueStatus failed (%d).\n", (int)ftStatus); return 1; } /* Check for time-out in getting data as shown by Queue Status. */ gettimeofday(&now_time, NULL); timersub(&now_time, &start_time, &elapsed_time); if (elapsed_time.tv_sec > timeout) { /* We've waited too long. Give up. */ printf("\n\07 Queue check timed out after %ld seconds\n", elapsed_time.tv_sec); printf(" queue check count = %d \n\n", queueChecks); printf(" Bytes in Read FIFO reported by Queue Check = %d \n\n", dwRxSize); printf(" Try Close - Open the ft245r and then checking the Queue again.\n\n"); FT_Close(ftHandle); sleep(1); ftStatus = FT_OpenEx(ft_dev_SN, FT_OPEN_BY_SERIAL_NUMBER, &ftHandle); if (ftStatus != FT_OK) { printf("\n Queue error recovery by FT_Open failed - exiting now.\n\n"); return 1; } printf(" FT Close-Open has been done - Restart the Check Queue loop.\n\n"); ++usb_reset_counts; // Increment the counter of USB Resets. goto Restart_Queue_Check; } } printf(" queue check count = %d \n\n", queueChecks); /* If we get here then the above Queue Status test has */ /* derermined that there are 8 bytes in the Read Queue. */ if(ftStatus == FT_OK) { ftStatus = FT_Read(ftHandle, ReadBuffer, dwRxSize, &dwBytesRead); if (ftStatus != FT_OK) { printf("Error FT_Read(%d)\n", (int)ftStatus); return 1; } if (dwBytesRead != dwRxSize) { printf("FT_Read only read %d (of %d) bytes\n", (int)dwBytesRead, (int)dwRxSize); return 1; } ++dvm_read_attempts; printf(" FT_Read read %d bytes. Read-buffer currently holds:\n\n", (int)dwBytesRead); dumpBuffer(ReadBuffer, (int)dwBytesRead); check_for_error = Check_DVM_Frame(ReadBuffer); if (check_for_error != 0) { ++dvm_data_frame_errors; } This_DVM_Reading = Volts_from_Buffer(ReadBuffer); if (check_for_error == 0) { DVM_Reads[Sample_Index] = This_DVM_Reading; ++Sample_Index; } } } /*==============================================================*/ /* */ /* The required number of DVM Samples have been collected. */ /* Now call the Analysis Functions */ /* */ /* Note that I'm passing to the analysis routines the */ /* actual number of Samples that were collected (not the */ /* desired number that we would like to collect). */ /* */ /* Before calling the analysis routines first report */ /* how long this run actually took in seconds and how */ /* many DVM Samples were actually collected */ /* */ /* Once we have received the DC and RMS values for this */ /* Measurement from the analysis routines: write them */ /* to the Output File and store them in the arrays that */ /* hold all of the DC and RMS Measurements from this run. */ /* */ /*==============================================================*/ gettimeofday(&now_time, NULL); timersub(&now_time, &run_start_time, &elapsed_time); printf("\n This DVM data collection run took %ld seconds\n", elapsed_time.tv_sec); Number_of_Samples_Collected = --Sample_Index; printf(" Number of DVM Samples actually collected = %d \n", Number_of_Samples_Collected); printf(" Number of DVM read attempts = %d \n", dvm_read_attempts ); printf(" Number of DVM Data Frame Errors = %d \n", dvm_data_frame_errors ); printf(" Number of USB Resets = %d \n", usb_reset_counts ); /* Now call the Analysis Routines */ min_max_locate(DVM_Reads, Number_of_Samples_Collected); calc_DC_and_RMSs(DVM_Reads, Number_of_Samples_Collected, pt_This_DC_Measurement, pt_This_RMS_Measurement); /* Now write to the Output File: This Measurement's Loop Index, */ /* This Measurement's DC Value, */ /* and This Measurement's AC RMS Value */ fprintf(fpout, "\n Measurement Loop = %4d", Loop_Index ); fprintf(fpout, " Average DC Value = %8.5f AC RMS = %8.5f", This_DC_Measurement, This_RMS_Measurement ); /* Store the values for the current Measurement in the arrays */ /* that hold all of the DC and RMS Measurements for this run. */ DC_Measurements_Array[Loop_Index] = This_DC_Measurement; RMS_Measurements_Array[Loop_Index] = This_RMS_Measurement; printf(" This completes Measurement Loop Number = %d \n", Loop_Index ); /*==============================================================*/ /* */ /* We have finished a Measurement, Close the ft245r USB */ /* connection. If this is NOT the last Measurement then */ /* Wait for the time between Measurements, and then */ /* Increment the Loop_Index and go back to the top of the */ /* loop over all Measurements. */ /* */ /*==============================================================*/ FT_Close(ftHandle); printf(" Closed USB Device - %s\n\n", ft_dev_SN); if (Loop_Index < Loops_to_Make) { sleep(wait_between_measurements); } ++Loop_Index; /* and back up to the Measurement */ /* Loops_to_Make While statement. */ } /*==============================================================*/ /* */ /* We reach here after ALL of the Measurements have been */ /* made and recorded. */ /* */ /* Calculate the Average of All of the DC Measurements and */ /* the Average of All of the RMS Measurements in this run */ /* and print these values on the screen and write them into */ /* the Output File. then */ /* */ /* Write a Trailer to the Output File and then */ /* cleanup before exiting. */ /* */ /*==============================================================*/ /* Calculate the Average of ALL of the DC and RMS Measurements */ printf(" \n\n All Measurements have now been made and recorded. \n"); fprintf(fpout," \n\n All Measurements have now been made and recorded. \n"); Temp_Index = 1; total_sum = 0.0; while (Temp_Index <= Loops_to_Make) { total_sum = total_sum + DC_Measurements_Array[Temp_Index]; ++Temp_Index; } avg_of_sum = total_sum / Loops_to_Make; printf("\n The average of All the DC Measurements = %8.5f", avg_of_sum); fprintf(fpout, "\n The average of All the DC Measurements = %8.5f", avg_of_sum); Temp_Index = 1; total_sum = 0.0; while (Temp_Index <= Loops_to_Make) { total_sum = total_sum + RMS_Measurements_Array[Temp_Index]; ++Temp_Index; } avg_of_sum = total_sum / Loops_to_Make; printf("\n The average of All the RMS Measurements = %8.5f", avg_of_sum); fprintf(fpout, "\n The average of All the RMS Measurements = %8.5f", avg_of_sum); /* Write the Trailer to the Output File */ fprintf(fpout," \n\n Trailer written at the end of the Output File. \n"); fprintf(fpout," Number of DVM Samples collected for the final Measurement = %d \n", Number_of_Samples_Collected); fprintf(fpout," Total Number of DVM Read attempts for all Measurements = %d \n", dvm_read_attempts ); fprintf(fpout," Total Number of DVM Data Frame Errors for all Measurements = %d \n", dvm_data_frame_errors ); fprintf(fpout," Total Number of USB Resets for all Measurements = %d \n", usb_reset_counts ); /* Obtain Current Time and add a Final Time-Stamp */ /* at the End of the Output File and on the Screen */ current_time = time(NULL); if (current_time == ((time_t)-1)) { (void) fprintf(stderr, "Failure to obtain the current time.\n"); exit(EXIT_FAILURE); } c_time_string = ctime(¤t_time); if (c_time_string == NULL) { (void) fprintf(stderr, "Failure to convert the current time.\n"); exit(EXIT_FAILURE); } fprintf(fpout, "\n\n Current time is %s \n\n", c_time_string); printf("\n\n Current time is %s", c_time_string); /* The Output File Trailer is complete - Close the Output File */ fclose(fpout); printf(" Closed the Output File - %s \n\n", output_filename); return 0; /* This ends the main function */ } /* */ /* Functions used to check the DVM data as each sample is acquired */ /* */ /* Rev. 17-Dec-2020 */ /* */ /* */ /* First the function to print out in hex the buffer contents */ /* */ int dumpBuffer(unsigned char *buffer, int elements) { int j; printf(" ["); for (j = 0; j < elements; j++) { if (j > 0) printf(", "); printf("0x%02X", buffer[j]); } printf("]\n\n"); return 0; /* This ends the dumpBuffer function */ } /* */ /* Function to extract from the DVM Data Frame */ /* a floating point version of the Voltage */ /* read by the DVM and to print the Voltage. */ /* */ /* The routine returns the floating point */ /* Voltage read by the DVM. */ /* */ double Volts_from_Buffer(unsigned char *buffer) { double f_work_1 = 0.0, f_work_2 = 0.0; f_work_1 = 10.0 * ( 0x0f & buffer[4] ); f_work_2 = 10.0 * (( 0x0f & buffer[3] ) + f_work_1 ); f_work_1 = 10.0 * (( 0x0f & buffer[2] ) + f_work_2 ); f_work_2 = 10.0 * (( 0x0f & buffer[1] ) + f_work_1 ); f_work_1 = (( 0x0f & buffer[0] ) + f_work_2 ); f_work_2 = f_work_1 / 10000.0 ; if ((0x01 & buffer[5]) == 0x01){ f_work_1 = 10.0 + f_work_2; } else{ f_work_1 = f_work_2; } if ((0x04 & buffer[5]) == 0x04){ f_work_2 = -1.0 * f_work_1; } else{ f_work_2 = f_work_1; } printf("\n "); printf("Volts floating = %7.4f", f_work_2); printf(" \n\n"); return f_work_2; /* This ends the Volts_from_Buffer function */ } /* Function to verify that the current 8 byte DVM readout data frame is error free. This function returns a zero if there are no errors and it returns a one if any DVM Data Frame error is found. The tests made are: - All 8 bytes have 0x1 in the high order nibble, i.e. the Data Flag is set Hi in all 8 bytes. - The first 5 bytes contain only BCD data, i.e. they are <= 0x9 in the low order nibble. - The low order nibble of the 6th byte must be either: 0x0 --> Polarity = Low (positive), Over Range = Low 0x1 --> Polarity = Low (positive), Over Range = Hi 0x4 --> Polarity = Hi (negative), Over Range = Low 0x5 --> Polarity = Hi (negative), Over Range = Hi In all cases Bit D (Over Load) must be Low and Bit B (Gnd) must be Low. - The low order nibble of the 7th byte must be 0xC, i.e. Not S/H Mode, 10 Volt Range, Range Bit C = Hi, Range Bits B and A = Low. - The low order nibble of the 8th byte must be 0xC, i.e. Not Remote Mode, Not Ratio Mode, DC Volts Function Bits B and A = Low. */ int Check_DVM_Frame(unsigned char *buffer) { int error_flag = 0; /* Verify that the Data Flag is Hi in all 8 bytes of the frame. */ if (((0x10 & buffer[0]) == 0x10) && ((0x10 & buffer[1]) == 0x10) && ((0x10 & buffer[2]) == 0x10) && ((0x10 & buffer[3]) == 0x10) && ((0x10 & buffer[4]) == 0x10) && ((0x10 & buffer[5]) == 0x10) && ((0x10 & buffer[6]) == 0x10) && ((0x10 & buffer[7]) == 0x10)){ printf(" All 8 Data Flags are Hi. \n"); } else{ printf(" At least one Data Flag is Low. \n\n"); error_flag = 1; } /* Verify that the first 5 bytes contain only BCD data. */ if (((0x0f & buffer[0]) <= 0x09) && ((0x0f & buffer[1]) <= 0x09) && ((0x0f & buffer[2]) <= 0x09) && ((0x0f & buffer[3]) <= 0x09) && ((0x0f & buffer[4]) <= 0x09)){ printf(" The first 5 bytes are all BCD. \n"); } else{ printf("\n At least one of the first 5 bytes is Not BCD. \n\n"); error_flag = 1; } /* Verify that the low order nibble of the 6th byte is either: 0x0, 0x1, 0x4, or 0x5 i.e. in all cases bits D and B must be Low. */ if (((0x08 & buffer[5]) == 0x00) && ((0x02 & buffer[5]) <= 0x00)){ printf(" The 6th byte is one of the 4 legal values. \n"); } else{ printf("\n The 6th byte is NOT one of the 4 legal values. \n\n"); error_flag = 1; } /* Verify that the low order nibble of the 7th byte is 0xC, i.e. the correct DVM Scale Range and Not S/H Mode. */ if ((0x0f & buffer[6]) == 0x0c){ printf(" The 7th byte is the correct value. \n"); } else{ printf("\n The 7th byte is NOT the correct value. \n\n"); error_flag = 1; } /* Verify that the low order nibble of the 8th byte is 0xC, i.e. the correct DC Volts Function and NOT Ratio or Remote. */ if ((0x0f & buffer[7]) == 0x0c){ printf(" The 8th byte is the correct value. \n"); } else{ printf("\n The 8th byte is NOT the correct value. \n\n"); error_flag = 1; } if (error_flag != 0) { printf("\07"); } return error_flag; /* This ends the Check_DVM_Frame function */ } /* */ /* This starts the Analysis part of the DVM code. */ /* */ /* Rev. Date 23-Dec-2020 */ /* */ /* */ /* The First Analysis section finds the minimum and maximum */ /* samples in the data set that was just collected. */ /* */ /* The minimum and maximum sample values and their */ /* sample index numbers are displayed. */ /* */ /* Recall that the samples are stored in an array called */ /* DVM_Reads[]. This is a "double" floating point array. */ /* */ /* In C this array starts at index = 0 but in this */ /* application the first DVM Reading is stored at index = 1. */ /* Thus if you have told this program to collect 10 readings */ /* they will be stored in the DVM_Reads[] 1 through 10. */ /* */ /* The number of samples in the DVM_Reads[] array is */ /* passed in the variable Sample_Index. */ /* */ int min_max_locate(double *DVM_Reads, int Number_of_Samples) { int min_sample_index = 1; double min_sample_value = 0.0; int max_sample_index = 1; double max_sample_value = 0.0; double min_spread_for_histogram = 0.10; /* Set the minimum min-to-max spread */ /* required for generating a histogram */ double min_to_max_spread = 0.0; double histo_increment = 0.0; double histo_cut_1 = 0.0; double histo_cut_2 = 0.0; double histo_cut_3 = 0.0; double histo_cut_4 = 0.0; double histo_cut_5 = 0.0; double histo_cut_6 = 0.0; double histo_cut_7 = 0.0; int count_bin_1 = 0; int count_bin_2 = 0; int count_bin_3 = 0; int count_bin_4 = 0; int count_bin_5 = 0; int count_bin_6 = 0; int count_bin_7 = 0; int count_bin_8 = 0; int Sample_Index = 1; min_sample_index = 1; min_sample_value = DVM_Reads[1]; max_sample_index = 1; max_sample_value = DVM_Reads[1]; while (Sample_Index <= Number_of_Samples) { if (DVM_Reads[Sample_Index] < min_sample_value) { min_sample_value = DVM_Reads[Sample_Index]; min_sample_index = Sample_Index; } if (DVM_Reads[Sample_Index] > max_sample_value) { max_sample_value = DVM_Reads[Sample_Index]; max_sample_index = Sample_Index; } ++Sample_Index; } printf("\n Minimum Sample Value = %7.4f", min_sample_value); printf("\n A Sample Index with the Minimum Sample Value = %d", min_sample_index); printf("\n\n Maximum Sample Value = %7.4f", max_sample_value); printf("\n A Sample Index with the Maximum Sample Value = %d", max_sample_index); printf("\n"); /* If the Min-Max Spread is big enough then Calculate an 8 bin historgram. */ /* */ /* The 8 bins in this histogram are equally spaced to cover the min-max spread. */ /* */ /* Except for the highest bin, incrementing the counter for a given bin */ /* requires that: low cut <= DVM_Reading < high_cut. */ /* */ /* For the highest bin, incrementing its counter */ /* requires that: low cut <= DVM_Reading <= high_cut. */ /* */ /* In this way the sum of the counts in the 8 histogram bins should */ /* always equal the total number of DVM_Readings that were collected. */ /* */ min_to_max_spread = max_sample_value - min_sample_value; if (min_to_max_spread > min_spread_for_histogram) { histo_increment = min_to_max_spread / 8.0; histo_cut_1 = min_sample_value + histo_increment; histo_cut_2 = histo_cut_1 + histo_increment; histo_cut_3 = histo_cut_2 + histo_increment; histo_cut_4 = histo_cut_3 + histo_increment; histo_cut_5 = histo_cut_4 + histo_increment; histo_cut_6 = histo_cut_5 + histo_increment; histo_cut_7 = histo_cut_6 + histo_increment; Sample_Index = 1; while (Sample_Index <= Number_of_Samples) { if ((min_sample_value <= DVM_Reads[Sample_Index]) && (DVM_Reads[Sample_Index] < histo_cut_1)) { ++ count_bin_1; } if ((histo_cut_1 <= DVM_Reads[Sample_Index]) && (DVM_Reads[Sample_Index] < histo_cut_2)) { ++ count_bin_2; } if ((histo_cut_2 <= DVM_Reads[Sample_Index]) && (DVM_Reads[Sample_Index] < histo_cut_3)) { ++ count_bin_3; } if ((histo_cut_3 <= DVM_Reads[Sample_Index]) && (DVM_Reads[Sample_Index] < histo_cut_4)) { ++ count_bin_4; } if ((histo_cut_4 <= DVM_Reads[Sample_Index]) && (DVM_Reads[Sample_Index] < histo_cut_5)) { ++ count_bin_5; } if ((histo_cut_5 <= DVM_Reads[Sample_Index]) && (DVM_Reads[Sample_Index] < histo_cut_6)) { ++ count_bin_6; } if ((histo_cut_6 <= DVM_Reads[Sample_Index]) && (DVM_Reads[Sample_Index] < histo_cut_7)) { ++ count_bin_7; } if ((histo_cut_7 <= DVM_Reads[Sample_Index]) && (DVM_Reads[Sample_Index] <= max_sample_value)) { ++ count_bin_8; } ++Sample_Index; } printf("\n Histo Bin from %7.4f to %7.4f has %4d counts", min_sample_value, histo_cut_1, count_bin_1); printf("\n Histo Bin from %7.4f to %7.4f has %4d counts", histo_cut_1, histo_cut_2, count_bin_2); printf("\n Histo Bin from %7.4f to %7.4f has %4d counts", histo_cut_2, histo_cut_3, count_bin_3); printf("\n Histo Bin from %7.4f to %7.4f has %4d counts", histo_cut_3, histo_cut_4, count_bin_4); printf("\n Histo Bin from %7.4f to %7.4f has %4d counts", histo_cut_4, histo_cut_5, count_bin_5); printf("\n Histo Bin from %7.4f to %7.4f has %4d counts", histo_cut_5, histo_cut_6, count_bin_6); printf("\n Histo Bin from %7.4f to %7.4f has %4d counts", histo_cut_6, histo_cut_7, count_bin_7); printf("\n Histo Bin from %7.4f to %7.4f has %4d counts", histo_cut_7, max_sample_value, count_bin_8); printf("\n"); } return 0; } /* */ /* The Second Analysis section finds the average or DC */ /* value, the DC RMS value, and the AC RMS value of all */ /* of the DVM samples that have been collected */ /* */ int calc_DC_and_RMSs(double *DVM_Reads, int Number_of_Samples, double *pt_This_DC_Measurement, double *pt_This_RMS_Measurement) { double total_sum = 0.0; double avg_of_sum = 0.0; double dc_rms = 0.0; double ac_rms = 0.0; double ac_content = 0.0; int Sample_Index = 1; /* Calculate the Average or DC value of the samples. */ while (Sample_Index <= Number_of_Samples) { total_sum = total_sum + DVM_Reads[Sample_Index]; ++Sample_Index; } avg_of_sum = total_sum / Number_of_Samples; printf("\n The average, aka DC, sample value = %8.5f", avg_of_sum); /* Calculate the DC RMS value of the samples. */ Sample_Index = 1; total_sum = 0.0; while (Sample_Index <= Number_of_Samples) { total_sum = total_sum + (DVM_Reads[Sample_Index] * DVM_Reads[Sample_Index]); ++Sample_Index; } dc_rms = sqrt(total_sum / Number_of_Samples); printf("\n\n The DC RMS of the samples = %8.5f", dc_rms); /* Calculate the AC RMS value of the samples. */ Sample_Index = 1; total_sum = 0.0; while (Sample_Index <= Number_of_Samples) { ac_content = DVM_Reads[Sample_Index] - avg_of_sum; total_sum = total_sum + (ac_content * ac_content); ++Sample_Index; } ac_rms = sqrt(total_sum / Number_of_Samples); printf("\n\n The AC RMS of the samples = %8.5f", ac_rms); printf("\n\n"); /* Now write the DC Value, and AC RMS Value */ /* to the variables that will carry these values */ /* back to the calling routine. */ *pt_This_DC_Measurement = avg_of_sum; *pt_This_RMS_Measurement = ac_rms; return 0; }