Conditional Compilation

CRBasic allows you to include or exclude sections of code in a program based on the data logger type or other conditions within the program, such as a user-defined constant (see Conditional Compilation Based on Evaluation of Constants). This capability—called conditional compilation—is implemented using #If, #Else, #ElseIf, #EndIf, and #UnDef syntax.The #If_no_remove declaration can be used in place of #If to specify conditional code that should not be removed from the resulting program when a Conditional Compile and Save is performed.

Conditional Compilation Based on data logger Type (LoggerType)

Many CRBasic data loggers use a default file extension that indicates the logger type the program was compiled for (for example, *.CR1X for a CR1000X-series logger).

In addition to data logger-specific file extensions, there are also 2 universal file extensions that allow a program to run on more than one type of data logger:

  1. .DLD

  • Original universal file extension

  • Compatible with both retired and current data logger models

  1. .CRB

  • New default file extension

  • Not compatible with retired data loggers

  • Will be used for all future data logger models

CR350 data loggers, as well as all GRANITE data loggers use the *.CRB extension. This extension is also valid for CR6 data loggers with OS 11 or later and CR1000X data loggers with OS 5 or later. See Program File Extensions for more information.

By using conditional compilation with a *.DLD or *.CRB file, you can create a single program that runs on multiple data logger types.

A common use case is when the same program must run on data loggers that support different options for a CRBasic instruction. For example, since voltage ranges vary among data logger types, you can use conditional #If/#ElseIf statements to assign the correct range codes. The example program below shows this approach:

Public PTemp, TCTemp

'Set the constant "Range" based on LoggerType
#If LoggerType = CR6
    Const Range=mv200C
#ElseIf LoggerType=CR1000
    Const Range=mv2_5C
#EndIf

DataTable (TempTab,True,-1)
  DataInterval (0,1,Min,10)
  Sample (1,TCTemp,FP2)
EndTable

BeginProg
  Scan (1,Sec,3,0)
    PanelTemp (PTemp,15000)
    
    'Range will bet set to mv200C for a CR6 or mv2_5c for a CR1000
    TCDiff (TCTemp,1,Range,U1,TypeT,PTemp,True ,0,15000,1.0,0)
    CallTable (TempTab)
  NextScan
EndProg

NOTE:  Beginning with CR1000X OS 8.4.0, a constant named is_CR1000Xe, can be used within #IF statements to conditionally compile code that is specific to the CR1000Xe.

     For example:

     #If LoggerType = CR1000X Then
       Const Modem_Power = SW12_1
     #ElseIf is_CR1000Xe Then
       'SW12_CSIO - CR1000Xe Only
       Const Modem_Power = SW12_CSIO
     #EndIf

Conditional Compilation Based on Evaluation of Constants

The following example program shows how conditional compilation can be used to include or exclude code that is compiled in the data logger based on the state of constants in the program. This program also uses the Custom Menu capability.

Using a keyboard display, the user selects which sensors are connected to the data logger. If a sensor is marked as “true” all the code associated with that sensor (measurements and data table information) is included in the program when compiled. See an example program below.

#UnDef

NOTE: The newer IncludeSection() instruction replaces the need to use #UnDef by allowing multiple named sections to be defined within a single include file, also called a file library.

#UnDef is commonly used with Const and #If/EndIf to assemble libraries or sections of code located in Include files. This approach is especially useful in systems with many components and measurements, where large programs often rely on multiple Include files for specific configuration options. Using #If and #UnDef enables conditional declaration of program sections so that multiple Include files can be consolidated into a single file.

For example, in the sample code below, #If is used to declare a constant named Section twice in the main program. The first declaration pulls in sensor settings from an Include file named cpu:Sensor_PT500_Lib.crb, while the second controls data storage using the same Include file. Without #UnDef, declaring the same constant twice would cause a compile error. Using #If together with #UnDef increases program flexibility and reduces the number of Include files required for system configuration.

#if LoggerEndian

The constant, LoggerEndian is used to determine if a data logger is big Closedendian Endianness refers to byte order. With the little-endian format, bytes are ordered with the least significant byte (the "little end") first. With the big-endian format, bytes are ordered with the most significant byte ("big end") first. The CR300, GRANITE 9, and GRANITE 10 dataloggers use the little-endian format. The CR800, CR1000, CR3000, CR6, CR1000X, and GRANITE 6 use the big-endian format. Byte order when sending string variables as serial data is identical in big-endian and little-endian CSI dataloggers. Only numeric values sent as multiple bytes require attention to big-endian and little-endian issues. of little endian.

LoggerEndian can be compared against CR_LITTLE_ENDIAN and CR_BIG_ENDIAN to determine the endianness of the datalogger.

Usage is as follows:

#If LoggerEndian = CR_LITTLE_ENDIAN

Const endianness_msg = "LITTLE ENDIAN"

#Else

Const endianness_msg = "BIG ENDIAN"

#EndIf

Or inversely

#If LoggerEndian = CR_BIG_ENDIAN

Const endianness_msg = "BIG ENDIAN"

#Else

Const endianness_msg = "LITTLE ENDIAN"

#EndIf

See an example program below: