// Actuator.cpp : 定义 DLL 的导出函数。
|
//
|
|
#include "pch.h"
|
#include "framework.h"
|
#include "Actuator.h"
|
|
#include <stdio.h>
|
#include <errno.h>
|
#include <stdlib.h>
|
#include <string.h>
|
|
#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
|
);
|
}
|