NemV4Test.cpp
The example shows how to use the Nemesys V4 API from application code.
#include <nem4_rs232_api.h>
#include <math.h>
#include <stdio.h>
/**
* If the returned result is an error, then print the error and return the
* error code
*/
#define RETURN_ON_ERROR(_result_) \
if ((_result_) < ERR_NOERR) { \
showError(_result_, __LINE__); \
return (_result_); }
/**
* Checks the given expression
*/
#define CHECK(_result_) \
if (!(_result_)) { \
printf("Check in line %d failed: %s\n", __LINE__, #_result_); \
fprintf(stderr, "Check in line %d failed: %s\n", __LINE__, #_result_); }
/**
* Print error code and error description via CsiErrorToString() to std::out
*/
static long showError(long ErrCode, int Line)
{
if (ErrCode < 0)
{
printf("Error in line %d: 0x%08x: - %s\n", Line, (uint32_t)abs(ErrCode), CsiErrorToString(ErrCode));
fprintf(stderr, "Error in line %d: 0x%08x: - %s\n", Line, (uint32_t)abs(ErrCode), CsiErrorToString(ErrCode));
}
return ErrCode;
}
/**
* Waits until pump stops
*/
{
long Result;
/**
* Poll the device until dosing has been finished
*/
do
{
double Level_ul;
Result = NemV4GetSyringeLevel(Nemesys, &Level_ul);
double Flow_ul_min;
Result = NemV4GetCurrentFlow(Nemesys, &Flow_ul_min);
printf("Level_ul: %f Flow_ul_min: %f\n", Level_ul, Flow_ul_min);
Result = NemV4IsStopped(Nemesys);
RETURN_ON_ERROR(Result);
CSI_SLEEP_MS(100);// do not block CPU
} while (0 == Result);
return Result;
}
/**
* Test unit conversion functions
*/
{
long Result;
printf("\n\ntestUnits ---------------------------------------------------\n");
printf("MinPos_mm: %f\n", MinPos_mm);
printf("MaxVel_mm_s: %f\n", MaxVel_mm_s);
printf("MaxVel_mm_min: %f\n", MaxVel_mm_min);
printf("SyringeArea_mm2: %f\n", SyringeArea_mm2);
double MaxFlow_ul_min = MaxVel_mm_min * SyringeArea_mm2;
printf("MaxFlow_ul_min: %f\n", MaxFlow_ul_min);
double MaxVolume_ul = (0 - MinPos_mm) * SyringeArea_mm2;
printf("MaxVolume_ul: %f\n", MaxVolume_ul);
printf("MaxVel_mm_min: %f\n", NemV4DeviceVelToMillimetresPerMinute(Nemesys1, Nemesys1->MaxVelocity));
printf("MaxLevel_ul: %f\n", MaxLevel_ul);
printf("MaxFlow_ul_min: %f\n", MaxFlow_ul_min);
int32_t MaxLevelPos = NemV4MicrolitresToDevicePos(Nemesys1, MaxLevel_ul);
printf("MaxLevelPos: %d\n", MaxLevelPos);
int32_t MaxVel = NemV4MicrolitresPerMinuteToDeviceVel(Nemesys1, MaxFlow_ul_min);
printf("MaxVel: %d\n", MaxVel);
Result = NemV4GetMaxFlow(Nemesys1, &MaxFlow_ul_min);
RETURN_ON_ERROR(Result);
printf("NemV4GetMaxFlow: %f\n", MaxFlow_ul_min);
NemV4GetMaxSyringeLevel(Nemesys1, &MaxLevel_ul);
RETURN_ON_ERROR(Result);
printf("NemV4GetMaxSyringeLevel: %f\n", MaxLevel_ul);
}
/**
* Tests the basic move functionality with device specific units
*/
{
long Result;
int32_t PosIs;
printf("\n\ntestBasicMoveFunctions --------------------------------------\n");
Result = NemV4GetPosIs(Nemesys1, &PosIs);
RETURN_ON_ERROR(Result);
printf("PosIs : %d\n", PosIs);
RETURN_ON_ERROR(Result);
CSI_SLEEP_MS(100);// give drive some time to start
Result = NemV4IsStopped(Nemesys1);
RETURN_ON_ERROR(Result);
printf("NemV4IsStopped: %ld\n", Result);
CHECK(0 == Result);
CSI_SLEEP_MS(2000);// give drive some time to move
Result = NemV4Stop(Nemesys1);
RETURN_ON_ERROR(Result);
CSI_SLEEP_MS(100);// give drive some time to stop
Result = NemV4IsStopped(Nemesys1);
RETURN_ON_ERROR(Result);
CHECK(1 == Result);
printf("NemV4IsStopped: %ld\n", Result);
RETURN_ON_ERROR(Result);
CSI_SLEEP_MS(100);// give drive some time to start
/**
* Poll the device until dosing has been finished
*/
do
{
int32_t PosIs;
Result = NemV4GetPosIs(Nemesys1, &PosIs);
RETURN_ON_ERROR(Result);
printf("PosIs : %d\n", PosIs);
Result = NemV4IsStopped(Nemesys1);
RETURN_ON_ERROR(Result);
CSI_SLEEP_MS(100);// do not block CPU
} while (0 == Result);
RETURN_ON_ERROR(Result);
return ERR_NOERR;
}
/**
* Tests set syringe level functionality
*/
{
long Result;
double MaxLevel_ul;
double MaxFlow_ul_min;
printf("\n\ntestSetSyringeLevel -----------------------------------------\n");
Result = NemV4GetMaxSyringeLevel(Nemesys1, &MaxLevel_ul);
RETURN_ON_ERROR(Result);
Result = NemV4GetMaxFlow(Nemesys1, &MaxFlow_ul_min);
RETURN_ON_ERROR(Result);
Result = NemV4SetSyringeLevel(Nemesys1, MaxLevel_ul, MaxFlow_ul_min);
RETURN_ON_ERROR(Result);
CSI_SLEEP_MS(100);// give drive some time to start
Result = waitForStopped(Nemesys1);
RETURN_ON_ERROR(Result);
Result = NemV4SetSyringeLevel(Nemesys1, 0, MaxFlow_ul_min);
RETURN_ON_ERROR(Result);
CSI_SLEEP_MS(1000);// give drive some time to start
Result = waitForStopped(Nemesys1);
RETURN_ON_ERROR(Result);
return ERR_NOERR;
}
/**
* Tests dose volume functionality
*/
{
long Result;
int32_t Distance = Nemesys1->MinPos / 10;
double MaxLevel_ul;
double MaxFlow_ul_min;
printf("\n\ntestDoseVolume ----------------------------------------------\n");
RETURN_ON_ERROR(Result);
Result = waitForStopped(Nemesys1);
RETURN_ON_ERROR(Result);
Distance = 0 - Distance;
Result = NemV4MoveDistance(Nemesys1, Distance, Nemesys1->MaxVelocity);
RETURN_ON_ERROR(Result);
Result = waitForStopped(Nemesys1);
RETURN_ON_ERROR(Result);
Result = NemV4GetMaxSyringeLevel(Nemesys1, &MaxLevel_ul);
RETURN_ON_ERROR(Result);
Result = NemV4GetMaxFlow(Nemesys1, &MaxFlow_ul_min);
RETURN_ON_ERROR(Result);
double Volume_ul = MaxLevel_ul / 5;
Result = NemV4DoseVolume(Nemesys1, Volume_ul, MaxFlow_ul_min);
RETURN_ON_ERROR(Result);
Result = waitForStopped(Nemesys1);
RETURN_ON_ERROR(Result);
Volume_ul = 0 - Volume_ul;
Result = NemV4DoseVolume(Nemesys1, Volume_ul, MaxFlow_ul_min);
RETURN_ON_ERROR(Result);
Result = waitForStopped(Nemesys1);
RETURN_ON_ERROR(Result);
return ERR_NOERR;
}
/**
* Test generate flow functionality
*/
{
double MaxFlow_ul_min;
long Result;
printf("\n\ntestGenerateFlow --------------------------------------------\n");
Result = NemV4GetMaxFlow(Nemesys1, &MaxFlow_ul_min);
RETURN_ON_ERROR(Result);
Result = NemV4GenerateFlow(Nemesys1, -MaxFlow_ul_min);
RETURN_ON_ERROR(Result);
Result = waitForStopped(Nemesys1);
RETURN_ON_ERROR(Result);
Result = NemV4GenerateFlow(Nemesys1, MaxFlow_ul_min);
RETURN_ON_ERROR(Result);
CSI_SLEEP_MS(3000);
Result = NemV4Stop(Nemesys1);
RETURN_ON_ERROR(Result);
return ERR_NOERR;
}
/**
* Tests analog in reading
*/
{
long Result;
printf("\n\ntestAnalogInReading -----------------------------------------\n");
int16_t AnalogValue_mV;
RETURN_ON_ERROR(Result);
printf("Analog %d: %d mV", NEM4_ANALOG_IN_EXTERNAL , AnalogValue_mV);
RETURN_ON_ERROR(Result);
printf("Analog %d: %d mV", NEM4_ANALOG_IN_FORCE_SENSOR , AnalogValue_mV);
return ERR_NOERR;
}
/**
* Tests setting of digital outputs
*/
{
long Result;
uint32_t DigOutMask = NEM4_DIG_OUT_BLUE_LED;
printf("\n\ntestDigitalOutputs ------------------------------------------\n");
//
// Blink the blue LED with frequency of 1 HZ using NemV4WriteDigitalOutputs
//
for (int i = 0; i < 5; ++i)
{
RETURN_ON_ERROR(Result);
CSI_SLEEP_MS(500);
Result = NemV4WriteDigitalOutputs(Nemesys1, DigOutMask, NEM4_DIG_OUT_BLUE_LED);
RETURN_ON_ERROR(Result);
CSI_SLEEP_MS(500);
}
//
// Blink the blue LED with frequency of 2 HZ using NemV4WriteDigitalOutput
//
for (int i = 0; i < 5; ++i)
{
RETURN_ON_ERROR(Result);
CSI_SLEEP_MS(250);
Result = NemV4WriteDigitalOutput(Nemesys1, NEM4_DIG_OUT_BLUE_LED, 1);
RETURN_ON_ERROR(Result);
CSI_SLEEP_MS(250);
}
return ERR_NOERR;
}
/**
* Test valve switching function
*/
{
long Result;
printf("\n\ntestValveSwitching ------------------------------------------\n");
//
// Cycle through all 4 valve positions
//
for (uint8_t ValvePosition = 0; ValvePosition <= 3; ++ValvePosition)
{
Result = NemV4SwitchValve(Nemesys1, ValvePosition);
RETURN_ON_ERROR(Result);
CSI_SLEEP_MS(1000);
}
return ERR_NOERR;
}
/**
* Tests force monitoring switching
*/
{
long Result;
uint32_t DigInputs;
printf("\n\ntestForceMonitoringSwitching --------------------------------\n");
//
// Normally safety stop should be inactive
//
Result = NemV4IsSafetyStopActive(Nemesys1);
RETURN_ON_ERROR(Result);
printf("SafetyStop: %ld\n", Result);
CHECK(0 == Result);
//
// We disable force monitoring - this should cause an activaton of the
// safety stop
//
Result = NemV4EnableForceMonitoring(Nemesys1, 0);
RETURN_ON_ERROR(Result);
//
// Safety stop should be on now
//
Result = NemV4IsSafetyStopActive(Nemesys1);
RETURN_ON_ERROR(Result);
printf("SafetyStop: %ld\n", Result);
CHECK(1 == Result);
//
// If safety stop is active, then the device should be disabled
//
Result = NemV4IsEnabled(Nemesys1);
RETURN_ON_ERROR(Result);
printf("IsEnabled: %ld\n", Result);
CHECK(0 == Result);
//
// We enable force monitoring - this should clear the safety stop
//
Result = NemV4EnableForceMonitoring(Nemesys1, 1);
RETURN_ON_ERROR(Result);
//
// Force monitoring is enabled so safety stop should be cleared now
//
Result = NemV4IsSafetyStopActive(Nemesys1);
RETURN_ON_ERROR(Result);
printf("SafetyStop: %ld\n", Result);
CHECK(0 == Result);
Result = NemV4SetEnabled(Nemesys1);
RETURN_ON_ERROR(Result);
//
// Now device should be enabled again
//
Result = NemV4IsEnabled(Nemesys1);
RETURN_ON_ERROR(Result);
printf("IsEnabled: %ld\n", Result);
CHECK(1 == Result);
return ERR_NOERR;
}
/**
* Tests force monitoring
*/
{
float Force_kN;
long Result;
printf("\n\ntestForceMonitoring -----------------------------------------\n");
Result = NemV4ReadForceSensor(Nemesys1, &Force_kN);
RETURN_ON_ERROR(Result);
printf("Force: %f kN\n", Force_kN);
Result = NemV4WriteForceLimit(Nemesys1, 0.1);
RETURN_ON_ERROR(Result);
return ERR_NOERR;
}
int main(int argc, char *argv[])
{
TNemesysV4 Nemesys1;
long Result;
//
// Disable std stream buffering for immediate output
//
setbuf(stdout, NULL);
setbuf(stderr, NULL);
printf("\n\nNemesys V4 API Test =========================================\n");
//
// First open the serial port 1 (on Windows COM6) with a baudrate of
// 115200 and a timeout value of 100 ms
//
RETURN_ON_ERROR(Result);
//
// If the port is open, we initialize the device object Nemesys1.
//
RETURN_ON_ERROR(Result);
//
// Now the device object is properly initialized and we can print some
// information from the initialized device object members
//
//
// Enable force monitoring - pumping is only possible if force monitoring
// is enabled
//
Result = NemV4EnableForceMonitoring(&Nemesys1, 1);
RETURN_ON_ERROR(Result);
//
// Ensure that device is not in fault state after power up
//
Result = NemV4ClearFault(&Nemesys1);
RETURN_ON_ERROR(Result);
//
// Now we enable the drive - after this call the position controller is
// active and the drive power stage is powered
//
Result = NemV4SetEnabled(&Nemesys1);
RETURN_ON_ERROR(Result);
//
// Check if enabling the device was successful - if not, then something
// went wrong and you should check errors
//
Result = NemV4IsEnabled(&Nemesys1);
RETURN_ON_ERROR(Result);
CHECK(1 == Result);
//
// Now run the various tests
//
Result = testUnits(&Nemesys1);
RETURN_ON_ERROR(Result);
Result = testBasicMoveFunctions(&Nemesys1);
RETURN_ON_ERROR(Result);
Result = testSetSyringeLevel(&Nemesys1);
RETURN_ON_ERROR(Result);
Result = testDoseVolume(&Nemesys1);
RETURN_ON_ERROR(Result);
Result = testGenerateFlow(&Nemesys1);
RETURN_ON_ERROR(Result);
Result = testAnalogInReading(&Nemesys1);
RETURN_ON_ERROR(Result);
Result = testDigitalOutputs(&Nemesys1);
RETURN_ON_ERROR(Result);
Result = testValveSwitching(&Nemesys1);
RETURN_ON_ERROR(Result);
Result = testForceMonitoringSwitching(&Nemesys1);
RETURN_ON_ERROR(Result);
Result = testForceMonitoring(&Nemesys1);
RETURN_ON_ERROR(Result);
//
// Now close the connection to the device
//
RETURN_ON_ERROR(Result);
printf("\n\nNemesys V4 API Test finished ================================\n");
return EXIT_SUCCESS;
}