// Actuator.cpp : 定义 DLL 的导出函数。 // #include "pch.h" #include "framework.h" #include "Actuator.h" #include #include #include #include #include "../../libmodbus-3.1.10/src/modbus.h" int nGoodtype = 1; ACTUATOR_API void* __stdcall CreatePlcDevice(const char* strIp, int nPort) { modbus_t* ctx = modbus_new_tcp(strIp, nPort); modbus_set_slave(ctx, 1); //modbus_set_debug(ctx, TRUE); modbus_set_error_recovery(ctx, MODBUS_ERROR_RECOVERY_LINK); return ctx; } //创建水分仪句柄 ACTUATOR_API void* __stdcall CreateWrDevice(const char* szSerialPort, int baud, char parity, int data_bit, int stop_bit) { modbus_t* ctx = modbus_new_rtu(szSerialPort, baud, parity, data_bit, stop_bit); modbus_set_slave(ctx, 1); //modbus_set_debug(ctx, TRUE); modbus_set_error_recovery(ctx, MODBUS_ERROR_RECOVERY_LINK); return ctx; } ACTUATOR_API int __stdcall Disconnect(void* ctxDev) { if (NULL == ctxDev) return 1; modbus_t* ctx = (modbus_t*)ctxDev; if (NULL == ctx) return 1; modbus_close(ctx); return 1; } //断开设备的连接 ACTUATOR_API int __stdcall DestroyDevice(void* ctxDev) { if (NULL == ctxDev) return 1; modbus_t* ctx = (modbus_t*)ctxDev; if (NULL == ctx) return 1; modbus_free(ctx); return 1; } ACTUATOR_API int __stdcall ConnectDevice(void* ctxDev) { if (NULL == ctxDev) return -1; modbus_t* ctx = (modbus_t*)ctxDev; return modbus_connect(ctx); } //从客户PLC获取粮种信息和状态信息 ACTUATOR_API int __stdcall ReadState(void* ctxDev, unsigned short* nState, unsigned short* nGrainType) { if (NULL == ctxDev) return -1; uint16_t tab_rp_registers[8] = { 0 }; int rc = modbus_read_registers((modbus_t*)ctxDev, 0, 3, tab_rp_registers); if (rc > 0) { *nGrainType = tab_rp_registers[0]; //粮种信息 switch (tab_rp_registers[0]) {//PLC 粮食 ID 转 装置 粮食 ID case 1: //PLC稻谷 *nGrainType = 2; break; case 2: //PLC玉米 *nGrainType = 4; break; case 3: //PLC黄豆 *nGrainType = 3; break; case 4: //PLC小麦 *nGrainType = 1; break; } *nState = tab_rp_registers[2]; //交互寄存器 } return rc; } //写状态给客户PLC ACTUATOR_API int __stdcall ResponseState(void* ctxDev, unsigned short nState) { if (NULL == ctxDev) return -1; unsigned short nStates[1] = { nState }; int rc = modbus_write_registers((modbus_t*)ctxDev, 2, 1, nStates); return rc; } //上传数据到客户PLC ACTUATOR_API int __stdcall UploadData(void* ctxDev, unsigned short* nDatas, unsigned short nSize) { if (NULL == ctxDev && nSize < 3) return -1; switch(nDatas[0]) {//设备粮种信息,转PLC两种信息 case 1: //小麦 nDatas[0] = 4; break; case 2: //水稻 nDatas[0] = 1; break; case 3: //黄豆 nDatas[0] = 3; break; case 4: //玉米 nDatas[0] = 2; break; } //2 和 1交换。 unsigned short nVal = nDatas[1]; //水分 nDatas[1] = nDatas[2];//水分和容重交换 nDatas[2] = nVal; int rc = modbus_write_registers((modbus_t*)ctxDev, 1, 1, nDatas); rc = modbus_write_registers((modbus_t*)ctxDev, 3, 2, &nDatas[1]); return rc; } int ExeCommands(void* ctxDev, unsigned short nCmdType, unsigned short nGrainType = 0, unsigned int nResponseSeconds = 0, unsigned int nResponseUSeconds = 500000) { if (NULL == ctxDev) return -1; unsigned char cmdType = (unsigned char)nCmdType; unsigned char grainType = (unsigned char)nGrainType; uint16_t val = (cmdType << 8) | grainType; //int val = (grainType << 8) | cmdType; uint32_t nOldSeconds = 0; uint32_t nOldUSeonds = 0; //获取旧时间 modbus_get_response_timeout((modbus_t*)ctxDev, &nOldSeconds, &nOldUSeonds); //设置新时间 modbus_set_response_timeout((modbus_t*)ctxDev, nResponseSeconds, nResponseUSeconds); int rc = modbus_write_register((modbus_t*)ctxDev, 0, val); //恢复旧时间 modbus_set_response_timeout((modbus_t*)ctxDev, nOldSeconds, nOldUSeonds); return rc; } //向水分仪发命令 ACTUATOR_API int __stdcall SendCommands(void* ctxDev, unsigned short nCmdType, unsigned short nGrainType, unsigned int nResponseSeconds, unsigned int nResponseUSeconds) { if (NULL == ctxDev) return -1; int ret = 0; //unsigned char cmdType = (unsigned char)nCmdType; //unsigned char grainType = (unsigned char)nGrainType; if (nGrainType > 0) //保持粮食品种信息 nGoodtype = nGrainType; if (nCmdType == WR_VERIFY) {//校准检测时候下发粮食品种信息 ret = ExeCommands(ctxDev, WR_GOODS, nGoodtype); if (ret < 0) printf("下发粮种失败!\n"); else ret = ExeCommands(ctxDev, WR_DETECT, nGrainType, nResponseSeconds, nResponseUSeconds); return ret; } else ret = ExeCommands(ctxDev, nCmdType, nGrainType, nResponseSeconds, nResponseUSeconds); return ret; } //向水分仪写参数 ACTUATOR_API int __stdcall WriteParams(void* ctxDev, unsigned short nStartFreq, unsigned short nStopFreq, unsigned short nStepFreq, unsigned short nDecayCode, unsigned short nAscValid ) { if (NULL == ctxDev) return -1; unsigned short nParams[10] = {nStartFreq,nStopFreq,nStepFreq,nDecayCode,nAscValid }; int rc = modbus_write_registers((modbus_t*)ctxDev, 5, 5, nParams); return rc; } //从水分仪写参数 (从0号寄存器开始,0号寄存器为电平,1号为重量,2号为温度,3号为湿度 ) ACTUATOR_API int __stdcall ReadDatas(void* ctxDev, unsigned short* nDatas, unsigned short nSize) { if (NULL == ctxDev) return -1; int rc = modbus_read_registers((modbus_t*)ctxDev, 0, nSize, nDatas); return rc; } //读校准数据 (10号寄存器) ACTUATOR_API int __stdcall ReadVcc(void* ctxDev, unsigned short* nVcc) { if (NULL == ctxDev) return -1; //int rc = modbus_read_registers((modbus_t*)ctxDev, 10, 1, nVcc); int rc = modbus_read_registers((modbus_t*)ctxDev, 0, 1, nVcc); return rc; } //单独读重量数据 (1号寄存器) ACTUATOR_API int __stdcall ReadWeight(void* ctxDev, unsigned short* nWeight) { if (NULL == ctxDev) return -1; uint32_t nOldSeconds = 0; uint32_t nOldUSeonds = 0; //获取旧时间 modbus_get_response_timeout((modbus_t*)ctxDev, &nOldSeconds, &nOldUSeonds); //设置新时间 modbus_set_response_timeout((modbus_t*)ctxDev, 10, 0); int rc = modbus_read_registers((modbus_t*)ctxDev, 1, 1, nWeight); //恢复旧时间 modbus_set_response_timeout((modbus_t*)ctxDev, nOldSeconds, nOldUSeonds); return rc; } ACTUATOR_API int __stdcall Linearize(float x[], float y[], double Coefficient[], const int n, const int nSampleNumber) { float A[2] = { 0 }, B[2] = { 0 }, C; //float Y[3][nSampleNumber] = { 0 }; float* yAlt = new float[3 * nSampleNumber]; float (*Y)[3] = (float (*)[3])yAlt; float temp; //float Co[3][n + 1] = { 0 }; float* coAlt = new float[3 * (n + 1)]; float (*Co)[3] = (float(*)[3])coAlt; memset(yAlt, 0, sizeof(float) * (3 * nSampleNumber)); memset(coAlt, 0, sizeof(float) * (3 * (n + 1))); unsigned char i, j; // float x[]={0,1,2,3,4,5,6,7,8,9,10,11}; // float y[]={2506,2200,1846,1440,1004,548,79,-387,-847,-1288,-1700,-2066}; int ret = 1; try { C = 0; for (i = 0; i < nSampleNumber; i++) { Y[0][i] = 1; C += y[i]; A[0] += x[i]; } A[0] /= nSampleNumber; C /= nSampleNumber; Co[0][0] = 1; Coefficient[0] = C; C = 0; for (i = 0; i < nSampleNumber; i++) { Y[1][i] = x[i] - A[0]; C += Y[1][i] * y[i]; B[0] += Y[1][i] * Y[1][i]; A[1] += x[i] * Y[1][i] * Y[1][i]; } A[1] /= B[0]; C /= B[0]; B[0] /= nSampleNumber; Co[1][0] = -1 * A[0]; Co[1][1] = 1; A[0] = A[1]; Coefficient[0] += Co[1][0] * C; Coefficient[1] = Co[1][1] * C; for (i = 2; i <= n; i++) { temp = 0; C = 0; A[1] = 0; B[1] = 0; for (j = 0; j < nSampleNumber; j++) { Y[2][j] = Y[1][j]; Y[2][j] *= (x[j] - A[0]); Y[2][j] -= (B[0] * Y[0][j]); C += Y[2][j] * y[j]; temp += Y[2][j] * Y[2][j]; if (i < n) { A[1] += x[j] * Y[2][j] * Y[2][j]; B[1] += Y[1][j] * Y[1][j]; } Y[0][j] = Y[1][j]; Y[1][j] = Y[2][j]; } C /= temp; for (j = i; j >= 1; j--) { Co[2][j] = Co[1][j - 1]; } for (j = 0; j < i; j++) { Co[2][j] -= Co[1][j] * A[0]; } for (j = 0; j <= i - 2; j++) { Co[0][j] *= B[0]; Co[2][j] -= Co[0][j]; } for (j = 0; j <= i; j++) { Co[0][j] = Co[1][j]; Co[1][j] = Co[2][j]; Co[2][j] = 0; } for (j = 0; j <= i; j++) { Coefficient[j] += C * Co[1][j]; } if (i < n) { B[0] = temp / B[1]; A[0] = A[1] / temp; } } } catch(...) { ret = -1; } if(yAlt) delete yAlt; if(coAlt) delete coAlt; return ret; } ACTUATOR_API double __stdcall CalcValue(unsigned short nDValue, double Coef0, double Coef1, double Coef2, double Coef3, double Coef4) { return ( Coef0 + Coef1 * nDValue + Coef2 * nDValue * nDValue + Coef3 * nDValue * nDValue * nDValue + Coef4 * nDValue * nDValue * nDValue * nDValue ); }