record5.c -- Record data with a continuous recorder.
/* record5.c */
/* Copyright(c) 1991-2007 by Motion Engineering, Inc. All rights reserved.
*
* This software contains proprietary and confidential information of
* Motion Engineering Inc., and its suppliers. Except as may be set forth
* in the license agreement under which this software is supplied, use,
* disclosure, or reproduction is prohibited without the prior express
* written consent of Motion Engineering, Inc.
*/
/*
:Record data with a continuous recorder
This program demonstrates how to use a continuous recorder to
record data gathered from an analog input source and perform
data analysis on each MPIEventTypeRECORDER_HIGH event.
The result can also be written to a text file using the processRecord function.
Upon each MPIEventTypeRECORDER_HIGH event, the function analyzeData will
loop through the data records and increment variable dataAnalysisResult
when the input triggers a user defined limit.
Warning! This is a sample program to assist in the integration of an
MEI motion controller with your application. It may not contain all
of the logic and safety features that your application requires.
The msgCHECK(...) macros used in the following sample code are intended
to convey our strong belief that ALL error return codes should be checked.
Actual application code should use specific error handling techniques (other
than msgCHECKs) best suited to your internal error recovery methods.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "stdmpi.h"
#include "stdmei.h"
#include "apputil.h"
#define RECORDER_NUMBER (0)
#define SQNODE_NUMBER (0)
#define INPUT_CHANNEL (0)
#define INPUT_MASK (0x0000FFFF)
#define PERIOD (0) /* Record every sample */
#define RECORD_COUNT (2000) /* Size of recorder records */
#define POINT_COUNT (1) /* Number of data points */
/* User defined trigger */
#define SCHMITTLOW (2000)
#define SCHMITTHIGH (4000)
/* Number of records recorded before MPIEventTypeRECORDER_HIGH is triggerred. */
#define HIGH_COUNT (2000)
long dataAnalysisResult = 0;
/* Perform basic command line parsing. (-control -server -port -trace) */
void basicParsing(int argc,
char *argv[],
MPIControlType *controlType,
MPIControlAddress *controlAddress)
{
long argIndex;
/* Parse command line for Control type and address */
argIndex = argControl(argc, argv, controlType, controlAddress);
/* Check for unknown/invalid command line arguments */
if (argIndex < argc) {
fprintf(stderr,"usage: %s %s\n", argv[0], ArgUSAGE);
exit(MPIMessageARG_INVALID);
}
}
/* Create and initialize MPI objects */
void programInit(MPIControl *control,
MPIControlType controlType,
MPIControlAddress *controlAddress,
MPIRecorder *recorder,
MPIRecorderRecord **records,
long recordCount,
MEISqNode *sqNode,
long sqNodeNumber,
MPIEventMgr *eventMgr,
MPINotify *notify,
Service *service)
{
MPIEventMask eventMask;
MPIRecorderStatus recorderStatus;
long returnValue;
/* Create motion controller object */
*control =
mpiControlCreate(controlType,
controlAddress);
msgCHECK(mpiControlValidate(*control));
/* Initialize motion controller */
returnValue =
mpiControlInit(*control);
msgCHECK(returnValue);
/* Create recorder object */
*recorder =
mpiRecorderCreate(*control, -1);
msgCHECK(mpiRecorderValidate(*recorder));
/* Create sqNode object */
*sqNode =
meiSqNodeCreate(*control, sqNodeNumber);
msgCHECK(meiSqNodeValidate(*sqNode));
/* Request notification of ALL events from recorder */
mpiEventMaskCLEAR(eventMask);
mpiEventMaskRECORDER(eventMask);
returnValue =
mpiRecorderEventNotifySet(*recorder,
eventMask,
NULL);
msgCHECK(returnValue);
/* Create event notification object for recorder*/
*notify =
mpiNotifyCreate(eventMask,
*recorder);
msgCHECK(mpiNotifyValidate(*notify));
/* Create event manager object */
*eventMgr =
mpiEventMgrCreate(*control);
msgCHECK(mpiEventMgrValidate(*eventMgr));
/* Append notify to event manager */
returnValue =
mpiEventMgrNotifyAppend(*eventMgr, *notify);
msgCHECK(returnValue);
/* Create service thread */
*service =
serviceCreate(*eventMgr,
-1, /* default (max) priority */
-1); /* -1 => enable interrupts */
meiAssert(*service != NULL);
returnValue =
mpiRecorderStatus(*recorder,
&recorderStatus,
NULL);
msgCHECK(returnValue);
/* Allocate memory for record buffer */
*records =
(MPIRecorderRecord *)meiPlatformAlloc(sizeof(MPIRecorderRecord) *
recordCount);
meiAssert(*records != NULL);
}
/* Perform certain cleanup actions and delete MPI objects */
void programCleanup(MPIControl *control,
MPIRecorder *recorder,
MPIRecorderRecord *records,
long recordCount,
MEISqNode *sqNode,
MPIEventMgr *eventMgr,
MPINotify *notify,
Service *service)
{
long returnValue;
/* Free recorder buffer */
returnValue =
meiPlatformFree(records,
(sizeof(MPIRecorderRecord) * recordCount));
meiAssert(returnValue == MPIMessageOK);
/* Delete service */
returnValue =
serviceDelete(*service);
msgCHECK(returnValue);
*service = MPIHandleVOID;
/* Delete event manager object */
returnValue =
mpiEventMgrDelete(*eventMgr);
msgCHECK(returnValue);
*eventMgr = MPIHandleVOID;
/* Delete event notification object */
returnValue =
mpiNotifyDelete(*notify);
msgCHECK(returnValue);
*notify = MPIHandleVOID;
/* Delete sqNode object */
returnValue =
meiSqNodeDelete(*sqNode);
msgCHECK(returnValue);
*sqNode = MPIHandleVOID;
/* Delete recorder object */
returnValue =
mpiRecorderDelete(*recorder);
msgCHECK(returnValue);
*recorder = MPIHandleVOID;
/* Delete motion controller object */
returnValue =
mpiControlDelete(*control);
msgCHECK(returnValue);
*control = MPIHandleVOID;
}
/* Print the records */
void analyzeData(MPIRecorderRecord *records,
long recordCount,
long inputMask)
{
MPIRecorderRecord *recordPtr;
long recordIndex;
MPI_BOOL trigger = FALSE;
/* Output record buffer to screen */
for(recordIndex = 0; recordIndex < recordCount; recordIndex++){
/* Cast records to MPIRecorderRecord pointer */
recordPtr = (MPIRecorderRecord *)&records[recordIndex];
/* Disable trigger when input is HIGH */
if ((recordPtr->point[0] & inputMask) > SCHMITTHIGH && trigger == TRUE)
{
trigger = FALSE;
dataAnalysisResult = dataAnalysisResult + 1;
printf("pills: %d\r", dataAnalysisResult);
}
/* Reset trigger when input is LOW */
if ((recordPtr->point[0] & inputMask) < SCHMITTLOW && trigger == FALSE)
trigger = TRUE;
}/* end for */
}
void writeDataToFile(MPIRecorderRecord *Record,
long recordCount,
long writeToFile)
{
/* Make sure there are records to analyze */
if (recordCount > 0)
{
FILE *outfile;
MPIRecorderRecord *record;
/* Open file if writing to file */
if(writeToFile)outfile = fopen("records.txt", "a+");
if (writeToFile?(outfile == NULL):0) /* only check if writing to file */
{ /* Error opening file */
fprintf(stderr,
"Could not open output file %s.\n",
"records.txt");
}
else
{
long recordIndex;
fprintf(writeToFile?outfile:stderr,"Recording started\n");
/* Loop through all the records */
for (recordIndex = 0; recordIndex < recordCount; recordIndex++)
{
record = (MPIRecorderRecord *)&Record[recordIndex];
fprintf(writeToFile?outfile:stderr,"%ld",record->point[0]);
fprintf(writeToFile?outfile:stderr,"\n");
}/* End for */
/* Close file at end of loop */
if(writeToFile)fclose(outfile);
}
}
}
/* Configure recorder */
configRecorder(MPIRecorder recorder,
MEISqNode sqNode,
long highCount,
long period,
long pointCount,
long inputMask)
{
MPIRecorderConfig recorderConfig; /* data recorder configuration handle */
long *analogPtr; /* analog input pointer */
long returnValue; /* return value from library */
/* Get analog input pointer */
returnValue =
meiSqNodeAnalogInPtr(sqNode,
INPUT_CHANNEL,
&inputMask,
&analogPtr);
msgCHECK(returnValue);
/* Set recorder record type */
returnValue =
mpiRecorderRecordConfig(recorder,
MPIRecorderRecordTypePOINT,
pointCount,
&analogPtr);
msgCHECK(returnValue);
/* Get recorder configuration handle */
returnValue =
mpiRecorderConfigGet(recorder,
&recorderConfig,
NULL);
msgCHECK(returnValue);
/* Config recorder parameters */
recorderConfig.period = period;
recorderConfig.highCount = highCount;
recorderConfig.bufferWrap = TRUE;
/* Set recorder configuration using handle */
returnValue =
mpiRecorderConfigSet(recorder,
&recorderConfig,
NULL);
msgCHECK(returnValue);
}
/* Start recorder with Recorder events enabled */
startRecorder(MPIRecorder recorder,
MPIRecorderRecord *records,
MPINotify notify,
long recordCount,
long highCount,
long inputMask)
{
long countGet;
long returnValue; /* return value from library */
/* Start recording */
returnValue =
mpiRecorderStart(recorder,
-1); /* -1 = continuous */
msgCHECK(returnValue);
/* Loop repeatedly */
while (meiPlatformKey(MPIWaitPOLL) <= 0) {
MPIEventStatus eventStatus;
/* Wait for recorder events */
returnValue =
mpiNotifyEventWait(notify,
&eventStatus,
MPIWaitFOREVER);
msgCHECK(returnValue);
returnValue =
mpiRecorderRecordGet(recorder,
recordCount,
(MPIRecorderRecord *)records,
&countGet);
msgCHECK(returnValue);
switch (eventStatus.type) {
case MPIEventTypeRECORDER_HIGH:{
/* Save data to text file */
writeDataToFile(records, recordCount, 1);
/* Perform data analysis */
analyzeData(records, highCount, inputMask);
break;
}/* End case */
case MPIEventTypeRECORDER_FULL:{
printf("FULL %d\n", countGet);
break;
}/* End case */
case MPIEventTypeRECORDER_DONE:{
printf("DONE %d\n", countGet);
break;
}/* End case */
default: {
printf("Unknown Current Event Status: %u \r \n", eventStatus.type);
break;
}/* End default */
}/* End switch */
}/* End while */
printf("\n");
}
/* Stop recorder */
void stopRecorder(MPIRecorder recorder)
{
long returnValue;
/* Stop recorder if not already stopped */
returnValue = mpiRecorderStop(recorder);
if(returnValue == MPIRecorderMessageSTOPPED)
{
returnValue = MPIMessageOK;
}
msgCHECK(returnValue);
}
/* Main function */
int main(int argc,
char *argv[])
{
MPIControl control; /* motion controller handle */
MPIControlType controlType;
MPIControlAddress controlAddress;
MPIRecorder recorder; /* data recorder handle */
MPIRecorderRecord *records;
MPINotify notify; /* event notification handle */
MPIEventMgr eventMgr; /* event manager handle */
Service service; /* service thread */
MEISqNode sqNode;
long recordCount = RECORD_COUNT;
long returnValue; /* return value from library */
/* Perform basic command line parsing. (-control -server -port -trace) */
basicParsing(argc,
argv,
&controlType,
&controlAddress);
/* Create and initialize MPI objects */
programInit(&control,
controlType,
&controlAddress,
&recorder,
&records,
recordCount,
&sqNode,
SQNODE_NUMBER,
&eventMgr,
¬ify,
&service);
/* Configure recorder */
configRecorder(recorder,
sqNode,
HIGH_COUNT,
PERIOD,
POINT_COUNT,
INPUT_MASK);
/* Start recorder with events enabled */
startRecorder(recorder,
records,
notify,
RECORD_COUNT,
HIGH_COUNT,
INPUT_MASK);
/* Stop recorder */
stopRecorder(recorder);
/* Perform certain cleanup actions and delete MPI objects */
programCleanup(&control,
&recorder,
records,
recordCount,
&sqNode,
&eventMgr,
¬ify,
&service);
return MPIMessageOK;
}
|