534 lines
21 KiB
C
534 lines
21 KiB
C
/*--------------------------------------------------------------------------
|
||
|
||
L A K E S H O R E 3 4 0 U T I L
|
||
|
||
A few utility functions for dealing with a LAKESHORE340 temperature controller
|
||
within the SINQ setup: host -- TCP/IP -- MAC --- RS-232.
|
||
|
||
Mark Koennecke, Juli 1997
|
||
Mark Lesha, January 2006 (based on ITC4 code)
|
||
|
||
Copyright:
|
||
|
||
Labor fuer Neutronenstreuung
|
||
Paul Scherrer Institut
|
||
CH-5423 Villigen-PSI
|
||
|
||
|
||
The authors hereby grant permission to use, copy, modify, distribute,
|
||
and license this software and its documentation for any purpose, provided
|
||
that existing copyright notices are retained in all copies and that this
|
||
notice is included verbatim in any distributions. No written agreement,
|
||
license, or royalty fee is required for any of the authorized uses.
|
||
Modifications to this software may be copyrighted by their authors
|
||
and need not follow the licensing terms described here, provided that
|
||
the new terms are clearly indicated on the first page of each file where
|
||
they apply.
|
||
|
||
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||
POSSIBILITY OF SUCH DAMAGE.
|
||
|
||
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
||
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
||
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
||
MODIFICATIONS.
|
||
----------------------------------------------------------------------------*/
|
||
#include <string.h>
|
||
#include <stdlib.h>
|
||
#include <stdio.h>
|
||
#include <assert.h>
|
||
#include <fortify.h>
|
||
#include <sics.h>
|
||
#include <modriv.h>
|
||
#include <rs232controller.h>
|
||
#include "serialsinq.h"
|
||
#include "lakeshore340util.h"
|
||
/*-------------------------------------------------------------------------*/
|
||
|
||
int LAKESHORE340_Check_Status(pLAKESHORE340 self)
|
||
/* Can be called to check for correct operation of the LAKESHORE340 */
|
||
{
|
||
int iRet, iRetry, busy, notbusy;
|
||
char pCommand[20];
|
||
char pReply[132];
|
||
/* Check the busy status. */
|
||
/* While busy, wait but not too long - set an upper limit of about 100 queries, */
|
||
/* should translate to about 1 or 2 seconds which is enough time for any commands */
|
||
/* to complete. Since we don't issue any time-consuming commands, this shouldn't */
|
||
/* be necessary anyway. */
|
||
/* Register a comms failure if a not-busy response isn't able to be received. */
|
||
iRetry=0;
|
||
printf("Checking status...");
|
||
do
|
||
{
|
||
sprintf(pCommand,"BUSY?");
|
||
usleep(50000); // Required to meet Lakeshore340 spec.
|
||
if ((iRet=transactRS232(self->controller,pCommand,strlen(pCommand),pReply,79))<=0)
|
||
{
|
||
printf("Comms error!\n");
|
||
return iRet; // Comms problem
|
||
}
|
||
busy=(strncmp(pReply,"1",15)==0);
|
||
notbusy=(strncmp(pReply,"0",15)==0);
|
||
if (notbusy)
|
||
{
|
||
printf("Status OK.\n");
|
||
return 1; // Lakeshore 340 is ready to accept command
|
||
}
|
||
} while((++iRetry<100)&&busy);
|
||
/* If we fell out of the loop, the Lakeshore 340 is either still busy */
|
||
/* or some bad response was received, log the response. */
|
||
sprintf(self->pAns,"BUSY response=%s",pReply);
|
||
printf("Busy or bad response received!\n");
|
||
return LAKESHORE340__BADREAD;
|
||
}
|
||
|
||
int LAKESHORE340_ConfigureAndQueryGen(pLAKESHORE340 self, char *command,
|
||
char *configandqueryparameters, char *configonlyparameters,char *diagnosis)
|
||
/* Issue a command to the Lakeshore 340, if this works, */
|
||
/* issue the corresponding query and check the result is correct. */
|
||
/* Log and return any errors. */
|
||
{
|
||
int iRet;
|
||
char pCommand[20];
|
||
char pReply[132];
|
||
/* Issue a command to the Lakeshore 340. */
|
||
if (configandqueryparameters&&*configandqueryparameters)
|
||
sprintf(pCommand,"%s %s,%s",command,configandqueryparameters,configonlyparameters);
|
||
else
|
||
sprintf(pCommand,"%s %s",command,configonlyparameters);
|
||
printf("Issuing command: '%s'...\n",pCommand);
|
||
usleep(50000); // Required to meet Lakeshore340 spec.
|
||
if ((iRet=writeRS232(self->controller,pCommand,strlen(pCommand)))!=1)
|
||
return iRet;
|
||
/* Issue the query corresponding to the command, */
|
||
/* then check the parameters match what was set. */
|
||
if (configandqueryparameters&&*configandqueryparameters)
|
||
sprintf(pCommand,"%s? %s",command,configandqueryparameters);
|
||
else
|
||
sprintf(pCommand,"%s?",command);
|
||
printf("Issuing query: '%s'...\n",pCommand);
|
||
usleep(50000); // Required to meet Lakeshore340 spec.
|
||
if ((iRet=transactRS232(self->controller,pCommand,strlen(pCommand),pReply,79))<=0)
|
||
{
|
||
printf("transactRS232 error! Code=%d.\n",iRet);
|
||
printf("DEBUG: pReply='%s' len=%d configonlyparameters='%s' len=%d\n",
|
||
pReply,strlen(pReply),configonlyparameters,strlen(configonlyparameters));
|
||
return iRet;
|
||
}
|
||
/* Query should return the same data parameters set in the configuration
|
||
(i.e. the configonlyparameters), the configandqueryparameters are used
|
||
to index objects and are common to both configuration and query. */
|
||
printf("DEBUG: pReply='%s' len=%d configonlyparameters='%s' len=%d\n",
|
||
pReply,strlen(pReply),configonlyparameters,strlen(configonlyparameters));
|
||
if (strcmp(pReply,configonlyparameters)!=0)
|
||
{
|
||
printf("Response was bad.\n");
|
||
if (diagnosis&&*diagnosis)
|
||
sprintf(self->pAns,"%s response=%s (%s.)",command,pReply,diagnosis);
|
||
else
|
||
sprintf(self->pAns,"%s response=%s",command,pReply);
|
||
return LAKESHORE340__BADREAD;
|
||
}
|
||
printf("Response was good.\n");
|
||
return 1;
|
||
}
|
||
|
||
int LAKESHORE340_ConfigureAndQuery(pLAKESHORE340 self, char *command,
|
||
char *parameters, char *diagnosis)
|
||
/* Use for config/query transactions that don't require index parameters in the query. */
|
||
{
|
||
return LAKESHORE340_ConfigureAndQueryGen(self,command,"",parameters,diagnosis);
|
||
}
|
||
|
||
int LAKESHORE340_SetControl(pLAKESHORE340 self, int iControl)
|
||
{
|
||
/* Attempt to set the sensor used for temperature control. */
|
||
/* Only use control loop #1 to do the control, use Kelvin units, */
|
||
/* and leave control enabled at next power-on. */
|
||
if (iControl==1)
|
||
return LAKESHORE340_ConfigureAndQueryGen(self,"CSET","1","A,1,1,1","");
|
||
else if (iControl==2)
|
||
return LAKESHORE340_ConfigureAndQueryGen(self,"CSET","1","B,1,1,1","");
|
||
else if (iControl==3)
|
||
return LAKESHORE340_ConfigureAndQueryGen(self,"CSET","1","C,1,1,1","");
|
||
else if (iControl==4)
|
||
return LAKESHORE340_ConfigureAndQueryGen(self,"CSET","1","D,1,1,1","");
|
||
else
|
||
return LAKESHORE340__BADPAR;
|
||
}
|
||
|
||
int LAKESHORE340_Setup(pLAKESHORE340 self, int iControl) /* Operations common to both Open and Config functions */
|
||
{
|
||
int iRet;
|
||
char pCommand[20];
|
||
char pReply[132];
|
||
|
||
/* MJL enable RS232 debugging mode. */
|
||
//setRS232Debug(self->controller,1);
|
||
//printf("***RS232 debug mode enabled for LAKESHORE340***\n");fflush(stdout);
|
||
|
||
/* Setup the comms port (the baudrate etc. are probably just academic since */
|
||
/* they must be correct if we have established comms, but the termination */
|
||
/* character setting is relevant - use just \r. */
|
||
if ((iRet=LAKESHORE340_ConfigureAndQuery(self,"COMM","3,5,2","bad comms setup"))!=1)
|
||
return iRet;
|
||
|
||
/* Reset the controller to power-on state. */
|
||
sprintf(pCommand,"*RST");
|
||
usleep(50000); // Required to meet Lakeshore340 spec.
|
||
if ((iRet=writeRS232(self->controller, pCommand,strlen(pCommand)))!=1)
|
||
return iRet;
|
||
|
||
/* Clear the interface status (and buffer, but that's irrelevant) */
|
||
/* just in case we want to use the internal status flags later on. */
|
||
/* Actually, we do *RST above, probably this isn't necessary. */
|
||
sprintf(pCommand,"*CLS");
|
||
usleep(50000); // Required to meet Lakeshore340 spec.
|
||
if ((iRet=writeRS232(self->controller, pCommand,strlen(pCommand)))!=1)
|
||
return iRet;
|
||
|
||
/* Check the LAKESHORE340 status */
|
||
/* Basically this just makes sure comms is up. */
|
||
if ((iRet=LAKESHORE340_Check_Status(self))!=1)
|
||
return iRet;
|
||
|
||
/* Check the POST status, it should be 0 and not 1. */
|
||
sprintf(pCommand,"*TST?");
|
||
usleep(50000); // Required to meet Lakeshore340 spec.
|
||
if ((iRet=transactRS232(self->controller,pCommand,strlen(pCommand),pReply,79))<=0)
|
||
return iRet;
|
||
if (strcmp(pReply,"0")!=0)
|
||
{
|
||
if (strcmp(pReply,"1")==0)
|
||
{
|
||
strcpy(self->pAns,"*TST=1 - POST failure, Lakeshore 340 is faulty.");
|
||
return LAKESHORE340__FAULT;
|
||
}
|
||
else // Unexpected response from *TST? query.
|
||
{
|
||
sprintf(self->pAns,"*TST response=%s",pReply);
|
||
return LAKESHORE340__BADREAD;
|
||
}
|
||
}
|
||
|
||
/* Check that the controller is a gen-new-wine Lakeshore 340 */
|
||
/* There's also the *REV command to check the firmware revision, but */
|
||
/* that would be going too far ;) */
|
||
sprintf(pCommand,"*IDN?",command);
|
||
usleep(50000); // Required to meet Lakeshore340 spec.
|
||
if ((iRet=transactRS232(self->controller,pCommand,strlen(pCommand),pReply,79))<=0)
|
||
return iRet;
|
||
if (strncmp(pReply,"LSCI,MODEL340",13)!=0)
|
||
{
|
||
strcpy(self->pAns,pReply);
|
||
return LAKESHORE340__NOLAKESHORE340;
|
||
}
|
||
|
||
/* Switch to remote operation - but leave the keypad unlocked */
|
||
if ((iRet=LAKESHORE340_ConfigureAndQuery(self,"MODE","2",""))!=1)
|
||
return iRet;
|
||
|
||
/* Make sure the keypad isn't locked out via the LOCK setting too */
|
||
if ((iRet=LAKESHORE340_ConfigureAndQuery(self,"LOCK","0,000",""))!=1)
|
||
return iRet;
|
||
|
||
/* Clear any alarms. */
|
||
sprintf(pCommand,"ALMRST");
|
||
usleep(50000); // Required to meet Lakeshore340 spec.
|
||
if ((iRet=writeRS232(self->controller, pCommand,strlen(pCommand)))!=1)
|
||
return iRet;
|
||
|
||
/* Set up the front panel display on the Lakeshore 340. */
|
||
/* Set 2 output fields, which we will use to display the set temp */
|
||
/* and the actual temp at the controlling sensor selected. */
|
||
/* Note: use 4,060,1 setting rather than just 4,60 so that the response */
|
||
/* matches exactly and we can use LAKESHORE340_ConfigureAndQuery ;) */
|
||
if ((iRet=LAKESHORE340_ConfigureAndQuery(self,"DISPLAY","4,060,1",""))!=1)
|
||
return iRet;
|
||
|
||
/* Set up the 4 fields on the front panel display to show both sensor temps. */
|
||
if ((iRet=LAKESHORE340_ConfigureAndQueryGen(self,"DISPFLD","1","A,1",""))!=1)
|
||
return iRet;
|
||
if ((iRet=LAKESHORE340_ConfigureAndQueryGen(self,"DISPFLD","2","B,1",""))!=1)
|
||
return iRet;
|
||
if ((iRet=LAKESHORE340_ConfigureAndQueryGen(self,"DISPFLD","3","C,1",""))!=1)
|
||
return iRet;
|
||
if ((iRet=LAKESHORE340_ConfigureAndQueryGen(self,"DISPFLD","4","D,1",""))!=1)
|
||
return iRet;
|
||
|
||
/* Set the sensor used for controlling temperature. */
|
||
/* Sets sensor A when iControl==1 and sensor B when iControl==2. */
|
||
if ((LAKESHORE340_SetControl(self,iControl))!=1)
|
||
return iRet;
|
||
|
||
/* Turn off the heater as a precaution. */
|
||
/* The heater gets turned on when we do any set operation. */
|
||
/* Also the heater will be turned off if SICS is shut down properly. */
|
||
if ((iRet=LAKESHORE340_ConfigureAndQuery(self,"RANGE","0",""))!=1)
|
||
return iRet;
|
||
|
||
/* Don't bother setting the controller's date & time
|
||
(not easy to code and probably wouldn't be useful). */
|
||
|
||
/* Check the LAKESHORE340 operating status one last time */
|
||
if ((iRet=LAKESHORE340_Check_Status(self))!=1)
|
||
return iRet;
|
||
|
||
return 1; /* Success */
|
||
}
|
||
|
||
int LAKESHORE340_Open(pLAKESHORE340 *pData, char *pRS232, int iSensor, int iCTRL, int iMode)
|
||
{
|
||
pLAKESHORE340 self = NULL;
|
||
|
||
self = (pLAKESHORE340)malloc(sizeof(LAKESHORE340));
|
||
if(self == NULL)
|
||
{
|
||
return LAKESHORE340__BADMALLOC;
|
||
}
|
||
*pData = self;
|
||
self->iControl = iCTRL;
|
||
self->iRead = iSensor;
|
||
self->iReadOnly = iMode;
|
||
|
||
/* The LAKESHORE340 doesn't require divisors or multipliers
|
||
and they are always forced to 1.0 */
|
||
self->fDiv = 1.0;
|
||
self->fMult = 1.0;
|
||
|
||
self->controller = NULL;
|
||
|
||
self->controller = (prs232)FindCommandData(pServ->pSics,pRS232,
|
||
"RS232 Controller");
|
||
if(!self->controller){
|
||
/*SCWrite(pCon,"ERROR: motor controller not found",eError); */
|
||
return LAKESHORE340__BADCOM;
|
||
}
|
||
|
||
if(!self->iReadOnly)
|
||
return LAKESHORE340_Setup(self, self->iControl);
|
||
}
|
||
/*--------------------------------------------------------------------------*/
|
||
void LAKESHORE340_Close(pLAKESHORE340 *pData)
|
||
{
|
||
pLAKESHORE340 self;
|
||
|
||
self = *pData;
|
||
if (!self)
|
||
return; // Just in case
|
||
|
||
/* Try to turn off the heater as a precaution. */
|
||
LAKESHORE340_ConfigureAndQuery(self,"RANGE","0","");
|
||
|
||
/* switch off remote operation */
|
||
/* Not sure if this is really necessary but do it just in case */
|
||
LAKESHORE340_ConfigureAndQuery(self,"MODE","1","");
|
||
|
||
return;
|
||
}
|
||
/*--------------------------------------------------------------------------*/
|
||
int LAKESHORE340_Config(pLAKESHORE340 *pData, int iTmo, int iRead, int iControl,
|
||
float fDiv,float fMult)
|
||
{
|
||
pLAKESHORE340 self;
|
||
|
||
self = *pData;
|
||
|
||
return LAKESHORE340_Setup(self, iControl);
|
||
}
|
||
/*--------------------------------------------------------------------------*/
|
||
int LAKESHORE340_Send(pLAKESHORE340 *pData, char *pCommand, char *pReply, int iLen)
|
||
{
|
||
int iRet,i,commandlen,isquery;
|
||
pLAKESHORE340 self;
|
||
|
||
self = *pData;
|
||
|
||
/* Send command direct to the LAKESHORE340 */
|
||
/* Because the LAKESHORE340 only provides a response for query commands (those
|
||
ending in a '?'), just perform a write for others and not a full transaction. */
|
||
commandlen=strlen(pCommand);
|
||
isquery=0;
|
||
for(i=0;i<commandlen&&!isquery;i++)
|
||
isquery=((pCommand[i]=='?')
|
||
&&(pCommand[i+1]==' '||pCommand[i+1]=='\0')); // any '? ' pattern or trailing '?' will do.
|
||
if (!isquery) // LAKESHORE340 does not send any response.
|
||
{
|
||
usleep(50000); // Required to meet Lakeshore340 spec.
|
||
iRet=writeRS232(self->controller,pCommand,commandlen);
|
||
*pReply='\0';
|
||
}
|
||
else // LAKESHORE340 will send a response.
|
||
{
|
||
usleep(50000); // Required to meet Lakeshore340 spec.
|
||
iRet=transactRS232(self->controller,pCommand,commandlen,pReply,iLen);
|
||
}
|
||
|
||
/* Check the LAKESHORE340 operating status after issuing the command, if it was successful */
|
||
if (iRet>=1)
|
||
iRet=LAKESHORE340_Check_Status(self);
|
||
return iRet;
|
||
}
|
||
/*--------------------------------------------------------------------------*/
|
||
int LAKESHORE340_Read(pLAKESHORE340 *pData, float *fVal)
|
||
{
|
||
char pCommand[20], pReply[132];
|
||
int iRet;
|
||
float fRead = -9999999.;
|
||
pLAKESHORE340 self;
|
||
|
||
self = *pData;
|
||
|
||
|
||
/* for the LAKESHORE340 there are three temp measurements available */
|
||
/* as 'A', 'B', 'C' and 'D'. (This is a bit different from the manual) */
|
||
/* We use the Kelvin readings (presumably the cryogenic 'furnace' */
|
||
/* operates at low temperatures, so it probably makes more sense) */
|
||
switch(self->iRead)
|
||
{
|
||
case 1:
|
||
sprintf(pCommand,"KRDG? A");
|
||
break;
|
||
case 2:
|
||
sprintf(pCommand,"KRDG? B");
|
||
break;
|
||
case 3:
|
||
sprintf(pCommand,"KRDG? C");
|
||
break;
|
||
case 4:
|
||
sprintf(pCommand,"KRDG? D");
|
||
break;
|
||
default:
|
||
return LAKESHORE340__BADPAR; // But shouldn't happen
|
||
}
|
||
|
||
usleep(50000); // Required to meet Lakeshore340 spec.
|
||
if ((iRet=transactRS232(self->controller,pCommand,strlen(pCommand),pReply,79))<=0)
|
||
return iRet;
|
||
|
||
iRet = sscanf(pReply,"%g",&fRead); // KRDG returns free-format exponentiated value
|
||
if(iRet != 1) // Not a number, probably an error response
|
||
{
|
||
return LAKESHORE340__BADREAD;
|
||
}
|
||
|
||
*fVal = fRead;
|
||
|
||
/* Check the LAKESHORE340 operating status after the read, and return */
|
||
iRet=LAKESHORE340_Check_Status(self);
|
||
return iRet;
|
||
}
|
||
/*-------------------------------------------------------------------------*/
|
||
int LAKESHORE340_Set(pLAKESHORE340 *pData, float fVal)
|
||
{
|
||
char pCommand[20], pCommandRead[20], pReply[132];
|
||
int iRet, i;
|
||
const float fPrecision = 0.1;
|
||
float fDelta, fRead;
|
||
pLAKESHORE340 self;
|
||
|
||
self = *pData;
|
||
|
||
if(self->iReadOnly)
|
||
{
|
||
return LAKESHORE340__READONLY;
|
||
}
|
||
|
||
/* Note we are using control loop #1 only for temperature control. */
|
||
sprintf(pCommand,"SETP 1,%1.1f",fVal);
|
||
sprintf(pCommandRead,"SETP? 1"); // To read back and check the set value
|
||
|
||
/* try three times: send, read, test, if OK return, else resend. */
|
||
/* MJL doesn't think this is necessary... left over from itc4 */
|
||
for(i = 0; i < 3; i++)
|
||
{
|
||
/* send SETP command, we don't get any response so use writeRS232 */
|
||
usleep(50000); // Required to meet Lakeshore340 spec.
|
||
if ((iRet=writeRS232(self->controller,pCommand,strlen(pCommand)))!=1)
|
||
return iRet;
|
||
/* read the set value again using the SETP? command */
|
||
usleep(50000); // Required to meet Lakeshore340 spec.
|
||
if ((iRet=transactRS232(self->controller,pCommandRead,strlen(pCommandRead),pReply,131))<=0)
|
||
return iRet;
|
||
printf("SETP: Response %d characters: '%s'\n",iRet,pReply);
|
||
if(pReply[0] == '-'&&strlen(pReply)>7)
|
||
{
|
||
strcpy(self->pAns,pReply);
|
||
return LAKESHORE340__BADCOM;
|
||
}
|
||
/* Convert the value read back. */
|
||
/* Note SETP? will return free-format exponentiated number, so use %g. */
|
||
if(sscanf(pReply,"%g",&fRead)!=1)
|
||
return LAKESHORE340__BADREAD;
|
||
printf(" Parsed response OK, value=%g\n",fRead);
|
||
/* check the value read back */
|
||
printf(" Setpoint=%g actual=%g\n",fVal,fRead);
|
||
fDelta = fRead - fVal;
|
||
if(fDelta < 0)
|
||
fDelta = -fDelta;
|
||
printf(" delta=%g precision=%g\n",fDelta,fPrecision);
|
||
if(fDelta < fPrecision)
|
||
{
|
||
/* Turn on the heater. (but it will already be on if there has been a previous set) */
|
||
/* Don't know what range is appropriate, but for the time being set to 50W */
|
||
/* which is setting 5 (maximum range). */
|
||
if ((iRet=LAKESHORE340_ConfigureAndQuery(self,"RANGE","5",""))!=1)
|
||
return iRet;
|
||
/* Success, but check the LAKESHORE340 operating status afterwards, and return */
|
||
/* Don't bother to repeat the write if we get an error here as it would indicate
|
||
a fault or overload in the LAKESHORE340, not a comms problem */
|
||
printf("SETP OK, checking status and returning.\n");
|
||
iRet=LAKESHORE340_Check_Status(self);
|
||
return iRet;
|
||
}
|
||
}
|
||
printf("SETP failed!\n");
|
||
return LAKESHORE340__BADSET;
|
||
}
|
||
/*-------------------------------------------------------------------------*/
|
||
void LAKESHORE340_ErrorTxt(pLAKESHORE340 *pData,int iCode, char *pError, int iLen)
|
||
{
|
||
char pBueffel[512];
|
||
pLAKESHORE340 self;
|
||
|
||
self = *pData;
|
||
|
||
switch(iCode)
|
||
{
|
||
case LAKESHORE340__BADCOM:
|
||
sprintf(pBueffel,"LAKESHORE340: Invalid command or offline, got %s",
|
||
self->pAns);
|
||
strncpy(pError,pBueffel,iLen);
|
||
break;
|
||
case LAKESHORE340__BADPAR:
|
||
strncpy(pError,"LAKESHORE340: Invalid parameter specified",iLen);
|
||
break;
|
||
case LAKESHORE340__BADMALLOC:
|
||
strncpy(pError,"LAKESHORE340: Error allocating memory in LAKESHORE340",iLen);
|
||
break;
|
||
case LAKESHORE340__BADREAD:
|
||
strncpy(pError,"LAKESHORE340: Badly formatted answer",iLen);
|
||
break;
|
||
case LAKESHORE340__BADSET:
|
||
strncpy(pError,"LAKESHORE340: Failed three times to write new set value to LAKESHORE340",iLen);
|
||
break;
|
||
case LAKESHORE340__FAULT: // Covers various LAKESHORE340 self-diagnosed fault conditions
|
||
sprintf(pBueffel,"LAKESHORE340: Internal fault condition detected: %s",self->pAns);
|
||
strncpy(pError,pBueffel,iLen);
|
||
break;
|
||
case LAKESHORE340__NOLAKESHORE340:
|
||
sprintf(pBueffel,"LAKESHORE340: Wrong model number (driver is for Model 340 only): %s",self->pAns);
|
||
strncpy(pError,pBueffel,iLen);
|
||
break;
|
||
default:
|
||
SerialError(iCode, pError,iLen);
|
||
break;
|
||
}
|
||
}
|