HOME > RT-C Language
Controller > Sample "Analog Input Control""
Board Settings (※ Execute once when program boots)
|
|
(1) Search Board
Get IO port to be used by PciFindDevice() of pcibus class.
|
|
(2) Initialize board
Output "Initialize process command" to IO port to initialize
board
|
|
(3) Set Sampling temrs
After outputing "setting command of sampling terms" to IO port,
output setting data ([input mode][Channel mode][clock source to
be used][sampling mode]).
|
|
(4) Set Range Width
After outputting "Setting command of Input Range" to IO port,
output settings of Input Range per each channel.
|
|
(5) Set interrupt mask
After outputting "Setting command of Interrupt factor" to IO
port, output settings of factor for interrupt signal
occurrance.
※ All must be prohibited.
|
|
Data Sampling (※ Always executing in operation)
|
|
(6) Issue Sampling start command
Output "Sampling start command" to IO port.
if sampling mode is software command, it takes a sampling to the designated channel.
|
|
(7) Wait for sampling
Get "analog input status" from IO port, check the state of
"DRE(DataReadEnable:0x02)"
If DRE is ON, you can get sampling data.
|
|
(8) Get Data
Get "analog input data" from IO port.
|
|
※ Repeat (6)~(8)
|
// *** Constant ***
/// <summary>
/// Input Range
/// </summary>
public enum RANGE : byte
{
B_1000 = 0x00, // Bipolar:-10 .. 10[V]
B_0500 = 0x01, // Bipolar:-5 .. 5[V]
B_0250 = 0x02, // Bipolar:-2.5 .. 2.5[V]
B_0125 = 0x03, // Bipolar:-1.25 .. 1.25[V]
U_1000 = 0x04, // Unipolar:0 .. 10[V]
U_0500 = 0x05, // Unipolar:0 .. 5[V]
U_0250 = 0x06, // Unipolar:0 .. 2.5[V]
U_0125 = 0x07 // Unipolar:0 .. 1.25[V]
}
/// <summary>
/// Define global variables
/// </summary>
public unsafe class GlobalVar
{
public static Boolean inExe; // Request Execution
public static Boolean inBusy; // Flag for Running
public static Boolean inErr; // Fral for In Error
public static UInt32 inErrCode; // Error Code
public static UInt16 IOPort = 0; // IO port of analaog board
public static Single fLo; // Voltage of minimum input
public static Single fHi; // Voltage of maximum input
public static UInt32 uiPos = 0; // Stored position of sampling data
public static UInt32 uiOvr = 0; // Buffer over flag for sampling data
public static void* lpData = null; // Buffer for sampling data raw value
public static void* lpVolt = null; // Buffer for sampling data[V]
public static UInt32 uiBuffSize; // Maximum buffer counts
public static UInt16 wData; // Buffer for sampling data instantaneous value
public static Single fData; // Sampling data [V]instantaneous value
}
/// <summary>
/// Define board setting value
/// </summary>
public unsafe class Board
{
// Target Board
public static UInt16 VenID = 0x1221; // CONTEC
public static UInt16 DevID = 0x8153; // AD12-16(PCI)
public static UInt16 DevIndex = 0; // Board ID:0
public static Byte bMaxCh = 16; // Board CH number
public static UInt16 Resolution = 0x0FFF; // Resolution
Byte bAIMode = 0; // Input mode 0:Single end 1:Differential
Byte bChMode = 1; // Channel mode 0:Single 1:Multi
Byte bSmpClok = 0; // Clock source to be used 0:Internal clock 1:External clock
Byte bSmpMode = 0; // Sampling mode 0:Manual Issue 1:Automatic Issue
// Smapling terms Setting value
public static Byte bAIMode = 0; // Input mode 0:Single end 1:Differential
public static Byte bChMode = 1; // Channel mode 0:Single 1:Multi
public static Byte bSmpClok = 0; // Clock source to be used 0:Internal clock 1:External clock
public static Byte bSmpMode = 0; // Sampling mode 0:Manual Issue 1:Automatic Issue
public static Byte bUseCh = 1; // CH numbers to be used
※In case of Differential input, half of board CH is maximum.
// Range Width Setting value
public static Byte bRange = (Byte)RANGE.B_1000; // Input Range
// Inerrupt Mask Setting value
public static Byte bFcr0 = 0xFF; // Interrupt mask0 ※Bit Unit (0:Occur 1:Prohibit)
public static Byte bFcr1 = 0xFF; // Interrupt mask1 ※Bit Unit (0:Occur 1:Prohibit)
}
/// <summary>
/// *****************************************************************************************************
/// Main Process Block
/// *****************************************************************************************************
/// </summary>
[FUNCTION_BLOCK]
public class _main
{
// *** Internal Variables ***
private RtMemory rmData; // Memory for Sampling Data
private RtMemory rmVolt; // Memory for Sampling Data[V]
// *** Internal Variables ***
/// <summary>
/// Search Target board
/// </summary>
private Boolean FindBoard()
{
UInt32 BaseAddr = 0;
if (pcibus.PciFindDevice(Board.VenID, Board.DevID, Board.DevIndex, 0, 1, ref BaseAddr) == false)
{
return false;
}
GlobalVar.IOPort = (UInt16)(BaseAddr & 0xFFFC);
return true;
}
/// <summary>
/// Intialize board
/// </summary>
private void InitalizeBord()
{
pcibus.OutBYTE((ushort)(GlobalVar.IOPort + 0x0008), 0);
}
/// <summary>
/// Set Sampling terms
/// </summary>
private void SetSampling()
{
// +----------+----------------+--------------------------+------------------+
// | D3 | D2 | D1 | D0 |
// +----------+----------------+--------------------------+------------------+
// |Input mode|Channel mode |Sampling Clock source |Sampling mode |
// +----------+----------------+--------------------------+------------------+
Byte byDATA = (Byte)(
(Board.bAIMode << 0x03)
| (Board.bChMode << 0x02)
| (Board.bSmpClok << 0x01)
| Board.bSmpMode
);
pcibus.OutBYTE((ushort)(GlobalVar.IOPort + 0x0008), 0x01); // Issue set command for Sampling terms
pcibus.OutBYTE((ushort)(GlobalVar.IOPort + 0x000C), byDATA); // Write Sampling terms
}
/// <summary>
/// Set range width
/// </summary>
private void SetRange()
{
// Issue set command for range
pcibus.OutBYTE((ushort)(GlobalVar.IOPort + 0x0008), 0x02);
// Process for range setting
for (Byte i = 0; i < Board.bUseCh; i++)
{
pcibus.OutBYTE((ushort)(GlobalVar.IOPort + 0x000C), i); // Set CH to be set
pcibus.OutBYTE((ushort)(GlobalVar.IOPort + 0x000D), (byte)Board.bRange); // Set range width
}
// Set Voltage of minimum input / Voltage of maximum input
switch ((byte)Board.bRange)
{
case (Byte)RANGE.B_1000:
GlobalVar.fLo = -10.0f;
GlobalVar.fHi = 10.0f;
break;
case (Byte)RANGE.B_0500:
GlobalVar.fLo = -5.0f;
GlobalVar.fHi = 5.0f;
break;
case (Byte)RANGE.B_0250:
GlobalVar.fLo = -2.5f;
GlobalVar.fHi = 2.5f;
break;
case (Byte)RANGE.B_0125:
GlobalVar.fLo = -1.25f;
GlobalVar.fHi = 1.25f;
break;
case (Byte)RANGE.U_1000:
GlobalVar.fLo = 0.0f;
GlobalVar.fHi = 10.0f;
break;
case (Byte)RANGE.U_0500:
GlobalVar.fLo = 0.0f;
GlobalVar.fHi = 5.0f;
break;
case (Byte)RANGE.U_0250:
GlobalVar.fLo = 0.0f;
GlobalVar.fHi = 2.5f;
break;
case (Byte)RANGE.U_0125:
GlobalVar.fLo = 0.0f;
GlobalVar.fHi = 1.25f;
break;
}
}
/// <summary>
/// Set Interrupt mask
/// </summary>
private void SetIntrMask()
{
// Issue set command for Interrupt mask
pcibus.OutBYTE((ushort)(GlobalVar.IOPort + 0x0008), 0x04);
// Set Interrupt mask
pcibus.OutBYTE((ushort)(GlobalVar.IOPort + 0x000C), Board.bFcr0);
pcibus.OutBYTE((ushort)(GlobalVar.IOPort + 0x000D), Board.bFcr1);
}
/// <summary>
/// PLC Program - Process in download
/// </summary>
public unsafe _main()
{
// Analog board setting
if (!FindBoard()) // Search analog board
{
GlobalVar.inErr = true; // Error
GlobalVar.inErrCode = 1; // Board
return;
}
InitalizeBord(); // Initialize board
SetSampling(); // Set Sampling terms
SetRange(); // Set Range Width
SetIntrMask(); // Set Interrupt mask
IecString80 sMemName = new IecString80();
sMemName.ctor();
GlobalVar.uiBuffSize = 4096;
// Secure area to save sampling data
sMemName.s.Init(\"RTC_AI_Data\");
rmData = new RtMemory(4096 * 2, (byte)HandleSelection.ROOT_PROCESS, sMemName);
if (rmData.GetLastErr() != 0)
{
IecString80 sProcName = new IecString80();
sProcName.ctor();
sProcName.s.Init(\"\");
rmData = new RtMemory(sProcName, sMemName);
if (rmData.GetLastErr() != 0)
{
GlobalVar.inErr = true;
GlobalVar.inErrCode = rmData.GetLastErr();
return;
}
}
// Secure area to save sampling data[V]
sMemName.s.Init(\"RTC_AI_Volt\");
rmVolt = new RtMemory(4096 * 4, (byte)HandleSelection.ROOT_PROCESS, sMemName);
if (rmVolt.GetLastErr() != 0)
{
IecString80 sProcName = new IecString80();
sProcName.ctor();
sProcName.s.Init(\"\");
rmVolt = new RtMemory(sProcName, sMemName);
if (rmVolt.GetLastErr() != 0)
{
GlobalVar.inErr = true;
GlobalVar.inErrCode = rmVolt.GetLastErr();
rmData.Delete(); // Release data area
rmData = null;
return;
}
}
// Initialize global variables
GlobalVar.inErr = false;
GlobalVar.inErrCode = 0;
GlobalVar.lpData = rmData.GetMemPtr();
GlobalVar.lpVolt = rmVolt.GetMemPtr();
GlobalVar.uiPos = 0;
GlobalVar.uiOvr = 0;
}
/// <summary>
/// PLC Program - Process in reset
/// </summary>
~_main()
{
if (rmData != null)
{
rmData.Delete(); // Release data area
rmData = null;
}
if (rmVolt != null)
{
rmVolt.Delete(); // Release data area
rmVolt = null;
}
}
/// <summary>
/// PLC Program - Process in start
/// </summary>
public void __Init()
{
GlobalVar.inExe = false;
}
/// <summary>
/// PLC Program - Process in executes
/// </summary>
public unsafe void __Process()
{
if (GlobalVar.inErr)
{
GlobalVar.inExe = false; // Execute request OFF
return;
}
if (GlobalVar.inExe != true) // If Execute request is not issued
{
GlobalVar.inExe = true; // Execute request ON and start sampling
}
/* --- Write ToDo here --- */
}
}
/// <summary>
/// *****************************************************************************************************
/// Data Sampling Process Block
/// *****************************************************************************************************
/// </summary>
[FUNCTION_BLOCK]
public class _sampling
{
// *** Constant ***
private const UInt16 NEXT_STAGE = 0x0000;
private const UInt16 BREAK_STAGE = 0xFFFF;
private enum STAGE : ushort
{
_00 = 0, // Issue Sampling start command
_01 = 1, // Wait for sampling
_02 = 2 // Get Data
}
// *** Internal Variables ***
private STAGE m_NextStage;
// *** Internal Variables ***
/// <summary>
/// Stage00 : Issue Sampling start command
/// </summary>
private UInt16 STAGE_00(ref STAGE stNext)
{
// If Execute Flag is OFF, complete stage process.
if (GlobalVar.inExe == false) return BREAK_STAGE;
// Clear analog input status
pcibus.InBYTE((ushort)(GlobalVar.IOPort + 0x0006));
// Issue Sampling start command
pcibus.OutBYTE((ushort)(GlobalVar.IOPort + 0x0004), (byte)(Board.bUseCh - 1)); // CH0~CH to used
stNext = STAGE._01; // NEXT: Go to sampling waiting stage
// Go to next stage
return NEXT_STAGE;
}
/// <summary>
/// Stage01 : sampling waiting
/// </summary>
private UInt16 STAGE_01(ref STAGE stNext)
{
// If Execute Flag is OFF, complete stage process.
if (GlobalVar.inExe == false) return BREAK_STAGE;
//------------------------------------------------------------------------
// Check analog input data to confirm whether DRE(DataReadEnable:0x02) is ON or not.
// "DRE ON means to complete sampling.
//------------------------------------------------------------------------
// Check analog input status
if (0 == (0x02 & pcibus.InBYTE((ushort)(GlobalVar.IOPort + 0x0006))))
{
return BREAK_STAGE; // brake for same stage is complete since it is in sampling
}
// Complete sampling
stNext = STAGE._02; // NEXT: Data get stage
// Go to next stage
return NEXT_STAGE;
}
/// <summary>
/// Stage02 : Get data
/// </summary>
private unsafe UInt16 STAGE_02(ref STAGE stNext)
{
// get data from CH0~designated CH
for (Byte i = 0; i < Board.bUseCh; i++)
{
// Get Sampling data
GlobalVar.wData = (UInt16)(pcibus.InHWORD(GlobalVar.IOPort) & 0x0FFF); // Get Sampling data
((UInt16*)GlobalVar.lpData)[GlobalVar.uiPos] = GlobalVar.wData; // Store acquired data
// Get Sampling data[V]
GlobalVar.fData = CalcInputVolt(GlobalVar.wData); // Change acquired data to voltage value
((Single*)GlobalVar.lpVolt)[GlobalVar.uiPos] = GlobalVar.fData; // Store changed data to memory
// Refresh next write position
GlobalVar.uiPos = (GlobalVar.uiPos + 1) % GlobalVar.uiBuffSize;
if (GlobalVar.uiPos == 0)
{
GlobalVar.uiOvr=1; // Over flag ON since write to buffer end.
}
}
stNext = STAGE._00; // NEXT: First stage
// Since complete getting data, finish stage process
return BREAK_STAGE;
}
/// <summary>
/// Calculate input voltage
/// </summary>
private Single CalcInputVolt(UInt16 wData)
{
// Input Data
// Input Voltage[V] = (───── * (Output Voltage[V] - Min Voltage[V])) + Max Volage[V]
// Resolution
return (((Single)wData / (Single)Board.Resolution) * (GlobalVar.fHi - GlobalVar.fLo)) + GlobalVar.fLo;
}
/// <summary>
/// PLC Program - Process in download
/// </summary>
public _sampling()
{
}
/// <summary>
/// PLC Program - Process in reset
/// </summary>
~_sampling()
{
}
/// <summary>
/// PLC Program - Process in start
/// </summary>
public unsafe void __Init()
{
GlobalVar.inBusy = false; // Execute Flag OFF
m_NextStage = STAGE._00; // Set first stage
}
/// <summary>
/// PLC Program - Process in execute
/// </summary>
public unsafe void __Process()
{
UInt16 wRet;
UInt16 woLoopCount;
// Sampling is not executed when error is occurring
if (GlobalVar.inErr)
{
GlobalVar.inBusy = false;
return;
}
// Sampling is not executed when buffer is not get
if (GlobalVar.lpData == null)
{
GlobalVar.inBusy = false;
return;
}
// Refresh Execute Flag according to execution request
if (GlobalVar.inBusy != GlobalVar.inExe)
{
GlobalVar.inBusy = GlobalVar.inExe;
}
// If there is an execution request, start stage process
if (GlobalVar.inExe)
{
for(woLoopCount = 0; woLoopCount < 1000; woLoopCount++)
{
switch (m_NextStage)
{
case STAGE._00:
wRet = STAGE_00(ref m_NextStage); // Stage00:Issue Sampling start command
break;
case STAGE._01:
wRet = STAGE_01(ref m_NextStage); // Stage01:Wait for sampling
break;
case STAGE._02:
wRet = STAGE_02(ref m_NextStage); // Stage02:Get Data
break;
default:
wRet = BREAK_STAGE; //
break;
}
if (wRet == BREAK_STAGE)
{
break; // Complete stage process
}
}
}
return;
}
}