본문 바로가기
아날로그회로(Analog Circuit)/ADC관련

[ZSSC3241] C#에서 calibrationL6.dll 사용법 (Using C/C++ DLL in C#: Implementing 7-Point Calibration with calibrationL6.dll)

by linuxgo 2025. 8. 10.
반응형

C#에서 C 또는 C++로 작성된 DLL 파일을 호출하는 것은 센서 데이터 처리, 하드웨어 제어, 또는 기존 C/C++ 라이브러리를 활용해야 할 때 자주 필요한 작업입니다. (Calling a C or C++ DLL from C# is often necessary for sensor data processing, hardware control, or leveraging existing C/C++ libraries.) 이 글에서는 calibrationL64.dll을 사용하여 7포인트 캘리브레이션(7-point calibration)을 구현하는 방법을 상세히 설명합니다. (This article explains in detail how to implement 7-point calibration using calibrationL64.dll.) 제공된 헤더 파일(calibrationL64.h)과 C 예제 코드를 기반으로, C#에서 DLL 함수를 호출하고 데이터를 처리하는 전체 과정을 다룹니다. (Based on the provided header file calibrationL64.h and C example code, it covers the entire process of calling DLL functions and processing data in C#.)

1. 소개(Introduction)

C#은 강력한 .NET 생태계와 객체지향 프로그래밍을 제공하지만, 성능이 중요한 하드웨어 관련 작업에서는 C/C++로 작성된 DLL을 사용하는 경우가 많습니다. (C# provides a powerful .NET ecosystem and object-oriented programming, but C/C++ DLLs are often used for performance-critical hardware-related tasks.) calibrationL64.dll은 센서 데이터를 보정하기 위한 계수 계산 및 데이터 변환 기능을 제공하는 라이브러리로, C#에서 이를 호출하려면 P/Invoke(Platform Invocation Services)를 사용해야 합니다. (calibrationL64.dll is a library that provides coefficient calculation and data conversion functions for sensor data correction, requiring P/Invoke to call it from C#.)

이 글에서는 다음과 같은 내용을 다룬다. (This article covers the following):

  • calibrationL64.dll의 함수와 상수 정의 (Functions and constants of calibrationL64.dll)
  • C#에서 DLL 함수 호출 방법 (How to call DLL functions in C#)
  • C 예제 코드를 C#으로 변환하여 7포인트 캘리브레이션 구현 (Implementing 7-point calibration by converting C example code to C#)

2. 개요 (Overview)

calibrationL64.dll은 센서 데이터(압력 및 온도)를 보정하기 위한 계수를 계산하고, 원시 데이터를 보정된 값으로 변환하는 기능을 제공합니다. (calibrationL64.dll calculates coefficients for correcting sensor data (pressure and temperature) and converts raw data to corrected values.) 헤더 파일(calibrationL64.h)에서 정의된 주요 요소는 다음과 같습니다 (The key elements defined in the header file calibrationL64.h are as follows).  

보정 dll 파일은 RENESAS에 요청을 하여 제공 받아야 한다.
(The calibration DLL file must be requested and obtained from Renesas)

