Skip to content

Instantly share code, notes, and snippets.

@clarle
Created May 9, 2013 14:39
Show Gist options
  • Save clarle/5547861 to your computer and use it in GitHub Desktop.
Save clarle/5547861 to your computer and use it in GitHub Desktop.
Standa device adapter for Micro-Manager
///////////////////////////////////////////////////////////////////////////////
// FILE: Standa.cpp
// PROJECT: Micro-Manager
// SUBSYSTEM: DeviceAdapters
//-----------------------------------------------------------------------------
// DESCRIPTION: Standa device adapters: 8SMC1-USBhF Microstep Driver
//
// COPYRIGHT: Leslie Lab, McGill University, Montreal, 2013
//
// LICENSE: This file is distributed under the BSD license.
//
// This file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES.
//
// AUTHOR: Clarence Leung, clarence.leung@mail.mcgill.ca, 2013
//
#ifdef WIN32
#include <windows.h>
#define snprintf _snprintf
#endif
#include "Standa.h"
#include <cstdio>
#include <string>
const char* StandaZStage::DeviceName_ = "ZStage";
const char* g_Standa_ZStageAxisLimitUm = "Limit_um";
const char* g_Standa_ZStageSerialNumber = "Serial Number";
USMC_Devices deviceList;
///////////////////////////////////////////////////////////////////////////////
// Exported MMDevice API
///////////////////////////////////////////////////////////////////////////////
MODULE_API void InitializeModuleData()
{
AddAvailableDeviceName(StandaZStage::DeviceName_, "Standa Z Stage");
}
MODULE_API MM::Device* CreateDevice(const char* deviceName)
{
if (deviceName == 0)
return 0;
if (strcmp(deviceName, StandaZStage::DeviceName_) == 0)
{
StandaZStage* s = new StandaZStage();
return s;
}
return 0;
}
MODULE_API void DeleteDevice(MM::Device* pDevice)
{
delete pDevice;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// ZStage
StandaZStage::StandaZStage() :
initialized_(false),
stepSizeUm_(0.001),
axisLimitUm_(500.0),
stepDivisor_(8),
stageSpeed_(2000.0),
serialNumber_(""),
deviceNumber_(NULL)
{
InitializeDefaultErrorMessages();
// create pre-initialization properties
// ------------------------------------
// Name
CreateProperty(MM::g_Keyword_Name, StandaZStage::DeviceName_, MM::String, true);
// Description
CreateProperty(MM::g_Keyword_Description, "Standa Z-stage driver adapter", MM::String, true);
CPropertyAction* pAct;
// Serial Number
pAct = new CPropertyAction (this, &StandaZStage::OnSerialNumber);
CreateProperty(g_Standa_ZStageSerialNumber, "Undefined", MM::String, false, pAct, true);
// Axis Limit in um
pAct = new CPropertyAction (this, &StandaZStage::OnAxisLimit);
CreateProperty(g_Standa_ZStageAxisLimitUm, "500.0", MM::Float, false, pAct, true);
}
StandaZStage::~StandaZStage()
{
Shutdown();
}
void StandaZStage::GetName(char* Name) const
{
CDeviceUtils::CopyLimitedString(Name, StandaZStage::DeviceName_);
}
bool StandaZStage::Busy()
{
return false;
}
int StandaZStage::Initialize()
{
// Initialize the list of devices to search for the stage
if (USMC_Init(deviceList))
return DEVICE_ERR;
// Iterate through the list of devices and find the one matching our serial number
for (DWORD i = 0; i < deviceList.NOD; i++) {
if (strcmp(deviceList.Serial[i], serialNumber_.c_str()) == 0) {
deviceNumber_ = i;
}
}
// If device not found, fail fast
if (deviceNumber_ == NULL)
return DEVICE_INVALID_PROPERTY_TYPE;
// Attempt to get the current state of the device
if (USMC_GetState(deviceNumber_, currentState_))
return DEVICE_ERR;
// Attempt to get the current position, in steps
int ret = GetPositionSteps(curSteps_);
if (ret != DEVICE_OK)
return ret;
initialized_ = true;
return DEVICE_OK;
}
int StandaZStage::Shutdown()
{
if (initialized_)
{
initialized_ = false;
}
return DEVICE_OK;
}
int StandaZStage::GetPositionUm(double &pos)
{
long steps;
int ret = GetPositionSteps(steps);
if (ret != DEVICE_OK)
return ret;
pos = steps * stepSizeUm_;
return DEVICE_OK;
}
int StandaZStage::SetPositionUm(double pos)
{
long steps = (long) (pos / stepSizeUm_ + 0.5);
return SetPositionSteps(steps);
}
int StandaZStage::GetPositionSteps(long& steps) {
if (USMC_GetState(deviceNumber_, currentState_))
return DEVICE_ERR;
steps = (long) currentState_.CurPos;
return DEVICE_OK;
}
int StandaZStage::SetPositionSteps(long steps)
{
// Get the initial starting parameters
if (USMC_GetStartParameters(deviceNumber_, startParameters_))
return DEVICE_ERR;
// Set the step divisor to our desired step divisor
startParameters_.SDivisor = stepDivisor_;
// Start the movement of the stepper motor
if (USMC_Start(deviceNumber_, (int) steps, stageSpeed_, startParameters_))
return DEVICE_ERR;
return DEVICE_OK;
}
int StandaZStage::SetOrigin()
{
return DEVICE_UNSUPPORTED_COMMAND;
}
int StandaZStage::GetLimits(double& min, double& max)
{
min = 0;
max = axisLimitUm_;
return DEVICE_OK;
}
///////////////////////////////////////////////////////////////////////////////
// Action handlers
///////////////////////////////////////////////////////////////////////////////
int StandaZStage::OnAxisLimit(MM::PropertyBase *pProp, MM::ActionType eAct)
{
if (eAct == MM::BeforeGet)
{
pProp->Set(axisLimitUm_);
SetPropertyLimits(MM::g_Keyword_Position, 0, axisLimitUm_);
}
else if (eAct == MM::AfterSet)
{
pProp->Get(axisLimitUm_);
}
return DEVICE_OK;
}
int StandaZStage::OnSerialNumber(MM::PropertyBase *pProp, MM::ActionType eAct)
{
if (eAct == MM::BeforeGet)
{
pProp->Set(serialNumber_.c_str());
}
else if (eAct == MM::AfterSet)
{
pProp->Get(serialNumber_);
}
return DEVICE_OK;
}
///////////////////////////////////////////////////////////////////////////////
// FILE: Standa.h
// PROJECT: Micro-Manager
// SUBSYSTEM: DeviceAdapters
//-----------------------------------------------------------------------------
// DESCRIPTION: Standa device adapters: 8SMC1-USBhF Microstep Driver
//
// COPYRIGHT: Leslie Lab, McGill University, Montreal, 2013
//
// LICENSE: This file is distributed under the BSD license.
//
// This file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES.
//
// AUTHOR: Clarence Leung, clarence.leung@mail.mcgill.ca, 2013
//
#ifndef _STANDA_H_
#define _STANDA_H_
// Standa headers
#include "../../../3rdparty/Standa/USMCDLL.h"
// MM headers
#include "../../MMDevice/MMDevice.h"
#include "../../MMDevice/DeviceBase.h"
#include "../../MMDevice/ModuleInterface.h"
//////////////////////////////////////////////////////////////////////////////
// StandaZStage class
// (device adapter)
//////////////////////////////////////////////////////////////////////////////
class StandaZStage : public CStageBase<StandaZStage>
{
public:
StandaZStage();
~StandaZStage();
// Device API
// ----------
int Initialize();
int Shutdown();
static const char* DeviceName_;
void GetName(char* pszName) const;
bool Busy();
// Stage API
// ---------
int SetPositionUm(double pos);
int GetPositionUm(double& pos);
int SetPositionSteps(long steps);
int GetPositionSteps(long& steps);
int SetOrigin();
int GetLimits(double& min, double& max);
int IsStageSequenceable(bool& isSequenceable) const {isSequenceable = false; return DEVICE_OK;}
bool IsContinuousFocusDrive() const {return false;}
// action interface
// ----------------
int OnAxisLimit(MM::PropertyBase* pProp, MM::ActionType eAct);
int OnSerialNumber(MM::PropertyBase* pProp, MM::ActionType eAct);
private:
bool initialized_;
long curSteps_;
double stepSizeUm_;
double axisLimitUm_;
int stepDivisor_;
float stageSpeed_;
std::string serialNumber_;
DWORD deviceNumber_;
USMC_State currentState_;
USMC_StartParameters startParameters_;
};
#endif //_STANDA_H_
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment