I am working on a project using an ESP32 WROOM hosting a webserver. The ESP32 is using the UART1 to read and write Modbus registers to a motor controller. I reference as HVFD. HVFD can be configured to either type "P1" or "WJ". The values in the P1 or WJ struct are never changing they are only used to fill the matching data in the HVFD struct. Is there a better way to do this?
FYI HVFD_Select is user selectable from the webserver the ESP is hosting. I actually pull the value for HVFD_Select from EEPROM but i am just simplifying the example.
int32_t Hoist_Output_Frequency;
int32_t Hoist_Output_Current;
int32_t Hoist_Output_Direction;
int32_t Hoist_Position;
int32_t Hoist_DI_Status;
int32_t Hoist_Operation_Status;
// Hoist EZSQ Settings Variables
int32_t Hoist_Micro_Low_Spd_Freq_Value = 0;
int32_t Hoist_Low_Spd_Freq_Value = 0;
int32_t Hoist_High_Spd_Freq_Value = 0;
int32_t Hoist_Micro_High_Spd_Freq_Value = 0;
int32_t Hoist_Speed_Control_Function_Value = 0;
int32_t Hoist_AAAS_Function_Value = 0;
int32_t Hoist_Load_Float_Value = 0;
int32_t Hoist_Shock_Load_Function_Value = 0;
// Hoist Accel & Decel Settings Settings Variables
int32_t Hoist_Alt_AD_Function_Value = 0;
int32_t Hoist_Acc1_Acc2_Function_Value = 0;
int32_t Hoist_Dec1_Dec2_Function_Value = 0;
int32_t Hoist_Acc1_Function_Value = 0;
int32_t Hoist_Dec1_Function_Value = 0;
int32_t Hoist_Acc2_Function_Value = 0;
int32_t Hoist_Dec2_Function_Value = 0;
typedef struct HVFD_Mon_s {
const char *Abbrv;
const char *Type;
const char *Json_Var;
bool Enable;
byte Register[8];
int Resp_Buf_Size;
int32_t *Data_Pointer;
} HVFD_Mon_t;
HVFD_Mon_t HVFD_Mon[] = {
// Monitors
{ "FM", "Monitor", "HOF", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, &Hoist_Output_Frequency },
{ "IOUT", "Monitor", "HOC", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, &Hoist_Output_Current },
{ "DIR", "Monitor", "HOD", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, &Hoist_Output_Direction },
{ "POS", "Monitor", "HPC", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, &Hoist_Position },
{ "DIM", "Monitor", "HDI", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, &Hoist_DI_Status },
{ "STATUS", "Monitor", "HOS", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, &Hoist_Operation_Status },
};
typedef struct HVFD_Settings_s {
const char *Abbrv;
const char *Type;
const char *Json_Var;
bool Enable;
byte Register[8];
int Resp_Buf_Size;
int Min_Value;
int Max_Value;
int32_t *Data_Pointer;
} HVFD_Settings_t;
HVFD_Settings_t HVFD_Settings[] = {
// EZSQ Settings
{ "MLSF", "Setting", "HMLSFV", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 0, 0, &Hoist_Micro_Low_Spd_Freq_Value },
{ "SLSF", "Setting", "HLSFV", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 0, 0, &Hoist_Low_Spd_Freq_Value },
{ "SHSF", "Setting", "HHSFV", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 0, 0, &Hoist_High_Spd_Freq_Value },
{ "MHSF", "Setting", "HMHSFV", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 0, 0, &Hoist_Micro_High_Spd_Freq_Value },
{ "SSCM", "Setting", "HSCFV", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 0, 0, &Hoist_Speed_Control_Function_Value },
{ "ASFS", "Setting", "HASFV", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 0, 0, &Hoist_AAAS_Function_Value },
{ "LFT", "Setting", "HLFTV", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 0, 0, &Hoist_Load_Float_Value },
{ "SLF", "Setting", "HSLFV", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 0, 0, &Hoist_Shock_Load_Function_Value },
// Accel & Decel Settings
{ "2CH", "Setting", "HALTAD", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 0, 0, &Hoist_Alt_AD_Function_Value},
{ "A1A2TF", "Setting", "HA1A2", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 0, 0, &Hoist_Acc1_Acc2_Function_Value},
{ "D1D2TF", "Setting", "HD1D2", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 0, 0, &Hoist_Dec1_Dec2_Function_Value},
{ "ACC1", "Setting", "HACC1", false,{ 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 0, 0, &Hoist_Acc1_Function_Value},
{ "DECEL1", "Setting", "HDEC1", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 0, 0, &Hoist_Dec1_Function_Value},
{ "ACC2", "Setting", "HACC2", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 0, 0, &Hoist_Acc2_Function_Value},
{ "DECEL2", "Setting", "HDEC2", false, { 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 0, 0, &Hoist_Dec2_Function_Value}
};
typedef struct P1_s {
const char *Param; // Just For Reference
const char *Abbrv;
const char *Desc; // Just For Reference
const char *Type;
byte Func_Addr[4];
int Resp_Buf_Size;
int Min_Value;
int Max_Value;
} P1_t;
P1_t P1[] = {
// Monitors
{ "dA-01", "FM", "Output Frequency Monitor", "Monitor", { 0x27, 0x10, 0x00, 0x01 }, 7, 0, 0 },
{ "dA-02", "IOUT", "Output Current Monitor", "Monitor", { 0x27, 0x11, 0x00, 0x01 }, 7, 0, 0 },
{ "dA-03", "DIR", "Output Direction Monitor", "Monitor", { 0x27, 0x12, 0x00, 0x01 }, 7, 0, 0 },
{ "dA-20", "POS", "Current Position Monitor", "Monitor", { 0x27, 0x23, 0x00, 0x02 }, 9, 0, 0 },
{ "dA-51", "DIM", "Input Terminal Monitor", "Monitor", { 0x27, 0x42, 0x00, 0x01 }, 7, 0, 0 },
{ "dC-35", "STATUS", "Operation Status Monitor", "Monitor", { 0x27, 0xFA, 0x00, 0x01 }, 7, 0, 0 },
// EZSQ Settings
{ "UE-10", "MLSF", "Low Micro-Speed Freq Setting", "Setting", { 0x47, 0xE9, 0x00, 0x01 }, 7, 250, 6000 },
{ "UE-11", "SLSF", "Low Speed Freq Setting", "Setting", { 0x47, 0xEA, 0x00, 0x01 }, 7, 250, 6000 },
{ "UE-12", "SHSF", "High Speed Freq Setting", "Setting", { 0x47, 0xEB, 0x00, 0x01 }, 7, 250, 6000 },
{ "UE-15", "MHSF", "High Micro-Speed Freq Setting", "Setting", { 0x47, 0xEE, 0x00, 0x01 }, 7, 250, 6000 },
{ "UE-18", "SSCM", "Standard Speed Control Setting", "Setting", { 0x47, 0xF1, 0x00, 0x01 }, 7, 0, 6 },
{ "UE-21", "ASAL", "Auto Speed Activation Level Setting", "Setting", { 0x47, 0xF4, 0x00, 0x01 }, 7, 0, 1000 },
{ "UE-22", "ASFS", "Auto Speed Function Setting", "Setting", { 0x47, 0xF5, 0x00, 0x01 }, 7, 0, 2 },
{ "UE-29", "LFT", "Load Float Time Setting", "Setting", { 0x47, 0xFC, 0x00, 0x01 }, 7, 50, 3000 },
{ "UE-52", "SLF", "Shock Load Function Setting", "Setting", { 0x48, 0x13, 0x00, 0x01 }, 7, 0, 2 },
// Accel & Decel Settings
{ "AC115", "2CH", "Switch Method To Acce2/Decel2 Setting", "Setting", { 0x2F, 0xB6, 0x00, 0x01 }, 7, 0, 2 },
{ "AC116", "A1A2TF", "Accel1 To Accel2 Trans Freq Setting", "Setting", { 0x2F, 0xB7, 0x00, 0x01 }, 7, 0, 59000 },
{ "AC117", "D1D2TF", "Decel1 To Decel2 Trans Freq Setting", "Setting", { 0x2F, 0xB8, 0x00, 0x01 }, 7, 0, 59000 },
{ "AC120", "ACC1", "Accel1 Setting", "Setting", { 0x2F, 0xBB, 0x00, 0x02 }, 9, 50, 59000 },
{ "AC122", "DECEL1", "Decel1 Setting", "Setting", { 0x2F, 0xBD, 0x00, 0x02 }, 9, 50, 59000 },
{ "AC124", "ACC2", "Accel2 Setting", "Setting", { 0x2F, 0xBF, 0x00, 0x02 }, 9, 50, 59000 },
{ "AC126", "DECEL2", "Decel2 Setting", "Setting", { 0x2F, 0xC1, 0x00, 0x02 }, 9, 50, 59000 }
};
typedef struct WJ_s {
const char *Param; // Just For Reference
const char *Abbrv;
const char *Desc; // Just For Reference
const char *Type;
byte Func_Addr[4];
int Resp_Buf_Size;
int Min_Value;
int Max_Value;
} WJ_t;
WJ_t WJ[] = {
// Monitors
{ "d001", "FM", "Output Frequency Monitor", "Monitor", { 0x10, 0x00, 0x00, 0x02 }, 9, 0, 0 },
{ "d002", "IOUT", "Output Current Monitor", "Monitor", { 0x10, 0x02, 0x00, 0x01 }, 7, 0, 0 },
{ "d003", "DIR", "Output Direction Monitor", "Monitor", { 0x10, 0x03, 0x00, 0x01 }, 7, 0, 0 },
{ "d030", "POS", "Current Position Monitor", "Monitor", { 0x10, 0x37, 0x00, 0x02 }, 9, 0, 0 },
{ "d005", "DIM", "Input Terminal Monitor", "Monitor", { 0x10, 0x06, 0x00, 0x01 }, 7, 0, 0 },
{ "J002", "STATUS", "Operation Status Monitor", "Monitor", { 0x00, 0x03, 0x00, 0x01 }, 7, 0, 0 },
// EZSQ Settings
{ "P100", "MLSF", "Low Micro-Speed Freq Setting", "Function", { 0x16, 0x65, 0x00, 0x01 }, 7, 250, 6000 },
{ "P101", "SLSF", "Low Speed Freq Setting", "Function", { 0x16, 0x66, 0x00, 0x01 }, 7, 250, 6000 },
{ "P102", "SHSF", "High Speed Freq Setting", "Function", { 0x16, 0x67, 0x00, 0x01 }, 7, 250, 6000 },
{ "P105", "MHSF", "High Micro-Speed Freq Setting", "Function", { 0x16, 0x6A, 0x00, 0x01 }, 7, 250, 6000 },
{ "P108", "SSCM", "Standard Speed Control Setting", "Function", { 0x16, 0x6D, 0x00, 0x01 }, 7, 0, 5 },
{ "P110", "ASFS", "Auto Speed Function Setting", "Function", { 0x16, 0x6F, 0x00, 0x01 }, 7, 0, 1 },
{ "P111", "ASAL", "Auto Speed Activation Level Setting", "Function", { 0x16, 0x70, 0x00, 0x01 }, 7, 0, 100 },
// Accel & Decel Settings
{ "A094", "2CH", "Switch Method To Acce2/Decel2 Setting", "Function", { 0x12, 0x77, 0x00, 0x01 }, 7, 0, 2 },
{ "A095", "A1A2TF", "Accel1 To Accel2 Trans Freq Setting", "Function", { 0x12, 0x78, 0x00, 0x02 }, 9, 0, 59000 },
{ "A096", "D1D2TF", "Decel1 To Decel2 Trans Freq Setting", "Function", { 0x12, 0x7A, 0x00, 0x02 }, 9, 0, 59000 },
{ "F002", "ACC1", "Accel1 Setting", "Function", { 0x11, 0x02, 0x00, 0x02 }, 9, 50, 59000 },
{ "F003", "DECEL1", "Decel1 Setting", "Function", { 0x11, 0x04, 0x00, 0x02 }, 9, 50, 59000 },
{ "A092", "ACC2", "Accel2 Setting", "Function", { 0x12, 0x73, 0x00, 0x02 }, 9, 50, 59000 },
{ "A093", "DECEL2", "Decel2 Setting", "Function", { 0x12, 0x75, 0x00, 0x02 }, 9, 50, 59000 }
};
void setup() {
int HVFD_Select = 1; // 1 = P1, 2 = WJ
int Hoist_VFD_Address = 3; // RS485 Node 1-10
switch (HVFD_Select) {
case 1: // P1 Model
for (int i = 0; i < sizeof(HVFD_Mon) / sizeof(HVFD_Mon[0]); i++) {
for (int j = 0; j < sizeof(P1) / sizeof(P1[0]); j++) {
if (P1[j].Abbrv == HVFD_Mon[i].Abbrv && P1[j].Type == HVFD_Mon[i].Type) {
HVFD_Mon[i].Enable = true;
HVFD_Mon[i].Register[0] = Hoist_VFD_Address;
HVFD_Mon[i].Register[2] = P1[j].Func_Addr[0];
HVFD_Mon[i].Register[3] = P1[j].Func_Addr[1];
HVFD_Mon[i].Register[4] = P1[j].Func_Addr[2];
HVFD_Mon[i].Register[5] = P1[j].Func_Addr[3];
uint16_t CRC = ModRTU_CRC(HVFD_Mon[i].Register, sizeof(HVFD_Mon[i].Register) - 2);
HVFD_Mon[i].Register[6] = CRC;
HVFD_Mon[i].Register[7] = (CRC >> 8);
HVFD_Mon[i].Resp_Buf_Size = P1[j].Resp_Buf_Size;
}
}
}
for (int i = 0; i < sizeof(HVFD_Settings) / sizeof(HVFD_Settings[0]); i++) {
for (int j = 0; j < sizeof(P1) / sizeof(P1[0]); j++) {
if (P1[j].Abbrv == HVFD_Settings[i].Abbrv && P1[j].Type == HVFD_Settings[i].Type) {
HVFD_Settings[i].Enable = true;
HVFD_Settings[i].Register[0] = Hoist_VFD_Address;
HVFD_Settings[i].Register[2] = P1[j].Func_Addr[0];
HVFD_Settings[i].Register[3] = P1[j].Func_Addr[1];
HVFD_Settings[i].Register[4] = P1[j].Func_Addr[2];
HVFD_Settings[i].Register[5] = P1[j].Func_Addr[3];
uint16_t CRC = ModRTU_CRC(HVFD_Settings[i].Register, sizeof(HVFD_Settings[i].Register) - 2);
HVFD_Settings[i].Register[6] = CRC;
HVFD_Settings[i].Register[7] = (CRC >> 8);
HVFD_Settings[i].Resp_Buf_Size = P1[j].Resp_Buf_Size;
HVFD_Settings[i].Min_Value = P1[j].Min_Value;
HVFD_Settings[i].Max_Value = P1[j].Max_Value;
}
}
}
break;
case 2: // WJ200 Model
for (int i = 0; i < sizeof(HVFD_Mon) / sizeof(HVFD_Mon[0]); i++) {
for (int j = 0; j < sizeof(WJ) / sizeof(WJ[0]); j++) {
if (WJ[j].Abbrv == HVFD_Mon[i].Abbrv && WJ[j].Type == HVFD_Mon[i].Type) {
HVFD_Mon[i].Enable = true;
HVFD_Mon[i].Register[0] = Hoist_VFD_Address;
HVFD_Mon[i].Register[2] = WJ[j].Func_Addr[0];
HVFD_Mon[i].Register[3] = WJ[j].Func_Addr[1];
HVFD_Mon[i].Register[4] = WJ[j].Func_Addr[2];
HVFD_Mon[i].Register[5] = WJ[j].Func_Addr[3];
uint16_t CRC = ModRTU_CRC(HVFD_Mon[i].Register, sizeof(HVFD_Mon[i].Register) - 2);
HVFD_Mon[i].Register[6] = CRC;
HVFD_Mon[i].Register[7] = (CRC >> 8);
HVFD_Mon[i].Resp_Buf_Size = WJ[j].Resp_Buf_Size;
}
}
}
for (int i = 0; i < sizeof(HVFD_Settings) / sizeof(HVFD_Settings[0]); i++) {
for (int j = 0; j < sizeof(WJ) / sizeof(WJ[0]); j++) {
if (WJ[j].Abbrv == HVFD_Settings[i].Abbrv && WJ[j].Type == HVFD_Settings[i].Type) {
HVFD_Settings[i].Enable = true;
HVFD_Settings[i].Register[0] = Hoist_VFD_Address;
HVFD_Settings[i].Register[2] = WJ[j].Func_Addr[0];
HVFD_Settings[i].Register[3] = WJ[j].Func_Addr[1];
HVFD_Settings[i].Register[4] = WJ[j].Func_Addr[2];
HVFD_Settings[i].Register[5] = WJ[j].Func_Addr[3];
uint16_t CRC = ModRTU_CRC(HVFD_Settings[i].Register, sizeof(HVFD_Settings[i].Register) - 2);
HVFD_Settings[i].Register[6] = CRC;
HVFD_Settings[i].Register[7] = (CRC >> 8);
HVFD_Settings[i].Resp_Buf_Size = WJ[j].Resp_Buf_Size;
HVFD_Settings[i].Min_Value = WJ[j].Min_Value;
HVFD_Settings[i].Max_Value = WJ[j].Max_Value;
}
}
}
break;
}
}
void loop(){}
uint16_t ModRTU_CRC(byte buf[], int len) {
uint16_t crc = 0xFFFF;
for (int pos = 0; pos < len; pos++) {
crc ^= (uint16_t)buf[pos]; // XOR byte into least sig. byte of crc
for (int i = 8; i != 0; i--) { // Loop over each bit
if ((crc & 0x0001) != 0) { // If the LSB is set
crc >>= 1; // Shift right and XOR 0xA001
crc ^= 0xA001;
} else // Else LSB is not set
crc >>= 1; // Just shift right
}
}
return crc;
}