2.1. 주요 상수 (Key Constants)

  • 계수 배열 크기 (Coefficient array size): COEFFICIENT_COUNT = 10
  • 계수 인덱스 (Coefficient indices):
    public const int INDEX_OFFSET_S = 0;
    public const int INDEX_GAIN_S = 1;
    public const int INDEX_TCG = 2;
    public const int INDEX_TCO = 3;
    public const int INDEX_SOT_TCO = 4;
    public const int INDEX_SOT_TCG = 5;
    public const int INDEX_SOT_S = 6;
    public const int INDEX_OFFSET_T = 7;
    public const int INDEX_GAIN_T = 8;
    public const int INDEX_SOT_T = 9
  • 계수 선택 플래그 (Coefficient selection flags):
    public const int CO_OFFSET_S = 0x1;
    public const int CO_GAIN_S = 0x2;
    public const int CO_TCG = 0x4;
    public const int CO_TCO = 0x8;
    public const int CO_SOT_TCO = 0x10;
    public const int CO_SOT_TCG = 0x20;
    public const int CO_SOT_S = 0x40;
    public const int CO_OFFSET_T = 0x80;
    public const int CO_GAIN_T = 0x100;
    public const int CO_SOT_T = 0x200;
  • 계수 범위 제한 (Coefficient range limits):
    public const int OFFSET_S_MAX = 0x7FFFFF;    // Offset_S 최대값 (Maximum value for Offset_S)
    public const int OFFSET_S_MIN = -0x7FFFFF;   // Offset_S 최소값 (Minimum value for Offset_S)
    public const int GAIN_S_MAX = 0x7FFFFF;      // Gain_S 최대값 (Maximum value for Gain_S)
    public const int GAIN_S_MIN = -0x7FFFFF;     // Gain_S 최소값 (Minimum value for Gain_S)
    public const int TCG_MAX = 0x7FFFFF;         // TCG 최대값 (Maximum value for TCG)
    public const int TCG_MIN = -0x7FFFFF;        // TCG 최소값 (Minimum value for TCG)
    public const int TCO_MAX = 0x7FFFFF;         // TCO 최대값 (Maximum value for TCO)
    public const int TCO_MIN = -0x7FFFFF;        // TCO 최소값 (Minimum value for TCO)
    public const int SOT_TCO_MAX = 0x7FFFFF;     // SOT_TCO 최대값 (Maximum value for SOT_TCO)
    public const int SOT_TCO_MIN = -0x7FFFFF;    // SOT_TCO 최소값 (Minimum value for SOT_TCO)
    public const int SOT_TCG_MAX = 0x7FFFFF;     // SOT_TCG 최대값 (Maximum value for SOT_TCG)
    public const int SOT_TCG_MIN = -0x7FFFFF;    // SOT_TCG 최소값 (Minimum value for SOT_TCG)
    public const int SOT_S_MAX = 0x7FFFFF;       // SOT_S 최대값 (Maximum value for SOT_S)
    public const int SOT_S_MIN = -0x7FFFFF;      // SOT_S 최소값 (Minimum value for SOT_S)
    public const int OFFSET_T_MAX = 0x7FFFFF;    // Offset_T 최대값 (Maximum value for Offset_T)
    public const int OFFSET_T_MIN = -0x7FFFFF;   // Offset_T 최소값 (Minimum value for Offset_T)
    public const int GAIN_T_MAX = 0x7FFFFF;      // Gain_T 최대값 (Maximum value for Gain_T)
    public const int GAIN_T_MIN = -0x7FFFFF;     // Gain_T 최소값 (Minimum value for Gain_T)
    public const int SOT_T_MAX = 0x7FFFFF;       // SOT_T 최대값 (Maximum value for SOT_T)
    public const int SOT_T_MIN = -0x7FFFFF;      // SOT_T 최소값 (Minimum value for SOT_T)

2.2. 주요 함수 (Key Functions)

  • CalculateCoefficients: 계수 계산 (Calculates coefficients)
  • VerifyCoefficients: 계수 범위 검증 (Verifies coefficient ranges)
  • ConvertBridgeFromPercent, ConvertBridgeToPercent: 압력 데이터 변환 (Converts pressure data)
  • GetCorrectedBridge, GetCorrectedTemp: 보정된 압력 및 온도 계산 (Calculates corrected pressure and temperature)
  • ConvertTempFromDegrees, ConvertTempToDegrees: 온도 데이터 변환 (Converts temperature data)

3. C#에서 DLL 호출 준비 (Preparing to Call DLL in C#)

