/*-------------------------------------------------------------------------- D I L U T I L A few utility functions for dealing with a Dillution emperature controller CC0-510/AVSI within the SINQ setup: host -- TCP/IP -- MAC --- RS-232. Mark Koennecke, October 1997 Copyright: see copyrigh.h ---------------------------------------------------------------------------- */ #include #include #include #include #include "serialsinq.h" #include "dillutil.h" #ifdef FORTIFY #include "fortify.h" #endif /* #define debug 1 */ /*-------------------------------------------------------------------------*/ int DILLU_Open(pDILLU * pData, char *pHost, int iPort, int iChannel, int iMode, char *pTransFile) { int iRet; char pCommand[80]; char pReply[132]; pDILLU self = NULL; pSTable pTable = NULL; FILE *fd = NULL; /* check translation file first */ fd = fopen(pTransFile, "r"); if (!fd) { return DILLU__FILENOTFOUND; } fgets(pReply, 131, fd); if (strstr(pReply, "DILLUTION") == NULL) { fclose(fd); return DILLU__NODILLFILE; } pTable = CreateTable(fd); fclose(fd); if (!pTable) { return DILLU__ERRORTABLE; } /* allocate a new data structure */ self = (pDILLU) malloc(sizeof(DILLU)); if (self == NULL) { return DILLU__BADMALLOC; } *pData = self; self->pTranstable = pTable; iRet = SerialOpen(&self->pData, pHost, iPort, iChannel); if (iRet != 1) { return iRet; } /* set an lengthy timeout for the configuration in order to prevent problems. */ iRet = SerialConfig(&self->pData, 100); if (iRet != 1) { return iRet; } self->iReadOnly = iMode; if (!self->iReadOnly) { /* switch to remote operation */ /* iRet = SerialWriteRead(&self->pData,"C1\r\n",pReply,131); if(iRet != 1) { return iRet; } */ } return 1; } /* --------------------------------------------------------------------------*/ void DILLU_Close(pDILLU * pData) { char pReply[132]; int iRet; pDILLU self; self = *pData; if (!self) return; /* switch to local operation */ iRet = SerialWriteRead(&self->pData, "C0\r\n", pReply, 131); /* ignore errors on this one, the thing may be down */ /* close connection */ SerialClose(&self->pData); /* free memory */ free(self); *pData = NULL; } /* --------------------------------------------------------------------------*/ int DILLU_Config(pDILLU * pData, int iTmo) { int iRet; char pReply[132]; char pCommand[10]; pDILLU self; self = *pData; /* first timeout */ if (iTmo > 0) { iRet = SerialConfig(&self->pData, iTmo); if (iRet < 0) { return iRet; } } return 1; } /* --------------------------------------------------------------------------*/ int DILLU_Send(pDILLU * pData, char *pCommand, char *pReply, int iLen) { pDILLU self; self = *pData; /* make sure, that there is a \r at the end of the command */ if (strchr(pCommand, (int) '\r') == NULL) { strcat(pCommand, "\r\n"); } return SerialWriteRead(&self->pData, pCommand, pReply, iLen); } /* --------------------------------------------------------------------------*/ int DILLU_Read(pDILLU * pData, float *fVal) { char pCommand[10], pReply[132]; int iRet; float fRead = -9999.; float fOhm; pDILLU self; self = *pData; /* send D command */ sprintf(pCommand, "D\r\n"); iRet = SerialWriteRead(&self->pData, pCommand, pReply, 131); if (iRet != 1) { return iRet; } /* read ohms */ iRet = sscanf(pReply, "%f", &fOhm); if (iRet != 1) { return DILLU__BADREAD; } if (fOhm > 9999890.) { return DILLU__SILLYANSWER; } /* convert to K */ iRet = InterpolateVal2(self->pTranstable, fOhm, &fRead); *fVal = fRead; return 1; } /*-------------------------------------------------------------------------*/ int DILLU_Set(pDILLU * pData, float fVal) { char pCommand[50], pReply[132]; int iRet, i, iRange, iExec; const float fPrecision = 0.0001; float fSet, fRead, fOhms, tmax, fTemp; pDILLU self; self = *pData; if (self->iReadOnly) { return DILLU__READONLY; } /* send D command to read current value */ sprintf(pCommand, "D\r\n"); iRet = SerialWriteRead(&self->pData, pCommand, pReply, 131); if (iRet != 1) { return iRet; } /* read ohms */ iRet = sscanf(pReply, "%f", &fRead); if (iRet != 1) { return DILLU__BADREAD; } if (fRead > 9999890.) { return DILLU__SILLYANSWER; } /* convert new set value to ohms */ iRet = InterpolateVal1(self->pTranstable, fVal, &fOhms); if (!iRet) { return DILLU__OUTOFRANGE; } /* set to remote operation */ #ifdef debug printf("C1\n"); #endif iRet = SerialWriteRead(&self->pData, "C1\r\n", pReply, 131); if (iRet != 1) { return iRet; } /* set heater power */ strcpy(pCommand, "G3\r"); if (fOhms > 1125) { strcpy(pCommand, "G2\r"); } if (fOhms > 4000) strcpy(pCommand, "G1\r"); #ifdef debug printf("A9\n"); #endif iRet = SerialWriteRead(&self->pData, "A9\r", pReply, 131); if (iRet != 1) { return iRet; } #ifdef debug printf("%s\n", pCommand); #endif iRet = SerialWriteRead(&self->pData, pCommand, pReply, 131); if (iRet != 1) { return iRet; } /* Integrator time constant */ strcpy(pCommand, "G2\r"); if (fOhms > 200) strcpy(pCommand, "G1\r"); if (fOhms > 2000) strcpy(pCommand, "G0\r"); strcpy(pCommand, "G7\r"); if (fOhms > 400.) { strcpy(pCommand, "G6\r"); } #ifdef debug printf("A4\n"); #endif iRet = SerialWriteRead(&self->pData, "A4\r", pReply, 131); if (iRet != 1) { return iRet; } #ifdef debug printf("%s\n", pCommand); #endif iRet = SerialWriteRead(&self->pData, pCommand, pReply, 131); if (iRet != 1) { return iRet; } /* derivator time constant */ if (fOhms > 1000.) { strcpy(pCommand, "G1\r"); } else { strcpy(pCommand, "G2\r"); } #ifdef debug printf("A5\n"); #endif iRet = SerialWriteRead(&self->pData, "A5\r", pReply, 131); if (iRet != 1) { return iRet; } #ifdef debug printf("%s\n", pCommand); iRet = 1; #endif iRet = SerialWriteRead(&self->pData, pCommand, pReply, 131); if (iRet != 1) { return iRet; } /* proportional gain */ if (fOhms > 500.) { strcpy(pCommand, "G3\r"); } if (fOhms > 1000) { strcpy(pCommand, "G2\r"); } if (fOhms > 2000) { strcpy(pCommand, "G1\r"); } #ifdef debug printf("A6\n"); #endif iRet = SerialWriteRead(&self->pData, "A6\r", pReply, 131); if (iRet != 1) { return iRet; } #ifdef debug printf("%s\n", pCommand); #endif iRet = SerialWriteRead(&self->pData, pCommand, pReply, 131); if (iRet != 1) { return iRet; } /* range calculation a la Elsenhans */ iRange = 1; fTemp = fOhms * 10000.; if ((fRead > 1.9) || (fOhms > 1.9)) { iRange = 2; fTemp = fOhms * 1000.; } if ((fRead > 19) || (fOhms > 19)) { iRange = 3; fTemp = fOhms * 100.; } if ((fRead > 190) || (fOhms > 190)) { iRange = 4; fTemp = fOhms * 10.; } if ((fRead > 750) || (fOhms > 750)) { iRange = 5; fTemp = fOhms; } if ((fRead > 19000) || (fOhms > 19000)) { iRange = 6; fTemp = fOhms / 10.; } if ((fRead > 190000) || (fOhms > 190000)) { iRange = 7; fTemp = fOhms / 100.; } sprintf(pCommand, "R%1.1d\r", iRange); #ifdef debug printf("%s\n", pCommand); #endif iRet = SerialWriteRead(&self->pData, pCommand, pReply, 131); if (iRet != 1) { return iRet; } /* finally set temperature */ #ifdef debug printf("Set Val befor hex: %d\n", (int) fTemp); #endif sprintf(pCommand, "G%4.4X\r", (int) fTemp); #ifdef debug printf("A3\n"); #endif iRet = SerialWriteRead(&self->pData, "A3\r", pReply, 131); if (iRet != 1) { return iRet; } #ifdef debug printf("%s\n", pCommand); #endif iRet = SerialWriteRead(&self->pData, pCommand, pReply, 131); if (iRet != 1) { return iRet; } /* unset remote operation, so that users may mess everything up from the panel */ #ifdef debug printf("C1\n"); #endif iRet = SerialWriteRead(&self->pData, "C0\r\n", pReply, 131); if (iRet != 1) { return iRet; } return 1; } /*-------------------------------------------------------------------------*/ void DILLU_Error2Text(pDILLU * pData, int iCode, char *pError, int iLen) { char pBueffel[512]; pDILLU self; self = *pData; switch (iCode) { case DILLU__FILENOTFOUND: strncpy(pError, "Translation Table file not found", iLen); return; break; case DILLU__NODILLFILE: strncpy(pError, "Translation Table file is not DILLU", iLen); return; break; case DILLU__ERRORTABLE: strncpy(pError, "Translation Table could not be created", iLen); return; break; case DILLU__BADREAD: strncpy(pError, "Message corrupted", iLen); return; break; case DILLU__SILLYANSWER: strncpy(pError, "Message corrupted", iLen); return; break; case DILLU__BADMALLOC: strncpy(pError, "Out of memory in Open_DILLU", iLen); return; break; case DILLU__READONLY: strncpy(pError, "DILLU is read-only", iLen); return; break; case DILLU__OUTOFRANGE: strncpy(pError, "Requested value is out of range", iLen); return; break; default: SerialError(iCode, pError, iLen); break; } }