capi_nemesys_forcemon_test.cpp

The source code shows how to use the force monitoring functionality of newer Nemesys 4 devices.

//============================================================================
/// \file capi_nemesys_test.cpp
/// \author Uwe Kindler
/// \date 11.07.2012
/// \brief Test of labbCAN pump API
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
#include <chrono>
#include <vector>
#include <labbcan/common/labbcan_test_helpers.h>
#include <usl/core/Thread.h>
#include <usl/core/PollingTimer.h>
#include <usl/math/uslmath.h>
#include <log4cplus/logger.h>
#include <diag/diag.h>
using namespace Usl;
#define BOOST_TEST_MODULE capi_nemesys_forcemon_test
#include <boost/test/unit_test.hpp>
using namespace boost::unit_test;
/**
* Make available program's arguments to all tests, recieving
* this fixture.
*/
struct ArgsFixture {
ArgsFixture(): argc(framework::master_test_suite().argc),
argv(framework::master_test_suite().argv){}
int argc;
char **argv;
};
BOOST_GLOBAL_FIXTURE( ArgsFixture );
//============================================================================
// DATA TYPES
//============================================================================
//============================================================================
// GLOBAL DATA
//============================================================================
dev_hdl Nemesys;
long Result;
//============================================================================
// Initialize C-API - open bus library
//============================================================================
BOOST_FIXTURE_TEST_CASE(testCapiOpen, ArgsFixture)
{
using namespace boost::unit_test;
const char* ConfigPath = "config/testconfig_qmixsdk";
if (argc > 1)
{
ConfigPath = argv[1];
}
Result = LCB_Open(ConfigPath, 0);
CAPI_REQUIRE_ERR_NOERR(Result);
}
//============================================================================
// Checks if retrieval of pump devices works properly
//============================================================================
BOOST_AUTO_TEST_CASE(testDeviceNameLookup)
{
Result = LCP_LookupPumpByName("Nemesys_S_1_Pump", &Nemesys);
CAPI_REQUIRE_ERR_NOERR(Result);
}
//============================================================================
// Test force monitoring config
//============================================================================
BOOST_AUTO_TEST_CASE(testForceMonitoringConfig)
{
Result = LCP_HasForceMonitoring(Nemesys);
BOOST_REQUIRE_EQUAL(1, Result);
int Prefix;
int ForceUnit;
Result = LCP_GetForceUnit(Nemesys, &Prefix, &ForceUnit);
BOOST_CHECK_EQUAL(Result, ERR_NOERR);
BOOST_TEST_MESSAGE("Force unit prefix: " << Prefix);
BOOST_TEST_MESSAGE("Force unit: " << ForceUnit);
double MaxForce;
Result = LCP_GetMaxDeviceForce(Nemesys, &MaxForce);
BOOST_CHECK_EQUAL(Result, ERR_NOERR);
BOOST_TEST_MESSAGE("Max. device force: " << MaxForce);
}
//============================================================================
// Checks if start of bus and logging works properly
//============================================================================
BOOST_AUTO_TEST_CASE(testBusStart)
{
Result = LCB_Start();
BOOST_CHECK_EQUAL(Result, ERR_NOERR);
Result = LCB_Log("C-API Log Test Message");
BOOST_CHECK_EQUAL(Result, ERR_NOERR);
}
//============================================================================
// Checks if enabling pumps works properly
//============================================================================
BOOST_AUTO_TEST_CASE(testPumpEnable)
{
Result = LCP_IsInFaultState(Nemesys);
BOOST_CHECK_GT(Result, -1);
if (Result)
{
Result = LCP_ClearFault(Nemesys);
BOOST_CHECK_EQUAL(Result, ERR_NOERR);
}
Result = LCP_Enable(Nemesys);
BOOST_CHECK_EQUAL(Result, ERR_NOERR);
CThread::sleep(500);// give pump some time to process enable request
Result = LCP_IsEnabled(Nemesys);
BOOST_CHECK_GT(Result, 0);
}
//============================================================================
void resolveForceOverload(dev_hdl Pump)
{
BOOST_TEST_MESSAGE("Resolving force overload...");
//
// We disable force monitoring
//
Result = LCP_EnableForceMonitoring(Pump, 0);
BOOST_REQUIRE_EQUAL(ERR_NOERR, Result);
//
// Normally force safety stop should be inactive now
//
BOOST_CHECK_EQUAL(Result, 0);
double MaxFlow;
Result = LCP_GetFlowRateMax(Nemesys, &MaxFlow);
BOOST_REQUIRE_EQUAL(ERR_NOERR, Result);
//
// Now reduce force by aspirating
//
double Flow = 0 - (MaxFlow / 100);
Result = LCP_GenerateFlow(Pump, Flow);
BOOST_REQUIRE_EQUAL(ERR_NOERR, Result);
int SafetyStopActive;
double CurrentForce;
do
{
SafetyStopActive = LCP_IsForceSafetyStopActive(Pump);
Result = LCP_ReadForceSensor(Pump, &CurrentForce);
if (Result < 0)
{
break;
}
BOOST_TEST_MESSAGE("Current force: " << CurrentForce);
CThread::sleep(500);
} while (!SafetyStopActive);
if (!SafetyStopActive)
{
BOOST_FAIL("Failed to reduce force");
return;
}
//
// We enable force monitoring
//
Result = LCP_EnableForceMonitoring(Pump, 1);
BOOST_REQUIRE_EQUAL(ERR_NOERR, Result);
//
// Force monitoring should be on now
//
Result = LCP_IsForceMonitoringEnabled(Nemesys);
BOOST_REQUIRE_EQUAL(1, Result);
//
// Safety stop should be cleared now
//
Result = LCP_IsForceSafetyStopActive(Nemesys);
BOOST_CHECK_EQUAL(Result, 0);
//
// Now we reduce the force to almost 0
//
Result = LCP_GenerateFlow(Pump, Flow);
BOOST_REQUIRE_EQUAL(ERR_NOERR, Result);
do
{
Result = LCP_ReadForceSensor(Pump, &CurrentForce);
if (ERR_NOERR == Result)
{
BOOST_TEST_MESSAGE("Current force: " << CurrentForce);
CThread::sleep(500);
}
} while(ERR_NOERR == Result && CurrentForce > 0.04);
LCP_StopPumping(Nemesys);
BOOST_REQUIRE_EQUAL(ERR_NOERR, Result);
}
//============================================================================
void testSafetyStop(dev_hdl Pump)
{
BOOST_TEST_MESSAGE("Producing force overload...");
//
// We enable force monitoring
//
Result = LCP_EnableForceMonitoring(Pump, 1);
BOOST_REQUIRE_EQUAL(ERR_NOERR, Result);
//
// Normally force safety stop should be inactive now
//
BOOST_CHECK_EQUAL(Result, 0);
double MaxFlow;
Result = LCP_GetFlowRateMax(Nemesys, &MaxFlow);
BOOST_REQUIRE_EQUAL(ERR_NOERR, Result);
//
// Now generate force by moving against a fixed block
//
double Flow = MaxFlow / 100;
Result = LCP_GenerateFlow(Pump, Flow);
BOOST_REQUIRE_EQUAL(ERR_NOERR, Result);
//
// Wait until safety stop is active
//
int SafetyStopActive;
do
{
SafetyStopActive = LCP_IsForceSafetyStopActive(Pump);
double CurrentForce;
Result = LCP_ReadForceSensor(Pump, &CurrentForce);
if (Result < 0)
{
break;
}
BOOST_TEST_MESSAGE("Current force: " << CurrentForce);
CThread::sleep(500);
} while (!SafetyStopActive);
if (!SafetyStopActive)
{
BOOST_FAIL("Failed to generate force overload");
return;
}
}
//============================================================================
// Test force monitoring
//============================================================================
BOOST_AUTO_TEST_CASE(testForceMonitoring)
{
double CurrentForce;
double ForceLimit = 0.11;
Result = LCP_WriteForceLimit(Nemesys, ForceLimit);
CAPI_REQUIRE_ERR_NOERR(Result);
//
// Check if force safety stop is active
//
int SafetyStopActive = LCP_IsForceSafetyStopActive(Nemesys);
BOOST_REQUIRE_GE(0, SafetyStopActive);
//
// If safety stop is not active, we try to produce a force overload situation
// by dispensing (moving the pusher against a fixed block)
//
if (!SafetyStopActive)
{
testSafetyStop(Nemesys);
}
//
// We are in a force overload situation and try to reduce the force by
// aspirating
//
resolveForceOverload(Nemesys);
//
// Now we activate the safety stop again by producing a force overload
//
testSafetyStop(Nemesys);
do
{
SafetyStopActive = LCP_IsForceSafetyStopActive(Nemesys);
CThread::sleep(1000);
if (SafetyStopActive < ERR_NOERR)
{
Result = SafetyStopActive;
break;
}
Result = LCP_ReadForceSensor(Nemesys, &CurrentForce);
if (Result < ERR_NOERR)
{
break;
}
//
// If the force has been lowered by 20 N then we call LCP_ClearForceSafetyStop()
// to resolve the force overload situation
//
if ((ForceLimit - 0.02) > CurrentForce)
{
Result = LCP_ClearForceSafetyStop(Nemesys);
if (Result < ERR_NOERR)
{
break;
}
}
BOOST_TEST_MESSAGE("Safety stop active - please lower force manually below "
<< (ForceLimit - 0.02) << " kN");
} while (SafetyStopActive);
}
//============================================================================
// Test force monitoring switching
//============================================================================
BOOST_AUTO_TEST_CASE(testForceMonitoringSwitching)
{
//
// Normally force safety stop should be inactive
//
Result = LCP_IsForceSafetyStopActive(Nemesys);
BOOST_CHECK_EQUAL(Result, 0);
//
// We disable force monitoring - this should cause and activation of the
// safety stop
//
Result = LCP_EnableForceMonitoring(Nemesys, 0);
BOOST_REQUIRE_EQUAL(ERR_NOERR, Result);
//
// Force monitoring should be off now
//
Result = LCP_IsForceMonitoringEnabled(Nemesys);
BOOST_REQUIRE_EQUAL(0, Result);
//
// Safety stop should be on now
//
Result = LCP_IsForceSafetyStopActive(Nemesys);
BOOST_CHECK_EQUAL(Result, 1);
//
// If safety stop is on, then pump should not be enabled
//
Result = LCP_IsEnabled(Nemesys);
BOOST_REQUIRE_EQUAL(0, Result);
//
// We enable force monitoring - this should clear the safety stop
//
Result = LCP_EnableForceMonitoring(Nemesys, 1);
BOOST_REQUIRE_EQUAL(ERR_NOERR, Result);
//
// Force monitoring should be on now
//
Result = LCP_IsForceMonitoringEnabled(Nemesys);
BOOST_REQUIRE_EQUAL(1, Result);
//
// Safety stop should be cleared now
//
Result = LCP_IsForceSafetyStopActive(Nemesys);
BOOST_CHECK_EQUAL(Result, 0);
//
// Now pump should be enabled again
//
Result = LCP_IsEnabled(Nemesys);
BOOST_REQUIRE_EQUAL(1, Result);
}
//============================================================================
// Checks if C-API can get closed properly
//============================================================================
BOOST_AUTO_TEST_CASE(testCapiClose)
{
Result = LCB_Stop();
BOOST_CHECK_EQUAL(ERR_NOERR, Result);
Result = LCB_Close();
BOOST_CHECK_EQUAL(ERR_NOERR, Result);
}
//---------------------------------------------------------------------------
// EOF capi_test.cpp