C#에서 C/C++ DLL을 호출하려면 다음 단계를 따라야 합니다 (To call a C/C++ DLL from C#, follow these steps):

  1. DLL 파일 준비 (Prepare the DLL file):
    • calibrationL64.dll을 프로젝트의 실행 파일 디렉토리(예: bin\Debug 또는 bin\Release)에 복사 (Copy calibrationL64.dll to the project's executable directory, e.g., bin\Debug or bin\Release).
    • DLL이 64비트인지 확인하고, C# 프로젝트의 플랫폼 대상을 x64로 설정 (Verify that the DLL is 64-bit and set the C# project platform target to x64).
  2. P/Invoke 사용 (Use P/Invoke):
    • System.Runtime.InteropServices 네임스페이스의 DllImport 속성을 사용하여 DLL 함수 선언 (Declare DLL functions using the DllImport attribute from the System.Runtime.InteropServices namespace).
    • 호출 규약(_stdcall)을 CallingConvention.StdCall로 설정 (Set the calling convention (_stdcall) to CallingConvention.StdCall).
  3. 데이터 형식 매핑 (Data type mapping):
    • C의 int → C# int
    • C의 double → C# double
    • C의 배열(int[], double*) → C# int[], double[]
    • 포인터(double*) → ref double 또는 배열 (Pointers (double*) → ref double or arrays)
  4. 오류 처리 (Error handling):
    • DllNotFoundException, EntryPointNotFoundException 예외 처리 (Handle DllNotFoundException and EntryPointNotFoundException).
    • 반환값 확인으로 DLL 호출 성공 여부 판단 (Check return values to determine DLL call success).

4. C# 구현: 7포인트 캘리브레이션 (C# Implementation: 7-Point Calibration)

아래는 C 예제 코드를 C#으로 변환한 전체 코드입니다. (The following is the complete C# code converted from the C example.) SampleCalibration7points 함수는 7포인트 데이터를 사용하여 계수를 계산하고, 보정된 압력 및 온도 값을 생성합니다. (The SampleCalibration7points function calculates coefficients using 7-point data and generates corrected pressure and temperature values.)

4.1. C# 코드 (상세 주석 포함) (C# Code with Detailed Comments)

using System;
using System.Runtime.InteropServices;

namespace CalibrationL64
{
    public class CalibrationL64Wrapper
    {
        // 계수 배열 크기 상수 (Coefficient array size constant)
        public const int COEFFICIENT_COUNT = 10;

        // 계수 배열의 인덱스 상수 (Coefficient indices)
        public const int INDEX_OFFSET_S = 0;
        public const int INDEX_GAIN_S = 1;
        public const int INDEX_TCG = 2;
        public const int INDEX_TCO = 3;
        public const int INDEX_SOT_TCO = 4;
        public const int INDEX_SOT_TCG = 5;
        public const int INDEX_SOT_S = 6;
        public const int INDEX_OFFSET_T = 7;
        public const int INDEX_GAIN_T = 8;
        public const int INDEX_SOT_T = 9;

        // selCoeffs 플래그 (Coefficient selection flags)
        public const int CO_OFFSET_S = 0x1;
        public const int CO_GAIN_S = 0x2;
        public const int CO_TCG = 0x4;
        public const int CO_TCO = 0x8;
        public const int CO_SOT_TCO = 0x10;
        public const int CO_SOT_TCG = 0x20;
        public const int CO_SOT_S = 0x40;
        public const int CO_OFFSET_T = 0x80;
        public const int CO_GAIN_T = 0x100;
        public const int CO_SOT_T = 0x200;

        // 계수 범위 제한 상수 (Coefficient range limit constants)
        public const int OFFSET_S_MAX = 0x7FFFFF;    // Offset_S 최대값 (Maximum value for Offset_S)
        public const int OFFSET_S_MIN = -0x7FFFFF;   // Offset_S 최소값 (Minimum value for Offset_S)
        public const int GAIN_S_MAX = 0x7FFFFF;      // Gain_S 최대값 (Maximum value for Gain_S)
        public const int GAIN_S_MIN = -0x7FFFFF;     // Gain_S 최소값 (Minimum value for Gain_S)
        public const int TCG_MAX = 0x7FFFFF;         // TCG 최대값 (Maximum value for TCG)
        public const int TCG_MIN = -0x7FFFFF;        // TCG 최소값 (Minimum value for TCG)
        public const int TCO_MAX = 0x7FFFFF;         // TCO 최대값 (Maximum value for TCO)
        public const int TCO_MIN = -0x7FFFFF;        // TCO 최소값 (Minimum value for TCO)
        public const int SOT_TCO_MAX = 0x7FFFFF;     // SOT_TCO 최대값 (Maximum value for SOT_TCO)
        public const int SOT_TCO_MIN = -0x7FFFFF;    // SOT_TCO 최소값 (Minimum value for SOT_TCO)
        public const int SOT_TCG_MAX = 0x7FFFFF;     // SOT_TCG 최대값 (Maximum value for SOT_TCG)
        public const int SOT_TCG_MIN = -0x7FFFFF;    // SOT_TCG 최소값 (Minimum value for SOT_TCG)
        public const int SOT_S_MAX = 0x7FFFFF;       // SOT_S 최대값 (Maximum value for SOT_S)
        public const int SOT_S_MIN = -0x7FFFFF;      // SOT_S 최소값 (Minimum value for SOT_S)
        public const int OFFSET_T_MAX = 0x7FFFFF;    // Offset_T 최대값 (Maximum value for Offset_T)
        public const int OFFSET_T_MIN = -0x7FFFFF;   // Offset_T 최소값 (Minimum value for Offset_T)
        public const int GAIN_T_MAX = 0x7FFFFF;      // Gain_T 최대값 (Maximum value for Gain_T)
        public const int GAIN_T_MIN = -0x7FFFFF;     // Gain_T 최소값 (Minimum value for Gain_T)
        public const int SOT_T_MAX = 0x7FFFFF;       // SOT_T 최대값 (Maximum value for SOT_T)
        public const int SOT_T_MIN = -0x7FFFFF;      // SOT_T 최소값 (Minimum value for SOT_T)

        // DLL 함수 선언 (DLL function declarations)
        [DllImport("calibrationL64.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern int CalculateCoefficients(
            [In, Out] int[] coefficients,  // 입출력: 계산된 계수 배열 (In/Out: Array of calculated coefficients)
            int numPoints,                 // 입력: 캘리브레이션 포인트 수 (Input: Number of calibration points)
            int selCoeffs,                 // 입력: 계산할 계수 플래그 (Input: Flags for coefficients to calculate)
            int CalType,                   // 입력: 캘리브레이션 타입 (Input: Calibration type)
            [In] double[] bridgeRaw,       // 입력: 원시 압력 데이터 (Input: Raw pressure data)
            [In] double[] bridgeDesired,   // 입력: 목표 압력 데이터 (Input: Desired pressure data)
            [In] double[] tempRaw,         // 입력: 원시 온도 데이터 (Input: Raw temperature data)
            [In] double[] tempDesired);    // 입력: 목표 온도 데이터 (Input: Desired temperature data)

        [DllImport("calibrationL64.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern int VerifyCoefficients([In] int[] coefficients); // 계수 범위 검증 (Verify coefficient ranges)

        [DllImport("calibrationL64.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern double ConvertBridgeFromPercent(double bridgeInPercent);

        [DllImport("calibrationL64.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern double ConvertBridgeToPercent(double bridgeInCodes);

        [DllImport("calibrationL64.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern double ConvertBridgeForCalibration(double bridgeInCodes, uint offsetInSteps);

        [DllImport("calibrationL64.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern double GetCorrectedBridge([In] int[] coefficients, double RawB, double RawT);

        [DllImport("calibrationL64.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern int ConvertTempFromDegrees(ref double tempInCodes, double tempInDegrees, double minTemp, double maxTemp);

        [DllImport("calibrationL64.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern int ConvertTempToDegrees(ref double tempInDegrees, int tempInCodes, double minTemp, double maxTemp);

        [DllImport("calibrationL64.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern double ConvertTempForCalibration(double bridgeInCodes, uint offsetInSteps);

        [DllImport("calibrationL64.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern double GetCorrectedTemp([In] int[] coefficients, double tempRaw);

        /// <summary>
        /// C#에서 계수 범위를 수동으로 검증하는 메서드 (Manually verify coefficient ranges in C#)
        /// </summary>
        /// <param name="coefficients">계수 배열 (Array of coefficients)</param>
        /// <returns>모든 계수가 범위 내에 있으면 true, 하나라도 범위를 벗어나면 false (True if all coefficients are within range, false if any are out of range)</returns>
        public static bool ManuallyVerifyCoefficients(int[] coefficients)
        {
            if (coefficients.Length != COEFFICIENT_COUNT)
            {
                Console.WriteLine("계수 배열 크기가 잘못되었습니다. (Invalid coefficient array size.)");
                return false;
            }

            // 각 계수의 범위 검증 (Verify each coefficient's range)
            if (coefficients[INDEX_OFFSET_S] > OFFSET_S_MAX || coefficients[INDEX_OFFSET_S] < OFFSET_S_MIN)
            {
                Console.WriteLine($"Offset_S 값이 범위를 벗어났습니다: {coefficients[INDEX_OFFSET_S]} (Offset_S out of range: {coefficients[INDEX_OFFSET_S]})");
                return false;
            }
            if (coefficients[INDEX_GAIN_S] > GAIN_S_MAX || coefficients[INDEX_GAIN_S] < GAIN_S_MIN)
            {
                Console.WriteLine($"Gain_S 값이 범위를 벗어났습니다: {coefficients[INDEX_GAIN_S]} (Gain_S out of range: {coefficients[INDEX_GAIN_S]})");
                return false;
            }
            if (coefficients[INDEX_TCG] > TCG_MAX || coefficients[INDEX_TCG] < TCG_MIN)
            {
                Console.WriteLine($"TCG 값이 범위를 벗어났습니다: {coefficients[INDEX_TCG]} (TCG out of range: {coefficients[INDEX_TCG]})");
                return false;
            }
            if (coefficients[INDEX_TCO] > TCO_MAX || coefficients[INDEX_TCO] < TCO_MIN)
            {
                Console.WriteLine($"TCO 값이 범위를 벗어났습니다: {coefficients[INDEX_TCO]} (TCO out of range: {coefficients[INDEX_TCO]})");
                return false;
            }
            if (coefficients[INDEX_SOT_TCO] > SOT_TCO_MAX || coefficients[INDEX_SOT_TCO] < SOT_TCO_MIN)
            {
                Console.WriteLine($"SOT_TCO 값이 범위를 벗어났습니다: {coefficients[INDEX_SOT_TCO]} (SOT_TCO out of range: {coefficients[INDEX_SOT_TCO]})");
                return false;
            }
            if (coefficients[INDEX_SOT_TCG] > SOT_TCG_MAX || coefficients[INDEX_SOT_TCG] < SOT_TCG_MIN)
            {
                Console.WriteLine($"SOT_TCG 값이 범위를 벗어났습니다: {coefficients[INDEX_SOT_TCG]} (SOT_TCG out of range: {coefficients[INDEX_SOT_TCG]})");
                return false;
            }
            if (coefficients[INDEX_SOT_S] > SOT_S_MAX || coefficients[INDEX_SOT_S] < SOT_S_MIN)
            {
                Console.WriteLine($"SOT_S 값이 범위를 벗어났습니다: {coefficients[INDEX_SOT_S]} (SOT_S out of range: {coefficients[INDEX_SOT_S]})");
                return false;
            }
            if (coefficients[INDEX_OFFSET_T] > OFFSET_T_MAX || coefficients[INDEX_OFFSET_T] < OFFSET_T_MIN)
            {
                Console.WriteLine($"Offset_T 값이 범위를 벗어났습니다: {coefficients[INDEX_OFFSET_T]} (Offset_T out of range: {coefficients[INDEX_OFFSET_T]})");
                return false;
            }
            if (coefficients[INDEX_GAIN_T] > GAIN_T_MAX || coefficients[INDEX_GAIN_T] < GAIN_T_MIN)
            {
                Console.WriteLine($"Gain_T 값이 범위를 벗어났습니다: {coefficients[INDEX_GAIN_T]} (Gain_T out of range: {coefficients[INDEX_GAIN_T]})");
                return false;
            }
            if (coefficients[INDEX_SOT_T] > SOT_T_MAX || coefficients[INDEX_SOT_T] < SOT_T_MIN)
            {
                Console.WriteLine($"SOT_T 값이 범위를 벗어났습니다: {coefficients[INDEX_SOT_T]} (SOT_T out of range: {coefficients[INDEX_SOT_T]})");
                return false;
            }

            return true; // 모든 계수가 범위 내에 있음 (All coefficients are within range)
        }

        /// <summary>
        /// 7포인트 캘리브레이션 데이터를 사용하여 계수를 계산하고 보정된 압력 및 온도 값을 생성합니다.
        /// (Calculates coefficients using 7-point calibration data and generates corrected pressure and temperature values.)
        /// </summary>
        /// <returns>성공 시 0, 오류 시 -1 (0 on success, -1 on error)</returns>
        public static int SampleCalibration7points()
        {
            try
            {
                // 계수 배열: 10개의 계수를 저장 (COEFFICIENT_COUNT=10), 0으로 초기화
                // (Coefficient array: Stores 10 coefficients, initialized to 0)
                int[] coefficients = new int[COEFFICIENT_COUNT];

                // 7포인트 캘리브레이션 데이터: {Pressure_ref[%], Pressure_raw, Tambient_ref, Tambient_raw}
                // (7-point calibration data: {Pressure_ref[%], Pressure_raw, Tambient_ref, Tambient_raw})
                double[,] cali_data = new double[7, 4]
                {
                    { 30, 982368,  10, 420864 },   // 포인트 1 (Point 1)
                    { 90, 7950208, 10, 420901 },   // 포인트 2 (Point 2)
                    { 30, 770304,  25, 1571148 },  // 포인트 3 (Point 3)
                    { 50, 2362176, 25, 1581184 },  // 포인트 4 (Point 4)
                    { 90, 7768800, 25, 1581104 },  // 포인트 5 (Point 5)
                    { 30, 547968,  40, 2749136 },  // 포인트 6 (Point 6)
                    { 90, 7620416, 40, 2749312 }   // 포인트 7 (Point 7)
                };

                // 데이터 배열: 각 포인트에 대한 원시 및 목표 값 저장
                // (Data arrays: Store raw and desired values for each point)
                double[] P_raw = new double[7];        // 원시 압력 데이터 (Raw pressure data)
                double[] P_des = new double[7];        // 목표 압력 데이터 (Desired pressure data)
                double[] T_raw = new double[7];        // 원시 온도 데이터 (Raw temperature data)
                double[] T_des = new double[7];        // 목표 온도 데이터 (Desired temperature data)
                double[] P_corr = new double[7];       // 보정된 압력 데이터 (Corrected pressure data)
                double[] T_corr = new double[7];       // 보정된 온도 데이터 (Corrected temperature data)
                double[] P_corr_percent = new double[7]; // 보정된 압력 데이터 (백분율) (Corrected pressure data in percentage)
                double[] T_corr_deg = new double[7];   // 보정된 온도 데이터 (도 단위) (Corrected temperature data in degrees)

                // 온도 범위: 온도 변환에 사용
                // (Temperature range: Used for temperature conversion)
                double T_min = -40.0;  // 최소 온도 (°C) (Minimum temperature)
                double T_max = 85.0;   // 최대 온도 (°C) (Maximum temperature)

                // 선택할 계수 플래그: 모든 계수를 계산하도록 설정
                // (Coefficient selection flags: Set to calculate all coefficients)
                int sel_coeff_7P = CO_OFFSET_S | CO_GAIN_S | CO_TCO | CO_TCG | CO_OFFSET_T |
                                   CO_GAIN_T | CO_SOT_TCO | CO_SOT_TCG | CO_SOT_T | CO_SOT_S;

                // 캘리브레이션 타입: 기본값 0 (문서에 따라 변경 가능)
                // (Calibration type: Default 0, can be changed based on documentation)
                int cali_type = 0;

                // 캘리브레이션 포인트 수: 7포인트
                // (Number of calibration points: 7 points)
                int cali_points = 7;

                // 데이터 재구성: cali_data에서 P_raw, P_des, T_raw, T_des 배열로 데이터 분리
                // (Data restructuring: Extract data from cali_data into P_raw, P_des, T_raw, T_des arrays)
                for (int i = 0; i < cali_points; i++)
                {
                    P_raw[i] = cali_data[i, 1]; // 원시 압력 데이터 추출 (Extract raw pressure data)
                    P_des[i] = ConvertBridgeFromPercent(cali_data[i, 0]); // 압력 백분율을 디지털 값으로 변환 (Convert pressure percentage to digital value)
                    T_raw[i] = cali_data[i, 3]; // 원시 온도 데이터 추출 (Extract raw temperature data)
                    ConvertTempFromDegrees(ref T_des[i], cali_data[i, 2], T_min, T_max); // 온도(도)를 디지털 값으로 변환 (Convert temperature in degrees to digital value)
                }

                // 계수 계산: DLL의 CalculateCoefficients 함수 호출
                // (Calculate coefficients: Call the CalculateCoefficients DLL function)
                int ret = CalculateCoefficients(coefficients, cali_points, sel_coeff_7P, cali_type,
                                               P_raw, P_des, T_raw, T_des);

                // 결과 출력: 계수 계산 성공 여부 및 계산된 계수 표시
                // (Output results: Display coefficient calculation success and calculated coefficients)
                Console.WriteLine($"CalculateCoefficients Result: {ret}"); // 0: 성공, 그 외: 오류 (0: success, other: error)
                Console.WriteLine("Coefficients: " + string.Join(", ", coefficients));

                // 계수 검증: DLL의 VerifyCoefficients 호출
                // (Verify coefficients: Call the VerifyCoefficients DLL function)
                int range_check = VerifyCoefficients(coefficients);
                Console.WriteLine($"VerifyCoefficients Result: {range_check}"); // 0: 정상, 1: 범위 초과 (0: normal, 1: out of range)

                // 추가 검증: C#에서 수동으로 계수 범위 확인
                // (Additional verification: Manually check coefficient ranges in C#)
                bool manual_check = ManuallyVerifyCoefficients(coefficients);
                Console.WriteLine($"Manual Coefficient Verification Result: {manual_check}"); // true: 정상, false: 범위 초과 (true: normal, false: out of range)

                // 보정된 값 계산: 각 포인트에 대해 보정된 압력 및 온도 계산
                // (Calculate corrected values: Compute corrected pressure and temperature for each point)
                for (int i = 0; i < cali_points; i++)
                {
                    T_corr[i] = GetCorrectedTemp(coefficients, T_raw[i]); // 온도 보정 (Temperature correction)
                    ConvertTempToDegrees(ref T_corr_deg[i], (int)T_corr[i], T_min, T_max); // 보정된 온도를 도 단위로 변환 (Convert corrected temperature to degrees)
                    P_corr[i] = GetCorrectedBridge(coefficients, P_raw[i], T_raw[i]); // 압력 보정 (Pressure correction)
                    P_corr_percent[i] = ConvertBridgeToPercent(P_corr[i]); // 보정된 압력을 백분율로 변환 (Convert corrected pressure to percentage)
                }

                // 결과 출력: 보정된 온도 및 압력 값 표시
                // (Output results: Display corrected temperature and pressure values)
                Console.WriteLine("\nCorrected Temperature [counts]:");
                Console.WriteLine(string.Join(", ", T_corr));
                Console.WriteLine("\nCorrected Temperature [degrees]:");
                Console.WriteLine(string.Join(", ", T_corr_deg));
                Console.WriteLine("\nCorrected Pressure [counts]:");
                Console.WriteLine(string.Join(", ", P_corr));
                Console.WriteLine("\nCorrected Pressure [percent]:");
                Console.WriteLine(string.Join(", ", P_corr_percent));

                return 0; // 성공적으로 완료 (Successfully completed)
            }
            catch (Exception ex)
            {
                // 예외 처리: DLL 호출 오류 또는 기타 예외 발생 시
                // (Exception handling: Handle DLL call errors or other exceptions)
                Console.WriteLine($"Error: {ex.Message}");
                return -1; // 오류 발생 (Error occurred)
            }
        }

        public static void Main()
        {
            // SampleCalibration7points 실행 및 결과 출력
            // (Execute SampleCalibration7points and display results)
            int result = SampleCalibration7points();
            Console.WriteLine($"SampleCalibration7points Result: {result}"); // 0: 성공, -1: 오류 (0: success, -1: error)
        }
    }
}

4.2. 코드 설명 (Code Explanation)

  • 상수 및 플래그 (Constants and Flags): 헤더 파일의 상수를 C# 상수로 정의하여 코드 가독성과 유지보수성을 높임. (Constants from the header file are defined as C# constants to improve code readability and maintainability.)
  • DLL 함수 선언 (DLL Function Declarations): DllImport를 사용하여 calibrationL64.dll의 함수를 호출 가능하도록 설정. (Use DllImport to enable calling functions from calibrationL64.dll.)
  • 데이터 처리 (Data Processing): 7포인트 데이터를 2D 배열(double[,])로 정의하고, 이를 1D 배열(P_raw, P_des, T_raw, T_des)로 변환. (Define 7-point data in a 2D array (double[,]) and convert to 1D arrays (P_raw, P_des, T_raw, T_des).)
  • 계수 계산 (Coefficient Calculation): CalculateCoefficients를 호출하여 계수를 계산하고, VerifyCoefficients로 범위 검증. (Call CalculateCoefficients to compute coefficients and VerifyCoefficients to validate ranges.)
  • 보정값 계산 (Corrected Value Calculation): GetCorrectedBridgeGetCorrectedTemp로 보정된 압력 및 온도 값을 계산. (Calculate corrected pressure and temperature values using GetCorrectedBridge and GetCorrectedTemp.)
  • 결과 출력 (Result Output): 보정된 값을 콘솔에 출력하여 확인. (Output corrected values to the console for verification.)

5. 실행 환경 설정 (Execution Environment Setup)

5.1. DLL 파일 준비 (Prepare the DLL File)

  • calibrationL64.dll을 프로젝트의 출력 디렉토리(예: bin\Debug)에 복사 (Copy calibrationL64.dll to the project's output directory, e.g., bin\Debug).
  • DLL이 64비트인지 확인하고, Visual Studio에서 프로젝트 속성 → 빌드 → 플랫폼 대상을 x64로 설정 (Verify that the DLL is 64-bit and set the project platform target to x64 in Visual Studio).

5.2. 종속성 (Dependencies)

  • DLL이 Microsoft Visual C++ 런타임에 의존할 수 있음. 대상 시스템에 최신 런타임 설치 확인 (The DLL may depend on the Microsoft Visual C++ Runtime; ensure the latest runtime is installed on the target system).
  • 예: Visual Studio 2015-2022용 Microsoft Visual C++ Redistributable (Example: Microsoft Visual C++ Redistributable for Visual Studio 2015-2022).

5.3. 오류 디버깅 (Error Debugging)

  • DllNotFoundException: DLL 파일이 실행 경로에 없는 경우 발생. 경로를 확인하거나 PATH 환경 변수에 추가 (Occurs when the DLL file is not in the execution path; check the path or add to the PATH environment variable).
  • EntryPointNotFoundException: 함수 이름이 잘못되었거나 DLL에서 내보내기되지 않은 경우 발생. dumpbin /exports calibrationL64.dll 명령어로 내보낸 함수 확인 (Occurs when the function name is incorrect or not exported from the DLL; use dumpbin /exports calibrationL64.dll to check exported functions).
  • VerifyCoefficients 반환값 1: 계수 값이 허용 범위(OFFSET_S_MAX, OFFSET_S_MIN 등)를 초과했음을 의미 (A return value of 1 from VerifyCoefficients indicates that coefficient values exceed allowed ranges, e.g., OFFSET_S_MAX, OFFSET_S_MIN).

6. 예상 출력 (Expected Output)

성공적으로 실행되면 다음과 같은 출력이 표시됩니다 (The following output is displayed upon successful execution):

CalculateCoefficients Result: 0
Coefficients: -520831, 5880723, 489, 379060, -4349, -296970, -278951, -317710, 3817446, -49055
VerifyCoefficients Result: 0
Corrected Temperature [counts]:
6710884, 6710949, 8712632, 8729989, 8729851, 10737550, 10737550
Corrected Temperature [degrees]:
10, 10, 25, 25, 25, 40, 40
Corrected Pressure [counts]:
5033172, 15099510, 5033171, 8388615, 15099510, 5033171, 15099510
Corrected Pressure [percent]:
30, 90, 30, 50, 90, 30, 90
SampleCalibration7points Result: 0

7. 결론 (Conclusion)

이 글에서는 calibrationL64.dll을 C#에서 호출하여 7포인트 캘리브레이션을 구현하는 방법을 상세히 다뤘습니다. (This article detailed how to implement 7-point calibration by calling calibrationL64.dll from C#.) P/Invoke를 활용한 DLL 호출, 데이터 형식 매핑, 오류 처리, 그리고 C 코드의 C# 변환 과정을 통해 실무에서 바로 활용 가능한 코드를 제공했습니다. (It provided practical code through P/Invoke DLL calls, data type mapping, error handling, and C-to-C# conversion.) 

키워드 (Keywords): C#, C++, DLL, P/Invoke, calibrationL64.dll, 7포인트 캘리브레이션 (7-point calibration), 계수 계산 (coefficient calculation), 센서 데이터 처리 (sensor data processing)

반응형