updated and added registers to match UDT

copy-pasted develop version of code, added tags required for UDT.
This commit is contained in:
RobertJDavis
2025-12-10 15:06:36 -06:00
parent 428bb7b367
commit a04324a8d6
5 changed files with 80 additions and 51 deletions

View File

@@ -14,7 +14,7 @@
default_envs = PHX3_VFD_ABB_ACH580_RTU ; Select here the name of the configuration you want to download
[env]
upload_port = COM9
upload_port = COM11
[common_env_options]
framework = arduino

View File

@@ -32,9 +32,7 @@
*/
template<>
FailState<ModbusRTU>::FailState(const std::vector<std::string>& activeAlarms) {
addStrategy("Motor Speed Used", new RampStrategy(0.0f, 200.0f, 1000 ));
addStrategy("Speed Feedback", new RampStrategy(0.0f, 200.0f, 1000 ));
addStrategy("Motor Speed estimated", new RampStrategy(0.0f, 200.0f, 1000 ));
addStrategy("Motor Current", new RampStrategy(0.0f, 20.0f, 1000 ));
addStrategy("Motor Torque", new RampStrategy(0.0f, 20.0f, 1000 ));
addStrategy("Inverter Temperature", new RampStrategy(0.0f, 1.0f, 1000 ));
@@ -42,7 +40,11 @@ FailState<ModbusRTU>::FailState(const std::vector<std::string>& activeAlarms) {
addStrategy("Output Frequency", new SingleValueStrategy(0.1f, 0.2f, 1000 ));
addStrategy("Output Voltage", new SingleValueStrategy(0.1f, 0.1f, 1000 ));
addStrategy("DC Voltage", new SingleValueStrategy(0.1f, 0.1f, 1000 ));
addStrategy("Output Power", new SingleValueStrategy(0.1f, 0.1f, 1000 ));
addStrategy("Motor Shaft Power", new SingleValueStrategy(0.1f, 0.1f, 1000 ));
addStrategy("AI1 Scaled", new RampStrategy(0.0f, 2.0f, 1000 ));
addStrategy("AI2 Scaled", new RampStrategy(0.0f, 5.0f, 1000 ));
addStrategy("AO1 Actual", new RampStrategy(0.0f, 2.0f, 1000 ));
}
/**
@@ -77,7 +79,17 @@ template<>
void FailState<ModbusRTU>::enterState(Equipment<ModbusRTU>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Fail State...");
/**
setPointValue(equipment, "Speed Scaling", 1800);
setPointValue(equipment, "Frequency Scaling", 60);
setPointValue(equipment, "Nominal Current", 65);
setPointValue(equipment, "Nominal Voltage", 480);
setPointValue(equipment, "Nominal Frequency", 60);
setPointValue(equipment, "Nominal Speed", 1800);
setPointValue(equipment, "Nominal Power", 50);
*/
setPointValue(equipment, "Run Status", 0);
setPointValue(equipment, "DI Status", 0);
}
/**

View File

@@ -41,19 +41,21 @@
*/
template<>
RunningState<ModbusRTU>::RunningState() {
addStrategy("Motor Speed Used", new RampStrategy(1800.0f, 100.0f, 1000));
addStrategy("Speed Feedback", new RampStrategy(1800.0f, 100.0f, 1000));
addStrategy("Motor Speed estimated", new RampStrategy(1800.0f, 100.0f, 1000));
addStrategy("Motor Current", new RampStrategy(65.0f, 7.0f, 1000));
addStrategy("Motor Torque", new RampStrategy(90.0f, 10.0f, 1000));
addStrategy("Inverter Temperature", new SquareStrategy(40.0f, 80.0f, 1000));
addStrategy("Inverter Temperature", new RampStrategy(70.0f, 1.0f, 1000));
addStrategy("Output Frequency", new RampStrategy(60.0f, 3.0f, 1000 ));
addStrategy("Output Voltage", new RampStrategy(480.0f, 15.0f, 1000 ));
addStrategy("DC Voltage", new RampStrategy(678.0f, 20.0f, 1000 ));
addStrategy("Output Power", new RampStrategy(36.7f, 2.0f, 1000 ));
addStrategy("Inverter kWh cnt", new TotalizerStrategy(1000));
addStrategy("Hours Run", new TotalizerStrategy(1000));
addStrategy("Motor Shaft Power", new RampStrategy(36.7f, 2.0f, 1000 ));
addStrategy("Inverter MWh counter", new TotalizerStrategy(1000));
addStrategy("Inverter kWh counter", new TotalizerStrategy(1000));
addStrategy("AI1 Scaled", new RampStrategy(10.0f, 1.0f, 1000 ));
addStrategy("AI2 Scaled", new RampStrategy(20.0f, 1.0f, 1000 ));
addStrategy("AO1 Actual", new RampStrategy(10.0f, 1.0f, 1000 ));
}
/**
@@ -89,30 +91,20 @@ State<ModbusRTU>* RunningState<ModbusRTU>::update(Equipment<ModbusRTU>* equipmen
float voltage_update = speed_pct * 480;
float dc_voltage_update = speed_pct * 678;
float current_update = speed_pct * speed_pct * 65;
float torque_update = speed_pct * speed_pct * 100; // This is a % of nominal motor torque
float torque_update = speed_pct * speed_pct * 100 * 10; // This is a % of nominal motor torque, x10 b/c is scaled by 100 in actual equipment, this register is only 10x
float freq_update = speed_pct * 60;
float power_update = speed_pct * speed_pct * speed_pct * 36.77f; // 50 hp ~ 36.77kW
float currentSP = getPointValue(equipment, "Speed Cmd");
Strategy_Behavior* motorSpeedUsed = getStrategy("Motor Speed Used");
// 2. Check if the strategy exists
if (motorSpeedUsed) {
// 3. Cast it to a RampStrategy pointer and call setSetpoint.
static_cast<RampStrategy*>(motorSpeedUsed)->setTarget(currentSP);
}
float AI1_update = speed_pct *10;
float AI2_update = speed_pct *20;
float AO1_update = speed_pct *10;
Strategy_Behavior* speedFeedback = getStrategy("Speed Feedback");
if (speedFeedback) {
static_cast<RampStrategy*>(speedFeedback)->setTarget(currentSP);
}
// To have Motor Speed estimated slightly different - for purposes of differentiating in Ignition
float rpm_est = currentSP * 0.98f;
Strategy_Behavior* motorSpeedEst = getStrategy("Motor Speed estimated");
if (motorSpeedEst) {
static_cast<RampStrategy*>(motorSpeedEst)->setTarget(rpm_est);
}
Strategy_Behavior* frequencystrategy = getStrategy("Output Frequency");
if (frequencystrategy) {
static_cast<RampStrategy*>(frequencystrategy)->setTarget(freq_update);
@@ -138,10 +130,25 @@ State<ModbusRTU>* RunningState<ModbusRTU>::update(Equipment<ModbusRTU>* equipmen
static_cast<RampStrategy*>(voltagestrategy)->setTarget(voltage_update);
}
Strategy_Behavior* powerstrategy = getStrategy("Output Power");
Strategy_Behavior* powerstrategy = getStrategy("Motor Shaft Power");
if (powerstrategy) {
static_cast<RampStrategy*>(powerstrategy)->setTarget(power_update);
}
Strategy_Behavior* AI1strategy = getStrategy("AI1 Scaled");
if (AI1strategy) {
static_cast<RampStrategy*>(AI1strategy)->setTarget(AI1_update);
}
Strategy_Behavior* AI2strategy = getStrategy("AI2 Scaled");
if (AI2strategy) {
static_cast<RampStrategy*>(AI2strategy)->setTarget(AI2_update);
}
Strategy_Behavior* AO1strategy = getStrategy("AO1 Actual");
if (AO1strategy) {
static_cast<RampStrategy*>(AO1strategy)->setTarget(AO1_update);
}
// Apply any strategies defined for the standby state
_applyStrategies(equipment);
@@ -158,6 +165,7 @@ void RunningState<ModbusRTU>::enterState(Equipment<ModbusRTU>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Running State...");
setPointValue(equipment, "Run Status", 1);
setPointValue(equipment, "DI Status", 1);
}
/**

View File

@@ -30,9 +30,7 @@
*/
template<>
StandbyState<ModbusRTU>::StandbyState() {
addStrategy("Motor Speed Used", new RampStrategy(0.0f, 200.0f, 1000 ));
addStrategy("Speed Feedback", new RampStrategy(0.0f, 200.0f, 1000 ));
addStrategy("Motor Speed estimated", new RampStrategy(0.0f, 200.0f, 1000 ));
addStrategy("Motor Current", new RampStrategy(0.0f, 20.0f, 1000 ));
addStrategy("Motor Torque", new RampStrategy(0.0f, 20.0f, 1000 ));
addStrategy("Inverter Temperature", new RampStrategy(0.0f, 1.0f, 1000 ));
@@ -40,7 +38,11 @@ StandbyState<ModbusRTU>::StandbyState() {
addStrategy("Output Frequency", new SingleValueStrategy(0.1f, 0.2f, 1000 ));
addStrategy("Output Voltage", new SingleValueStrategy(0.1f, 0.1f, 1000 ));
addStrategy("DC Voltage", new SingleValueStrategy(0.1f, 0.1f, 1000 ));
addStrategy("Output Power", new SingleValueStrategy(0.1f, 0.1f, 1000 ));
addStrategy("Motor Shaft Power", new SingleValueStrategy(0.1f, 0.1f, 1000 ));
addStrategy("AI1 Scaled", new RampStrategy(0.0f, 2.0f, 1000 ));
addStrategy("AI2 Scaled", new RampStrategy(0.0f, 5.0f, 1000 ));
addStrategy("AO1 Actual", new RampStrategy(0.0f, 2.0f, 1000 ));
}
/**
@@ -85,6 +87,7 @@ void StandbyState<ModbusRTU>::enterState(Equipment<ModbusRTU>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Standby State...");
setPointValue(equipment, "Run Status", 0);
setPointValue(equipment, "DI Status", 0);
}
/**

View File

@@ -6,7 +6,7 @@
*
* This file contains important configurations for the Modbus RTU communication
* and the specific register map for the emulated device.
* These are 32-bit modbus registers.
* These are 16-bit modbus registers.
* Added "Run Status" and "Fault Status" to simulated hard IO points and send feedback to PLC during simulation.
*/
@@ -56,32 +56,38 @@
*/
modbusMap mb_map[] =
{
{HR, 149, 1800, "Speed Cmd"}, // arbitrary register number - receive signal from PLC (hardwire IO in field); expecting rpm (1800 rpm max)
{HR, 151, 0, "Start/Stop"}, // arbitrary register number - receive signal from PLC (hardwire IO in practice)
{HR, 149, 1650, "Speed Cmd"}, // arbitrary register number - receive signal from PLC (hardwire IO in field); expecting rpm (1800 rpm max)
{HR, 151, 1, "Start/Stop"}, // arbitrary register number - receive signal from PLC (hardwire IO in practice)
{HR, 152, 0, "HOA Command"}, // arbitrary register number - not used in program
{HR, 154, 0, "Run Status"}, // arbitrary register number - 0:off, 1:on (simulated hardwire IO) sending feedback to PLC during simulation.
{HR, 155, 1, "Fault Status"}, // arbitrary register number - 0:faulted, 1:not faulted (simulated hardwire IO). When = 0, will turn off VFD.
{HR, 156, 0, "Speed Feedback"}, // arbitrary register number - send signal to PLC (simulated hardwire IO). Will be equal to Motor Speed Used register
// {HR, 156, 0, "Speed Feedback"}, // arbitrary register number - send signal to PLC (simulated hardwire IO). Will be equal to Motor Speed Used register
{HR_FLOAT, 20201, 0, "Motor Speed Used"}, // RJD: 1800 rpm max
{HR_FLOAT, 20203, 0, "Motor Speed estimated"}, // RJD: 1800 rpm max
{HR_FLOAT, 20211, 0, "Output Frequency"}, // 60 Hz @100% speed
{HR_FLOAT, 20213, 0, "Motor Current"}, // RJD: Changed from HR_10x to HR, 65 FLA
{HR_FLOAT, 20219, 0, "Motor Torque"}, // % of nominal torque
{HR_FLOAT, 20221, 0, "DC Voltage"}, // approx 678 VDC @100% speed
{HR_FLOAT, 20225, 0, "Output Voltage"}, // RJD: 480 VAC
{HR_FLOAT, 20227, 0, "Output Power"}, //max 372580 // RJD: Changed from HR_10x to HR, 50 hp ~ 36.77 kW
{HR_FLOAT, 20239, 0, "Inverter kWh cnt"},
{HR_FLOAT, 21005, 0, "Hours Run"},
{HR_FLOAT, 21021, 0, "Inverter Temperature"}, // RJD: Changed from HR_10x to HR, % of fault limit
{HR, 100, 0, "Speed Feedback"}, // 1800 rpm max
{HR, 105, 0, "Output Frequency"}, // 60 Hz @100% speed
{HR, 106, 0, "Motor Current"}, // 65 FLA
{HR_10x, 109, 0, "Motor Torque"}, // % of nominal torque
{HR_10x, 110, 0, "DC Voltage"}, // approx 678 VDC @100% speed
{HR, 112, 0, "Output Voltage"}, // 480 VAC
{HR_10x, 116, 0, "Motor Shaft Power"}, // 50 hp ~ 36.77 kW
{HR, 118, 0, "Inverter MWh counter"},
{HR, 119, 0, "Inverter kWh counter"},
{HR, 510, 0, "Inverter Temperature"}, // RJD: Changed from HR_10x to HR, % of fault limit
{HR, 519, 0, "Diagnostic Word"}, // not used in program. Bit 9:Drive Over-Temp Alarm
{HR, 21243, 0, "HOA Status Word"}, // not used in program
{HR, 20801, 0, "Trip Fault"}, // not used in program
{HR, 20821, 0, "Last Fault"}, // not used in program
{HR, 20823, 0, "2nd to last Fault"}, // not used in program
{HR, 20825, 0, "3rd to last Fault"}, // not used in program
{HR, 21221, 0, "Main Status Word"}, // not used in program
{HR, 21231, 0, "Drive Status Word 1"}, // not used in program
{HR, 1000, 0, "DI Status"}, // Bit 0: input 1, Bit 1: Input 2
{HR, 1211, 0, "AI1 Scaled"}, // output frequency/speed reference, 0-10V
{HR, 1221, 0, "AI2 Scaled"}, // actual feedback 0-20mA
{HR, 1310, 0, "AO1 Actual"}, // output frequency 0-10V
{HR, 1910, 0, "External Control Location"}, // not used in program. Bit 13, 0:false, 1:true
{HR, 4600, 1800, "Speed Scaling"}, // 1800 rpm
{HR, 4601, 60, "Frequency Scaling"}, // 60 Hz
{HR, 9905, 65, "Nominal Current"}, // 65 A
{HR_10x, 9906, 4800, "Nominal Voltage"}, // 480 V
{HR_10x, 9907, 600, "Nominal Frequency"}, // 60 Hz
{HR, 9908, 1800, "Nominal Speed"}, // 1800 rpm
{HR_10x, 9909, 500, "Nominal Power"}, // 50 hp
};
//Size of modbus map used in FOR cycles, automatically calculated.
/**