[r1]: / XYChartCurvesOverlapping.project  Maximize  Restore  History

Download this file

242 lines (209 with data), 2.7 MB

enum
-------------------------------------------------------------------------------
VisuSync
-------------------------------------------------------------------------------


PROGRAM VisuSync

VAR_INPUT
    udiCycleCounter: UDINT;
END_VAR
udiCycleCounter := udiCycleCounter +1;
-------------------------------------------------------------------------------
Overlap
-------------------------------------------------------------------------------


PROGRAM Overlap

VAR_INPUT
    xyChart: VisuStructXYChart;
    AxisX: VisuStructXYChartAxis;
    AxisY1: VisuStructXYChartAxis;
    Curve: VisuStructXYChartCurve;
    DataX: ARRAY [..] OF ;
    DataY: ARRAY [..] OF ;
    iCurveHeapSize: INT;
    iNumCurve: INT;
    xStart: BOOL;
    sText: string;
    rOffset: REAL;
    xShowTrace: BOOL;
    xNotVisMsg: BOOL;
    xChangeZoom: BOOL;
END_VAR

VAR
    xFirst: BOOL;
    xDoIt: BOOL;
    ePendingCmd: ENUM_CMD_PENDING;
    rTrigStart: R_TRIG;
    fTrigTimer: F_TRIG;
    rTrigZoom: R_TRIG;
    iCalc: INT;
    iLoop: INT;
    ix: INT;
    timer: TP;
    sampleTime: TIME;
    xTimerEnd: BOOL;
    rXValue: REAL;
    rYValue: REAL;
    udiCycleCounter: UDINT;
    udiCycleWait: UDINT;
    tDelay: TON;
    xDelay: BOOL;
    xDelayEnd: BOOL;
    iActualZoom: INT;
END_VAR
(**********************************************************************************************
   The scope of this application is to show how to use XYChart element in overlapping mode.
   It simply generates a curve and when the curve arrives at a certain point,
   it informs the element to push it in the heap.
   The next curve is generated with an offset on X and Y, to have the possibility to see the 
   difference with the previous one.
   When we reach the maximum number of curves to display, we will clean all and start again
***********************************************************************************************)


//------------------------------------------------------------------
// Initial settings
IF xFirst THEN
   Curve.iCurveHeapSize := iCurveHeapSize;                  // We will maintain 4 curves in the heap
   Curve.eOverlap := VisuEnumXYChartCvOverlapType.OVERLAP;  // We will work in overlapping mode 
   Curve.diIndexMin := 1;                                   // We set the initial indexes to use
   Curve.diIndexMax := 1;
   iNumCurve := Curve.iCurveHeapSize;                       // We will display as many curves as the heap size
   xNotVisMsg := TRUE;
END_IF

//------------------------------------------------------------------
// We change the text of the button
IF xStart THEN
   sText := 'Stop drawing';
ELSE   
   sText := 'Start drawing';
END_IF   

//------------------------------------------------------------------
// We enable/disable the tracking of the curve drawing using level lines
xDoIt := FALSE;
IF xShowTrace THEN
   xDoIt := TRUE;
END_IF   
AxisX.aLevelLine[1].xEnable  := xDoIt;
AxisY1.aLevelLine[1].xEnable := xDoIt;

//------------------------------------------------------------------
// Detect the zoom cahnging 
rTrigZoom(CLK:=xChangeZoom, Q=>xDoIt);
IF xDoIt THEN
   xChangeZoom := xDoIt := FALSE;
   IF iActualZoom = 0 THEN
      iActualZoom := 1;
      AxisX.rMin := -5;
      AxisX.rMax := 20;
      AxisY1.rMin := 0;
      AxisY1.rMax := 10;
   ELSE   
      iActualZoom := 0;
      AxisX.rMin := -2;
      AxisX.rMax := 15;
      AxisY1.rMin := -1;
      AxisY1.rMax := 5;
	END_IF
END_IF   
 
//------------------------------------------------------------------
// We start the curve drawing 
rTrigStart(CLK:=xStart, Q=>xDoIt);
IF xDoIt THEN
   xDoIt := FALSE;
   // We clean up the arrays
   FOR ix := 1 TO 200 BY 1 DO
       DataX[ix] := 0.0;
       DataY[ix] := 0.0;
   END_FOR
   iCalc := 1;          // The initial calculation point of our curve
   iLoop := 0;          // No loop right now
   rOffset := 0.0;      // No curve offset right now
   
   // If we did a "start" and next a "stop", we can have some curves in the heap.
   // In this way we will remove them
   Curve.eCurveHeapCmd := VisuEnumXYChartCvHeapCmd.CLEAN;
   udiCycleCounter := VisuSync.udiCycleCounter;  // Save cycle counter 
   ePendingCmd := ENUM_CMD_PENDING.CLEAN;
   udiCycleWait := 10;                 // How many cycle to wait the command ending  
   xNotVisMsg := TRUE;
