Files
sics/site_ansto/hardsup/lh45util.c
Ferdi Franceschini c36768a722 Removed junk which that dopey computer in the Koala cabin keeps pasting into files.
r2145 | ffr | 2007-09-03 12:52:35 +1000 (Mon, 03 Sep 2007) | 2 lines
2012-11-15 13:23:47 +11:00

438 lines
14 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*--------------------------------------------------------------------------
L H 4 5 U T I L
A few utility functions for dealing with a LH45 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" BA nxsave=truSIS, 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 "lh45util.h"
#include <serialsinq.h>
#include <unistd.h>
/* -------------------------------------------------------------------------*/
// Because the Julabo LH45 may return non-printing characters such as DC1 and DC3
// at the beginning of its responses,r Data Number! we provide a functin to strip them off.
char *ReplyStart(char *pReply)
{
while(*pReply<0x20&&*pReply!='\0') // chuck out any and all control characters, CR, LF etc.
pReply++;
return pReply;
}
int LH45_Check_Status(pLH45 self) /* Can be called to check for correct operation of the LH45 */
{
int iRet;
char pCommand[20];
char pReply[132],*pReplyStart;
/* Check the status. It should read '03 REMOTE START' or possibly '03 REMOTE START,DEGASING'. */
/* If there is any LH45 overload or other fault condition it will be detected here. */
// printf("Checking LH45 status...");fflush(stdout);
printf("Getting STATUS \n");fflush(stdout);
sprintf(pCommand,"STATUS");
iRet = transactRS232(self->controller, pCommand,strlen(pCommand),
pReply,79);
pReplyStart=ReplyStart(pReply);
usleep(500000);
if(iRet <= 0)
{
//transactRS232(self->co/home/mrt/workspacentroller,"\nDEBUG: RS232 transaction bad.\n",28,pReply,79);
return iRet;
}
printf("Status is: '%s'\n",pReplyStart);fflush(stdout);
int i;
for(i=0;i<strlen(pReply);i++)
printf("0x%02x ",((unsigned char *)pReply)[i]);
printf("\n");
if (strncmp(pReplyStart,"03 REMOTE START",15)!=0)
{
//transactRS232(self->controller,"\nDEBUG: RS232 response bad\n",27,pReply,79);
//transactRS232(self->controller,pReply,strlen(pReply),pReply,79);
strcpy(self->pAns,pReplyStart);
return LH45__FAULT;
}
//transactRS232(self->controller,"\nDEBUG: Status reply is good!\n",30,pReply,79);
return 1; // 1 = no fault
}
int LH45_Setup(pLH45 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 LH45***\n");fflush(stdout);
/* switch to remote operation - although don't want it to initialise */
/* NOTE: The Julabo does not provide any response for 'out' commands,
so we just use writeRS232 not transactRS232 for these */
//printf("Issuing out_mode_05 0 command...");fflush(stdout);
sprintf(pCommand,"OUT_MODE_05 0");
iRet = writeRS232(self->controller, pCommand,strlen(pCommand));
usleep(500000);
printf("OUT_MODE_05 1 is completed \n");fflush(stdout);
if(iRet != 1)
{
return iRet;
}
/* if(pReply[0] == '-') // Probably an error response
{
strcpy(self->pAns,pReply);
return LH45__BADCOM;
} */
/* Check the LH45 operating status */
if ((iRet=LH45_Check_Status(self))!=1)
return iRet;
/* Set heater sensor */
/* For the LH45 there is a choice of internal or external sensor control,
set internal when iControl==1 and external when iControl==2 */
sprintf(pCommand,"OUT_MODE_04 %d",self->iControl - 1);
iRet = writeRS232(self->controller, pCommand,strlen(pCommand));
usleep(500000);
printf("OUT_MODE_04 Response is completed \n");fflush(stdout);
if(iRet != 1)
{
return LH45__BADCOM;
}
/* else if(pReply[0] == '-') // Probably an error response
{
strcpy(self->pAns,pReply);
return LH45__BADCOM;
} */
self->iControl=iControl; // Store control sensor setting since it was assigned to the LH45 successfully
/* reset timeout - currently not being used */
/* iRet = SerialConfig(&self->pData, 10);
if(iRet != 1)
{
return iRet;
} */
/* Check the LH45 operating status one last time */
if ((iRet=LH45_Check_Status(self))!=1)
return iRet;
return 1; /* Success */
}
int LH45_Open(pLH45 *pData, char *pRS232, int iSensor, int iCTRL, int iMode)
{
pLH45 self = NULL;
self = (pLH45)malloc(sizeof(LH45));
if(self == NULL)
{
return LH45__BADMALLOC;
}
*pData = self;
self->iControl = iCTRL;
self->iRead = iSensor;
self->iReadOnly = iMode;
/* The LH45 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 LH45__BADCOM;
}
if(!self->iReadOnly)
return LH45_Setup(self, self->iControl);
return 1;
}
/*--------------------------------------------------------------------------*/
void LH45_Close(pLH45 *pData)
{
int iRet;
//char pReply[132];
char pCommand[20];
pLH45 self;
self = *pData;
if (!self)
return; // Just in case
/* switch off remote operation */
/* Not sure if this is really necessary but do it just in case */
sprintf(pCommand,"OUT_MODE_05 0");
iRet = writeRS232(self->controller, pCommand,strlen(pCommand));
usleep(500000);
/* Don't bother checking the status but record any error reply */
/* if(pReply[0] == '-') // Probably an error response
strcpy(self->pAns,pReply); */
return;
}
/*--------------------------------------------------------------------------*/
int LH45_Config(pLH45 *pData, int iTmo, int iRead, int iControl,
float fDiv,float fMult)
{
pLH45 self;
self = *pData;
return LH45_Setup(self, iControl);
}
/* --------------------------------------------------------------------------*/
int LH45_Send(pLH45 *pData, char *pCommand, char *pReply, int iLen)
{
int iRet;
pLH45 self;
self = *pData;
char *pReplyStart;
/* make sure, that there is a \r at the end of the command */
/* if(strchr(pCommand,(int)'\r') == NULL)
{
strcat(pCommand,"\r");
} */
/* Send command direct to the LH45 */
/* Because the Julabo LH45 only provides a response for the 'version', 'status'
and 'in' commands and not for the 'out' commands, just perform a write
for those and not a full transaction. */
if (strncasecmp(pCommand,"OUT",3)==0) // 'OUT' command; LH45 does not send any response.
{
iRet=writeRS232(self->controller,pCommand,strlen(pCommand));
usleep(500000);
*pReply='\0';
}
else
{
iRet=transactRS232(self->controller,pCommand,strlen(pCommand),pReply,iLen);
pReplyStart=ReplyStart(pReply);
// In this case we need to actually shift the buffer content since it is passed in from outside
char *ptoReply=pReply;
do {
*ptoReply++=*pReplyStart;
} while(*pReplyStart++);
}
if(iRet <= 0)
return iRet;
/* Check the LH45 operating status after issuing the command, and return */
iRet=LH45_Check_Status(self);
return iRet;
}
/*--------------------------------------------------------------------------*/
int LH45_Read(pLH45 *pData, float *fVal)
{
char pCommand[20], pReply[132], *pReplyStart;
int iRet;
float fRead = -9999999.;
pLH45 self;
self = *pData;
/* for the LH45 there are three temp measurements available */
switch(self->iRead)
{
case 1:
sprintf(pCommand,"IN_PV_00");
break;
case 2:
sprintf(pCommand,"IN_PV_02");
break;
case 3:
sprintf(pCommand,"IN_PV_03");
break;
default:
return LH45__BADPAR; // But shouldn't happen
}
iRet = transactRS232(self->controller, pCommand,strlen(pCommand),
pReply,79);
pReplyStart=ReplyStart(pReply);
usleep(500000);
if(iRet <= 0)
{
return iRet;
}
//sprintf(self->pAns,"The read value is '%s'\n and the command is: '%s' \n",pReply,pCommand);
//return LH45__FAULT;
if(pReplyStart == '-'&&strlen(pReplyStart)>7) // Not a number (-XXX.X\r), probably an error response
{
strcpy(self->pAns,pReplyStart);
return LH45__BADCOM;
}
iRet = sscanf(pReplyStart,"%f",&fRead);
if (iRet == 1)
*fVal = fRead;
/* Check the LH45 operating status after the read, and return */
iRet=LH45_Check_Status(self);
return iRet;
}
/* -------------------------------------------------------------------------*/
int LH45_Set(pLH45 *pData, float fVal)
{
char pCommand[20], pCommandRead[20], pReply[132], *pReplyStart;;
int iRet, i;
const float fPrecision = 0.1;
float fDelta, fRead;
pLH45 self;
self = *pData;
if(self->iReadOnly)
{
return LH45__READONLY;
}
sprintf(pCommand,"OUT_SP_00 %1.1f",fVal);
sprintf(pCommandRead,"IN_SP_00"); // To read back and check the set value
/* try three times: send, read, test, if OK return, else resend. */
for(i = 0; i < 3; i++)
{
/* send command, since it's an 'out' we don't get any response, so use writeRS232 */
iRet = writeRS232(self->controller,pCommand,strlen(pCommand));
usleep(500000);
//writeRS232(self->controller,pReply,strlen(pReply)); // MJL DEBUG
if(iRet != 1)
{
return iRet;
}
/* if(pReply[0] == '-') // Probably an error response
{
strcpy(self->pAns,pReply);
return LH45__BADCOM;
} */
/* read the set value again using the 'in' command */
iRet = transactRS232(self->controller,pCommandRead,strlen(pCommandRead),pReply,131);
pReplyStart=ReplyStart(pReply);
usleep(500000);
//writeRS232(self->controller,pReply,strlen(pReply)); // MJL DEBUG
if(iRet <= 0)
{
return iRet;
}
if(pReplyStart == '-'&&strlen(pReplyStart)>7) // Not a number (-XXX.X\r), probably an error response
{
strcpy(self->pAns,pReplyStart);
return LH45__BADCOM;
}
/* Convert the value read back. */
iRet=sscanf(pReplyStart,"%f",&fRead);
if(iRet != 1)
{
return LH45__BADREAD;
}
/* check the value read back */
fDelta = fRead - fVal;
if(fDelta < 0)
fDelta = -fDelta;
if(fDelta < fPrecision)
{
sprintf(pCommand,"OUT_MODE_05 1");
iRet = writeRS232(self->controller, pCommand,strlen(pCommand));
usleep(500000);
if(iRet == 1)
{
/* Success, but check the LH45 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 LH45, not a comms problem */
iRet=LH45_Check_Status(self);
return iRet;
}
}
}
return LH45__BADSET;
}
/* -------------------------------------------------------------------------*/
void LH45_ErrorTxt(pLH45 *pData,int iCode, char *pError, int iLen)
{
char pBueffel[512];
pLH45 self;
self = *pData;
switch(iCode)
{
case LH45__BADCOM:
sprintf(pBueffel,"LH45: Invalid command or offline, got %s",
self->pAns);
strncpy(pError,pBueffel,iLen);
break;
case LH45__BADPAR:
strncpy(pError,"LH45: Invalid parameter specified",iLen);
break;
case LH45__BADMALLOC:
strncpy(pError,"LH45: Error allocating memory in LH45",iLen);
break;
case LH45__BADREAD:
strncpy(pError,"LH45: Badly formatted answer",iLen);
break;
case LH45__BADSET:
strncpy(pError,"LH45: Failed three times to write new set value to LH45",iLen);
break;
case LH45__FAULT: // Covers various LH45 self-diagnosed fault conditions
sprintf(pBueffel,"LH45: Internal fault condition detected: %s",self->pAns);
strncpy(pError,pBueffel,iLen);
break;
default:
SerialError(iCode, pError,iLen);
break;
}
}