END_IF

//------------------------------------------------------------------
// Timer for data generation 
timer(IN:=xStart, PT:=sampleTime, Q=>xTimerEnd) ;
IF xTimerEnd = FALSE THEN
   timer(IN:=xTimerEnd, PT:=sampleTime, Q=>xTimerEnd) ;
END_IF ;
	
// Timer clock detection
fTrigTimer(CLK:=xTimerEnd, Q=>xDoIt) ;
IF xDoIt THEN
   xDoIt := FALSE;
   IF (ePendingCmd = ENUM_CMD_PENDING.NO_CMD) AND NOT xDelay THEN   // only if we don't have pending command
      
      // When arrive the tick of the clock
      // we do the curve calculation
      IF iCalc <= 126 THEN                            // If we are in the calculation limit
         FctGetXYValues(iCalc-1, rXValue, rYValue);   // Get new values  
         DataX[iCalc] := rXValue + rOffset;           // Store the value in the arrays
         DataY[iCalc] := rYValue + rOffset;
         Curve.diIndexMax := iCalc;                   // The last valid value in the array 
         iCalc := iCalc+1;                      
      ELSE                       // We have finish to calculate the curve
         xDelay := TRUE;         // Enable delay time to finish the display curve
		END_IF
      AxisX.aLevelLine[1].rValue  := DataX[Curve.diIndexMax];      // Update the position for curve tracking
      AxisY1.aLevelLine[1].rValue := DataY[Curve.diIndexMax];
   END_IF
END_IF

//------------------------------------------------------------------
// Test the delay time to finish the display curve 
tDelay(IN:=xDelay, PT:=T#2S, Q=>xDelayEnd);
IF xDelay THEN
   IF xDelayEnd THEN
      xDelay := FALSE;
      
      // We have finish to calculate the curve
      iCalc := 1;                            // Reset the calculation value
      iLoop := iLoop+1;                      // We are facing a new loop
      IF iLoop < iNumCurve THEN              // I've room again, update the curve !
         Curve.eCurveHeapCmd := VisuEnumXYChartCvHeapCmd.UPDATE;     // We update the curve
         ePendingCmd := ENUM_CMD_PENDING.UPDATE;  // Update pending
      ELSE                                   // Heap full
         iLoop := 0 ;                        // We will start with a neww loop
         Curve.eCurveHeapCmd := VisuEnumXYChartCvHeapCmd.CLEAN;     // We clean the heap   
         ePendingCmd := ENUM_CMD_PENDING.CLEAN;   // Clean 
         udiCycleWait := 50;                 // How many cycle to wait the command ending, to have time to see the last curve, before clean all 
         xNotVisMsg := FALSE;
      END_IF    
	END_IF
   udiCycleCounter := VisuSync.udiCycleCounter;  // save cycle counter 
END_IF

//------------------------------------------------------------------
// If there's a clean command pending, we wait some cycles
// to have the possibility to see the last curve
IF ePendingCmd = ENUM_CMD_PENDING.CLEAN THEN
   IF (ABS(VisuSync.udiCycleCounter - udiCycleCounter) > udiCycleWait) AND (Curve.eCurveHeapCmd = VisuEnumXYChartCvHeapCmd.NO) THEN
      iLoop := 0 ;                        // We will start with a neww loop
      rOffset := 0.0;                     // No curve offset
      ePendingCmd := ENUM_CMD_PENDING.NO_CMD;      
      xNotVisMsg := TRUE;
   END_IF
END_IF

//----------------------------------------------------------------------------------------
// If there's an update command pending, we simply wait the end of the command
IF ePendingCmd = ENUM_CMD_PENDING.UPDATE THEN
   IF Curve.eCurveHeapCmd = VisuEnumXYChartCvHeapCmd.NO THEN
      iCalc := 1;                         // Reset the calculation value
      rOffset := rOffset + 0.3;           // Next curve will have an offset
      Curve.diIndexMax := iCalc;          // Reset to init curve
      ePendingCmd := ENUM_CMD_PENDING.NO_CMD;      
      xNotVisMsg := TRUE;
   END_IF
END_IF

xFirst := FALSE;



VAR_INPUT
    iValue: INT;
    rXValue: REFERENCE TO REAL;
    rYValue: REFERENCE TO REAL;
END_VAR

VAR
    rValue: REAL;
END_VAR
// X = t − 2 sin t
// Y = 2 − 2 cos t

rValue  := INT_TO_REAL(iValue);
rValue  := rValue/10.0;
rXValue := rValue - 2.0*SIN(rValue);
rYValue := 2.0 - 2.0*COS(rValue);