Merge pull request #40 from emmanuelsrlok/develop

Update Main branch from development to keep the latest devices from DFR and PHX equipment added.
This commit is contained in:
Emmanuel HC
2025-10-31 10:42:50 -05:00
committed by GitHub
54 changed files with 2731 additions and 1242 deletions

View File

@@ -87,6 +87,15 @@ protected:
* @param strategy A pointer to the Strategy_Behavior object. The State takes ownership.
*/
void addStrategy(const std::string& pointDescription, Strategy_Behavior* strategy);
/**
* @brief Modify specifyc bits of a Modbus point in this state.
* @param equipment Pointer to the Equipment instance.
* @param pointName The description key of the Modbus point to write to.
* @param bitPosition The position to which the function will write to.
* @param state The new state of the selected bit.
*/
void setBitValue(Equipment<T>* equipment, const std::string& pointName, int bitPosition, bool state);
/**
* @brief returns a behavior strategy for a specific Modbus point in this state.
* @param pointDescription The description of the Modbus point your need to get.
@@ -218,4 +227,44 @@ void State<T>::_applyStrategies(Equipment<T>* equipment) {
}
}
/**
* @brief Controls a specific bit within an integer Modbus word (like a Holding or Input Register).
*
* This function bypasses the standard float logic to perform direct bit manipulation.
*
* @param equipment Pointer to the Equipment instance.
* @param pointName The description key of the Modbus point to modify.
* @param bitPosition The 0-based index of the bit to set/clear (0-15 for a 16-bit word).
* @param state If true, the bit is set (to 1); if false, the bit is cleared (to 0).
*/
template<typename T>
void State<T>::setBitValue(Equipment<T>* equipment, const std::string& pointName, int bitPosition, bool state) {
Modbus_Point<T>* point = equipment->getModbus_Point(pointName);
// Safety check: Ensure the point exists and isn't a decorated multi-word type (Float or Long)
// Note: Standard 16-bit Hreg/Ireg will return PointType::GENERIC.
if (!point || point->getType() != PointType::GENERIC || bitPosition < 0 || bitPosition > 15) {
// You can add an error logging statement here if needed, like Serial.printf(...)
return;
}
// 1. Get the current integer value directly from the point
int currentValue = point->getValue();
// 2. Create the bit mask
// '1 << bitPosition' shifts a 1 to the position we want to affect
int mask = 1 << bitPosition;
if (state) {
// 3. Set the bit (make it 1): Use the bitwise OR operator
currentValue |= mask;
} else {
// 3. Clear the bit (make it 0): Use the bitwise AND operator with the NOT (inverse) of the mask
currentValue &= ~mask;
}
// 4. Write the new integer value back
point->setValue(currentValue);
}
#endif

View File

@@ -43,7 +43,7 @@ float SingleValueStrategy::execute(float currentValue) {
}
int noiseInt = rand() % 201;
noiseInt -= 100;
float noise = (static_cast<float>(noiseInt) / 100) * _noiseMagnitude;
float noise = (static_cast<float>(noiseInt) / 100.0f) * _noiseMagnitude;
Serial.printf("Single value strategy with noise. %f \n", noise);
return _setpoint + noise;
}

View File

@@ -1,5 +1,4 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
@@ -11,10 +10,10 @@
[platformio]
default_envs = PDU_Maverick_Power_TCP ; Select here the name of the configuration you want to download
default_envs = CRAH_PETRA_PAHHC_600_C6_TCP ; Select here the name of the configuration you want to download
[env]
upload_port = COM15
upload_port = COM50
[common_env_options]
framework = arduino
@@ -37,6 +36,13 @@ extends = common_env_options
build_flags = -D USE_MODBUS_IP ;Importat configuration, this flags is used to configure the program
build_src_filter = -<*> +<Base_TCP> ;Add the specific folder path here
;----------------------------------------------------------------------------------------------------
[env:CRAH_PETRA_PAHHC_600_C6_TCP]
platform = espressif32
board = dfrobot_firebeetle2_esp32e
extends = common_env_options
build_flags = -D USE_MODBUS_IP
build_src_filter = -<*> +<BMS/CRAH/CRAH_PETRA_PAHHC_600_C6_TCP>
[env:POD_MBB_Power_Meter_TCP]
platform = espressif32
board = dfrobot_firebeetle2_esp32e
@@ -132,7 +138,6 @@ extends = common_env_options
build_flags = -D USE_MODBUS_IP
build_src_filter = -<*> +<EPMS/ATS/ATS_800_RPD>
[env:Susol_Smart_MCCB_TCP]
platform = espressif32
board = dfrobot_firebeetle2_esp32e
@@ -195,3 +200,15 @@ board = dfrobot_firebeetle2_esp32e
extends = common_env_options
build_flags = -D USE_MODBUS_IP
build_src_filter = -<*> +<EPMS/UPS/UPS_Vertiv_APM2_TCP>
[env:CH_York_YVAA_RTU]
platform = espressif32
board = dfrobot_firebeetle2_esp32e
extends = common_env_options
build_src_filter = -<*> +<BMS/CHILLER/CH_York_YVAA_RTU>
[env:PHX3_VFD_ABB_ACH580_RTU]
platform = espressif32
board = dfrobot_firebeetle2_esp32e
extends = common_env_options
build_src_filter = -<*> +<BMS/VFD/PHX3_VFD_ABB_ACH580_RTU>

View File

@@ -0,0 +1,43 @@
# CHILLER YORK YVAA 0428IOK46BAVTXX TCP
## Brief Introduction
*** NOTE! ***
This code has not been verified with Chiller and Chiller Manager PLC program.
It is a best-guess based on a preliminary review of Chiller PLC program, but
has yet to be fully vetted and local tested with PLC programs.
Chiller receives Temp SP and Enable from PLC (Modscan)
Alarms are also simulated via Modscan, though those signals will be internal to Chiller
Many hard IO points are simulated using Modscan.
Assumes all Modbus points are for monitoring only and go to Ignition - not sent to PLC
## List of Equipment
This cofiguration has been used for these models:
* **YVAA**: 10-14-25
## Hardware Prerequisites
The code is written for an ESP8266/ESP32-style microcontroller with WiFi capabilities.
* **Microcontroller**: [Firebeetle 2 ESP32.](https://www.dfrobot.com/product-2231.html)
---
## States and Strategies
Updates Alarms States. If any active alarms --> FailState
Updates Free Cooling Mode: Free Cooling Mode is activated using a coil, for simulation purposes only.
Modbus points are simulated, mostly with a SingleValue strategy for image verification in Ignition.
While in RunningState, the Supply Temp dynamically ramps to the Supply Temp SP sent from PLC (Modscan)
The CHW In and CHW Out temperature values also dynamically ramp to match the Return and Supply Temps.
### Standby State
* **Chiller Status**: set to 0
* **Operational Code**: set to 77
* **Chiller Start Command**: set to 0
### Running State
* **Chiller status**: set to 1
* **Supply Temperature**: **Ramp Strategy** ramps to Temp Setpoint from PLC (Modscan)
### Fail State
* **Chiller Status**: set to 0

View File

@@ -0,0 +1,85 @@
/**
* @file StateUtils.cpp
* @brief Implementation of the StateUtils class.
* @author Robert J. Davis
* @date 2025-10-14
*
* This file contains implementation of utility functions that are used in multiple States.
*/
#include "Strategies/Strategy_Ramp.h"
#include "Strategies/Strategy_Random.h"
#include "Strategies/Strategy_Saw.h"
#include "Strategies/Strategy_SingleValue.h"
#include "Strategies/Strategy_Square.h"
#include "Strategies/Strategy_PID.h"
#include "ModbusPoints/Modbus_Point.h"
#include "ModbusPoints/Modbus_FloatDecorator.h"
#include "Equipment/Equipment.h"
#include "States/State_Standby.h"
#include "States/State_Running.h"
#include "States/State_Fail.h"
#include "States/State.h"
#include "StateUtils.h"
#include <vector>
#include <string>
#if defined(USE_MODBUS_IP)
#include <ModbusIP_ESP8266.h>
#else
#include <ModbusRTU.h>
#endif
/**
* @brief Updates Alarms states
*
* This function will update the Alarm status DI bits according to the Alarm Commands from Coils (Modscan)
* The appropriate Fault Code will also be set to 56 (Condenser Fan VSD Warning)
*
* This is a function used in the update() of the Standby, Running, and Fail States.
*
*/
void updateAlarms(Equipment<ModbusRTU>* equipment){
Modbus_Point<ModbusRTU>* Sys1FanAlarmCommand = equipment->getModbus_Point("Sys 1 Fan Fault ON");
Modbus_Point<ModbusRTU>* Sys2FanAlarmCommand = equipment->getModbus_Point("Sys 2 Fan Fault ON");
Modbus_Point<ModbusRTU>* Sys1FanAlarm = equipment->getModbus_Point("Sys 1 Fan Fault Alarm");
Modbus_Point<ModbusRTU>* Sys2FanAlarm = equipment->getModbus_Point("Sys 2 Fan Fault Alarm");
if (Sys1FanAlarmCommand) {
Sys1FanAlarm->setValue(Sys1FanAlarmCommand->getValue());
if (Sys1FanAlarmCommand->getValue() == 1){
equipment->setModbus_Point("Sys 1 Fault Code", 56);
}
else equipment->setModbus_Point("Sys 1 Fault Code", 0);
}
if (Sys2FanAlarmCommand) {
Sys2FanAlarm->setValue(Sys2FanAlarmCommand->getValue());
if (Sys2FanAlarmCommand->getValue() == 1){
equipment->setModbus_Point("Sys 2 Fault Code", 56);
}
else equipment->setModbus_Point("Sys 2 Fault Code", 0);
}
}
/**
* @brief Updates Free Cooling Mode
*
* This function will update the Free Cooling Mode and Valve based on Free Cooling Command
* received from Modscan. This is for simulation purposes only - in practice, the Chiller
* will transition to Free Cooling Mode based on its own internal logic.
*
* For ease of testing, this is a function used in the update() of the Standby, Running, and Fail States.
*
*/
void updateFreeCooling(Equipment<ModbusRTU>* equipment){
Modbus_Point<ModbusRTU>* FreeCoolingCommand = equipment->getModbus_Point("Free Cooling Mode ON");
Modbus_Point<ModbusRTU>* FreeCoolingMode = equipment->getModbus_Point("Free Cooling Mode");
Modbus_Point<ModbusRTU>* FreeCoolingValve = equipment->getModbus_Point("Free Cooling Valve");
if (FreeCoolingCommand->getValue() == 1) {
FreeCoolingMode->setValue(1);
FreeCoolingValve->setValue(1);
}
else {
FreeCoolingMode->setValue(0);
FreeCoolingValve->setValue(0);
}
}

View File

@@ -0,0 +1,43 @@
/**
* @file config.h
* @brief StateUtils class
* @author Robert J Davis
* @date 2025-10-06
*
* Defines the StateUtils class, which contains utility functions used in multiple States.
*/
#pragma once
#include "ModbusPoints/Modbus_Point.h"
#include "ModbusPoints/Modbus_FloatDecorator.h"
#include "Equipment/Equipment.h"
#include "States/State_Standby.h"
#include "States/State_Running.h"
#include "States/State_Fail.h"
#include "States/State.h"
#include <vector>
#include <string>
#if defined(USE_MODBUS_IP)
#include <ModbusIP_ESP8266.h>
#else
#include <ModbusRTU.h>
#endif
template <typename T>
class State;
/**
* @brief Updates Alarms states
* @param equipment Pointer to the Equipment instance.
* @return void
*/
void updateAlarms(Equipment<ModbusRTU>* equipment);
/**
* @brief Updates Free Cooling Mode
* @param equipment Pointer to the Equipment instance.
* @return void
*/
void updateFreeCooling(Equipment<ModbusRTU>* equipment);

View File

@@ -0,0 +1,107 @@
/**
* @file State_Fail.cpp
* @brief Implementation of the FailState class.
* @author Robert J. Davis
* @date 2025-10-14
*
* This file contains the implementation for the FailState, which defines
* the behavior of the equipment when it has entered a fault condition.
*/
#include "ModbusPoints/Modbus_Point.h"
#include "Equipment/Equipment.h"
#include "Strategies/Strategy_Ramp.h"
#include "Strategies/Strategy_SingleValue.h"
#include "Strategies/Strategy_PID.h"
#include "States/State_Standby.h"
#include "States/State_Running.h"
#include "States/State_Fail.h"
#include "StateUtils.h"
#include <vector>
#include <string>
#if defined(USE_MODBUS_IP)
#include <ModbusIP_ESP8266.h>
#else
#include <ModbusRTU.h>
#endif
/**
* @brief Constructs a new FailState object.
*
* This constructor receives a list of alarm descriptions and creates strategies
* to set the Compressor and Fan kW to 0.
*
* @param activeAlarms A vector of strings, where each string is the
* description of a Modbus point to be set as an active alarm.
*/
template<>
FailState<ModbusRTU>::FailState(const std::vector<std::string>& activeAlarms) {
addStrategy("Sys 1 Compressor Pct FLA", new SingleValueStrategy(0.0f, 0.0f, 1000));
addStrategy("Sys 2 Compressor Pct FLA", new SingleValueStrategy(0.0f, 0.0f, 1000));
addStrategy("Sys 1 Fan KW", new SingleValueStrategy(0.0f, 0.0f, 1000));
addStrategy("Sys 2 Fan KW", new SingleValueStrategy(0.0f, 0.0f, 1000));
addStrategy("Sys 1 Compressor KW", new SingleValueStrategy(0.0f, 0.0f, 1000));
addStrategy("Sys 2 Compressor KW", new SingleValueStrategy(0.0f, 0.0f, 1000));
}
/**
* @brief Executes the fail state's logic for one update cycle.
*
* This method first updates all alarms states and Free Cooling Mode (for ease of testing).
* If all alarms have been cleared --> StandbyState.
* If alarms are still active, ensures the Chiller Start Command remains at 0.
*
* @param equipment Pointer to the Equipment instance.
* @return A pointer to a new State if a transition should occur, otherwise nullptr.
*/
template<>
State<ModbusRTU>* FailState<ModbusRTU>::update(Equipment<ModbusRTU>* equipment) {
// Update alarms states, Free Cooling mode, Freeze Protection Mode
updateAlarms(equipment);
updateFreeCooling(equipment);
const std::vector<std::string> alarmDescriptions = {
"Sys 1 Alarm", "Sys 2 Alarm", "Sys 1 Fan Fault Alarm", "Sys 2 Fan Fault Alarm",
};
// If no alarms active --> send to StandbyState()
bool alarms_active = false;
for (const auto& desc : alarmDescriptions) {
Modbus_Point<ModbusRTU>* point = equipment->getModbus_Point(desc);
if (point->getValue() == 1) {
alarms_active = true;
}
}
if (!alarms_active) return new StandbyState<ModbusRTU>();
setPointValue(equipment, "Chiller Start Command", 0);
_applyStrategies(equipment);
return nullptr;
}
/**
* @brief Logic to execute once when entering the fail state.
* Sets the Chiller Status to off, and updates the Operational Code for Systems to 77 (Not Running)
* The Chiller Start Command is also set to 0.
* @param equipment Pointer to the Equipment instance.
*/
template<>
void FailState<ModbusRTU>::enterState(Equipment<ModbusRTU>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Fail State...");
setPointValue(equipment, "Chiller Start Command", 0);
setPointValue(equipment, "Chiller Status", 0);
setPointValue(equipment, "Sys 1 Operational Code", 77);
setPointValue(equipment, "Sys 2 Operational Code", 77);
}
/**
* @brief Logic to execute once when exiting the fail state.
* @param equipment Pointer to the Equipment instance.
*/
template<>
void FailState<ModbusRTU>::exitState(Equipment<ModbusRTU>* equipment) {
// Cleanup logic to run when the equipment leaves this state
Serial.println("Exit Fail State...");
}

View File

@@ -0,0 +1,171 @@
/**
* @file State_Running.cpp
* @brief Implementation of the RunningState class.
* @author Robert J Davis
* @date 2025-10-12
*
* This file contains the implementation for the RunningState, which defines
* the behavior of the equipment when it is actively running.
*/
#include "ModbusPoints/Modbus_Point.h"
#include "ModbusPoints/Modbus_FloatDecorator.h"
#include "Equipment/Equipment.h"
#include "Strategies/Strategy_Ramp.h"
#include "Strategies/Strategy_Random.h"
#include "Strategies/Strategy_Saw.h"
#include "Strategies/Strategy_SingleValue.h"
#include "Strategies/Strategy_Square.h"
#include "Strategies/Strategy_PID.h"
#include "Strategies/Strategy_Totalizer.h"
#include "States/State_Standby.h"
#include "States/State_Running.h"
#include "States/State_Fail.h"
#include "States/State.h"
#include "StateUtils.h"
#include <vector>
#include <string>
#if defined(USE_MODBUS_IP)
#include <ModbusIP_ESP8266.h>
#else
#include <ModbusRTU.h>
#endif
/**
* @brief Constructs a new RunningState object.
*
* This constructor initializes behavior strategies active during the running
* state including various analog values, number of starts for each System and totalizers
* for the run-hours of each System.
*/
template<>
RunningState<ModbusRTU>::RunningState() {
addStrategy("Supply Temp", new RampStrategy(67.0f, 1.0f, 1000));
addStrategy("Return Temp", new SawStrategy(79.0f, 83.0f, 1.0f, 1000));
addStrategy("Ambient Temp", new SingleValueStrategy(100.0f, 1.0f, 1000));
addStrategy("System CHW Out", new RampStrategy(67.0f, 1.0f, 1000));
addStrategy("System CHW In", new RampStrategy(81.0f, 1.0f, 1000));
addStrategy("Sys 1 Condenser Temp", new SingleValueStrategy(125.0f, 5.0f, 1000));
addStrategy("Sys 2 Condenser Temp", new SingleValueStrategy(125.0f, 5.0f, 1000));
addStrategy("Sys 1 Oil Pressure", new SingleValueStrategy(450.0f, 5.0f, 1000));
addStrategy("Sys 2 Oil Pressure", new SingleValueStrategy(450.0f, 5.0f, 1000));
addStrategy("Sys 1 Suction Pressure", new SingleValueStrategy(70.0f, 2.0f, 1000));
addStrategy("Sys 2 Suction Pressure", new SingleValueStrategy(70.0f, 2.0f, 1000));
addStrategy("Sys 1 Discharge Pressure", new SingleValueStrategy(375.0f, 4.0f, 1000));
addStrategy("Sys 2 Discharge Pressure", new SingleValueStrategy(375.0f, 4.0f, 1000));
addStrategy("Sys 1 Compressor Pct FLA", new SingleValueStrategy(93.0f, 2.0f, 1000));
addStrategy("Sys 2 Compressor Pct FLA", new SingleValueStrategy(93.0f, 2.0f, 1000));
addStrategy("Sys 1 Run Hours", new TotalizerStrategy(1000));
addStrategy("Sys 2 Run Hours", new TotalizerStrategy(1000));
addStrategy("Local Leaving Temp Setpoint", new SingleValueStrategy(70.0f, 0.0f, 1000));
addStrategy("Sys 1 Fan KW", new SingleValueStrategy(35.0f, 2.0f, 1000));
addStrategy("Sys 2 Fan KW", new SingleValueStrategy(23.0f, 2.0f, 1000));
addStrategy("Sys 1 Compressor KW", new SingleValueStrategy(304.0f, 5.0f, 1000));
addStrategy("Sys 2 Compressor KW", new SingleValueStrategy(198.0f, 5.0f, 1000));
}
/**
* @brief Executes the running state's logic for one update cycle.
*
* This method first checks if there are any active alarms --> FailState.
* Also checks for Free Cooling Mode (for ease of testing)
* If no alarms are active, checks for "Chiller Start Command" = 0 (Modscan, but will be from PLC)
* for a command to transition to the Standby state. If no transition is requested, it updates the
* rampStrategy targetValues for the Supply Temp, CHW In, CHW Out analog values and applies the
* strategies defined for the running state.
*
* If no transition occurs, it applies the strategies defined for the running state.
*
* @param equipment Pointer to the Equipment instance.
* @return A pointer to a new State if a transition should occur, otherwise nullptr.
*/
template<>
State<ModbusRTU>* RunningState<ModbusRTU>::update(Equipment<ModbusRTU>* equipment) {
// Update alarms states, Free Cooling mode, Freeze Protection Mode
updateAlarms(equipment);
updateFreeCooling(equipment);
std::vector<std::string> activeAlarmsDescriptions = {};
const std::vector<std::string> alarmDescriptions = {
"Sys 1 Alarm", "Sys 2 Alarm", "Sys 1 Fan Fault Alarm", "Sys 2 Fan Fault Alarm",
};
// Loop through alarms, create array of active alarms and send to FailState if any alarms are active
bool alarms_active = false;
for (const auto& desc : alarmDescriptions) {
Modbus_Point<ModbusRTU>* point = equipment->getModbus_Point(desc);
if (point->getValue() == 1) {
activeAlarmsDescriptions.push_back(desc);
alarms_active = true;
}
}
if (alarms_active) return new FailState<ModbusRTU>(activeAlarmsDescriptions);
// If no alarms active and Start Command = 0--> send to StandbyState()
int Chiller_Enable = getPointValue(equipment, "Chiller Start Command"); // Modscan COIL 1
if (Chiller_Enable == 0){
return new StandbyState<ModbusRTU>();
}
// Set the Supply Temp ramp target value equal to the Chiller Temp Setpoint
// Ramp CHW In Temp to Return Temp and CHW Out Temp to Supply Temp
float BMS_Temp_Setpoint = getPointValue(equipment, "Chiller Temp Setpoint");
float supplyTemp = getPointValue(equipment, "Supply Temp");
float returnTemp = getPointValue(equipment, "Return Temp");
Strategy_Behavior* Supply_Temp_strat = getStrategy("Supply Temp");
Strategy_Behavior* CHW_Out_strat = getStrategy("System CHW Out");
Strategy_Behavior* CHW_In_strat = getStrategy("System CHW In");
if (Supply_Temp_strat){
static_cast<RampStrategy*>(Supply_Temp_strat)->setTarget(BMS_Temp_Setpoint);
static_cast<RampStrategy*>(CHW_Out_strat)->setTarget(supplyTemp);
static_cast<RampStrategy*>(CHW_In_strat)->setTarget(returnTemp);
}
// Apply any strategies defined for the standby state
_applyStrategies(equipment);
return nullptr;
}
/**
* @brief Logic to execute once when entering the running state.
*
* Sets the "Chiller Status" point to indicate the unit is running.
* Update System Operational Code to 78 (Running).
* Increment a counter for number of starts for each System.
* We are assuming when the Chiller is commanded to run that both Systems will activate.
* Not enough information in Vendor SOO to add details for running systems independently,
* switching to Free-Cooling Mode, etc.
*
* @param equipment Pointer to the Equipment instance.
*/
template<>
void RunningState<ModbusRTU>::enterState(Equipment<ModbusRTU>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Running State...");
setPointValue(equipment, "Chiller Status", 1);
setPointValue(equipment, "Sys 1 Operational Code", 78);
setPointValue(equipment, "Sys 2 Operational Code", 78);
// Add one to the System 1 and 2 Starts counter
int Sys1_num_starts = getPointValue(equipment, "Sys 1 Starts");
int Sys2_num_starts = getPointValue(equipment, "Sys 2 Starts");
Sys1_num_starts++;
Sys2_num_starts++;
setPointValue(equipment, "Sys 1 Starts", Sys1_num_starts);
setPointValue(equipment, "Sys 2 Starts", Sys2_num_starts);
}
/**
* @brief Logic to execute once when exiting the running state.
* @param equipment Pointer to the Equipment instance.
*/
template<>
void RunningState<ModbusRTU>::exitState(Equipment<ModbusRTU>* equipment) {
// Cleanup logic to run when the equipment leaves this state
Serial.println("Exit Running State...");
}

View File

@@ -0,0 +1,136 @@
/**
* @file State_Standby.cpp
* @brief Implementation of the StandbyState class.
* @author Robert J Davis
* @date 2025-10-13
*
* This file contains the implementation for the StandbyState, which defines
* the behavior of the equipment when it is in an idle or standby mode.
*/
#include "ModbusPoints/Modbus_Point.h"
#include "ModbusPoints/Modbus_FloatDecorator.h"
#include "Equipment/Equipment.h"
#include "Strategies/Strategy_Ramp.h"
#include "Strategies/Strategy_Random.h"
#include "Strategies/Strategy_Saw.h"
#include "Strategies/Strategy_SingleValue.h"
#include "Strategies/Strategy_Square.h"
#include "Strategies/Strategy_PID.h"
#include "States/State_Standby.h"
#include "States/State_Running.h"
#include "States/State_Fail.h"
#include "States/State.h"
#include "StateUtils.h"
#include <vector>
#include <string>
#if defined(USE_MODBUS_IP)
#include <ModbusIP_ESP8266.h>
#else
#include <ModbusRTU.h>
#endif
/**
* @brief Constructs a new StandbyState object.
*
* In this state, the equipment is idle. This constructor initializes strategies
* to bring the system to a safe, idle condition. It sets a stable value for
* the analog readings and takes Fans and Compressors to 0 kW.
*/
template<>
StandbyState<ModbusRTU>::StandbyState() {
addStrategy("Supply Temp", new SingleValueStrategy(80.0f, 1.0f, 1000));
addStrategy("Return Temp", new SingleValueStrategy(80.0f, 1.0f, 1000));
addStrategy("Ambient Temp", new SingleValueStrategy(100.0f, 1.0f, 1000));
addStrategy("System CHW Out", new SingleValueStrategy(80.0f, 1.0f, 1000));
addStrategy("System CHW In", new SingleValueStrategy(80.0f, 1.0f, 1000));
addStrategy("Sys 1 Condenser Temp", new SingleValueStrategy(124.0f, 1.0f, 1000));
addStrategy("Sys 2 Condenser Temp", new SingleValueStrategy(124.0f, 1.0f, 1000));
addStrategy("Sys 1 Oil Pressure", new SingleValueStrategy(420.0f, 1.0f, 1000));
addStrategy("Sys 2 Oil Pressure", new SingleValueStrategy(420.0f, 1.0f, 1000));
addStrategy("Sys 1 Suction Pressure", new SingleValueStrategy(70.0f, 1.0f, 1000));
addStrategy("Sys 2 Suction Pressure", new SingleValueStrategy(70.0f, 1.0f, 1000));
addStrategy("Sys 1 Discharge Pressure", new SingleValueStrategy(70.0f, 1.0f, 1000));
addStrategy("Sys 2 Discharge Pressure", new SingleValueStrategy(70.0f, 1.0f, 1000));
addStrategy("Sys 1 Compressor Pct FLA", new SingleValueStrategy(0.0f, 0.0f, 1000));
addStrategy("Sys 2 Compressor Pct FLA", new SingleValueStrategy(0.0f, 0.0f, 1000));
addStrategy("Local Leaving Temp Setpoint", new SingleValueStrategy(70.0f, 0.0f, 1000));
addStrategy("Sys 1 Fan KW", new SingleValueStrategy(0.0f, 0.0f, 1000));
addStrategy("Sys 2 Fan KW", new SingleValueStrategy(0.0f, 0.0f, 1000));
addStrategy("Sys 1 Compressor KW", new SingleValueStrategy(0.0f, 0.0f, 1000));
addStrategy("Sys 2 Compressor KW", new SingleValueStrategy(0.0f, 0.0f, 1000));
}
/**
* @brief Executes the standby state's logic for one update cycle.
*
* This method first checks if there are any active alarms --> FailState.
* Also checks for Free Cooling Mode (for ease of testing)
* If no alarms are active, checks for "Chiller Start Command" (Modscan, but will be from PLC)
* for a command to transition to the Running state. If no transition is requested, it applies
* the strategies defined for the standby state.
*
* @param equipment Pointer to the Equipment instance.
* @return A pointer to a new State if a transition should occur, otherwise nullptr.
*/
template<>
State<ModbusRTU>* StandbyState<ModbusRTU>::update(Equipment<ModbusRTU>* equipment) {
// Update alarms states, Free Cooling mode, Freeze Protection Mode
updateAlarms(equipment);
updateFreeCooling(equipment);
std::vector<std::string> activeAlarmsDescriptions = {};
const std::vector<std::string> alarmDescriptions = {
"Sys 1 Alarm", "Sys 2 Alarm", "Sys 1 Fan Fault Alarm", "Sys 2 Fan Fault Alarm",
};
// Loop through alarms, create array of active alarms and send to FailState if any alarms are active
bool alarms_active = false;
for (const auto& desc : alarmDescriptions) {
Modbus_Point<ModbusRTU>* point = equipment->getModbus_Point(desc);
if (point->getValue() == 1) {
activeAlarmsDescriptions.push_back(desc);
alarms_active = true;
}
}
if (alarms_active) return new FailState<ModbusRTU>(activeAlarmsDescriptions);
// If no alarms active and Start Command = 1--> send to RunningState()
int Chiller_Enable = getPointValue(equipment, "Chiller Start Command"); // Modscan COIL 1
if (Chiller_Enable == 1){
return new RunningState<ModbusRTU>();
}
// Apply any strategies defined for the standby state
_applyStrategies(equipment);
return nullptr;
}
/**
* @brief Logic to execute once when entering the standby state.
* Sets the "Chiller Status" point to indicate the unit is not running.
* Updates Operational Codes for Sys 1 and Sys 2
* Ensure Chiller Start Command is reset to 0.
* @param equipment Pointer to the Equipment instance.
*/
template<>
void StandbyState<ModbusRTU>::enterState(Equipment<ModbusRTU>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Standby State...");
setPointValue(equipment, "Chiller Start Command", 0);
setPointValue(equipment, "Chiller Status", 0);
setPointValue(equipment, "Sys 1 Operational Code", 77);
setPointValue(equipment, "Sys 2 Operational Code", 77);
}
/**
* @brief Logic to execute once when exiting the standby state.
* @param equipment Pointer to the Equipment instance.
*/
template<>
void StandbyState<ModbusRTU>::exitState(Equipment<ModbusRTU>* equipment) {
// Cleanup logic to run when the equipment leaves this state
Serial.println("Exit Standby State...");
}

View File

@@ -0,0 +1,119 @@
/**
* @file config.h
* @brief Main configuration file for the York Chiller (RTU) emulator.
* @author Robert J Davis
* @date 2025-10-12
*
* This file contains important configurations for the Modbus RTU communication
* and the specific register map for the emulated device.
*/
#ifndef CONFIG_H
#define CONFIG_H
#include <ModbusRTU.h>
#include "core.h"
#include "Equipment/Equipment.h"
#if defined(USE_MODBUS_IP)
/**
* @defgroup ModbusTCPConfig Modbus IP Configuration
* @brief Parameters for Modbus TCP communication.
* @{
*/
#include <ModbusIP_ESP8266.h>
const char *ssid = "wifi_name"; /**< @brief The SSID of the WiFi network. */
const char *password = "wifi_password"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(192, 168, 1, 234); /**< @brief The static IP address for the device. */
IPAddress gateway(192, 168, 1, 1); /**< @brief The gateway IP address. */
IPAddress subnet(255, 255, 255, 0); /**< @brief The subnet mask. */
ModbusIP mb;
#else
/**
* @defgroup ModbusRTUConfig Modbus RTU Configuration
* @brief Parameters for serial Modbus RTU communication.
* @{
*/
#include <ModbusRTU.h>
const int BAUDRATE = 19200; /**< @brief The serial communication speed in bits per second. */
const int RX_PIN = 17; /**< @brief The GPIO pin used for receiving data (RX). */
const int TX_PIN = 16; /**< @brief The GPIO pin used for transmitting data (TX). */
const int RST_PIN = 4; /**< @brief The GPIO pin connected to the RS485 driver's DE/RE pins for direction control. */
const int MODBUS_ID = 1; /**< @brief The unique slave ID for this device on the Modbus bus. */
/** @} */
/** @brief Global instance of the Modbus RTU server. */
ModbusRTU mb;
#endif
/**
* @brief The Modbus map for the Equipment device.
* This array defines all the Modbus points available on the emulated device.
* The `description` field is crucial as it's used to look up points within the application logic.
*/
modbusMap mb_map[] =
{
{COIL, 0, 0, "Chiller Start Command"}, // Use in Modscan - Hard IO in SCP, Used for Arduino simulation only
{COIL, 1, 0, "Sys 1 Alarm"}, // Use in Modscan - Hard IO in SCP, Used for Arduino simulation only
{COIL, 2, 0, "Sys 2 Alarm"}, // Use in Modscan - Hard IO in SCP, Used for Arduino simulation only
{COIL, 3, 0, "Sys 1 Fan Fault ON"}, // Use in Modscan - Used for Arduino simulation only
{COIL, 4, 0, "Sys 2 Fan Fault ON"}, // Use in Modscan - Used for Arduino simulation only
{COIL, 5, 0, "Free Cooling Mode ON"}, // Use in Modscan - Used for Arduino simulation only
{DI, 0, 0, "Sys 1 Fan Fault Alarm"},
{DI, 1, 0, "Sys 2 Fan Fault Alarm"},
{HR, 0, 0, "Chiller Status"}, // Use in Modscan - Hard IO in SCP, Used for Arduino simulation only
{HR, 1, 0, "Chiller Temp Setpoint"}, // Use in Modscan - Hard IO in SCP, Used for Arduino simulation only
{HR, 2, 0, "Supply Temp"}, // Use in Modscan - Hard IO in SCP (PICS?), Used for Arduino simulation only
{HR, 3, 0, "Return Temp"}, // Use in Modscan - Hard IO in SCP (PICS?), Used for Arduino simulation only
{HR, 4, 70, "System CHW Out"},
{HR, 5, 70, "System CHW In"},
{HR, 7, 0, "Sys 1 Condenser Temp"},
{HR, 9, 0, "Ambient Temp"},
{HR, 11, 0, "Sys 1 Oil Pressure"},
{HR, 12, 0, "Sys 1 Suction Pressure"},
{HR, 13, 0, "Sys 1 Discharge Pressure"},
{HR, 14, 0, "Sys 1 Compressor Pct FLA"},
{HR, 15, 0, "Sys 1 Run Hours"},
{HR, 16, 0, "Sys 1 Starts"},
{HR, 20, 0, "Sys 2 Oil Pressure"},
{HR, 21, 0, "Sys 2 Suction Pressure"},
{HR, 22, 0, "Sys 2 Discharge Pressure"},
{HR, 23, 0, "Sys 2 Compressor Pct FLA"},
{HR, 24, 0, "Sys 2 Run Hours"},
{HR, 25, 0, "Sys 2 Starts"},
{HR, 29, 77, "Sys 1 Operational Code"},
{HR, 30, 0, "Sys 1 Fault Code"},
{HR, 31, 77, "Sys 2 Operational Code"},
{HR, 32, 0, "Sys 2 Fault Code"},
{HR, 39, 0, "Local Leaving Temp Setpoint"},
{HR, 40, 0, "Sys 1 Fan KW"},
{HR, 41, 0, "Sys 1 Compressor KW"},
{HR, 42, 0, "Sys 2 Fan KW"},
{HR, 43, 0, "Sys 2 Compressor KW"},
{HR, 49, 0, "Sys 2 Condenser Temp"},
{HR, 50, 0, "Free Cooling Mode"},
{HR, 51, 0, "Free Cooling Valve"},
};
//Size of modbus map used in FOR cycles, automatically calculated.
/**
* @brief The total number of entries in the `mb_map` array.
* This is calculated at compile time and used for iterating over the map.
*/
const int map_size = sizeof(mb_map) / sizeof(mb_map[0]);
/**
* @brief The main loop update interval in milliseconds.
*/
int interval = 250;
#endif // CONFIG_H

View File

@@ -0,0 +1,78 @@
/**
* @file main.cpp
* @brief Main execution program for the Daikin Chiller (RTU) Emulator.
* @author Emmanuel Hernandez Cruz
* @date 2025-09-02
*
* @details This file contains the main execution program for an Arduino-based
* emulator of a Daikin Chiller unit. The program communicates via the
* Modbus RTU protocol over a serial connection.
*
* The setup() function initializes the following:
* - Serial communication for debugging.
* - A Modbus RTU server with parameters from config.h.
* - Modbus points (Coils, Holding Registers, etc.) based on a predefined map in config.h.
*
* The loop() function continuously:
* - Services the Modbus RTU server to handle incoming requests.
* - Periodically calls the main update loop for the emulated equipment, which
* manages state transitions and behavior strategies.
*
* @see config.h for Modbus RTU and register map configuration.
* @see Equipment.h for the main equipment logic.
* @see State.h for different equipment states.
* @see Strategies/Strategy_Behavior.h for value generation strategies.
* @see Modbus_Point.h for the base class for all Modbus points.
*/
//=================================================================================================================================
//Libraries and declaration of variables.
#include <Arduino.h>
#include "config.h"
#include "ModbusPoints/Modbus_PointFactory.h"
//=================================================================================================================================
/**
* @brief Initializes the application.
* @details This function runs once at startup. It configures the serial communication
* for debugging and the Modbus RTU server. It then creates and initializes all
* the Modbus points based on the `mb_map` array in `config.h`.
*/
const int rtsPin = 4;
void setup() {
Serial.begin(115200);
Serial.println("Setup function started");
Serial2.begin(BAUDRATE, SERIAL_8N1, RX_PIN, TX_PIN);
mb.begin(&Serial2, RST_PIN); // Start the server
mb.slave(MODBUS_ID); // Set the slave ID
for(int i = 0; i < map_size; i++){
Modbus_Point<ModbusRTU>* point = createModbus_Point(&mb, mb_map[i].category, mb_map[i].address, mb_map[i].value, mb_map[i].description);
if (point) {
point->addToModbusServer();
EquipmentInstance.addModbus_Point(mb_map[i].description, point);
}
}
Serial.println("Setup function ended");
}
//=================================================================================================================================
/**
* @brief The main application loop.
* @details This function runs repeatedly after setup() has completed. It performs two main actions:
* 1. It continuously services the Modbus server by calling `mb.task()` to handle
* incoming requests from a Modbus master.
* 2. At a fixed interval (defined in `config.h`), it calls `EquipmentInstance.update()`
* to run the emulator's internal state machine and behavior logic.
*/
void loop() {
mb.task();
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
unsigned long startTime = millis();
EquipmentInstance.update();
unsigned long endTime = millis();
unsigned long elapsedTime = endTime - startTime;
Serial.printf("Control Execution time: %d ms\n", elapsedTime);
}
}

View File

@@ -38,16 +38,26 @@
*/
template<>
RunningState<ModbusIP>::RunningState() {
addStrategy("CW Valve Position", new PIDStrategy("RAT Setpoint", 1000, "RAT"));
addStrategy("Operating Hours EC Fan #1", new TotalizerStrategy(10000));
addStrategy("Operating Hours EC Fan #2", new TotalizerStrategy(10000));
addStrategy("Operating Hours EC Fan #3", new TotalizerStrategy(10000));
addStrategy("Operating Hours EC Fan #4", new TotalizerStrategy(10000));
addStrategy("Operating Hours EC Fan #5", new TotalizerStrategy(10000));
addStrategy("Operating Hours EC Fan #6", new TotalizerStrategy(10000));
addStrategy("Operating Hours EC Fan #7", new TotalizerStrategy(10000));
addStrategy("Operating Hours EC Fan #8", new TotalizerStrategy(10000));
addStrategy("Operating Hours EC Fan #9", new TotalizerStrategy(10000));
addStrategy("CW Valve Position", new PIDStrategy("SAT Setpoint", 2000, "SAT Reading"));
addStrategy("SAT Reading", new SingleValueStrategy(0.0f, 3.0f, 1000));
addStrategy("Speed EC Fan #1", new RampStrategy(0.0f, 500.0f, 1000));
addStrategy("Speed EC Fan #2", new RampStrategy(0.0f, 500.0f, 1000));
addStrategy("Speed EC Fan #3", new RampStrategy(0.0f, 500.0f, 1000));
addStrategy("Speed EC Fan #4", new RampStrategy(0.0f, 500.0f, 1000));
addStrategy("Speed EC Fan #5", new RampStrategy(0.0f, 500.0f, 1000));
addStrategy("Speed EC Fan #6", new RampStrategy(0.0f, 500.0f, 1000));
addStrategy("Speed EC Fan #7", new RampStrategy(0.0f, 500.0f, 1000));
addStrategy("Speed EC Fan #8", new RampStrategy(0.0f, 500.0f, 1000));
addStrategy("Speed EC Fan #9", new RampStrategy(0.0f, 500.0f, 1000));
addStrategy("Operating Hours EC Fan #1", new TotalizerStrategy(1100));
addStrategy("Operating Hours EC Fan #2", new TotalizerStrategy(1200));
addStrategy("Operating Hours EC Fan #3", new TotalizerStrategy(1300));
addStrategy("Operating Hours EC Fan #4", new TotalizerStrategy(1250));
addStrategy("Operating Hours EC Fan #5", new TotalizerStrategy(1350));
addStrategy("Operating Hours EC Fan #6", new TotalizerStrategy(1450));
addStrategy("Operating Hours EC Fan #7", new TotalizerStrategy(1150));
addStrategy("Operating Hours EC Fan #8", new TotalizerStrategy(1180));
addStrategy("Operating Hours EC Fan #9", new TotalizerStrategy(1340));
}
/**
@@ -74,63 +84,36 @@ State<ModbusIP>* RunningState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
return new StandbyState<ModbusIP>();
}
Modbus_Point<ModbusIP>* faultCode = equipment->getModbus_Point("Fault Code");
int faultCodeValue = faultCode ? faultCode->getValue() : 0;
switch (faultCodeValue){
case 1:
return new FailState<ModbusIP>({"Alarm SAT Sensor Fault"});
case 2:
return new FailState<ModbusIP>({"Alarm RAH Sensor Fault"});
case 3:
return new FailState<ModbusIP>({"Alarm RAT Sensor Fault"});
case 4:
return new FailState<ModbusIP>({"Alarm Filter DP Sensor Fault"});
case 5:
return new FailState<ModbusIP>({"Alarm Flooding"});
case 6:
return new FailState<ModbusIP>({"Alarm Dirty Filter"});
case 7:
return new FailState<ModbusIP>({"Alarm High RAT"});
case 8:
return new FailState<ModbusIP>({"Alarm Low RAT"});
case 9:
return new FailState<ModbusIP>({"Alarm High SAT"});
case 10:
return new FailState<ModbusIP>({"Alarm Low SAT"});
case 11:
return new FailState<ModbusIP>({"Alarm High RAH"});
case 12:
return new FailState<ModbusIP>({"Alarm Low RAH"});
case 13:
return new FailState<ModbusIP>({"Alarm Phase Failure"});
case 14:
return new FailState<ModbusIP>({"Alarm Condensate Pump"});
case 15:
return new FailState<ModbusIP>({"Alarm Smoke"});
case 16:
return new FailState<ModbusIP>({"Alarm Fire"});
case 17:
return new FailState<ModbusIP>({"Alarm EC Fan #1"});
case 18:
return new FailState<ModbusIP>({"Alarm EC Fan #2"});
case 19:
return new FailState<ModbusIP>({"Alarm EC Fan #3"});
case 20:
return new FailState<ModbusIP>({"Alarm EC Fan #4"});
case 21:
return new FailState<ModbusIP>({"Alarm EC Fan #5"});
case 22:
return new FailState<ModbusIP>({"Alarm EC Fan #6"});
case 23:
return new FailState<ModbusIP>({"Alarm EC Fan #7"});
case 24:
return new FailState<ModbusIP>({"Alarm EC Fan #8"});
case 25:
return new FailState<ModbusIP>({"Alarm EC Fan #9"});
default:
break;
}
float rat = getPointValue(equipment, "RAT");
setPointValue(equipment, "RAT Reading", rat);
float speed = getPointValue(equipment, "Setting EC Fan Speed");
Strategy_Behavior* fan1_rs = getStrategy("Speed EC Fan #1");
static_cast<RampStrategy*>(fan1_rs)->setTarget(4200.0f * (speed /100.0f));
Strategy_Behavior* fan2_rs = getStrategy("Speed EC Fan #2");
static_cast<RampStrategy*>(fan2_rs)->setTarget(4200.0f * (speed /100.0f));
Strategy_Behavior* fan3_rs = getStrategy("Speed EC Fan #3");
static_cast<RampStrategy*>(fan3_rs)->setTarget(4200.0f * (speed /100.0f));
Strategy_Behavior* fan4_rs = getStrategy("Speed EC Fan #4");
static_cast<RampStrategy*>(fan4_rs)->setTarget(4200.0f * (speed /100.0f));
Strategy_Behavior* fan5_rs = getStrategy("Speed EC Fan #5");
static_cast<RampStrategy*>(fan5_rs)->setTarget(4200.0f * (speed /100.0f));
Strategy_Behavior* fan6_rs = getStrategy("Speed EC Fan #6");
static_cast<RampStrategy*>(fan6_rs)->setTarget(4200.0f * (speed /100.0f));
Strategy_Behavior* fan7_rs = getStrategy("Speed EC Fan #7");
static_cast<RampStrategy*>(fan7_rs)->setTarget(4200.0f * (speed /100.0f));
Strategy_Behavior* fan8_rs = getStrategy("Speed EC Fan #8");
static_cast<RampStrategy*>(fan8_rs)->setTarget(4200.0f * (speed /100.0f));
Strategy_Behavior* fan9_rs = getStrategy("Speed EC Fan #9");
static_cast<RampStrategy*>(fan9_rs)->setTarget(4200.0f * (speed /100.0f));
float value = getPointValue(equipment, "CW Valve Position");
Serial.printf("CW Valve Position: %0.2f\n", value);
float sat_setpoint = getPointValue(equipment, "SAT Setpoint");
Strategy_Behavior* sat_svs = getStrategy("SAT Reading");
static_cast<SingleValueStrategy*>(sat_svs)->setSetpoint(sat_setpoint);
// Apply any strategies defined for the standby state
_applyStrategies(equipment);
return nullptr;

View File

@@ -21,10 +21,10 @@
* @{
*/
#include <ModbusIP_ESP8266.h>
const char *ssid = "wifi_name"; /**< @brief The SSID of the WiFi network. */
const char *password = "wifi_password"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(192, 168, 1, 234); /**< @brief The static IP address for the device. */
IPAddress gateway(192, 168, 1, 1); /**< @brief The gateway IP address. */
const char *ssid = "QTS_CDR_Arduino"; /**< @brief The SSID of the WiFi network. */
const char *password = "123abc456"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(172, 17, 33, 11); /**< @brief The static IP address for the device. */
IPAddress gateway(172, 17, 33, 1); /**< @brief The gateway IP address. */
IPAddress subnet(255, 255, 255, 0); /**< @brief The subnet mask. */
ModbusIP mb;
@@ -60,81 +60,82 @@
*/
modbusMap mb_map[] =
{
{HR, 15, 0, "State Control"}, //Internal to control from Modscan
{HR, 16, 0, "Fault Code"},
{HR_FLOAT, 18, 0, "RAT"}, //Internal Fault code from Modscan
{HR_FLOAT, 1, 0, "SAT Setpoint"},
{HR_FLOAT, 681, 0, "RAT Setpoint"},
{HR_FLOAT, 111, 0, "High RAT Limit"},
{HR_FLOAT, 114, 0, "Low RAT Limit"},
{HR_FLOAT, 118, 0, "High SAT Limit"},
{HR_FLOAT, 122, 0, "Low SAT Limit"},
{HR_FLOAT, 685, 0, "High RAH Limit"},
{HR_FLOAT, 689, 0, "Low RAH Limit"},
{HR, 5, 0, "Setting the EC Fan Max Speed"},
{HR, 695, 0, "Setting the EC Fan Min Speed"},
{HR_FLOAT, 693, 0, "Setting Room Temp"},
{HR, 691, 0, "Setting EC Fan Speed "},
{DI, 146, 0, "Alarm SAT Sensor Fault"},
{DI, 1246, 0, "Alarm RAH Sensor Fault"},
{DI, 1245, 0, "Alarm RAT Sensor Fault"},
{DI, 1250, 0, "Alarm Filter DP Sensor Fault"},
{DI, 51, 0, "Alarm Flooding"},
{DI, 1096, 0, "Alarm Dirty Filter"},
{DI, 1367, 0, "Alarm High RAT"},
{DI, 1099, 0, "Alarm Low RAT"},
{DI, 118, 0, "Alarm High SAT"},
{DI, 122, 0, "Alarm Low SAT"},
{DI, 1307, 0, "Alarm High RAH"},
{DI, 1308, 0, "Alarm Low RAH"},
{DI, 1342, 0, "Alarm Common"},
{DI, 148, 0, "Alarm Phase Failure"},
{DI, 1370, 0, "Alarm Condensate Pump"},
{DI, 1368, 0, "Alarm Smoke"},
{DI, 1369, 0, "Alarm Fire"},
{DI, 131, 0, "Alarm EC Fan #1"},
{DI, 132, 0, "Alarm EC Fan #2"},
{DI, 133, 0, "Alarm EC Fan #3"},
{DI, 134, 0, "Alarm EC Fan #4"},
{DI, 135, 0, "Alarm EC Fan #5"},
{DI, 136, 0, "Alarm EC Fan #6"},
{DI, 1360, 0, "Alarm EC Fan #7"},
{DI, 1361, 0, "Alarm EC Fan #8"},
{DI, 1362, 0, "Alarm EC Fan #9"},
{DI, 138, 0, "Run Status EC Fan #1"},
{DI, 139, 0, "Run Status EC Fan #2"},
{DI, 140, 0, "Run Status EC Fan #3"},
{DI, 141, 0, "Run Status EC Fan #4"},
{DI, 142, 0, "Run Status EC Fan #5"},
{DI, 143, 0, "Run Status EC Fan #6"},
{DI, 1363, 0, "Run Status EC Fan #7"},
{DI, 1364, 0, "Run Status EC Fan #8"},
{DI, 1365, 0, "Run Status EC Fan #9"},
{IR_FLOAT, 99, 0, "SAT Reading"},
{IR_FLOAT, 70, 0, "RAH Reading"},
{IR_FLOAT, 101, 0, "RAT Reading"},
{IR_FLOAT, 106, 0, "Filter DP Reading"},
{IR_FLOAT, 496, 0, "CW Valve Position"},
{IR, 53, 0, "Speed EC Fan #1"},
{IR, 228, 0, "Speed EC Fan #2"},
{IR, 229, 0, "Speed EC Fan #3"},
{IR, 230, 0, "Speed EC Fan #4"},
{IR, 231, 0, "Speed EC Fan #5"},
{IR, 232, 0, "Speed EC Fan #6"},
{IR, 678, 0, "Speed EC Fan #7"},
{IR, 679, 0, "Speed EC Fan #8"},
{IR, 680, 0, "Speed EC Fan #9"},
{IR, 274, 0, "Operating Hours EC Fan #1"},
{IR, 233, 0, "Operating Hours EC Fan #2"},
{IR, 244, 0, "Operating Hours EC Fan #3"},
{IR, 235, 0, "Operating Hours EC Fan #4"},
{IR, 236, 0, "Operating Hours EC Fan #5"},
{IR, 245, 0, "Operating Hours EC Fan #6"},
{IR, 486, 0, "Operating Hours EC Fan #7"},
{IR, 487, 0, "Operating Hours EC Fan #8"},
{IR, 488, 0, "Operating Hours EC Fan #9"},
{COIL, 301, 0, "ON/OFF Command By BMS"},
{COIL, 302, 0, "Enable Off By Supervisory"},
{HR, 13, 0, "Delta"},
{HR, 14, 0, "State Control"}, //Internal to control from Modscan
{HR, 15, 0, "Fault Code"},
{HR_FLOAT, 17, 0, "RAT"}, //Internal Fault code from Modscan
{HR_FLOAT, 0, 0, "SAT Setpoint"},
{HR_FLOAT, 680, 0, "RAT Setpoint"},
{HR_FLOAT, 110, 0, "High RAT Limit"},
{HR_FLOAT, 113, 0, "Low RAT Limit"},
{HR_FLOAT, 117, 0, "High SAT Limit"},
{HR_FLOAT, 121, 0, "Low SAT Limit"},
{HR_FLOAT, 684, 0, "High RAH Limit"},
{HR_FLOAT, 688, 0, "Low RAH Limit"},
{HR, 4, 0, "Setting the EC Fan Max Speed"},
{HR, 694, 0, "Setting the EC Fan Min Speed"},
{HR_FLOAT, 692, 0, "Setting Room Temp"},
{HR_FLOAT, 690, 0, "Setting EC Fan Speed"},
{DI, 145, 0, "Alarm SAT Sensor Fault"},
{DI, 1245, 0, "Alarm RAH Sensor Fault"},
{DI, 1244, 0, "Alarm RAT Sensor Fault"},
{DI, 1249, 0, "Alarm Filter DP Sensor Fault"},
{DI, 50, 0, "Alarm Flooding"},
{DI, 1095, 0, "Alarm Dirty Filter"},
{DI, 1366, 0, "Alarm High RAT"},
{DI, 1098, 0, "Alarm Low RAT"},
{DI, 117, 0, "Alarm High SAT"},
{DI, 121, 0, "Alarm Low SAT"},
{DI, 1306, 0, "Alarm High RAH"},
{DI, 1307, 0, "Alarm Low RAH"},
{DI, 1341, 0, "Alarm Common"},
{DI, 147, 0, "Alarm Phase Failure"},
{DI, 1369, 0, "Alarm Condensate Pump"},
{DI, 1367, 0, "Alarm Smoke"},
{DI, 1368, 0, "Alarm Fire"},
{DI, 130, 0, "Alarm EC Fan #1"},
{DI, 131, 0, "Alarm EC Fan #2"},
{DI, 132, 0, "Alarm EC Fan #3"},
{DI, 133, 0, "Alarm EC Fan #4"},
{DI, 134, 0, "Alarm EC Fan #5"},
{DI, 135, 0, "Alarm EC Fan #6"},
{DI, 1359, 0, "Alarm EC Fan #7"},
{DI, 1360, 0, "Alarm EC Fan #8"},
{DI, 1361, 0, "Alarm EC Fan #9"},
{DI, 137, 0, "Run Status EC Fan #1"},
{DI, 138, 0, "Run Status EC Fan #2"},
{DI, 139, 0, "Run Status EC Fan #3"},
{DI, 140, 0, "Run Status EC Fan #4"},
{DI, 141, 0, "Run Status EC Fan #5"},
{DI, 142, 0, "Run Status EC Fan #6"},
{DI, 1362, 0, "Run Status EC Fan #7"},
{DI, 1363, 0, "Run Status EC Fan #8"},
{DI, 1364, 0, "Run Status EC Fan #9"},
{IR_FLOAT, 98, 0, "SAT Reading"},
{IR_FLOAT, 69, 0, "RAH Reading"},
{IR_FLOAT, 100, 0, "RAT Reading"},
{IR_FLOAT, 105, 0, "Filter DP Reading"},
{IR_FLOAT, 495, 0, "CW Valve Position"},
{IR, 52, 0, "Speed EC Fan #1"},
{IR, 227, 0, "Speed EC Fan #2"},
{IR, 228, 0, "Speed EC Fan #3"},
{IR, 229, 0, "Speed EC Fan #4"},
{IR, 230, 0, "Speed EC Fan #5"},
{IR, 231, 0, "Speed EC Fan #6"},
{IR, 677, 0, "Speed EC Fan #7"},
{IR, 678, 0, "Speed EC Fan #8"},
{IR, 679, 0, "Speed EC Fan #9"},
{IR, 273, 0, "Operating Hours EC Fan #1"},
{IR, 232, 0, "Operating Hours EC Fan #2"},
{IR, 243, 0, "Operating Hours EC Fan #3"},
{IR, 234, 0, "Operating Hours EC Fan #4"},
{IR, 235, 0, "Operating Hours EC Fan #5"},
{IR, 244, 0, "Operating Hours EC Fan #6"},
{IR, 485, 0, "Operating Hours EC Fan #7"},
{IR, 486, 0, "Operating Hours EC Fan #8"},
{IR, 487, 0, "Operating Hours EC Fan #9"},
{COIL, 300, 0, "ON/OFF Command By BMS"},
{COIL, 301, 0, "Enable Off By Supervisory"},
{COIL, 264, 0, "Alarm Reset"}
};
//Size of modbus map used in FOR cycles, automatically calculated.

View File

@@ -75,6 +75,8 @@ void updateAlarms(Equipment<ModbusIP>* equipment){
"Alarm Condensate Pump ON", "Alarm Fire ON", "Alarm Smoke ON"
};
// NOTE: Per UMAS hardwire signals, alarm opened in case of normal operation, closed in case of alarm condition
// 0: no alarm, 1: alarm
int numAlarms = 0;
for (int i =0; i< alarmCommands.size() && i < alarmDescriptions.size(); ++i) {
Modbus_Point<ModbusIP>* commandPoint = equipment->getModbus_Point(alarmCommands[i]);

View File

@@ -82,8 +82,8 @@ State<ModbusIP>* FailState<ModbusIP>::update(Equipment<ModbusIP>* equipment) {
setPointValue(equipment, "ON/OFF Command By BMS", 0);
// The only way to exit the Fail State is for Leak Detect Alarm to turn off, then enter Standby State.
bool leakDetected = equipment->getModbus_Point("Alarm Leak Detect");
if (leakDetected == 0){
bool leakDetected = getPointValue(equipment, "Alarm Leak Detect");
if (!leakDetected){
return new StandbyState<ModbusIP>();
}
@@ -93,7 +93,7 @@ State<ModbusIP>* FailState<ModbusIP>::update(Equipment<ModbusIP>* equipment) {
/**
* @brief Logic to execute once when entering the fail state.
* When entering failed state, turn all fans off (fan status --> 0) and set BMS Command --> 0
* When entering failed state, turn all fans off (fan status --> 1) and set BMS Command --> 0
* @param equipment Pointer to the Equipment instance.
*/
template<>
@@ -107,11 +107,12 @@ void FailState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
"Run Status Fan 7", "Run Status Fan 8", "Run Status Fan 9"
};
// Loop through and set all motor statuses to 0
// Per UMAS submittal Hardwired Run Status signals- 0: fans running, 1: fans stopped
// Loop through and set all motor statuses to 1
for (const auto& desc : motorStatusDescriptions) {
Modbus_Point<ModbusIP>* point = equipment->getModbus_Point(desc);
if (point) {
point->setValue(0);
point->setValue(1);
}
};

View File

@@ -114,7 +114,6 @@ State<ModbusIP>* RunningState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
// Check to see if BMS Command set to OFF --> Place unit in Standby
// Removed logic of placing unit on standby if BMS_Enable_Source != 2 for ease in testing Mode Feedback.
if (On_Off_Command == 0){
setPointValue(equipment, "ON/OFF Command By BMS", 0);
return new StandbyState<ModbusIP>();
}
@@ -164,18 +163,19 @@ void RunningState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
"Run Status Fan 7", "Run Status Fan 8", "Run Status Fan 9"
};
// Loop through and set all motor statuses to 1
// Per UMAS submittal Hardwired Run Status signals- 0: fans running, 1: fans stopped
// Loop through and set all motor statuses to 0
for (const auto& desc : motorStatusDescriptions) {
Modbus_Point<ModbusIP>* point = equipment->getModbus_Point(desc);
if (point) {
point->setValue(1);
point->setValue(0);
}
}
}
/**
* @brief Logic to execute once when exiting the running state.
* Sets the "Run Status" for all EC fans to 0 before transitioning to the next state.
* Sets the "Run Status" for all EC fans to 1 (stopped) before transitioning to the next state.
* @param equipment Pointer to the Equipment instance.
*/
template<>
@@ -188,11 +188,12 @@ void RunningState<ModbusIP>::exitState(Equipment<ModbusIP>* equipment) {
"Run Status Fan 7", "Run Status Fan 8", "Run Status Fan 9"
};
// Loop through and set all motor statuses to 0
// Per UMAS submittal Hardwired Run Status signals- 0: fans running, 1: fans stopped
// Loop through and set all motor statuses to 1
for (const auto& desc : motorStatusDescriptions) {
Modbus_Point<ModbusIP>* point = equipment->getModbus_Point(desc);
if (point) {
point->setValue(0);
point->setValue(1);
}
}
}

View File

@@ -105,7 +105,7 @@ State<ModbusIP>* StandbyState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
/**
* @brief Logic to execute once when entering the standby state.
* This method performs cleanup by setting all EC fan run status points to 0.
* This method performs cleanup by setting all EC fan run status points to 1 (stopped).
* The BMS Command is also set to OFF.
* @param equipment Pointer to the Equipment instance.
*/
@@ -120,11 +120,12 @@ void StandbyState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
"Run Status Fan 7", "Run Status Fan 8", "Run Status Fan 9"
};
// Loop through and set all motor statuses to 0
// Per UMAS submittal Hardwired Run Status signals- 0: fans running, 1: fans stopped
// Loop through and set all motor statuses to 1
for (const auto& desc : motorStatusDescriptions) {
Modbus_Point<ModbusIP>* point = equipment->getModbus_Point(desc);
if (point) {
point->setValue(0);
point->setValue(1);
}
};

View File

@@ -99,15 +99,15 @@ modbusMap mb_map[] =
{IR, 50, 0, "Alarm Fan 7"},
{IR, 54, 0, "Alarm Fan 8"},
{IR, 58, 0, "Alarm Fan 9"},
{IR, 27, 0, "Run Status Fan 1"}, // Send to PLC
{IR, 31, 0, "Run Status Fan 2"}, // Send to PLC
{IR, 35, 0, "Run Status Fan 3"}, // Send to PLC
{IR, 39, 0, "Run Status Fan 4"}, // Send to PLC
{IR, 43, 0, "Run Status Fan 5"}, // Send to PLC
{IR, 47, 0, "Run Status Fan 6"}, // Send to PLC
{IR, 51, 0, "Run Status Fan 7"}, // Send to PLC
{IR, 55, 0, "Run Status Fan 8"}, // Send to PLC
{IR, 59, 0, "Run Status Fan 9"}, // Send to PLC
{IR, 27, 1, "Run Status Fan 1"}, // Send to PLC
{IR, 31, 1, "Run Status Fan 2"}, // Send to PLC
{IR, 35, 1, "Run Status Fan 3"}, // Send to PLC
{IR, 39, 1, "Run Status Fan 4"}, // Send to PLC
{IR, 43, 1, "Run Status Fan 5"}, // Send to PLC
{IR, 47, 1, "Run Status Fan 6"}, // Send to PLC
{IR, 51, 1, "Run Status Fan 7"}, // Send to PLC
{IR, 55, 1, "Run Status Fan 8"}, // Send to PLC
{IR, 59, 1, "Run Status Fan 9"}, // Send to PLC
{IR, 25, 0, "Speed Fan 1"},
{IR, 29, 0, "Speed Fan 2"},
{IR, 33, 0, "Speed Fan 3"},
@@ -126,7 +126,7 @@ modbusMap mb_map[] =
{IR, 52, 0, "Operating Hours Fan 7"},
{IR, 56, 0, "Operating Hours Fan 8"},
{IR, 60, 0, "Operating Hours Fan 9"},
{IR, 61, 0, "Control Mode Selected"},
{IR, 61, 0, "Control Mode Selected"}, // 0: BMS+Speed, 1: BMS+Room Temp, 2: Return Temp
{IR_FLOAT, 63, 0, "Amps Fan 1"},
{IR_FLOAT, 65, 0, "Amps Fan 2"},
{IR_FLOAT, 67, 0, "Amps Fan 3"},
@@ -141,8 +141,9 @@ modbusMap mb_map[] =
{HR_FLOAT, 17, 0, "Supply Air Temp Setpoint"}, // Receive signal from PLC
{HR_FLOAT, 21, 0, "Fan Min Speed"}, // Send to PLC
{HR_FLOAT, 23, 0, "Fan Max Speed"}, // Send to PLC
{HR, 25, 0, "BMS Control Source"}, // Receive signal from PLC
{HR, 26, 0, "BMS Enable Source"}, // Receive signal from PLC
{HR, 25, 0, "BMS Control Source"}, // Receive signal from PLC 0:Speed, 1:Room Temp
{HR, 26, 2, "BMS Enable Source"}, // Receive signal from PLC 0:Keypad, 1:DI, 2:BMS
{HR, 99, 0, "CRAH Heartbeat"} // Placeholder - we don't have this from UMAS yet. Not used in logic yet.
};
//Size of modbus map used in FOR cycles, automatically calculated.

View File

@@ -0,0 +1,40 @@
# VFD ABB ACH580 RTU
## Brief Introduction
This is based on a 50hp motor, 480V, 65 FLA, 60Hz, 1800 rpm (PHX3 DC1/2)
## List of Equipment
This configuration has been used for these models:
* **ACH580**: 10-23-2025
* **Model**: 09-15-23
* **Model**: 09-15-25
## Hardware Prerequisites
The code is written for an ESP8266/ESP32-style microcontroller with WiFi capabilities and at least one hardware serial port for RS485 communication.
* **Microcontroller**: [Firebeetle 2 ESP32.](https://www.dfrobot.com/product-2231.html)
* **RS485 Transceiver**: [RS485 Shield for Arduino.](https://www.dfrobot.com/product-1024.html)
---
## States and Strategies
The hardwire IO signals to/from VFD/PLC are Start Cmd, Stop Cmd, Speed Command, Speed Feedback, VFD Run Status, VFD Fault.
User needs to set the speed command (HR 150) in RPM from the PLC
User needs to set the Start command (HR 151) from the PLC
It appears these registers were arbitrarily chosen for the purpose of this Arduino simulation.
The registers selected are based on FS Config file from CDR project.
Currently there is no connection on Speed Feedback, Run Status, or Fault from Arduino to PICS
### Standby State
* **Equipment**: Equipment parameters go back to 0
### Running State
* **Ramp Strategy**: The following regisers will dynamically ramp based upon the Speed Cmd:
* Motor Speed Used, Motor Speed estimated, Output Frequency, Motor Current, Motor Torque, DC Voltage, Output Voltage, Output Power
* The logic is based on Affinity laws and nominal motor values stated in the Introduction section.
* **Square Strategy**: Inverter Temperature switches between 40 and 80 based on inherited code.
* **Totalizers Strategy**: Inverter kWh cnt, Hours Run
### Fail State
* Not used

View File

@@ -0,0 +1,77 @@
/**
* @file State_Fail.cpp
* @brief Implementation of the FailState class.
* @author Emmanuel Hernandez Cruz
* @date 2025-09-05
*
* This file contains the implementation for the FailState, which defines
* the behavior of the equipment when it has entered a fault condition.
*/
#include "States/State_Standby.h"
#include "States/State_Fail.h"
#include "ModbusPoints/Modbus_Point.h"
#include "Equipment/Equipment.h"
#include "Strategies/Strategy_SingleValue.h"
#include "Strategies/Strategy_PID.h"
#include <vector>
#include <string>
#if defined(USE_MODBUS_IP)
#include <ModbusIP_ESP8266.h>
#else
#include <ModbusRTU.h>
#endif
/**
* @brief Constructs a new FailState object.
*
* This constructor receives a list of alarm descriptions and creates strategies
* to set the corresponding Modbus points to a value of 1, indicating an
* active alarm. It also initializes a PID strategy for the valve position.
*/
template<>
FailState<ModbusRTU>::FailState(const std::vector<std::string>& activeAlarms) {
// Simulate a failure: set common alarm and a specific fan alarm.
}
/**
* @brief Executes the fail state's logic for one update cycle.
*
* This method checks the "Clear Alm" Modbus point for a command to transition
* back to Standby, which would typically happen after a fault is cleared by a
* user. If no transition is requested, it continues to apply the failure strategies.
*
* @param equipment Pointer to the Equipment instance.
* @return A pointer to a new State if a transition should occur, otherwise nullptr.
*/
template<>
State<ModbusRTU>* FailState<ModbusRTU>::update(Equipment<ModbusRTU>* equipment) {
// STATE control, add conditions if change to a different state is needed
Serial.println("Fail update function");
_applyStrategies(equipment);
return nullptr;
}
/**
* @brief Logic to execute once when entering the fail state. Sets the main alarm bit.
* @param equipment Pointer to the Equipment instance.
*/
template<>
void FailState<ModbusRTU>::enterState(Equipment<ModbusRTU>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Fail State...");
}
/**
* @brief Logic to execute once when exiting the fail state. Clears the main alarm bit.
* @param equipment Pointer to the Equipment instance.
*/
template<>
void FailState<ModbusRTU>::exitState(Equipment<ModbusRTU>* equipment) {
// Cleanup logic to run when the equipment leaves this state
Serial.println("Exit Fail State...");
}

View File

@@ -0,0 +1,163 @@
/**
* @file State_Running.cpp
* @brief Implementation of the RunningState class.
* @author Emmanuel Hernandez Cruz, Robert J Davis
* @date 2025-10-22
*
* This file contains the implementation for the RunningState, which defines
* the behavior of the equipment when it is actively running.
*/
#include "States/State_Standby.h"
#include "States/State_Running.h"
#include "States/State_Fail.h"
#include "Strategies/Strategy_Behavior.h"
#include "Strategies/Strategy_PID.h"
#include "Strategies/Strategy_Ramp.h"
#include "Strategies/Strategy_Totalizer.h"
#include "Strategies/Strategy_Random.h"
#include "Strategies/Strategy_SingleValue.h"
#include "Strategies/Strategy_Saw.h"
#include "Strategies/Strategy_Square.h"
#include "Equipment/Equipment.h"
#include "ModbusPoints/Modbus_Point.h"
#include "ModbusPoints/Modbus_FloatDecorator.h"
#include <vector>
#include <string>
#if defined(USE_MODBUS_IP)
#include <ModbusIP_ESP8266.h>
#else
#include <ModbusRTU.h>
#endif
/**
* @brief Constructs a new RunningState object.
*
* This constructor initializes behavior strategies active during the running
* state, such as a PID controller for the 'CW Valve Position' and totalizers
* for the run-hours of each EC fan.
*/
template<>
RunningState<ModbusRTU>::RunningState() {
addStrategy("Motor Speed Used", 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("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));
}
/**
* @brief Executes the running state's logic for one update cycle.
*
* This method first checks for state transition commands:
* 1. It reads the "ON/OFF Command By BMS" point. If it's 0, it transitions to StandbyState.
* 2. It reads the "Fault Code" point. If it's non-zero, it transitions to FailState,
* passing the corresponding alarm description.
*
* If no transition occurs, it applies the strategies defined for the running state.
*
* @param equipment Pointer to the Equipment instance.
* @return A pointer to a new State if a transition should occur, otherwise nullptr.
*/
template<>
State<ModbusRTU>* RunningState<ModbusRTU>::update(Equipment<ModbusRTU>* equipment) {
// STATE control, add conditions if change to a different state is needed
Serial.println("Running update function");
float speed_pct = getPointValue(equipment, "Speed Cmd") / 1800.0f;
// Based on Affinity Laws. Motor: 65 FLA, 480V, 60Hz, 1800 rpm, 50hp
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 freq_update = speed_pct * 60;
float power_update = speed_pct * speed_pct * speed_pct * 36.77f; // 50 hp ~ 36.77kW
int VFD_Start_Stop = getPointValue(equipment, "Start/Stop");
if (VFD_Start_Stop == 0){
return new StandbyState<ModbusRTU>();
}
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);
}
// 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);
}
Strategy_Behavior* currentstrategy = getStrategy("Motor Current");
if (currentstrategy) {
static_cast<RampStrategy*>(currentstrategy)->setTarget(current_update);
}
Strategy_Behavior* torquestrategy = getStrategy("Motor Torque");
if (torquestrategy) {
static_cast<RampStrategy*>(torquestrategy)->setTarget(torque_update);
}
Strategy_Behavior* dcvoltagestrategy = getStrategy("DC Voltage");
if (dcvoltagestrategy) {
static_cast<RampStrategy*>(dcvoltagestrategy)->setTarget(dc_voltage_update);
}
Strategy_Behavior* voltagestrategy = getStrategy("Output Voltage");
if (voltagestrategy) {
static_cast<RampStrategy*>(voltagestrategy)->setTarget(voltage_update);
}
Strategy_Behavior* powerstrategy = getStrategy("Output Power");
if (powerstrategy) {
static_cast<RampStrategy*>(powerstrategy)->setTarget(power_update);
}
// Apply any strategies defined for the standby state
_applyStrategies(equipment);
return nullptr;
}
/**
* @brief Logic to execute once when entering the running state.
* Sets the "Chiller Sts" point to indicate the unit is running.
* @param equipment Pointer to the Equipment instance.
*/
template<>
void RunningState<ModbusRTU>::enterState(Equipment<ModbusRTU>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Running State...");
}
/**
* @brief Logic to execute once when exiting the running state.
* Sets the "Chiller Sts" point to indicate the unit is no longer running.
* @param equipment Pointer to the Equipment instance.
*/
template<>
void RunningState<ModbusRTU>::exitState(Equipment<ModbusRTU>* equipment) {
// Cleanup logic to run when the equipment leaves this state
Serial.println("Exit Running State...");
setPointValue(equipment, "Output Frequency", 0.0f);
}

View File

@@ -0,0 +1,90 @@
/**
* @file State_Standby.cpp
* @brief Implementation of the StandbyState class.
* @author Emmanuel Hernandez Cruz, Robert J Davis
* @date 2025-10-23
*
* This file contains the implementation for the StandbyState, which defines
* the behavior of the equipment when it is in an idle or standby mode.
*/
#include "States/State_Running.h"
#include "States/State_Fail.h"
#include "ModbusPoints/Modbus_Point.h"
#include "ModbusPoints/Modbus_FloatDecorator.h"
#include "Equipment/Equipment.h"
#include "Strategies/Strategy_Ramp.h"
#include "Strategies/Strategy_SingleValue.h"
#include <vector>
#include <string>
#if defined(USE_MODBUS_IP)
#include <ModbusIP_ESP8266.h>
#else
#include <ModbusRTU.h>
#endif
/**
* @brief Constructs a new StandbyState object.
*
* In this state, the equipment is idle. This constructor initializes several
* strategies to generate random values for various status points, simulating
* a live but non-operational unit.
*/
template<>
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 Speed Used", 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 ));
}
/**
* @brief Executes the standby state's logic for one update cycle.
*
* This method checks the "Chiller On-Off" Modbus point for a command to
* transition to the Running state. If no transition is requested, it applies
* the strategies defined for the standby state.
*
* @param equipment Pointer to the Equipment instance.
* @return A pointer to a new State if a transition should occur, otherwise nullptr.
*/
template<>
State<ModbusRTU>* StandbyState<ModbusRTU>::update(Equipment<ModbusRTU>* equipment) {
// STATE control, add conditions if change to a different state is needed
Serial.println("Standby update function");
int VFD_Start_Stop = getPointValue(equipment, "Start/Stop");
if (VFD_Start_Stop == 1){
return new RunningState<ModbusRTU>();
}
// Apply any strategies defined for the standby state
_applyStrategies(equipment);
return nullptr;
}
/**
* @brief Logic to execute once when entering the standby state.
* Sets the "Chiller Sts" point to indicate the unit is not running.
* @param equipment Pointer to the Equipment instance.
*/
template<>
void StandbyState<ModbusRTU>::enterState(Equipment<ModbusRTU>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Standby State...");
}
/**
* @brief Logic to execute once when exiting the standby state.
* @param equipment Pointer to the Equipment instance.
*/
template<>
void StandbyState<ModbusRTU>::exitState(Equipment<ModbusRTU>* equipment) {
// Cleanup logic to run when the equipment leaves this state
}

View File

@@ -0,0 +1,100 @@
/**
* @file config.h
* @brief Main configuration file for the ABB ACH580 (VFD) emulator.
* @author Emmanuel Hernandez Cruz, Robert J Davis
* @date 2025-10-22
*
* This file contains important configurations for the Modbus RTU communication
* and the specific register map for the emulated device.
*/
#ifndef CONFIG_H
#define CONFIG_H
#include <ModbusRTU.h>
#include "core.h"
#include "Equipment/Equipment.h"
#if defined(USE_MODBUS_IP)
/**
* @defgroup ModbusTCPConfig Modbus IP Configuration
* @brief Parameters for Modbus TCP communication.
* @{
*/
#include <ModbusIP_ESP8266.h>
const char *ssid = "wifi_name"; /**< @brief The SSID of the WiFi network. */
const char *password = "wifi_password"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(192, 168, 1, 234); /**< @brief The static IP address for the device. */
IPAddress gateway(192, 168, 1, 1); /**< @brief The gateway IP address. */
IPAddress subnet(255, 255, 255, 0); /**< @brief The subnet mask. */
ModbusIP mb;
#else
/**
* @defgroup ModbusRTUConfig Modbus RTU Configuration
* @brief Parameters for serial Modbus RTU communication.
* @{
*/
#include <ModbusRTU.h>
const int BAUDRATE = 19200; /**< @brief The serial communication speed in bits per second. */
const int RX_PIN = 17; /**< @brief The GPIO pin used for receiving data (RX). */
const int TX_PIN = 16; /**< @brief The GPIO pin used for transmitting data (TX). */
const int RST_PIN = 4; /**< @brief The GPIO pin connected to the RS485 driver's DE/RE pins for direction control. */
const int MODBUS_ID = 1; /**< @brief The unique slave ID for this device on the Modbus bus. */
/** @} */
/** @brief Global instance of the Modbus RTU server. */
ModbusRTU mb;
#endif
/**
* @brief The Modbus map for the Equipment device.
* This array defines all the Modbus points available on the emulated device.
* The `description` field is crucial as it's used to look up points within the application logic.
*/
modbusMap mb_map[] =
{
{HR, 149, 0, "Speed Cmd"}, // expecting rpm (1800 rpm max)
{HR, 151, 0, "Start/Stop"},
{HR, 152, 0, "HOA Command"},
{HR, 100, 0, "Motor Speed Used"}, // RJD: 1800 rpm max
{HR, 101, 0, "Motor Speed estimated"}, // RJD: 1800 rpm max
{HR_10x, 105, 0, "Output Frequency"}, // 60 Hz @100% speed
{HR, 106, 0, "Motor Current"}, // RJD: Changed from HR_10x to HR, 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"}, // RJD: 480 VAC
{HR, 113, 0, "Output Power"}, //max 372580 // RJD: Changed from HR_10x to HR, 50 hp ~ 36.77 kW
{HR_10x, 119, 0, "Inverter kWh cnt"},
{HR, 502, 0, "Hours Run"},
{HR, 510, 0, "Inverter Temperature"}, // RJD: Changed from HR_10x to HR, % of fault limit
{HR, 521, 0, "HOA Status Word"},
{HR, 410, 0, "Last Fault"},
{HR, 411, 0, "2nd to last Fault"},
{HR, 412, 0, "3rd to last Fault"},
{HR, 439, 0, "Event Word Param"},
{HR, 610, 0, "Status Word 1"},
{HR, 615, 0, "Status Word 2"},
{HR, 616, 0, "Status Word 3"},
{HR, 617, 0, "Status Word 4"},
{HR, 618, 0, "Status Word 5"},
{HR, 619, 0, "Status Word 6"},
{HR, 620, 0, "Status Word 7"},
{HR, 621, 0, "Status Word 8"},
};
//Size of modbus map used in FOR cycles, automatically calculated.
/**
* @brief The total number of entries in the `mb_map` array.
* This is calculated at compile time and used for iterating over the map.
*/
const int map_size = sizeof(mb_map) / sizeof(mb_map[0]);
/**
* @brief The main loop update interval in milliseconds.
*/
int interval = 250;
#endif // CONFIG_H

View File

@@ -0,0 +1,78 @@
/**
* @file main.cpp
* @brief Main execution program for the Daikin Chiller (RTU) Emulator.
* @author Emmanuel Hernandez Cruz
* @date 2025-09-02
*
* @details This file contains the main execution program for an Arduino-based
* emulator of a Daikin Chiller unit. The program communicates via the
* Modbus RTU protocol over a serial connection.
*
* The setup() function initializes the following:
* - Serial communication for debugging.
* - A Modbus RTU server with parameters from config.h.
* - Modbus points (Coils, Holding Registers, etc.) based on a predefined map in config.h.
*
* The loop() function continuously:
* - Services the Modbus RTU server to handle incoming requests.
* - Periodically calls the main update loop for the emulated equipment, which
* manages state transitions and behavior strategies.
*
* @see config.h for Modbus RTU and register map configuration.
* @see Equipment.h for the main equipment logic.
* @see State.h for different equipment states.
* @see Strategies/Strategy_Behavior.h for value generation strategies.
* @see Modbus_Point.h for the base class for all Modbus points.
*/
//=================================================================================================================================
//Libraries and declaration of variables.
#include <Arduino.h>
#include "config.h"
#include "ModbusPoints/Modbus_PointFactory.h"
//=================================================================================================================================
/**
* @brief Initializes the application.
* @details This function runs once at startup. It configures the serial communication
* for debugging and the Modbus RTU server. It then creates and initializes all
* the Modbus points based on the `mb_map` array in `config.h`.
*/
const int rtsPin = 4;
void setup() {
Serial.begin(115200);
Serial.println("Setup function started");
Serial2.begin(BAUDRATE, SERIAL_8N1, RX_PIN, TX_PIN);
mb.begin(&Serial2, RST_PIN); // Start the server
mb.slave(MODBUS_ID); // Set the slave ID
for(int i = 0; i < map_size; i++){
Modbus_Point<ModbusRTU>* point = createModbus_Point(&mb, mb_map[i].category, mb_map[i].address, mb_map[i].value, mb_map[i].description);
if (point) {
point->addToModbusServer();
EquipmentInstance.addModbus_Point(mb_map[i].description, point);
}
}
Serial.println("Setup function ended");
}
//=================================================================================================================================
/**
* @brief The main application loop.
* @details This function runs repeatedly after setup() has completed. It performs two main actions:
* 1. It continuously services the Modbus server by calling `mb.task()` to handle
* incoming requests from a Modbus master.
* 2. At a fixed interval (defined in `config.h`), it calls `EquipmentInstance.update()`
* to run the emulator's internal state machine and behavior logic.
*/
void loop() {
mb.task();
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
unsigned long startTime = millis();
EquipmentInstance.update();
unsigned long endTime = millis();
unsigned long elapsedTime = endTime - startTime;
Serial.printf("Control Execution time: %d ms\n", elapsedTime);
}
}

View File

@@ -1,8 +1,8 @@
/**
* @file State_Running.cpp
* @brief Implementation of the RunningState class.
* @author Emmanuel Hernandez Cruz
* @date 2025-09-05
* @author Emmanuel Hernandez Cruz, Robert J Davis
* @date 2025-10-22
*
* This file contains the implementation for the RunningState, which defines
* the behavior of the equipment when it is actively running.
@@ -41,8 +41,11 @@
*/
template<>
RunningState<ModbusRTU>::RunningState() {
addStrategy("Inverter Temperature", new SquareStrategy(40.0f, 80.0f,1000));
addStrategy("Inverter Temperature", new SquareStrategy(40.0f, 80.0f, 1000));
addStrategy("Motor Speed Used", new RampStrategy(100.0f, 10.0f, 1000));
addStrategy("Motor Speed Estimated", new RampStrategy(80.0f, 10.0f, 1000));
addStrategy("Motor Current", new RampStrategy(65.0f, 2.0f, 1000));
addStrategy("Motor Torque", new RampStrategy(200.0f, 10.0f, 1000));
}
/**

View File

@@ -39,20 +39,19 @@
template<>
RunningState<ModbusIP>::RunningState() {
addStrategy("Source 1 Volts AB", new SingleValueStrategy(0.0F, 0.0f, 1000));
addStrategy("Source 1 Volts BC", new SingleValueStrategy(0.0F, 0.0f, 1000));
addStrategy("Source 2 Volts CA", new SingleValueStrategy(0.0F, 0.0f, 1000));
addStrategy("Source 2 Volts AB", new SingleValueStrategy(480.0F, 2.0f, 1000));
addStrategy("Source 2 Volts BC", new SingleValueStrategy(480.0F, 2.0f, 1000));
addStrategy("Source 2 Volts CA", new SingleValueStrategy(480.0F, 2.0f, 1000));
addStrategy("Source 1 Frequency", new SingleValueStrategy(0.0f, 0.0f, 1000));
addStrategy("Source 2 Frequency", new SingleValueStrategy(60.0f, 1.0f, 1000));
addStrategy("Power Factor", new SingleValueStrategy(90.0f, 2.0f, 1000));
addStrategy("Amps A", new SingleValueStrategy(1.0f, 5.0f, 1000));
addStrategy("Amps B", new SingleValueStrategy(1.0f, 5.0f, 1000));
addStrategy("Amps C", new SingleValueStrategy(1.0f, 5.0f, 1000));
addStrategy("Volts AB", new SingleValueStrategy(480.0f, 2.0f, 1000));
addStrategy("Votls BC", new SingleValueStrategy(480.0f, 2.0f, 1000));
addStrategy("Volts CA", new SingleValueStrategy(480.0f, 2.0f, 1000));
addStrategy("Amps A", new SingleValueStrategy(1.0f, 3.0f, 1000));
addStrategy("Amps B", new SingleValueStrategy(1.0f, 3.0f, 1000));
addStrategy("Amps C", new SingleValueStrategy(1.0f, 3.0f, 1000));
addStrategy("Total Active Power", new SingleValueStrategy(6.0f, 5.0f, 1000));
addStrategy("Total Apparent Power", new SingleValueStrategy(6.0f, 5.0f, 1000));
}
@@ -78,20 +77,40 @@ State<ModbusIP>* RunningState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
return new StandbyState<ModbusIP>();
}
int I_load = getPointValue(equipment, "ATS_Load");
int I_rating = getPointValue(equipment, "ATS_Rating");
float load = static_cast<float>(I_load);
float rating = static_cast<float>(I_rating);
float real_load = rating * (load/100.0f);
float load = getPointValue(equipment, "ATS_Load");
float rating = getPointValue(equipment, "ATS_Rating");
float sim_load = rating * (load/100.0f);
Strategy_Behavior* ampsA_svs = getStrategy("Amps A");
Strategy_Behavior* ampsB_svs = getStrategy("Amps B");
Strategy_Behavior* ampsC_svs = getStrategy("Amps C");
static_cast<SingleValueStrategy*>(ampsA_svs)->setSetpoint(real_load);
static_cast<SingleValueStrategy*>(ampsB_svs)->setSetpoint(real_load);
static_cast<SingleValueStrategy*>(ampsC_svs)->setSetpoint(real_load);
static_cast<SingleValueStrategy*>(ampsA_svs)->setSetpoint(sim_load);
static_cast<SingleValueStrategy*>(ampsB_svs)->setSetpoint(sim_load);
static_cast<SingleValueStrategy*>(ampsC_svs)->setSetpoint(sim_load);
// Apply any strategies defined for the standby state
float v_ab = getPointValue(equipment, "Source 2 Volts AB");
float v_bc = getPointValue(equipment, "Source 2 Volts BC");
float v_ca = getPointValue(equipment, "Source 2 Volts CA");
float i_a = getPointValue(equipment, "Amps A");
float i_b = getPointValue(equipment, "Amps B");
float i_c = getPointValue(equipment, "Ampc C");
float pwr = ((v_ab * i_a) + (v_bc * i_b) + (v_ca * i_c));
setPointValue(equipment, "Total Active Power", pwr*1000.0f);
float pf = getPointValue(equipment, "Power Factor");
float a_pwr = pwr * (pf/100.0f);
setPointValue(equipment, "Total Apparent Power", a_pwr*1000.0f);
float preferred = getPointValue(equipment, "ATS_Preferred");
if (preferred == 1.0f){
setPointValue(equipment, "Source 1 Preferred", 1.0f);
setPointValue(equipment, "Source 2 Preferred", 0.0f);
}
if (preferred == 2.0f){
setPointValue(equipment, "Source 1 Preferred", 0.0f);
setPointValue(equipment, "Source 2 Preferred", 1.0f);
}
_applyStrategies(equipment);
return nullptr;
}
@@ -113,6 +132,11 @@ void RunningState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
setPointValue(equipment, "Source 1 Preferred", 1);
setPointValue(equipment, "Source 2 Preferred", 0);
setPointValue(equipment, "Source 1 Volts AB", 0.0f);
setPointValue(equipment, "Source 1 Volts BC", 0.0f);
setPointValue(equipment, "Source 1 Volts CA", 0.0f);
setPointValue(equipment, "Source 1 Frequency", 0.0f);
int transferQty = getPointValue(equipment, "Number of Transfers");
setPointValue(equipment, "Number of Transfers", transferQty + 1);
}

View File

@@ -37,21 +37,21 @@
*/
template<>
StandbyState<ModbusIP>::StandbyState() {
// You can add initialization code here if needed
addStrategy("Source 1 Volts AB", new SingleValueStrategy(480.0F, 2.0f, 1000));
addStrategy("Source 1 Volts BC", new SingleValueStrategy(480.0F, 2.0f, 1000));
addStrategy("Source 1 Volts CA", new SingleValueStrategy(480.0F, 2.0f, 1000));
addStrategy("Source 2 Volts AB", new SingleValueStrategy(0.0F, 0.0f, 1000));
addStrategy("Source 2 Volts BC", new SingleValueStrategy(0.0F, 0.0f, 1000));
addStrategy("Source 2 Volts CA", new SingleValueStrategy(0.0F, 0.0f, 1000));
addStrategy("Source 1 Frequency", new SingleValueStrategy(60.0f, 1.0f, 1000));
addStrategy("Source 2 Frequency", new SingleValueStrategy(0.0f, 0.0f, 1000));
// You can add initialization code here if needed
addStrategy("Source 1 Volts AB", new SingleValueStrategy(480.0F, 2.0f, 1000));
addStrategy("Source 1 Volts BC", new SingleValueStrategy(480.0F, 2.0f, 1000));
addStrategy("Source 1 Volts CA", new SingleValueStrategy(480.0F, 2.0f, 1000));
addStrategy("Source 1 Frequency", new SingleValueStrategy(60.0f, 1.0f, 1000));
addStrategy("Power Factor", new SingleValueStrategy(90.0f, 2.0f, 1000));
addStrategy("Volts AB", new SingleValueStrategy(480.0f, 2.0f, 1000));
addStrategy("Votls BC", new SingleValueStrategy(480.0f, 2.0f, 1000));
addStrategy("Volts CA", new SingleValueStrategy(480.0f, 2.0f, 1000));
addStrategy("Amps A", new SingleValueStrategy(1.0f, 3.0f, 1000));
addStrategy("Amps B", new SingleValueStrategy(1.0f, 3.0f, 1000));
addStrategy("Amps C", new SingleValueStrategy(1.0f, 3.0f, 1000));
addStrategy("Total Active Power", new SingleValueStrategy(6.0f, 5.0f, 1000));
addStrategy("Total Apparent Power", new SingleValueStrategy(6.0f, 5.0f, 1000));
addStrategy("Power Factor", new SingleValueStrategy(90.0f, 2.0f, 1000));
addStrategy("Amps A", new SingleValueStrategy(1.0f, 5.0f, 1000));
addStrategy("Amps B", new SingleValueStrategy(1.0f, 5.0f, 1000));
addStrategy("Amps C", new SingleValueStrategy(1.0f, 5.0f, 1000));
}
/**
@@ -73,19 +73,42 @@ State<ModbusIP>* StandbyState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
return new RunningState<ModbusIP>();
}
int I_load = getPointValue(equipment, "ATS_Load");
int I_rating = getPointValue(equipment, "ATS_Rating");
float load = static_cast<float>(I_load);
float rating = static_cast<float>(I_rating);
float real_load = rating * (load/100.0f);
float load = getPointValue(equipment, "ATS_Load");
float rating = getPointValue(equipment, "ATS_Rating");
float sim_load = rating * (load/100.0f);
Strategy_Behavior* ampsA_svs = getStrategy("Amps A");
Strategy_Behavior* ampsB_svs = getStrategy("Amps B");
Strategy_Behavior* ampsC_svs = getStrategy("Amps C");
static_cast<SingleValueStrategy*>(ampsA_svs)->setSetpoint(real_load);
static_cast<SingleValueStrategy*>(ampsB_svs)->setSetpoint(real_load);
static_cast<SingleValueStrategy*>(ampsC_svs)->setSetpoint(real_load);
static_cast<SingleValueStrategy*>(ampsA_svs)->setSetpoint(sim_load);
static_cast<SingleValueStrategy*>(ampsB_svs)->setSetpoint(sim_load);
static_cast<SingleValueStrategy*>(ampsC_svs)->setSetpoint(sim_load);
// Apply any strategies defined for the standby state
float v_ab = getPointValue(equipment, "Source 1 Volts AB");
float v_bc = getPointValue(equipment, "Source 1 Volts BC");
float v_ca = getPointValue(equipment, "Source 1 Volts CA");
float i_a = getPointValue(equipment, "Amps A");
float i_b = getPointValue(equipment, "Amps B");
float i_c = getPointValue(equipment, "Ampc C");
float pwr = ((v_ab * i_a) + (v_bc * i_b) + (v_ca * i_c));
setPointValue(equipment, "Total Active Power", pwr*1000.0f);
float pf = getPointValue(equipment, "Power Factor");
float a_pwr = pwr * (pf/100.0f);
setPointValue(equipment, "Total Apparent Power", a_pwr*1000.0f);
/*setPointValue(equipment, "S2 kW", kw);
setPointValue(equipment, "S2 MWh", mwh);*/
float preferred = getPointValue(equipment, "ATS_Preferred");
if (preferred == 1.0f){
setPointValue(equipment, "Source 1 Preferred", 1.0f);
setPointValue(equipment, "Source 2 Preferred", 0.0f);
}
if (preferred == 2.0f){
setPointValue(equipment, "Source 1 Preferred", 0.0f);
setPointValue(equipment, "Source 2 Preferred", 1.0f);
}
_applyStrategies(equipment);
return nullptr;
}
@@ -107,6 +130,11 @@ void StandbyState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
setPointValue(equipment, "Source 1 Preferred", 0);
setPointValue(equipment, "Source 2 Preferred", 1);
setPointValue(equipment, "Source 2 Volts AB", 0.0f);
setPointValue(equipment, "Source 2 Volts BC", 0.0f);
setPointValue(equipment, "Source 2 Volts CA", 0.0f);
setPointValue(equipment, "Source 2 Frequency", 0.0f);
int transferQty = getPointValue(equipment, "Number of Transfers");
setPointValue(equipment, "Number of Transfers", transferQty + 1);
}

View File

@@ -21,10 +21,10 @@
* @{
*/
#include <ModbusIP_ESP8266.h>
const char *ssid = "wifi_ssid"; /**< @brief The SSID of the WiFi network. */
const char *password = "wifi_password"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(192, 168, 1, 15); /**< @brief The static IP address for the device. */
IPAddress gateway(192, 168, 1, 1); /**< @brief The gateway IP address. */
const char *ssid = "QTS_CDR_Arduino"; /**< @brief The SSID of the WiFi network. */
const char *password = "123abc456"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(172, 17, 33, 172); /**< @brief The static IP address for the device. */
IPAddress gateway(172, 17, 33, 1); /**< @brief The gateway IP address. */
IPAddress subnet(255, 255, 255, 0); /**< @brief The subnet mask. */
ModbusIP mb;
@@ -60,6 +60,7 @@
*/
modbusMap mb_map[] =
{
{HR, 8, 0, "ATS_Preferred"}, //Internal to control from Modscan
{HR, 9, 0, "ATS_Source"}, //Internal to control from Modscan
{HR, 10, 0, "ATS_Load"}, //Internal Fault code from Modscan
{HR, 11, 0, "ATS_Rating"}, //Internal Fault code from Modscan
@@ -86,9 +87,9 @@ modbusMap mb_map[] =
{IR, 6158, 0, "Amps A"},
{IR, 6159, 0, "Amps B"},
{IR, 6160, 0, "Amps C"},
{IR_LONG, 6165, 0, "Total Active Power"},
{IR_LONG, 6169, 0, "Total Apparent Power"},
{IR, 6171, 0, "Power Factor"},
{IR_LONG, 6165, 0, "Total Active Power"}, //0.001
{IR_LONG, 6169, 0, "Total Apparent Power"}, //0.001
{IR, 6171, 0, "Power Factor"}, //0.001
{IR, 6263, 0, "Number of Transfers"},
{IR, 6297, 0, "Alarm Status Bits"},

View File

@@ -39,15 +39,15 @@
template<>
RunningState<ModbusIP>::RunningState() {
addStrategy("S2 Volts AB", new SingleValueStrategy(480.0F, 2.0f, 1000));
addStrategy("S2 Volts BC", new SingleValueStrategy(480.0F, 2.0f, 1000));
addStrategy("S2 Volts CA", new SingleValueStrategy(480.0F, 2.0f, 1000));
addStrategy("S2 Volts AB", new SingleValueStrategy(4800.0F, 10.0f, 1000));
addStrategy("S2 Volts BC", new SingleValueStrategy(4800.0F, 10.0f, 1000));
addStrategy("S2 Volts CA", new SingleValueStrategy(4800.0F, 10.0f, 1000));
addStrategy("PF", new SingleValueStrategy(90.0f, 2.0f, 1000));
addStrategy("PF", new SingleValueStrategy(910.0f, 20.0f, 1000));
addStrategy("S2 Amps A", new SingleValueStrategy(1.0f, 5.0f, 1000));
addStrategy("S2 Amps B", new SingleValueStrategy(1.0f, 5.0f, 1000));
addStrategy("S2 Amps C", new SingleValueStrategy(1.0f, 5.0f, 1000));
addStrategy("S2 Amps A", new SingleValueStrategy(200.0f, 100.0f, 1000));
addStrategy("S2 Amps B", new SingleValueStrategy(200.0f, 100.0f, 1000));
addStrategy("S2 Amps C", new SingleValueStrategy(200.0f, 100.0f, 1000));
}
@@ -74,34 +74,47 @@ State<ModbusIP>* RunningState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
}
float volts_AB = getPointValue(equipment, "S2 Volts AB");
float volts_BC = getPointValue(equipment, "S2 Volts BC");
float volts_AC = getPointValue(equipment, "S2 Volts CA");
float volts_CA = getPointValue(equipment, "S2 Volts CA");
setPointValue(equipment, "S2 Volts AN", volts_AB/1.732);
setPointValue(equipment, "S2 Volts BN", volts_BC/1.732);
setPointValue(equipment, "S2 Volts CN", volts_AC/1.732);
setPointValue(equipment, "S2 Volts CN", volts_CA/1.732);
int I_load = getPointValue(equipment, "ATS_Load");
int I_rating = getPointValue(equipment, "ATS_Rating");
float load = static_cast<float>(I_load);
float rating = static_cast<float>(I_rating);
float real_load = rating * (load/100.0f);
float sim_load = rating * (load/100.0f);
Strategy_Behavior* ampsA_svs = getStrategy("S2 Amps A");
Strategy_Behavior* ampsB_svs = getStrategy("S2 Amps B");
Strategy_Behavior* ampsC_svs = getStrategy("S2 Amps C");
static_cast<SingleValueStrategy*>(ampsA_svs)->setSetpoint(real_load);
static_cast<SingleValueStrategy*>(ampsB_svs)->setSetpoint(real_load);
static_cast<SingleValueStrategy*>(ampsC_svs)->setSetpoint(real_load);
static_cast<SingleValueStrategy*>(ampsA_svs)->setSetpoint(sim_load*1000.0f);
static_cast<SingleValueStrategy*>(ampsB_svs)->setSetpoint(sim_load*1000.0f);
static_cast<SingleValueStrategy*>(ampsC_svs)->setSetpoint(sim_load*1000.0f);
float pf = getPointValue(equipment, "PF");
float get_pf = getPointValue(equipment, "PF");
float pf = get_pf/1000.0f;
float kw = (1.732f * ((volts_AB + volts_BC + volts_AC)/3.0f) * real_load * pf)/1000;
float kva = (1.732f * ((volts_AB + volts_BC + volts_AC)/3.0f) * real_load)/1000;
float real_v_AB = volts_AB/1000.0f;
float real_v_BC = volts_BC/1000.0f;
float real_v_CA = volts_CA/1000.0f;
float kw = (1.732f * ((real_v_AB + real_v_BC + real_v_CA)/3.0f) * sim_load * pf)*10;
float mwh = kw *600.0f;
setPointValue(equipment, "S2 kW", kw);
setPointValue(equipment, "S2 kVA", kva);
setPointValue(equipment, "S2 MWh", mwh);
float preferred = getPointValue(equipment, "ATS_Preferred");
if (preferred == 1.0f){
setBitValue(equipment, "Source Preferred", 9, true);
setBitValue(equipment, "Source Preferred", 8, false);
}
if (preferred == 2.0f){
setBitValue(equipment, "Source Preferred", 9, false);
setBitValue(equipment, "Source Preferred", 8, true);
}
// Apply any strategies defined for the standby state
_applyStrategies(equipment);
return nullptr;
@@ -117,9 +130,6 @@ void RunningState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Running State...");
// You could also update a Modbus register to show the "standby" state
setPointValue(equipment, "Source Active", 32);
setPointValue(equipment, "Source Preferred", 512);
setPointValue(equipment, "S1 Volts AB", 0.0f);
setPointValue(equipment, "S1 Volts BC", 0.0f);
setPointValue(equipment, "S1 Volts CA", 0.0f);
@@ -129,6 +139,14 @@ void RunningState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
setPointValue(equipment, "S1 Amps A", 0.0f);
setPointValue(equipment, "S1 Amps B", 0.0f);
setPointValue(equipment, "S1 Amps C", 0.0f);
setPointValue(equipment, "S1 kW", 0.0f);
setPointValue(equipment, "S1 MWh", 0.0f);
setBitValue(equipment, "Source Active", 4, false);
setBitValue(equipment, "Source Active", 3, true);
setBitValue(equipment, "Source Preferred", 8, false);
setBitValue(equipment, "Source Preferred", 9, true);
}
/**

View File

@@ -38,15 +38,15 @@
template<>
StandbyState<ModbusIP>::StandbyState() {
// You can add initialization code here if needed
addStrategy("S1 Volts AB", new SingleValueStrategy(480.0F, 2.0f, 1000));
addStrategy("S1 Volts BC", new SingleValueStrategy(480.0F, 2.0f, 1000));
addStrategy("S1 Volts CA", new SingleValueStrategy(480.0F, 2.0f, 1000));
addStrategy("S1 Volts AB", new SingleValueStrategy(4800.0F, 10.0f, 1000));
addStrategy("S1 Volts BC", new SingleValueStrategy(4800.0F, 10.0f, 1000));
addStrategy("S1 Volts CA", new SingleValueStrategy(4800.0F, 10.0f, 1000));
addStrategy("PF", new SingleValueStrategy(90.0f, 2.0f, 1000));
addStrategy("PF", new SingleValueStrategy(910.0f, 20.0f, 1000));
addStrategy("S1 Amps A", new SingleValueStrategy(1.0f, 5.0f, 1000));
addStrategy("S1 Amps B", new SingleValueStrategy(1.0f, 5.0f, 1000));
addStrategy("S1 Amps C", new SingleValueStrategy(1.0f, 5.0f, 1000));
addStrategy("S1 Amps A", new SingleValueStrategy(200.0f, 100.0f, 1000));
addStrategy("S1 Amps B", new SingleValueStrategy(200.0f, 100.0f, 1000));
addStrategy("S1 Amps C", new SingleValueStrategy(200.0f, 100.0f, 1000));
}
/**
@@ -68,33 +68,46 @@ State<ModbusIP>* StandbyState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
}
float volts_AB = getPointValue(equipment, "S1 Volts AB");
float volts_BC = getPointValue(equipment, "S1 Volts BC");
float volts_AC = getPointValue(equipment, "S1 Volts CA");
float volts_CA = getPointValue(equipment, "S1 Volts CA");
setPointValue(equipment, "S1 Volts AN", volts_AB/1.732);
setPointValue(equipment, "S1 Volts BN", volts_BC/1.732);
setPointValue(equipment, "S1 Volts CN", volts_AC/1.732);
setPointValue(equipment, "S1 Volts CN", volts_CA/1.732);
int I_load = getPointValue(equipment, "ATS_Load");
int I_rating = getPointValue(equipment, "ATS_Rating");
float load = static_cast<float>(I_load);
float rating = static_cast<float>(I_rating);
float real_load = rating * (load/100.0f);
float sim_load = rating * (load/100.0f);
Strategy_Behavior* ampsA_svs = getStrategy("S1 Amps A");
Strategy_Behavior* ampsB_svs = getStrategy("S1 Amps B");
Strategy_Behavior* ampsC_svs = getStrategy("S1 Amps C");
static_cast<SingleValueStrategy*>(ampsA_svs)->setSetpoint(real_load);
static_cast<SingleValueStrategy*>(ampsB_svs)->setSetpoint(real_load);
static_cast<SingleValueStrategy*>(ampsC_svs)->setSetpoint(real_load);
static_cast<SingleValueStrategy*>(ampsA_svs)->setSetpoint(sim_load*1000.0f);
static_cast<SingleValueStrategy*>(ampsB_svs)->setSetpoint(sim_load*1000.0f);
static_cast<SingleValueStrategy*>(ampsC_svs)->setSetpoint(sim_load*1000.0f);
float pf = getPointValue(equipment, "PF");
float get_pf = getPointValue(equipment, "PF");
float pf = get_pf/1000.0f;
float real_v_AB = volts_AB/1000.0f;
float real_v_BC = volts_BC/1000.0f;
float real_v_CA = volts_CA/1000.0f;
float kw = (1.732f * ((real_v_AB + real_v_BC + real_v_CA)/3.0f) * sim_load * pf)*10;
float mwh = kw *600.0f;
float kw = (1.732f * ((volts_AB + volts_BC + volts_AC)/3.0f) * real_load * pf)/1000;
float kva = (1.732f * ((volts_AB + volts_BC + volts_AC)/3.0f) * real_load)/1000;
float preferred = getPointValue(equipment, "ATS_Preferred");
if (preferred == 1.0f){
setBitValue(equipment, "Source Preferred", 9, true);
setBitValue(equipment, "Source Preferred", 8, false);
}
if (preferred == 2.0f){
setBitValue(equipment, "Source Preferred", 9, false);
setBitValue(equipment, "Source Preferred", 8, true);
}
setPointValue(equipment, "S1 kW", kw);
setPointValue(equipment, "S1 kVA", kva);
setPointValue(equipment, "S1 MWh", mwh);
_applyStrategies(equipment);
return nullptr;
}
@@ -109,8 +122,6 @@ template<>
void StandbyState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Standby State...");
setPointValue(equipment, "Source Active", 64);
setPointValue(equipment, "Source Preferred", 1024);
setPointValue(equipment, "S2 Volts AB", 0.0f);
setPointValue(equipment, "S2 Volts BC", 0.0f);
@@ -121,6 +132,14 @@ void StandbyState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
setPointValue(equipment, "S2 Amps A", 0.0f);
setPointValue(equipment, "S2 Amps B", 0.0f);
setPointValue(equipment, "S2 Amps C", 0.0f);
setPointValue(equipment, "S2 kW", 0.0f);
setPointValue(equipment, "S2 MWh", 0.0f);
setBitValue(equipment, "Source Active", 3, false);
setBitValue(equipment, "Source Active", 4, true);
setBitValue(equipment, "Source Preferred", 8, false);
setBitValue(equipment, "Source Preferred", 9, true);
}
/**

View File

@@ -23,7 +23,7 @@
#include <ModbusIP_ESP8266.h>
const char *ssid = "QTS_CDR_Arduino"; /**< @brief The SSID of the WiFi network. */
const char *password = "123abc456"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(172, 17, 33, 241); /**< @brief The static IP address for the device. */
IPAddress local_IP(172, 17, 33, 173); /**< @brief The static IP address for the device. */
IPAddress gateway(172, 17, 33, 1); /**< @brief The gateway IP address. */
IPAddress subnet(255, 255, 255, 0); /**< @brief The subnet mask. */
@@ -60,35 +60,37 @@
*/
modbusMap mb_map[] =
{
{HR, 8, 0, "ATS_Preferred"}, //Internal to control from Modscan
{HR, 9, 0, "ATS_Source"}, //Internal to control from Modscan
{HR, 10, 0, "ATS_Load"},
{HR, 11, 0, "ATS_Rating"}, //Internal Fault code from Modscan
{HR, 50009, 0, "PF"},
{HR_LONG, 50001, 0, "S2 Volts AB"},
{HR_LONG, 50004, 0, "S2 Volts AN"},
{HR_LONG, 50007, 0, "S2 Volts BC"},
{HR_LONG, 50010, 0, "S2 Volts BN"},
{HR_LONG, 50013, 0, "S2 Volts CA"},
{HR_LONG, 50016, 0, "S2 Volts CN"},
{HR_LONG, 50019, 0, "S1 Volts AB"},
{HR_LONG, 50022, 0, "S1 Volts AN"},
{HR_LONG, 50025, 0, "S1 Volts BC"},
{HR_LONG, 50028, 0, "S1 Volts BN"},
{HR_LONG, 50031, 0, "S1 Volts CA"},
{HR_LONG, 50034, 0, "S1 Volts CN"},
{HR_LONG, 50037, 0, "S2 Amps A"},
{HR_LONG, 50040, 0, "S2 Amps B"},
{HR_LONG, 50043, 0, "S2 Amps C"},
{HR_LONG, 50060, 0, "S2 kW"},
{HR_LONG, 50064, 0, "S2 MWh"},
{HR, 50078, 0, "Source Preferred"}, // bit 8 and bit 9
{HR, 50082, 0, "Source Active"}, //bit2 and bit 3
{HR_LONG, 50091, 0, "S1 Amps A"},
{HR, 50093, 0, "S1 kW"},
{HR_LONG, 50094, 0, "S1 Amps B"},
{HR_LONG, 50097, 0, "S1 Amps C"},
{HR_LONG, 50100, 0, "S1 MWh"},
{HR, 50009, 0, "PF"}, //0.001x
{HR_LONG, 50001, 0, "S2 Volts AB"}, //0.1x
{HR_LONG, 50004, 0, "S2 Volts AN"}, //0.1x
{HR_LONG, 50007, 0, "S2 Volts BC"}, //0.1x
{HR_LONG, 50010, 0, "S2 Volts BN"}, //0.1x
{HR_LONG, 50013, 0, "S2 Volts CA"}, //0.1x
{HR_LONG, 50016, 0, "S2 Volts CN"}, //0.1x
{HR_LONG, 50019, 0, "S1 Volts AB"}, //0.1x
{HR_LONG, 50022, 0, "S1 Volts AN"}, //0.1x
{HR_LONG, 50025, 0, "S1 Volts BC"}, //0.1x
{HR_LONG, 50028, 0, "S1 Volts BN"}, //0.1x
{HR_LONG, 50031, 0, "S1 Volts CA"}, //0.1x
{HR_LONG, 50034, 0, "S1 Volts CN"}, //0.1x
{HR_LONG, 50037, 0, "S2 Amps A"}, //0.001x
{HR_LONG, 50040, 0, "S2 Amps B"}, //0.001x
{HR_LONG, 50043, 0, "S2 Amps C"}, //0.001x
{HR_LONG, 50060, 0, "S2 kW"},
{HR_LONG, 50064, 0, "S2 MWh"}, //0.01x
{HR, 50078, 0, "Source Preferred"}, //bit9 source1 bit8 source 2
{HR, 50082, 0, "Source Active"}, //bit4 source1 bit3 source 2
{HR_LONG, 50091, 0, "S1 Amps A"}, //.001x
{HR, 50093, 0, "S1 kW"}, //.1x
{HR_LONG, 50094, 0, "S1 Amps B"}, //.001x
{HR_LONG, 50097, 0, "S1 Amps C"}, //.001x
{HR_LONG, 50100, 0, "S1 MWh"}, //.01x
};
//Size of modbus map used in FOR cycles, automatically calculated.

View File

@@ -38,11 +38,11 @@
*/
template<>
RunningState<ModbusIP>::RunningState() {
addStrategy("Volts AB", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("Volts BC", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("Volts CA", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("Volts AB", new SingleValueStrategy(4800.0F, 5.0f, 1000));
addStrategy("Volts BC", new SingleValueStrategy(4800.0F, 5.0f, 1000));
addStrategy("Volts CA", new SingleValueStrategy(4800.0F, 5.0f, 1000));
addStrategy("PF", new SingleValueStrategy(90.0f, 1.0f, 1000));
addStrategy("PF", new SingleValueStrategy(900.0f, 1.0f, 1000));
addStrategy("Amps A", new SingleValueStrategy(1.0f, 10.0f, 1000));
addStrategy("Amps B", new SingleValueStrategy(1.0f, 10.0f, 1000));
@@ -66,9 +66,11 @@ template<>
State<ModbusIP>* RunningState<ModbusIP>::update(Equipment<ModbusIP>* equipment) {
// STATE control, add conditions if change to a different state is needed
Serial.println("Running update function");
Serial.println("Running update function");
float State_Ctrl = getPointValue(equipment, "State Control");
if (State_Ctrl == 1){
if (State_Ctrl == 0.0f){
return new StandbyState<ModbusIP>();
}
if (State_Ctrl == 2.0f){
return new StandbyState<ModbusIP>();
}
// Apply any strategies defined for the standby state
@@ -76,9 +78,9 @@ State<ModbusIP>* RunningState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
float volts_BC = getPointValue(equipment, "Volts BC");
float volts_AC = getPointValue(equipment, "Volts CA");
setPointValue(equipment, "Volts AN", volts_AB/1.732);
setPointValue(equipment, "Volts BN", volts_BC/1.732);
setPointValue(equipment, "Volts CN", volts_AC/1.732);
setPointValue(equipment, "Volts AN", volts_AB/1.732f);
setPointValue(equipment, "Volts BN", volts_BC/1.732f);
setPointValue(equipment, "Volts CN", volts_AC/1.732f);
int I_load = getPointValue(equipment, "Load");
@@ -86,18 +88,21 @@ State<ModbusIP>* RunningState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
float load = static_cast<float>(I_load);
float rating = static_cast<float>(I_rating);
float real_load = rating * (load/100.0f);
setPointValue(equipment, "Amps A", real_load);
setPointValue(equipment, "Amps B", real_load);
setPointValue(equipment, "Amps C", real_load);
setPointValue(equipment, "Amps A", real_load * 10.0f);
setPointValue(equipment, "Amps B", real_load * 10.0f);
setPointValue(equipment, "Amps C", real_load * 10.0f);
setPointValue(equipment, "Amps G", volts_AB * 0.037f);
setPointValue(equipment, "Amps N", volts_BC * 0.034f);
float pf = getPointValue(equipment, "PF");
float kw = (1.732f * ((volts_AB + volts_BC + volts_AC)/3.0f) * real_load * (pf/100))/100;
float kva = (1.732f * ((volts_AB + volts_BC + volts_AC)/3.0f) * real_load)/100;
float kva = (1.732f * ((volts_AB + volts_BC + volts_AC)/4.0f) * real_load * (pf/100.0f))/100000.0f;
float kw = (1.732f * ((volts_AB + volts_BC + volts_AC)/4.0f) * real_load )/10000.0f;
setPointValue(equipment, "kW", kw);
setPointValue(equipment, "kVA", kva);
setPointValue(equipment, "kWh", 1724.0f);
// Apply any strategies defined for the standby state
_applyStrategies(equipment);
return nullptr;
@@ -113,7 +118,8 @@ void RunningState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Running State...");
// You could also update a Modbus register to show the "standby" state
setPointValue(equipment, "CB Position", 1);
setBitValue(equipment, "CB Position", 0, true);
setBitValue(equipment, "CB Position", 12, false);
}
/**

View File

@@ -57,9 +57,16 @@ State<ModbusIP>* StandbyState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
// STATE control, add conditions if change to a different state is needed
Serial.println("Standby update function");
float State_Ctrl = getPointValue(equipment, "State Control");
if (State_Ctrl == 2){
if (State_Ctrl == 1.0f){
return new RunningState<ModbusIP>();
}
if (State_Ctrl == 0.0f){
setBitValue(equipment, "CB Position", 12, false);
}
if (State_Ctrl == 2.0f){
setBitValue(equipment, "CB Position", 12, true);
}
// Apply any strategies defined for the standby state
_applyStrategies(equipment);
return nullptr;
@@ -75,7 +82,7 @@ template<>
void StandbyState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Standby State...");
setPointValue(equipment, "CB Position", 0);
setBitValue(equipment, "CB Position", 0, false);
setPointValue(equipment, "Volts AB", 0.0f);
setPointValue(equipment, "Volts BC", 0.0f);
setPointValue(equipment, "Volts CA", 0.0f);
@@ -86,8 +93,11 @@ void StandbyState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
setPointValue(equipment, "Amps A", 0.0f);
setPointValue(equipment, "Amps B", 0.0f);
setPointValue(equipment, "Amps C", 0.0f);
setPointValue(equipment, "Amps G", 0.0f);
setPointValue(equipment, "Amps N", 0.0f);
setPointValue(equipment, "kW", 0.0f);
setPointValue(equipment, "kVA", 0.0f);
setPointValue(equipment, "kWh", 0.0f);
}
/**

View File

@@ -23,8 +23,8 @@
#include <ModbusIP_ESP8266.h>
const char *ssid = "QTS_CDR_Arduino"; /**< @brief The SSID of the WiFi network. */
const char *password = "123abc456"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(172, 17, 30, 241); /**< @brief The static IP address for the device. */
IPAddress gateway(172, 17, 30, 1); /**< @brief The gateway IP address. */
IPAddress local_IP(172, 17, 33, 154); /**< @brief The static IP address for the device. */
IPAddress gateway(172, 17, 33, 1); /**< @brief The gateway IP address. */
IPAddress subnet(255, 255, 255, 0); /**< @brief The subnet mask. */
ModbusIP mb;
@@ -63,7 +63,7 @@ modbusMap mb_map[] =
{HR, 9, 0, "State Control"}, //Open-Close Cmd
{HR, 10, 0, "Load"}, //Adjustble Load
{HR, 11, 0, "Rating"}, //Max amp to calculate kw, kVA, etc
{IR_LONG, 41, 0, "CB Position"},
{IR, 41, 0, "CB Position"}, //b0 close open b12 tripped
{IR_LONG, 101, 0, "Amps A"},
{IR_LONG, 103, 0, "Amps B"},
{IR_LONG, 105, 0, "Amps C"},

View File

@@ -68,7 +68,10 @@ State<ModbusIP>* RunningState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
// STATE control, add conditions if change to a different state is needed
Serial.println("Running update function");
float State_Ctrl = getPointValue(equipment, "State Control");
if (State_Ctrl == 1){
if (State_Ctrl == 0){
return new StandbyState<ModbusIP>();
}
if (State_Ctrl == 2){
return new StandbyState<ModbusIP>();
}
// Apply any strategies defined for the standby state
@@ -118,6 +121,7 @@ void RunningState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
Serial.println("Enter Running State...");
// You could also update a Modbus register to show the "standby" state
setPointValue(equipment, "CB Position", 2048);
setPointValue(equipment, "CB Trip", 0.0f);
}

View File

@@ -57,9 +57,16 @@ State<ModbusIP>* StandbyState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
// STATE control, add conditions if change to a different state is needed
Serial.println("Standby update function");
float State_Ctrl = getPointValue(equipment, "State Control");
if (State_Ctrl == 2){
if (State_Ctrl == 1){
return new RunningState<ModbusIP>();
}
if (State_Ctrl == 0){
setPointValue(equipment, "CB Trip", 0.0f);
}
if (State_Ctrl == 2){
setPointValue(equipment, "CB Trip", 1.0f);
}
// Apply any strategies defined for the standby state
_applyStrategies(equipment);
return nullptr;

View File

@@ -21,10 +21,10 @@
* @{
*/
#include <ModbusIP_ESP8266.h>
const char *ssid = "wifi_name"; /**< @brief The SSID of the WiFi network. */
const char *password = "wifi_password"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(192, 168, 1, 234); /**< @brief The static IP address for the device. */
IPAddress gateway(192, 168, 1, 1); /**< @brief The gateway IP address. */
const char *ssid = "QTS_CDR_Arduino"; /**< @brief The SSID of the WiFi network. */
const char *password = "123abc456"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(172, 17, 33, 167); /**< @brief The static IP address for the device. */
IPAddress gateway(172, 17, 33, 1); /**< @brief The gateway IP address. */
IPAddress subnet(255, 255, 255, 0); /**< @brief The subnet mask. */
ModbusIP mb;

View File

@@ -61,7 +61,10 @@ State<ModbusIP>* RunningState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
// STATE control, add conditions if change to a different state is needed
Serial.println("Running update function");
float State_Ctrl = getPointValue(equipment, "State Control");
if (State_Ctrl == 1){
if (State_Ctrl == 0.0f){
return new StandbyState<ModbusIP>();
}
if (State_Ctrl == 2.0f){
return new StandbyState<ModbusIP>();
}
@@ -92,7 +95,9 @@ void RunningState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Running State...");
// You could also update a Modbus register to show the "standby" state
setPointValue(equipment, "Status", 4);
setBitValue(equipment, "Status", 2, true);
setBitValue(equipment, "Tripped", 0, false);
}

View File

@@ -57,9 +57,16 @@ State<ModbusIP>* StandbyState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
// STATE control, add conditions if change to a different state is needed
Serial.println("Standby update function");
float State_Ctrl = getPointValue(equipment, "State Control");
if (State_Ctrl == 2){
if (State_Ctrl == 1.0f){
return new RunningState<ModbusIP>();
}
if (State_Ctrl == 0.0f){
setBitValue(equipment, "Tripped", 0, false);
}
if (State_Ctrl == 2.0f){
setBitValue(equipment, "Tripped", 0, true);
}
// Apply any strategies defined for the standby state
_applyStrategies(equipment);
return nullptr;
@@ -75,11 +82,13 @@ template<>
void StandbyState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Standby State...");
setPointValue(equipment, "Status", 0);
setPointValue(equipment, "Amps A", 0.0f);
setPointValue(equipment, "Amps B", 0.0f);
setPointValue(equipment, "Amps C", 0.0f);
setPointValue(equipment, "Amps N", 0.0f);
setBitValue(equipment, "Status", 2, false);
}
/**

View File

@@ -21,10 +21,10 @@
* @{
*/
#include <ModbusIP_ESP8266.h>
const char *ssid = "wifi_name"; /**< @brief The SSID of the WiFi network. */
const char *password = "wifi_password"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(192, 168, 1, 238); /**< @brief The static IP address for the device. */
IPAddress gateway(192, 138, 1, 1); /**< @brief The gateway IP address. */
const char *ssid = "QTS_CDR_Arduino"; /**< @brief The SSID of the WiFi network. */
const char *password = "123abc456"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(172, 17, 33, 149); /**< @brief The static IP address for the device. */
IPAddress gateway(172, 17, 33, 1); /**< @brief The gateway IP address. */
IPAddress subnet(255, 255, 255, 0); /**< @brief The subnet mask. */
ModbusIP mb;
@@ -64,11 +64,12 @@ modbusMap mb_map[] =
{HR, 10, 0, "Load"},
{HR, 11, 0, "Rating"},
{IR, 2, 0, "Status"},
{IR, 2, 0, "Status"}, //bit 2 open-close,
{IR, 3, 0, "Amps A"},
{IR, 5, 0, "Amps B"},
{IR, 7, 0, "Amps C"},
{IR, 9, 0, "Amps N"},
{IR, 13, 0, "Tripped"}, //bit 0 tripped
};
//Size of modbus map used in FOR cycles, automatically calculated.

View File

@@ -68,7 +68,10 @@ State<ModbusIP>* RunningState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
// STATE control, add conditions if change to a different state is needed
Serial.println("Running update function");
float State_Ctrl = getPointValue(equipment, "State Control");
if (State_Ctrl == 1){
if (State_Ctrl == 0.0f){
return new StandbyState<ModbusIP>();
}
if (State_Ctrl == 2.0f){
return new StandbyState<ModbusIP>();
}
// Apply any strategies defined for the standby state
@@ -116,7 +119,9 @@ void RunningState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Running State...");
// You could also update a Modbus register to show the "standby" state
setPointValue(equipment, "CB Position", 4096);
setBitValue(equipment, "CB Position", 12, true);
setBitValue(equipment, "CB Position", 9, false);
}

View File

@@ -57,9 +57,17 @@ State<ModbusIP>* StandbyState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
// STATE control, add conditions if change to a different state is needed
Serial.println("Standby update function");
float State_Ctrl = getPointValue(equipment, "State Control");
if (State_Ctrl == 2){
if (State_Ctrl == 1.0f){
return new RunningState<ModbusIP>();
}
if (State_Ctrl == 0.0f){
setBitValue(equipment, "CB Position", 9, false);
}
if (State_Ctrl == 2.0f){
setBitValue(equipment, "CB Position", 9, true);
}
// Apply any strategies defined for the standby state
_applyStrategies(equipment);
return nullptr;
@@ -86,6 +94,7 @@ void StandbyState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
setPointValue(equipment, "Amps A", 0.0f);
setPointValue(equipment, "Amps B", 0.0f);
setPointValue(equipment, "Amps C", 0.0f);
setBitValue(equipment, "CB Position", 12, false);
}
/**

View File

@@ -23,7 +23,7 @@
#include <ModbusIP_ESP8266.h>
const char *ssid = "QTS_CDR_Arduino"; /**< @brief The SSID of the WiFi network. */
const char *password = "123abc456"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(172, 17, 33, 132); /**< @brief The static IP address for the device. */
IPAddress local_IP(172, 17, 33, 141); /**< @brief The static IP address for the device. */
IPAddress gateway(172, 17, 33, 1); /**< @brief The gateway IP address. */
IPAddress subnet(255, 255, 255, 0); /**< @brief The subnet mask. */
@@ -64,7 +64,7 @@ modbusMap mb_map[] =
{HR, 10, 0, "Load"},
{HR, 11, 0, "Rating"},
{IR, 207, 0, "CB Position"},
{IR, 207, 0, "CB Position"}, //bit 9 trip bit 12 open closed
{IR_FLOAT, 215, 0, "Amps A"},
{IR_FLOAT, 217, 0, "Amps B"},
{IR_FLOAT, 219, 0, "Amps C"},

View File

@@ -36,79 +36,90 @@
* state, such as a PID controller for the 'CW Valve Position' and totalizers
* for the run-hours of each EC fan.
*/
std::string cbs[] = {"CB0", "CB1", "CB2", "CB3", "CB4", "CB5", "CB6", "CB7", "CB8", };
std::string cbs[] = {"CB1", "CB2", "CB3", "CB4", "CB5", "CB6", "CB7", "CB8"};
template<>
RunningState<ModbusIP>::RunningState() {
//Example
addStrategy("System Input RMS C-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("System Input RMS Current Phase A", new RampStrategy(10.0F, 5.0f, 1000));
//
addStrategy("Input_I1", new SingleValueStrategy(40.0f, 30.0f, 1000));
addStrategy("Input_I2", new SingleValueStrategy(40.0f, 30.0f, 1000));
addStrategy("Input_I3", new SingleValueStrategy(40.0f, 30.0f, 1000));
addStrategy("Input_kVA", new SingleValueStrategy(150.0f, 100.0f, 1000));
addStrategy("Input_kVAR", new SingleValueStrategy(150.0f, 100.0f, 1000));
addStrategy("Input_kW", new SingleValueStrategy(150.0f, 100.0f, 1000));
addStrategy("Input_kWh", new SingleValueStrategy(3.0f, 2.0f, 1000));
addStrategy("Input_PF", new SingleValueStrategy(150.0f, 100.0f, 1000));
addStrategy("Input_V_AB", new SingleValueStrategy(3.0f, 2.0f, 1000));
addStrategy("Input_V_AN", new SingleValueStrategy(3.0f, 2.0f, 1000));
addStrategy("Input_V_BC", new SingleValueStrategy(3.0f, 2.0f, 1000));
addStrategy("Input_V_BN", new SingleValueStrategy(3.0f, 2.0f, 1000));
addStrategy("Input_V_CA", new SingleValueStrategy(3.0f, 2.0f, 1000));
addStrategy("Input_V_CN", new SingleValueStrategy(3.0f, 2.0f, 1000));
addStrategy("Input_LL_Avg", new SingleValueStrategy(3.0f, 2.0f, 1000));
addStrategy("Input_LN_Avg", new SingleValueStrategy(3.0f, 2.0f, 1000));
for (const std::string& cb : cbs) {
std::string tag = "";
tag = cb + "_V1N";
addStrategy(tag, new SingleValueStrategy(0.0f, 2.0f, 1000));
tag = "";
tag = cb + "_V2N";
addStrategy(tag, new SingleValueStrategy(0.0f, 2.0f, 1000));
tag = cb + "_I1";
addStrategy(tag, new SingleValueStrategy(40.0f, 30.0f, 1000));
tag = "";
tag = cb + "_V3N";
addStrategy(tag, new SingleValueStrategy(0.0f, 2.0f, 1000));
tag = cb + "_I2";
addStrategy(tag, new SingleValueStrategy(40.0f, 30.0f, 1000));
tag = "";
tag = cb + "_L1PF";
addStrategy(tag, new SingleValueStrategy(93.0f, 2.0f, 1000));
tag = cb + "_I3";
addStrategy(tag, new SingleValueStrategy(40.0f, 30.0f, 1000));
tag = "";
tag = cb + "_L2PF";
addStrategy(tag, new SingleValueStrategy(93.0f, 2.0f, 1000));
tag = cb + "_kVA";
addStrategy(tag, new SingleValueStrategy(150.0f, 100.0f, 1000));
tag = "";
tag = cb + "_L3PF";
addStrategy(tag, new SingleValueStrategy(93.0f, 2.0f, 1000));
tag = cb + "_kVA1";
addStrategy(tag, new SingleValueStrategy(150.0f, 100.0f, 1000));
tag = "";
tag = cb + "_V1THD";
addStrategy(tag, new SingleValueStrategy(2.0f, 2.0f, 1000));
tag = cb + "_kVA2";
addStrategy(tag, new SingleValueStrategy(150.0f, 100.0f, 1000));
tag = "";
tag = cb + "_V2THD";
addStrategy(tag, new SingleValueStrategy(2.0f, 2.0f, 1000));
tag = cb + "_kVA3";
addStrategy(tag, new SingleValueStrategy(150.0f, 100.0f, 1000));
tag = "";
tag = cb + "_V3THD";
addStrategy(tag, new SingleValueStrategy(2.0f, 2.0f, 1000));
tag = "";
tag = cb + "_I1THD";
addStrategy(tag, new SingleValueStrategy(10.0f, 2.0f, 1000));
tag = cb + "_kVAR";
addStrategy(tag, new SingleValueStrategy(150.0f, 100.0f, 1000));
tag = "";
tag = cb + "_I2THD";
addStrategy(tag, new SingleValueStrategy(10.0f, 2.0f, 1000));
tag = cb + "_kW";
addStrategy(tag, new SingleValueStrategy(150.0f, 100.0f, 1000));
tag = "";
tag = cb + "_I3THD";
addStrategy(tag, new SingleValueStrategy(10.0f, 2.0f, 1000));
tag = cb + "_kW1";
addStrategy(tag, new SingleValueStrategy(150.0f, 100.0f, 1000));
tag = "";
tag = cb + "_I1Kfactor";
addStrategy(tag, new SingleValueStrategy(3.0f, 2.0f, 1000));
tag = cb + "_kW2";
addStrategy(tag, new SingleValueStrategy(150.0f, 100.0f, 1000));
tag = "";
tag = cb + "_I2Kfactor";
addStrategy(tag, new SingleValueStrategy(3.0f, 2.0f, 1000));
tag = cb + "_kW3";
addStrategy(tag, new SingleValueStrategy(150.0f, 100.0f, 1000));
tag = "";
tag = cb + "_I3Kfactor";
addStrategy(tag, new SingleValueStrategy(3.0f, 2.0f, 1000));
tag = cb + "_kWh";
addStrategy(tag, new SingleValueStrategy(0.1f, 100.0f, 1000));
tag = "";
tag = cb + "_I1TDD";
addStrategy(tag, new SingleValueStrategy(5.0f, 2.0f, 1000));
tag = "";
tag = cb + "_I2TDD";
addStrategy(tag, new SingleValueStrategy(5.0f, 2.0f, 1000));
tag = "";
tag = cb + "_I3TDD";
addStrategy(tag, new SingleValueStrategy(5.0f, 2.0f, 1000));
tag = "";
tag = cb + "_V12";
addStrategy(tag, new SingleValueStrategy(0.0f, 2.0f, 1000));
tag = "";
tag = cb + "_V23";
addStrategy(tag, new SingleValueStrategy(0.0f, 2.0f, 1000));
tag = "";
tag = cb + "_V31";
addStrategy(tag, new SingleValueStrategy(0.0f, 2.0f, 1000));
tag = cb + "_PF";
addStrategy(tag, new SingleValueStrategy(150.0f, 100.0f, 1000));
}
addStrategy("Output_I1", new SingleValueStrategy(30.0f, 20.0f, 1000));
addStrategy("Output_I2", new SingleValueStrategy(30.0f, 30.0f, 1000));
addStrategy("Output_I3", new SingleValueStrategy(30.0f, 20.0f, 1000));
addStrategy("Output_IG", new SingleValueStrategy(30.0f, 30.0f, 1000));
addStrategy("Output_IN", new SingleValueStrategy(30.0f, 20.0f, 1000));
addStrategy("Output_kVA1", new SingleValueStrategy(150.0f, 100.0f, 1000));
addStrategy("Output_kVA2", new SingleValueStrategy(150.0f, 100.0f, 1000));
addStrategy("Output_kVA3", new SingleValueStrategy(150.0f, 100.0f, 1000));
addStrategy("Output_kWh", new SingleValueStrategy(3.0f, 2.0f, 1000));
addStrategy("Output_PF", new SingleValueStrategy(150.0f, 100.0f, 1000));
addStrategy("Output_V_AB", new SingleValueStrategy(30.0f, 20.0f, 1000));
addStrategy("Output_V_AN", new SingleValueStrategy(30.0f, 30.0f, 1000));
addStrategy("Output_V_BC", new SingleValueStrategy(30.0f, 20.0f, 1000));
addStrategy("Output_V_BN", new SingleValueStrategy(30.0f, 30.0f, 1000));
addStrategy("Output_V_CA", new SingleValueStrategy(30.0f, 20.0f, 1000));
addStrategy("Output_V_CN", new SingleValueStrategy(30.0f, 30.0f, 1000));
}
/**
@@ -139,14 +150,14 @@ State<ModbusIP>* RunningState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
float cb_count = 0.0f;
for (const std::string& cb :cbs){
std::string tag = "";
tag = "Px " + cb;
if (cb == "CB0") continue;
tag = "Px_" + cb;
float cb_status = getPointValue(equipment, tag);
if (static_cast<int>(cb_status)){
if (cb_status == 1.0f){
cb_count += 1.0f;
}
}
Serial.printf("CB_ CLosed = %f \n", cb_count);
int cb_num = 1;
for (const std::string& cb : cbs) {
std::string tag = "";
Strategy_Behavior* strategy = nullptr;
@@ -155,126 +166,224 @@ State<ModbusIP>* RunningState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
float cb_status = getPointValue(equipment, tag);
float percent_load = getPointValue(equipment, "Px Load");
float Rating = getPointValue(equipment, "Px Rating");
float total_load = Rating * (percent_load /100.0f);
float cb_load = total_load / cb_count;
if (static_cast<bool>(cb_status) == 1){
tag = "";
tag = cb + "_V1N";
strategy = getStrategy(tag);
static_cast<SingleValueStrategy*>(strategy)->setSetpoint(270.0f);
tag = "";
tag = cb + "_V2N";
strategy = getStrategy(tag);
static_cast<SingleValueStrategy*>(strategy)->setSetpoint(270.0f);
tag = "";
tag = cb + "_V3N";
strategy = getStrategy(tag);
static_cast<SingleValueStrategy*>(strategy)->setSetpoint(270.0f);
tag = "";
tag = cb + "_V12";
strategy = getStrategy(tag);
static_cast<SingleValueStrategy*>(strategy)->setSetpoint(480.0f);
tag = "";
tag = cb + "_V23";
strategy = getStrategy(tag);
static_cast<SingleValueStrategy*>(strategy)->setSetpoint(480.0f);
tag = "";
tag = cb + "_V31";
strategy = getStrategy(tag);
static_cast<SingleValueStrategy*>(strategy)->setSetpoint(480.0f);
float cb_load = 400.0f * (percent_load /1000.0f);
if (cb_status == 1.0f){
setBitValue(equipment, "CB_Status", cb_num, true);
setBitValue(equipment, "CB_Tripped", cb_num, false);
tag = "";
tag = cb + "_I1";
setPointValue(equipment, tag, total_load);
setPointValue(equipment, tag, cb_load * 1000.0f);
tag = "";
tag = cb + "_I2";
setPointValue(equipment, tag, total_load);
setPointValue(equipment, tag, cb_load * 1000.0f);
tag = "";
tag = cb + "_I3";
setPointValue(equipment, tag, total_load);
setPointValue(equipment, tag, cb_load * 1000.0f);
tag = "";
tag = cb + "_L1KW";
setPointValue(equipment, tag, total_load*1.715f);
tag = cb + "_PF";
setPointValue(equipment, tag, 910.0f);
tag = "";
tag = cb + "_L2KW";
setPointValue(equipment, tag, total_load*1.715f);
tag = "";
tag = cb + "_L3KW";
setPointValue(equipment, tag, total_load*1.715f);
tag = "";
tag = cb + "_L1KVar";
setPointValue(equipment, tag, total_load*1.715*0.9f);
tag = "";
tag = cb + "_L2KVar";
setPointValue(equipment, tag, total_load*1.715*0.9f);
tag = "";
tag = cb + "_L3KVar";
setPointValue(equipment, tag, total_load*1.715*0.9f);
}else{
tag = "";
tag = cb + "_V1N";
strategy = getStrategy(tag);
static_cast<SingleValueStrategy*>(strategy)->setSetpoint(0.0f);
tag = "";
tag = cb + "_V2N";
strategy = getStrategy(tag);
static_cast<SingleValueStrategy*>(strategy)->setSetpoint(0.0f);
tag = "";
tag = cb + "_V3N";
strategy = getStrategy(tag);
static_cast<SingleValueStrategy*>(strategy)->setSetpoint(0.0f);
tag = "";
tag = cb + "_V12";
strategy = getStrategy(tag);
static_cast<SingleValueStrategy*>(strategy)->setSetpoint(0.0f);
tag = "";
tag = cb + "_V23";
strategy = getStrategy(tag);
static_cast<SingleValueStrategy*>(strategy)->setSetpoint(0.0f);
tag = "";
tag = cb + "_V31";
strategy = getStrategy(tag);
static_cast<SingleValueStrategy*>(strategy)->setSetpoint(0.0f);
tag = cb + "_PF";
float pf = getPointValue(equipment, tag);
tag = "";
tag = cb + "_I1";
setPointValue(equipment, tag, total_load);
tag = "";
tag = cb + "_I2";
setPointValue(equipment, tag, total_load);
tag = "";
tag = cb + "_I3";
setPointValue(equipment, tag, total_load);
tag = "";
tag = cb + "_L1KW";
setPointValue(equipment, tag, total_load*0.0f);
tag = cb + "_kW1";
setPointValue(equipment, tag, cb_load * 48000.0f * pf);
float kW1 = getPointValue(equipment, tag);
tag = "";
tag = cb + "_L2KW";
setPointValue(equipment, tag, total_load*0.0f);
tag = cb + "_kW2";
setPointValue(equipment, tag, cb_load * 48000.0f * pf);
float kW2 = getPointValue(equipment, tag);
tag = "";
tag = cb + "_L3KW";
setPointValue(equipment, tag, total_load*0.0f);
tag = cb + "_kW3";
setPointValue(equipment, tag, cb_load * 48000.0f * pf);
float kW3 = getPointValue(equipment, tag);
tag = "";
tag = cb + "_kW";
setPointValue(equipment, tag, ((kW1 + kW2 + kW3) / 3.0f)*1000.0f);
tag = "";
tag = cb + "_kWh";
setPointValue(equipment, tag, 1325.0f);
tag = "";
tag = cb + "_kVA";
setPointValue(equipment, tag, cb_load * 480.0f * 10000.0f);
tag = "";
tag = cb + "_kVA";
setPointValue(equipment, tag, cb_load * 480.0f * 10000.0f);
tag = "";
tag = cb + "_kVA";
setPointValue(equipment, tag, cb_load * 480.0f * 10000.0f);
tag = "";
tag = cb + "_L1KVar";
setPointValue(equipment, tag, total_load*0.0f);
tag = cb + "_kVA1";
float kVA1 = getPointValue(equipment, tag);
tag = "";
tag = cb + "_L2KVar";
setPointValue(equipment, tag, total_load*0.0f);
tag = cb + "_kVA2";
float kVA2 = getPointValue(equipment, tag);
tag = "";
tag = cb + "_L3KVar";
setPointValue(equipment, tag, total_load*0.0f);
tag = cb + "_kVA3";
float kVA3 = getPointValue(equipment, tag);
float kVA = (kVA1 + kVA2 + kVA3) * 1732.0f;
tag = "";
tag = cb + "_kVA";
setPointValue(equipment, tag, kVA);
tag = "";
tag = cb + "_kVAR";
setPointValue(equipment, tag, kVA / pf);
}
else{
if (cb_status == 2.0f){
setBitValue(equipment, "CB_Tripped", cb_num, true);
} else {
setBitValue(equipment, "CB_Tripped", cb_num, false);
}
setBitValue(equipment, "CB_Status", cb_num, false);
tag = "";
tag = cb + "_I1";
setPointValue(equipment, tag, 40.0f);
tag = "";
tag = cb + "_I2";
setPointValue(equipment, tag, 0.0f);
tag = "";
tag = cb + "_I3";
setPointValue(equipment, tag, 40.0f);
tag = "";
tag = cb + "_kVA";
setPointValue(equipment, tag, 150.0f);
tag = "";
tag = cb + "_kVA1";
setPointValue(equipment, tag, 150.0f);
tag = "";
tag = cb + "_kVA2";
setPointValue(equipment, tag, 150.0f);
tag = "";
tag = cb + "_kVA3";
setPointValue(equipment, tag, 150.0f);
tag = "";
tag = cb + "_kVAR";
setPointValue(equipment, tag, 150.0f);
tag = "";
tag = cb + "_kW";
setPointValue(equipment, tag, 150.0f);
tag = "";
tag = cb + "_kW1";
setPointValue(equipment, tag, 150.0f);
tag = "";
tag = cb + "_kW2";
setPointValue(equipment, tag, 150.0f);
tag = "";
tag = cb + "_kW3";
setPointValue(equipment, tag, 150.0f);
tag = "";
tag = cb + "_kWh";
setPointValue(equipment, tag, 0.5f);
tag = "";
tag = cb + "_PF";
setPointValue(equipment, tag, 150.0f);
}
cb_num++;
}
Serial.printf("CB_ CLosed = %f \n", cb_count);
if (cb_count > 0.0f){
Serial.println("At least one breaker closed...");
float percent_load = getPointValue(equipment, "Px Load");
float cb_load = 400.0f * (percent_load /1000.0f);
setPointValue(equipment, "Input_I1", cb_count * cb_load *100.0f);
setPointValue(equipment, "Input_I2", cb_count * cb_load *100.0f);
setPointValue(equipment, "Input_I3", cb_count * cb_load *100.0f);
setPointValue(equipment, "Output_I1", cb_count * cb_load *100.0f);
setPointValue(equipment, "Output_I2", cb_count * cb_load*100.0f);
setPointValue(equipment, "Output_I3", cb_count * cb_load*100.0f);
setPointValue(equipment, "Output_IG", cb_count * 750.0f);
setPointValue(equipment, "Output_IN", cb_count * 482.0f);
float pf = 0.92f;
setPointValue(equipment, "Input_PF", pf * 930.0f);
setPointValue(equipment, "Output_PF", pf);
float i1 = getPointValue(equipment, "Input_I1");
float i2 = getPointValue(equipment, "Input_I2");
float i3 = getPointValue(equipment, "Input_I3");
setPointValue(equipment, "Input_kW", 480.0f * ((i1 + i2 + i3) / 3.0f));
float kW = getPointValue(equipment, "Input_kW");
setPointValue(equipment, "Input_kVA", kW * 1.732f);
setPointValue(equipment, "Output_kVA1", (kW * 1.732f)/3.0f);
setPointValue(equipment, "Output_kVA2", (kW * 1.732f)/3.0f);
setPointValue(equipment, "Output_kVA3", (kW * 1.732f)/3.0f);
setPointValue(equipment, "Input_kVAR", kW * 1.732f* pf);
setPointValue(equipment, "Output_kVAR", kW * 1.732f* pf);
setPointValue(equipment, "Output_kW1", kW /3.0f);
setPointValue(equipment, "Output_kW2", kW /3.0f);
setPointValue(equipment, "Output_kW3", kW /3.0f);
setPointValue(equipment, "Output_kWh", 1423.0f);
setPointValue(equipment, "Input_V_AB", 4800.0f);
setPointValue(equipment, "Input_V_AN", 2700.0f);
setPointValue(equipment, "Input_V_BC", 4800.0f);
setPointValue(equipment, "Input_V_BN", 2700.0f);
setPointValue(equipment, "Input_V_CA", 4800.0f);
setPointValue(equipment, "Input_V_CN", 2700.0f);
setPointValue(equipment, "Input_LL_Avg", 4800.0f);
setPointValue(equipment, "Input_LN_Avg", 2700.0f);
setPointValue(equipment, "Output_V_AB", 4800.0f);
setPointValue(equipment, "Output_V_AN", 2700.0f);
setPointValue(equipment, "Output_V_BC", 4800.0f);
setPointValue(equipment, "Output_V_BN", 2700.0f);
setPointValue(equipment, "Output_V_CA", 4800.0f);
setPointValue(equipment, "Output_V_CN", 2700.0f);
} else {
Serial.println("No breaker closed...");
setPointValue(equipment, "Input_I1", 50.0f);
setPointValue(equipment, "Input_I2", 50.0f);
setPointValue(equipment, "Input_I3", 50.0f);
setPointValue(equipment, "Output_I1", 50.0f);
setPointValue(equipment, "Output_I2", 50.0f);
setPointValue(equipment, "Output_I3", 50.0f);
setPointValue(equipment, "Output_IG", 50.0f);
setPointValue(equipment, "Output_IN", 50.0f);
setPointValue(equipment, "Input_PF", 0.0f);
setPointValue(equipment, "Output_PF", 0.0f);
setPointValue(equipment, "Input_kW", 0.0f);
setPointValue(equipment, "Input_kVA", 0.0f);
setPointValue(equipment, "Output_kVA1", 0.0f);
setPointValue(equipment, "Output_kVA2", 0.0f);
setPointValue(equipment, "Output_kVA3", 0.0f);
setPointValue(equipment, "Input_kVAR", 0.0f);
setPointValue(equipment, "Output_kVAR", 0.0f);
setPointValue(equipment, "Output_kW1", 0.0f);
setPointValue(equipment, "Output_kW2", 0.0f);
setPointValue(equipment, "Output_kW3", 0.0f);
setPointValue(equipment, "Output_kWh", 1.0f);
setPointValue(equipment, "Input_V_AB", 4800.0f);
setPointValue(equipment, "Input_V_AN", 2700.0f);
setPointValue(equipment, "Input_V_BC", 4800.0f);
setPointValue(equipment, "Input_V_BN", 2700.0f);
setPointValue(equipment, "Input_V_CA", 4800.0f);
setPointValue(equipment, "Input_V_CN", 2700.0f);
setPointValue(equipment, "Input_LL_Avg", 4800.0f);
setPointValue(equipment, "Input_LN_Avg", 2700.0f);
setPointValue(equipment, "Output_V_AB", 10.0f);
setPointValue(equipment, "Output_V_AN", 10.0f);
setPointValue(equipment, "Output_V_BC", 10.0f);
setPointValue(equipment, "Output_V_BN", 10.0f);
setPointValue(equipment, "Output_V_CA", 10.0f);
setPointValue(equipment, "Output_V_CN", 10.0f);
}
// Apply any strategies defined for the standby state
_applyStrategies(equipment);
return nullptr;

View File

@@ -79,6 +79,16 @@ template<>
void StandbyState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Standby State...");
setPointValue(equipment, "Input_V_AB", 0.0f);
setPointValue(equipment, "Input_V_AN", 0.0f);
setPointValue(equipment, "Input_V_BC", 0.0f);
setPointValue(equipment, "Input_V_BN", 0.0f);
setPointValue(equipment, "Input_V_CA", 0.0f);
setPointValue(equipment, "Input_V_CN", 0.0f);
setPointValue(equipment, "Input_LL_Avg", 0.0f);
setPointValue(equipment, "Input_LN_Avg", 0.0f);
setPointValue(equipment, "Output_PF", 0.0f);
}
/**

View File

@@ -21,11 +21,11 @@
* @{
*/
#include <ModbusIP_ESP8266.h>
const char *ssid = "wifi_ssid"; /**< @brief The SSID of the WiFi network. */
const char *password = "wifi_password"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(192, 168, 1, 178); /**< @brief The static IP address for the device. */
IPAddress gateway(192, 168, 1, 1); /**< @brief The gateway IP address. */
IPAddress subnet(254, 254, 254, 0); /**< @brief The subnet mask. */
const char *ssid = "QTS_CDR_Arduino"; /**< @brief The SSID of the WiFi network. */
const char *password = "123abc456"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(172, 17, 33, 181); /**< @brief The static IP address for the device. */
IPAddress gateway(172, 17, 33, 1); /**< @brief The gateway IP address. */
IPAddress subnet(255, 255, 255, 0); /**< @brief The subnet mask. */
ModbusIP mb;
#else
@@ -46,8 +46,6 @@
ModbusRTU mb;
#endif
/**
* @defgroup ModbusMapConfig Modbus Map Configuration
* @brief Defines the Modbus register map and related parameters for the emulator.
@@ -64,441 +62,189 @@ modbusMap mb_map[] = {
// Write Registers (as Input Registers - 3X)
//***************************************
{HR, 9, 0, "Px Ctrl"},
{HR, 10, 0, "Px Rating"}, //Watts
{HR, 10, 0, "Px Rating"}, //Amps
{HR, 11, 0, "Px Load"}, //%load
{COIL, 9, 0, "Px_CB0"},
{COIL, 10, 0, "Px_CB1"},
{COIL, 11, 0, "Px_CB2"},
{COIL, 12, 0, "Px_CB3"},
{COIL, 13, 0, "Px_CB4"},
{COIL, 14, 0, "Px_CB5"},
{COIL, 15, 0, "Px_CB6"},
{COIL, 16, 0, "Px_CB7"},
{COIL, 17, 0, "Px_CB8"},
{HR, 19, 0, "Px_Input"},
{HR, 20, 0, "Px_CB1"},
{HR, 21, 0, "Px_CB2"},
{HR, 22, 0, "Px_CB3"},
{HR, 23, 0, "Px_CB4"},
{HR, 24, 0, "Px_CB5"},
{HR, 25, 0, "Px_CB6"},
{HR, 26, 0, "Px_CB7"},
{HR, 27, 0, "Px_CB8"},
{HR, 28, 0, "Px_Output"},
// System Status
{IR_FLOAT, 0, 0, "CB0_V1N" },
{IR_FLOAT, 2, 0, "CB0_V2N" },
{IR_FLOAT, 4, 0, "CB0_V3N" },
{IR_FLOAT, 6, 0, "CB0_I1" },
{IR_FLOAT, 8, 0, "CB0_I2" },
{IR_FLOAT, 10, 0, "CB0_I3" },
{IR_FLOAT, 12, 0, "CB0_L1KW" },
{IR_FLOAT, 14, 0, "CB0_L2KW" },
{IR_FLOAT, 16, 0, "CB0_L3KW" },
{IR_FLOAT, 18, 0, "CB0_L1KVar" },
{IR_FLOAT, 20, 0, "CB0_L2KVar" },
{IR_FLOAT, 22, 0, "CB0_L3KVar" },
{IR_FLOAT, 24, 0, "CB0_L1KVA" },
{IR_FLOAT, 26, 0, "CB0_L2KVA" },
{IR_FLOAT, 28, 0, "CB0_L3KVA" },
{IR_FLOAT, 30, 0, "CB0_L1PF" },
{IR_FLOAT, 32, 0, "CB0_L2PF" },
{IR_FLOAT, 34, 0, "CB0_L3PF" },
{IR_FLOAT, 36, 0, "CB0_V1THD" },
{IR_FLOAT, 38, 0, "CB0_V2THD" },
{IR_FLOAT, 40, 0, "CB0_V3THD" },
{IR_FLOAT, 42, 0, "CB0_I1THD" },
{IR_FLOAT, 44, 0, "CB0_I2THD" },
{IR_FLOAT, 46, 0, "CB0_I3THD" },
{IR_FLOAT, 48, 0, "CB0_I1Kfactor" },
{IR_FLOAT, 50, 0, "CB0_I2Kfactor" },
{IR_FLOAT, 52, 0, "CB0_I3Kfactor" },
{IR_FLOAT, 54, 0, "CB0_I1TDD" },
{IR_FLOAT, 56, 0, "CB0_I2TDD" },
{IR_FLOAT, 58, 0, "CB0_I3TDD" },
{IR_FLOAT, 60, 0, "CB0_V12" },
{IR_FLOAT, 62, 0, "CB0_V23" },
{IR_FLOAT, 64, 0, "CB0_V31" },
{IR_FLOAT, 66, 0, "CB0_TotalKW" },
{IR_FLOAT, 68, 0, "CB0_TotalKVar" },
{IR_FLOAT, 70, 0, "CB0_TotalKVA" },
{IR_FLOAT, 72, 0, "CB0_TotalPF" },
{IR_FLOAT, 74, 0, "CB0_TotalPFLag" },
{IR_FLOAT, 76, 0, "CB0_TotalPFLead" },
{IR_FLOAT, 78, 0, "CB0_TotalKWImport" },
{IR_FLOAT, 80, 0, "CB0_TotalKWExport" },
{IR_FLOAT, 82, 0, "CB0_TotalKVarImport" },
{IR_FLOAT, 84, 0, "CB0_TotalKVarExport" },
{IR_FLOAT, 86, 0, "CB0_LN_Avg" },
{IR_FLOAT, 88, 0, "CB0_LL_Avg" },
{IR_FLOAT, 92, 0, "CB0_TotalKWh" },
// PDU Input
{IR_LONG, 6, 0, "Input_I1" }, //0.01
{IR_LONG, 8, 0, "Input_I2" }, //0.01
{IR_LONG, 10, 0, "Input_I3" }, //0.01
{IR_LONG, 70, 0, "Input_kVA" }, //0.001
{IR_LONG, 68, 0, "Input_KVAR" }, //0.001
{IR_LONG, 66, 0, "Input_kW" }, //0.001
{IR_LONG, 66, 0, "Input_kWh" }, //0.1
{IR_LONG, 72, 0, "Input_PF" }, //0.001
{IR_LONG, 60, 0, "Input_V_AB" }, //0.1
{IR_LONG, 0, 0, "Input_V_AN" }, //0.1
{IR_LONG, 62, 0, "Input_V_BC" }, //0.1
{IR_LONG, 2, 0, "Input_V_BN" }, //0.1
{IR_LONG, 64, 0, "Input_V_CA" }, //0.1
{IR_LONG, 4, 0, "Input_V_CN" }, //0.1
{IR_LONG, 88, 0, "Input_LL_Avg" },//0.1
{IR_LONG, 86, 0, "Input_LN_Avg" },//0.1
// Circuit Breaker 1 (CB1)
{IR_LONG, 106, 0, "CB1_I1" }, //0.01x
{IR_LONG, 108, 0, "CB1_I2" }, //0.01x
{IR_LONG, 110, 0, "CB1_I3" }, //0.01x
{IR_LONG, 170, 0, "CB1_kVA" }, //0.001x
{IR_LONG, 124, 0, "CB1_kVA1" }, //0.001x
{IR_LONG, 126, 0, "CB1_kVA2" }, //0.001x
{IR_LONG, 128, 0, "CB1_kVA3" }, //0.001x
{IR_LONG, 168, 0, "CB1_kVAR" }, //0.001x
{IR_LONG, 166, 0, "CB1_kW" }, //0.001x
{IR_LONG, 112, 0, "CB1_kW1" }, //0.001x
{IR_LONG, 114, 0, "CB1_kW2" }, //0.001x
{IR_LONG, 116, 0, "CB1_kW3" }, //0.001x
{IR_LONG, 1113, 0, "CB1_kWh" },
{IR_LONG, 172, 0, "CB1_PF" }, //0.001x
// Circuit Breaker 1 (OB01)
{IR_FLOAT, 100, 0, "CB1_V1N" },
{IR_FLOAT, 102, 0, "CB1_V2N" },
{IR_FLOAT, 104, 0, "CB1_V3N" },
{IR_FLOAT, 106, 0, "CB1_I1" },
{IR_FLOAT, 108, 0, "CB1_I2" },
{IR_FLOAT, 110, 0, "CB1_I3" },
{IR_FLOAT, 112, 0, "CB1_L1KW" },
{IR_FLOAT, 114, 0, "CB1_L2KW" },
{IR_FLOAT, 116, 0, "CB1_L3KW" },
{IR_FLOAT, 118, 0, "CB1_L1KVar" },
{IR_FLOAT, 120, 0, "CB1_L2KVar" },
{IR_FLOAT, 122, 0, "CB1_L3KVar" },
{IR_FLOAT, 124, 0, "CB1_L1KVA" },
{IR_FLOAT, 126, 0, "CB1_L2KVA" },
{IR_FLOAT, 128, 0, "CB1_L3KVA" },
{IR_FLOAT, 130, 0, "CB1_L1PF" },
{IR_FLOAT, 132, 0, "CB1_L2PF" },
{IR_FLOAT, 134, 0, "CB1_L3PF" },
{IR_FLOAT, 136, 0, "CB1_V1THD" },
{IR_FLOAT, 138, 0, "CB1_V2THD" },
{IR_FLOAT, 140, 0, "CB1_V3THD" },
{IR_FLOAT, 142, 0, "CB1_I1THD" },
{IR_FLOAT, 144, 0, "CB1_I2THD" },
{IR_FLOAT, 146, 0, "CB1_I3THD" },
{IR_FLOAT, 148, 0, "CB1_I1Kfactor" },
{IR_FLOAT, 150, 0, "CB1_I2Kfactor" },
{IR_FLOAT, 152, 0, "CB1_I3Kfactor" },
{IR_FLOAT, 154, 0, "CB1_I1TDD" },
{IR_FLOAT, 156, 0, "CB1_I2TDD" },
{IR_FLOAT, 158, 0, "CB1_I3TDD" },
{IR_FLOAT, 160, 0, "CB1_V12" },
{IR_FLOAT, 162, 0, "CB1_V23" },
{IR_FLOAT, 164, 0, "CB1_V31" },
{IR_FLOAT, 166, 0, "CB1_TotalKW" },
{IR_FLOAT, 168, 0, "CB1_TotalKVar" },
{IR_FLOAT, 170, 0, "CB1_TotalKVA" },
{IR_FLOAT, 172, 0, "CB1_TotalPF" },
{IR_FLOAT, 174, 0, "CB1_TotalPFLag" },
{IR_FLOAT, 176, 0, "CB1_TotalPFLead" },
{IR_FLOAT, 178, 0, "CB1_TotalKWImport" },
{IR_FLOAT, 180, 0, "CB1_TotalKWExport" },
{IR_FLOAT, 182, 0, "CB1_TotalKVarImport" },
{IR_FLOAT, 184, 0, "CB1_TotalKVarExport" },
{IR_FLOAT, 186, 0, "CB1_LN_Avg" },
{IR_FLOAT, 188, 0, "CB1_LL_Avg" },
// Circuit Breaker 2 (CB1)
{IR_LONG, 206, 0, "CB2_I1" }, //0.01x
{IR_LONG, 208, 0, "CB2_I2" }, //0.01x
{IR_LONG, 210, 0, "CB2_I3" }, //0.01x
{IR_LONG, 270, 0, "CB2_kVA" }, //0.001x
{IR_LONG, 224, 0, "CB2_kVA1" }, //0.001x
{IR_LONG, 226, 0, "CB2_kVA2" }, //0.001x
{IR_LONG, 228, 0, "CB2_kVA3" }, //0.001x
{IR_LONG, 268, 0, "CB2_kVAR" }, //0.001x
{IR_LONG, 266, 0, "CB2_kW" }, //0.001x
{IR_LONG, 212, 0, "CB2_kW1" }, //0.001x
{IR_LONG, 214, 0, "CB2_kW2" }, //0.001x
{IR_LONG, 216, 0, "CB2_kW3" }, //0.001x
{IR_LONG, 1168, 0, "CB2_kWh" },
{IR_LONG, 272, 0, "CB2_PF" }, //0.001x
// Circuit Breaker 2 (OB02)
{IR_FLOAT, 200, 0, "CB2_V1N" },
{IR_FLOAT, 202, 0, "CB2_V2N" },
{IR_FLOAT, 204, 0, "CB2_V3N" },
{IR_FLOAT, 206, 0, "CB2_I1" },
{IR_FLOAT, 208, 0, "CB2_I2" },
{IR_FLOAT, 210, 0, "CB2_I3" },
{IR_FLOAT, 212, 0, "CB2_L1KW" },
{IR_FLOAT, 214, 0, "CB2_L2KW" },
{IR_FLOAT, 216, 0, "CB2_L3KW" },
{IR_FLOAT, 218, 0, "CB2_L1KVar" },
{IR_FLOAT, 220, 0, "CB2_L2KVar" },
{IR_FLOAT, 222, 0, "CB2_L3KVar" },
{IR_FLOAT, 224, 0, "CB2_L1KVA" },
{IR_FLOAT, 226, 0, "CB2_L2KVA" },
{IR_FLOAT, 228, 0, "CB2_L3KVA" },
{IR_FLOAT, 230, 0, "CB2_L1PF" },
{IR_FLOAT, 232, 0, "CB2_L2PF" },
{IR_FLOAT, 234, 0, "CB2_L3PF" },
{IR_FLOAT, 236, 0, "CB2_V1THD" },
{IR_FLOAT, 238, 0, "CB2_V2THD" },
{IR_FLOAT, 240, 0, "CB2_V3THD" },
{IR_FLOAT, 242, 0, "CB2_I1THD" },
{IR_FLOAT, 244, 0, "CB2_I2THD" },
{IR_FLOAT, 246, 0, "CB2_I3THD" },
{IR_FLOAT, 248, 0, "CB2_I1Kfactor" },
{IR_FLOAT, 250, 0, "CB2_I2Kfactor" },
{IR_FLOAT, 252, 0, "CB2_I3Kfactor" },
{IR_FLOAT, 254, 0, "CB2_I1TDD" },
{IR_FLOAT, 256, 0, "CB2_I2TDD" },
{IR_FLOAT, 258, 0, "CB2_I3TDD" },
{IR_FLOAT, 260, 0, "CB2_V12" },
{IR_FLOAT, 262, 0, "CB2_V23" },
{IR_FLOAT, 264, 0, "CB2_V31" },
{IR_FLOAT, 266, 0, "CB2_TotalKW" },
{IR_FLOAT, 268, 0, "CB2_TotalKVar" },
{IR_FLOAT, 270, 0, "CB2_TotalKVA" },
{IR_FLOAT, 272, 0, "CB2_TotalPF" },
{IR_FLOAT, 274, 0, "CB2_TotalPFLag" },
{IR_FLOAT, 276, 0, "CB2_TotalPFLead" },
{IR_FLOAT, 278, 0, "CB2_TotalKWImport" },
{IR_FLOAT, 280, 0, "CB2_TotalKWExport" },
{IR_FLOAT, 282, 0, "CB2_TotalKVarImport" },
{IR_FLOAT, 284, 0, "CB2_TotalKVarExport" },
{IR_FLOAT, 286, 0, "CB2_LN_Avg" },
{IR_FLOAT, 288, 0, "CB2_LL_Avg" },
// Circuit Breaker 3 (CB1)
{IR_LONG, 306, 0, "CB3_I1" }, //0.01x
{IR_LONG, 308, 0, "CB3_I2" }, //0.01x
{IR_LONG, 310, 0, "CB3_I3" }, //0.01x
{IR_LONG, 370, 0, "CB3_kVA" }, //0.001x
{IR_LONG, 324, 0, "CB3_kVA1" }, //0.001x
{IR_LONG, 326, 0, "CB3_kVA2" }, //0.001x
{IR_LONG, 328, 0, "CB3_kVA3" }, //0.001x
{IR_LONG, 368, 0, "CB3_kVAR" }, //0.001x
{IR_LONG, 366, 0, "CB3_kW" }, //0.001x
{IR_LONG, 312, 0, "CB3_kW1" }, //0.001x
{IR_LONG, 314, 0, "CB3_kW2" }, //0.001x
{IR_LONG, 316, 0, "CB3_kW3" }, //0.001x
{IR_LONG, 1223, 0, "CB3_kWh" },
{IR_LONG, 372, 0, "CB3_PF" }, //0.001x
// Circuit Breaker 3 (OB03)
{IR_FLOAT, 300, 0, "CB3_V1N" },
{IR_FLOAT, 302, 0, "CB3_V2N" },
{IR_FLOAT, 304, 0, "CB3_V3N" },
{IR_FLOAT, 306, 0, "CB3_I1" },
{IR_FLOAT, 308, 0, "CB3_I2" },
{IR_FLOAT, 310, 0, "CB3_I3" },
{IR_FLOAT, 312, 0, "CB3_L1KW" },
{IR_FLOAT, 314, 0, "CB3_L2KW" },
{IR_FLOAT, 316, 0, "CB3_L3KW" },
{IR_FLOAT, 318, 0, "CB3_L1KVar" },
{IR_FLOAT, 320, 0, "CB3_L2KVar" },
{IR_FLOAT, 322, 0, "CB3_L3KVar" },
{IR_FLOAT, 324, 0, "CB3_L1KVA" },
{IR_FLOAT, 326, 0, "CB3_L2KVA" },
{IR_FLOAT, 328, 0, "CB3_L3KVA" },
{IR_FLOAT, 330, 0, "CB3_L1PF" },
{IR_FLOAT, 332, 0, "CB3_L2PF" },
{IR_FLOAT, 334, 0, "CB3_L3PF" },
{IR_FLOAT, 336, 0, "CB3_V1THD" },
{IR_FLOAT, 338, 0, "CB3_V2THD" },
{IR_FLOAT, 340, 0, "CB3_V3THD" },
{IR_FLOAT, 342, 0, "CB3_I1THD" },
{IR_FLOAT, 344, 0, "CB3_I2THD" },
{IR_FLOAT, 346, 0, "CB3_I3THD" },
{IR_FLOAT, 348, 0, "CB3_I1Kfactor" },
{IR_FLOAT, 350, 0, "CB3_I2Kfactor" },
{IR_FLOAT, 352, 0, "CB3_I3Kfactor" },
{IR_FLOAT, 354, 0, "CB3_I1TDD" },
{IR_FLOAT, 356, 0, "CB3_I2TDD" },
{IR_FLOAT, 358, 0, "CB3_I3TDD" },
{IR_FLOAT, 360, 0, "CB3_V12" },
{IR_FLOAT, 362, 0, "CB3_V23" },
{IR_FLOAT, 364, 0, "CB3_V31" },
{IR_FLOAT, 366, 0, "CB3_TotalKW" },
{IR_FLOAT, 368, 0, "CB3_TotalKVar" },
{IR_FLOAT, 370, 0, "CB3_TotalKVA" },
{IR_FLOAT, 372, 0, "CB3_TotalPF" },
{IR_FLOAT, 374, 0, "CB3_TotalPFLag" },
{IR_FLOAT, 376, 0, "CB3_TotalPFLead" },
{IR_FLOAT, 378, 0, "CB3_TotalKWImport" },
{IR_FLOAT, 380, 0, "CB3_TotalKWExport" },
{IR_FLOAT, 382, 0, "CB3_TotalKVarImport" },
{IR_FLOAT, 384, 0, "CB3_TotalKVarExport" },
{IR_FLOAT, 386, 0, "CB3_LN_Avg" },
{IR_FLOAT, 388, 0, "CB3_LL_Avg" },
// Circuit Breaker 4 (CB1)
{IR_LONG, 406, 0, "CB4_I1" }, //0.01x
{IR_LONG, 408, 0, "CB4_I2" }, //0.01x
{IR_LONG, 410, 0, "CB4_I3" }, //0.01x
{IR_LONG, 470, 0, "CB4_kVA" }, //0.001x
{IR_LONG, 424, 0, "CB4_kVA1" }, //0.001x
{IR_LONG, 426, 0, "CB4_kVA2" }, //0.001x
{IR_LONG, 428, 0, "CB4_kVA3" }, //0.001x
{IR_LONG, 468, 0, "CB4_kVAR" }, //0.001x
{IR_LONG, 466, 0, "CB4_kW" }, //0.001x
{IR_LONG, 412, 0, "CB4_kW1" }, //0.001x
{IR_LONG, 414, 0, "CB4_kW2" }, //0.001x
{IR_LONG, 416, 0, "CB4_kW3" }, //0.001x
{IR_LONG, 1278, 0, "CB4_kWh" },
{IR_LONG, 472, 0, "CB4_PF" }, //0.001x
// Circuit Breaker 4 (OB04)
{IR_FLOAT, 400, 0, "CB4_V1N" },
{IR_FLOAT, 402, 0, "CB4_V2N" },
{IR_FLOAT, 404, 0, "CB4_V3N" },
{IR_FLOAT, 406, 0, "CB4_I1" },
{IR_FLOAT, 408, 0, "CB4_I2" },
{IR_FLOAT, 410, 0, "CB4_I3" },
{IR_FLOAT, 412, 0, "CB4_L1KW" },
{IR_FLOAT, 414, 0, "CB4_L2KW" },
{IR_FLOAT, 416, 0, "CB4_L3KW" },
{IR_FLOAT, 418, 0, "CB4_L1KVar" },
{IR_FLOAT, 420, 0, "CB4_L2KVar" },
{IR_FLOAT, 422, 0, "CB4_L3KVar" },
{IR_FLOAT, 424, 0, "CB4_L1KVA" },
{IR_FLOAT, 426, 0, "CB4_L2KVA" },
{IR_FLOAT, 428, 0, "CB4_L3KVA" },
{IR_FLOAT, 430, 0, "CB4_L1PF" },
{IR_FLOAT, 432, 0, "CB4_L2PF" },
{IR_FLOAT, 434, 0, "CB4_L3PF" },
{IR_FLOAT, 436, 0, "CB4_V1THD" },
{IR_FLOAT, 438, 0, "CB4_V2THD" },
{IR_FLOAT, 440, 0, "CB4_V3THD" },
{IR_FLOAT, 442, 0, "CB4_I1THD" },
{IR_FLOAT, 444, 0, "CB4_I2THD" },
{IR_FLOAT, 446, 0, "CB4_I3THD" },
{IR_FLOAT, 448, 0, "CB4_I1Kfactor" },
{IR_FLOAT, 450, 0, "CB4_I2Kfactor" },
{IR_FLOAT, 452, 0, "CB4_I3Kfactor" },
{IR_FLOAT, 454, 0, "CB4_I1TDD" },
{IR_FLOAT, 456, 0, "CB4_I2TDD" },
{IR_FLOAT, 458, 0, "CB4_I3TDD" },
{IR_FLOAT, 460, 0, "CB4_V12" },
{IR_FLOAT, 462, 0, "CB4_V23" },
{IR_FLOAT, 464, 0, "CB4_V31" },
{IR_FLOAT, 466, 0, "CB4_TotalKW" },
{IR_FLOAT, 468, 0, "CB4_TotalKVar" },
{IR_FLOAT, 470, 0, "CB4_TotalKVA" },
{IR_FLOAT, 472, 0, "CB4_TotalPF" },
{IR_FLOAT, 474, 0, "CB4_TotalPFLag" },
{IR_FLOAT, 476, 0, "CB4_TotalPFLead" },
{IR_FLOAT, 478, 0, "CB4_TotalKWImport" },
{IR_FLOAT, 480, 0, "CB4_TotalKWExport" },
{IR_FLOAT, 482, 0, "CB4_TotalKVarImport" },
{IR_FLOAT, 484, 0, "CB4_TotalKVarExport" },
{IR_FLOAT, 486, 0, "CB4_LN_Avg" },
{IR_FLOAT, 488, 0, "CB4_LL_Avg" },
// Circuit Breaker 5 (CB1)
{IR_LONG, 506, 0, "CB5_I1" }, //0.01x
{IR_LONG, 508, 0, "CB5_I2" }, //0.01x
{IR_LONG, 510, 0, "CB5_I3" }, //0.01x
{IR_LONG, 570, 0, "CB5_kVA" }, //0.001x
{IR_LONG, 524, 0, "CB5_kVA1" }, //0.001x
{IR_LONG, 526, 0, "CB5_kVA2" }, //0.001x
{IR_LONG, 528, 0, "CB5_kVA3" }, //0.001x
{IR_LONG, 568, 0, "CB5_kVAR" }, //0.001x
{IR_LONG, 566, 0, "CB5_kW" }, //0.001x
{IR_LONG, 512, 0, "CB5_kW1" }, //0.001x
{IR_LONG, 514, 0, "CB5_kW2" }, //0.001x
{IR_LONG, 516, 0, "CB5_kW3" }, //0.001x
{IR_LONG, 1333, 0, "CB5_kWh" },
{IR_LONG, 572, 0, "CB5_PF" }, //0.001x
// Circuit Breaker 5 (OB05)
{IR_FLOAT, 500, 0, "CB5_V1N" },
{IR_FLOAT, 502, 0, "CB5_V2N" },
{IR_FLOAT, 504, 0, "CB5_V3N" },
{IR_FLOAT, 506, 0, "CB5_I1" },
{IR_FLOAT, 508, 0, "CB5_I2" },
{IR_FLOAT, 510, 0, "CB5_I3" },
{IR_FLOAT, 512, 0, "CB5_L1KW" },
{IR_FLOAT, 514, 0, "CB5_L2KW" },
{IR_FLOAT, 516, 0, "CB5_L3KW" },
{IR_FLOAT, 518, 0, "CB5_L1KVar" },
{IR_FLOAT, 520, 0, "CB5_L2KVar" },
{IR_FLOAT, 522, 0, "CB5_L3KVar" },
{IR_FLOAT, 524, 0, "CB5_L1KVA" },
{IR_FLOAT, 526, 0, "CB5_L2KVA" },
{IR_FLOAT, 528, 0, "CB5_L3KVA" },
{IR_FLOAT, 530, 0, "CB5_L1PF" },
{IR_FLOAT, 532, 0, "CB5_L2PF" },
{IR_FLOAT, 534, 0, "CB5_L3PF" },
{IR_FLOAT, 536, 0, "CB5_V1THD" },
{IR_FLOAT, 538, 0, "CB5_V2THD" },
{IR_FLOAT, 540, 0, "CB5_V3THD" },
{IR_FLOAT, 542, 0, "CB5_I1THD" },
{IR_FLOAT, 544, 0, "CB5_I2THD" },
{IR_FLOAT, 546, 0, "CB5_I3THD" },
{IR_FLOAT, 548, 0, "CB5_I1Kfactor" },
{IR_FLOAT, 550, 0, "CB5_I2Kfactor" },
{IR_FLOAT, 552, 0, "CB5_I3Kfactor" },
{IR_FLOAT, 554, 0, "CB5_I1TDD" },
{IR_FLOAT, 556, 0, "CB5_I2TDD" },
{IR_FLOAT, 558, 0, "CB5_I3TDD" },
{IR_FLOAT, 560, 0, "CB5_V12" },
{IR_FLOAT, 562, 0, "CB5_V23" },
{IR_FLOAT, 564, 0, "CB5_V31" },
{IR_FLOAT, 566, 0, "CB5_TotalKW" },
{IR_FLOAT, 568, 0, "CB5_TotalKVar" },
{IR_FLOAT, 570, 0, "CB5_TotalKVA" },
{IR_FLOAT, 572, 0, "CB5_TotalPF" },
{IR_FLOAT, 574, 0, "CB5_TotalPFLag" },
{IR_FLOAT, 576, 0, "CB5_TotalPFLead" },
{IR_FLOAT, 578, 0, "CB5_TotalKWImport" },
{IR_FLOAT, 580, 0, "CB5_TotalKWExport" },
{IR_FLOAT, 582, 0, "CB5_TotalKVarImport" },
{IR_FLOAT, 584, 0, "CB5_TotalKVarExport" },
{IR_FLOAT, 586, 0, "CB5_LN_Avg" },
{IR_FLOAT, 588, 0, "CB5_LL_Avg" },
// Circuit Breaker 6 (CB1)
{IR_LONG, 606, 0, "CB6_I1" }, //0.01x
{IR_LONG, 608, 0, "CB6_I2" }, //0.01x
{IR_LONG, 610, 0, "CB6_I3" }, //0.01x
{IR_LONG, 670, 0, "CB6_kVA" }, //0.001x
{IR_LONG, 624, 0, "CB6_kVA1" }, //0.001x
{IR_LONG, 626, 0, "CB6_kVA2" }, //0.001x
{IR_LONG, 628, 0, "CB6_kVA3" }, //0.001x
{IR_LONG, 668, 0, "CB6_kVAR" }, //0.001x
{IR_LONG, 666, 0, "CB6_kW" }, //0.001x
{IR_LONG, 612, 0, "CB6_kW1" }, //0.001x
{IR_LONG, 614, 0, "CB6_kW2" }, //0.001x
{IR_LONG, 616, 0, "CB6_kW3" }, //0.001x
{IR_LONG, 1388, 0, "CB6_kWh" },
{IR_LONG, 672, 0, "CB6_PF" }, //0.001x
// Circuit Breaker 6 (OB06)
{IR_FLOAT, 600, 0, "CB6_V1N" },
{IR_FLOAT, 602, 0, "CB6_V2N" },
{IR_FLOAT, 604, 0, "CB6_V3N" },
{IR_FLOAT, 606, 0, "CB6_I1" },
{IR_FLOAT, 608, 0, "CB6_I2" },
{IR_FLOAT, 610, 0, "CB6_I3" },
{IR_FLOAT, 612, 0, "CB6_L1KW" },
{IR_FLOAT, 614, 0, "CB6_L2KW" },
{IR_FLOAT, 616, 0, "CB6_L3KW" },
{IR_FLOAT, 618, 0, "CB6_L1KVar" },
{IR_FLOAT, 620, 0, "CB6_L2KVar" },
{IR_FLOAT, 622, 0, "CB6_L3KVar" },
{IR_FLOAT, 624, 0, "CB6_L1KVA" },
{IR_FLOAT, 626, 0, "CB6_L2KVA" },
{IR_FLOAT, 628, 0, "CB6_L3KVA" },
{IR_FLOAT, 630, 0, "CB6_L1PF" },
{IR_FLOAT, 632, 0, "CB6_L2PF" },
{IR_FLOAT, 634, 0, "CB6_L3PF" },
{IR_FLOAT, 636, 0, "CB6_V1THD" },
{IR_FLOAT, 638, 0, "CB6_V2THD" },
{IR_FLOAT, 640, 0, "CB6_V3THD" },
{IR_FLOAT, 642, 0, "CB6_I1THD" },
{IR_FLOAT, 644, 0, "CB6_I2THD" },
{IR_FLOAT, 646, 0, "CB6_I3THD" },
{IR_FLOAT, 648, 0, "CB6_I1Kfactor" },
{IR_FLOAT, 650, 0, "CB6_I2Kfactor" },
{IR_FLOAT, 652, 0, "CB6_I3Kfactor" },
{IR_FLOAT, 654, 0, "CB6_I1TDD" },
{IR_FLOAT, 656, 0, "CB6_I2TDD" },
{IR_FLOAT, 658, 0, "CB6_I3TDD" },
{IR_FLOAT, 660, 0, "CB6_V12" },
{IR_FLOAT, 662, 0, "CB6_V23" },
{IR_FLOAT, 664, 0, "CB6_V31" },
{IR_FLOAT, 666, 0, "CB6_TotalKW" },
{IR_FLOAT, 668, 0, "CB6_TotalKVar" },
{IR_FLOAT, 670, 0, "CB6_TotalKVA" },
{IR_FLOAT, 672, 0, "CB6_TotalPF" },
{IR_FLOAT, 674, 0, "CB6_TotalPFLag" },
{IR_FLOAT, 676, 0, "CB6_TotalPFLead" },
{IR_FLOAT, 678, 0, "CB6_TotalKWImport" },
{IR_FLOAT, 680, 0, "CB6_TotalKWExport" },
{IR_FLOAT, 682, 0, "CB6_TotalKVarImport" },
{IR_FLOAT, 684, 0, "CB6_TotalKVarExport" },
{IR_FLOAT, 686, 0, "CB6_LN_Avg" },
{IR_FLOAT, 688, 0, "CB6_LL_Avg" },
// Circuit Breaker 7 (OB07)
{IR_FLOAT, 700, 0, "CB7_V1N" },
{IR_FLOAT, 702, 0, "CB7_V2N" },
{IR_FLOAT, 704, 0, "CB7_V3N" },
{IR_FLOAT, 706, 0, "CB7_I1" },
{IR_FLOAT, 708, 0, "CB7_I2" },
{IR_FLOAT, 710, 0, "CB7_I3" },
{IR_FLOAT, 712, 0, "CB7_L1KW" },
{IR_FLOAT, 714, 0, "CB7_L2KW" },
{IR_FLOAT, 716, 0, "CB7_L3KW" },
{IR_FLOAT, 718, 0, "CB7_L1KVar" },
{IR_FLOAT, 720, 0, "CB7_L2KVar" },
{IR_FLOAT, 722, 0, "CB7_L3KVar" },
{IR_FLOAT, 724, 0, "CB7_L1KVA" },
{IR_FLOAT, 726, 0, "CB7_L2KVA" },
{IR_FLOAT, 728, 0, "CB7_L3KVA" },
{IR_FLOAT, 730, 0, "CB7_L1PF" },
{IR_FLOAT, 732, 0, "CB7_L2PF" },
{IR_FLOAT, 734, 0, "CB7_L3PF" },
{IR_FLOAT, 736, 0, "CB7_V1THD" },
{IR_FLOAT, 738, 0, "CB7_V2THD" },
{IR_FLOAT, 740, 0, "CB7_V3THD" },
{IR_FLOAT, 742, 0, "CB7_I1THD" },
{IR_FLOAT, 744, 0, "CB7_I2THD" },
{IR_FLOAT, 746, 0, "CB7_I3THD" },
{IR_FLOAT, 748, 0, "CB7_I1Kfactor" },
{IR_FLOAT, 750, 0, "CB7_I2Kfactor" },
{IR_FLOAT, 752, 0, "CB7_I3Kfactor" },
{IR_FLOAT, 754, 0, "CB7_I1TDD" },
{IR_FLOAT, 756, 0, "CB7_I2TDD" },
{IR_FLOAT, 758, 0, "CB7_I3TDD" },
{IR_FLOAT, 760, 0, "CB7_V12" },
{IR_FLOAT, 762, 0, "CB7_V23" },
{IR_FLOAT, 764, 0, "CB7_V31" },
{IR_FLOAT, 766, 0, "CB7_TotalKW" },
{IR_FLOAT, 768, 0, "CB7_TotalKVar" },
{IR_FLOAT, 770, 0, "CB7_TotalKVA" },
{IR_FLOAT, 772, 0, "CB7_TotalPF" },
{IR_FLOAT, 774, 0, "CB7_TotalPFLag" },
{IR_FLOAT, 776, 0, "CB7_TotalPFLead" },
{IR_FLOAT, 778, 0, "CB7_TotalKWImport" },
{IR_FLOAT, 780, 0, "CB7_TotalKWExport" },
{IR_FLOAT, 782, 0, "CB7_TotalKVarImport" },
{IR_FLOAT, 784, 0, "CB7_TotalKVarExport" },
{IR_FLOAT, 786, 0, "CB7_LN_Avg" },
{IR_FLOAT, 788, 0, "CB7_LL_Avg" },
// Circuit Breaker 8 (OB08)
{IR_FLOAT, 800, 0, "CB8_V1N" },
{IR_FLOAT, 802, 0, "CB8_V2N" },
{IR_FLOAT, 804, 0, "CB8_V3N" },
{IR_FLOAT, 806, 0, "CB8_I1" },
{IR_FLOAT, 808, 0, "CB8_I2" },
{IR_FLOAT, 810, 0, "CB8_I3" },
{IR_FLOAT, 812, 0, "CB8_L1KW" },
{IR_FLOAT, 814, 0, "CB8_L2KW" },
{IR_FLOAT, 816, 0, "CB8_L3KW" },
{IR_FLOAT, 818, 0, "CB8_L1KVar" },
{IR_FLOAT, 820, 0, "CB8_L2KVar" },
{IR_FLOAT, 822, 0, "CB8_L3KVar" },
{IR_FLOAT, 824, 0, "CB8_L1KVA" },
{IR_FLOAT, 826, 0, "CB8_L2KVA" },
{IR_FLOAT, 828, 0, "CB8_L3KVA" },
{IR_FLOAT, 830, 0, "CB8_L1PF" },
{IR_FLOAT, 832, 0, "CB8_L2PF" },
{IR_FLOAT, 834, 0, "CB8_L3PF" },
{IR_FLOAT, 836, 0, "CB8_V1THD" },
{IR_FLOAT, 838, 0, "CB8_V2THD" },
{IR_FLOAT, 840, 0, "CB8_V3THD" },
{IR_FLOAT, 842, 0, "CB8_I1THD" },
{IR_FLOAT, 844, 0, "CB8_I2THD" },
{IR_FLOAT, 846, 0, "CB8_I3THD" },
{IR_FLOAT, 848, 0, "CB8_I1Kfactor" },
{IR_FLOAT, 850, 0, "CB8_I2Kfactor" },
{IR_FLOAT, 852, 0, "CB8_I3Kfactor" },
{IR_FLOAT, 854, 0, "CB8_I1TDD" },
{IR_FLOAT, 856, 0, "CB8_I2TDD" },
{IR_FLOAT, 858, 0, "CB8_I3TDD" },
{IR_FLOAT, 860, 0, "CB8_V12" },
{IR_FLOAT, 862, 0, "CB8_V23" },
{IR_FLOAT, 864, 0, "CB8_V31" },
{IR_FLOAT, 866, 0, "CB8_TotalKW" },
{IR_FLOAT, 868, 0, "CB8_TotalKVar" },
{IR_FLOAT, 870, 0, "CB8_TotalKVA" },
{IR_FLOAT, 872, 0, "CB8_TotalPF" },
{IR_FLOAT, 874, 0, "CB8_TotalPFLag" },
{IR_FLOAT, 876, 0, "CB8_TotalPFLead" },
{IR_FLOAT, 878, 0, "CB8_TotalKWImport" },
{IR_FLOAT, 880, 0, "CB8_TotalKWExport" },
{IR_FLOAT, 882, 0, "CB8_TotalKVarImport" },
{IR_FLOAT, 884, 0, "CB8_TotalKVarExport" },
{IR_FLOAT, 886, 0, "CB8_LN_Avg" },
{IR_FLOAT, 888, 0, "CB8_LL_Avg" },
// Circuit Breaker 7 (CB1)
{IR_LONG, 706, 0, "CB7_I1" }, //0.01x
{IR_LONG, 708, 0, "CB7_I2" }, //0.01x
{IR_LONG, 710, 0, "CB7_I3" }, //0.01x
{IR_LONG, 770, 0, "CB7_kVA" }, //0.001x
{IR_LONG, 724, 0, "CB7_kVA1" }, //0.001x
{IR_LONG, 726, 0, "CB7_kVA2" }, //0.001x
{IR_LONG, 728, 0, "CB7_kVA3" }, //0.001x
{IR_LONG, 768, 0, "CB7_kVAR" }, //0.001x
{IR_LONG, 766, 0, "CB7_kW" }, //0.001x
{IR_LONG, 712, 0, "CB7_kW1" }, //0.001x
{IR_LONG, 714, 0, "CB7_kW2" }, //0.001x
{IR_LONG, 716, 0, "CB7_kW3" }, //0.001x
{IR_LONG, 1443, 0, "CB7_kWh" },
{IR_LONG, 772, 0, "CB7_PF" }, //0.001x
// Circuit Breaker 8 (CB1)
{IR_LONG, 806, 0, "CB8_I1" }, //0.01x
{IR_LONG, 808, 0, "CB8_I2" }, //0.01x
{IR_LONG, 810, 0, "CB8_I3" }, //0.01x
{IR_LONG, 870, 0, "CB8_kVA" }, //0.001x
{IR_LONG, 824, 0, "CB8_kVA1" }, //0.001x
{IR_LONG, 826, 0, "CB8_kVA2" }, //0.001x
{IR_LONG, 828, 0, "CB8_kVA3" }, //0.001x
{IR_LONG, 868, 0, "CB8_kVAR" }, //0.001x
{IR_LONG, 866, 0, "CB8_kW" }, //0.001x
{IR_LONG, 812, 0, "CB8_kW1" }, //0.001x
{IR_LONG, 814, 0, "CB8_kW2" }, //0.001x
{IR_LONG, 816, 0, "CB8_kW3" }, //0.001x
{IR_LONG, 1498, 0, "CB8_kWh" },
{IR_LONG, 872, 0, "CB8_PF" }, //0.001x
// PDU Output
{IR_LONG, 906, 0, "Output_I1" }, //0.01x
{IR_LONG, 908, 0, "Output_I2" },
{IR_LONG, 910, 0, "Output_I3" },
{IR_LONG, 1068, 0, "Output_IG" },
{IR_LONG, 1066, 0, "Output_IN" },
{IR_LONG, 924, 0, "Output_kVA1" }, //0.001
{IR_LONG, 926, 0, "Output_kVA2" },
{IR_LONG, 928, 0, "Output_kVA3" },
{IR_LONG, 968, 0, "Output_kVAR" }, //0.001
{IR_LONG, 912, 0, "Output_kW1" }, //0.001x
{IR_LONG, 914, 0, "Output_kW2" },
{IR_LONG, 916, 0, "Output_kW3" },
{IR_LONG, 1086, 0, "Output_kWh" },
{IR_LONG, 1091, 0, "Output_PF" }, //0.001
{IR_LONG, 960, 0, "Output_V_AB" },
{IR_LONG, 900, 0, "Output_V_AN" }, //0.01x
{IR_LONG, 962, 0, "Output_V_BC" },
{IR_LONG, 902, 0, "Output_V_BN" },
{IR_LONG, 964, 0, "Output_V_CA" },
{IR_LONG, 904, 0, "Output_V_CN" },
{IR, 1550, 0, "CB_Status" },
{IR, 1551, 0, "CB_Tripped" },
};
//Size of modbus map used in FOR cycles, automatically calculated.

View File

@@ -43,7 +43,7 @@ RunningState<ModbusIP>::RunningState() {
addStrategy("Volts CA", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("PF", new SingleValueStrategy(0.9f, 0.05f, 1000));
addStrategy("Frequency", new SingleValueStrategy(60.0f, 0.7f, 1000));
addStrategy("Amps A", new SingleValueStrategy(1.0f, 10.0f, 1000));
addStrategy("Amps B", new SingleValueStrategy(1.0f, 10.0f, 1000));
addStrategy("Amps C", new SingleValueStrategy(1.0f, 10.0f, 1000));

View File

@@ -87,6 +87,7 @@ void StandbyState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
setPointValue(equipment, "Amps C", 0.0f);
setPointValue(equipment, "kW", 0.0f);
setPointValue(equipment, "kVA", 0.0f);
setPointValue(equipment, "Frequency", 0.0f);
}
/**

View File

@@ -23,8 +23,8 @@
#include <ModbusIP_ESP8266.h>
const char *ssid = "QTS_CDR_Arduino"; /**< @brief The SSID of the WiFi network. */
const char *password = "123abc456"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(172, 17, 30, 241); /**< @brief The static IP address for the device. */
IPAddress gateway(172, 17, 30, 1); /**< @brief The gateway IP address. */
IPAddress local_IP(172, 17, 33, 174); /**< @brief The static IP address for the device. */
IPAddress gateway(172, 17, 33, 1); /**< @brief The gateway IP address. */
IPAddress subnet(255, 255, 255, 0); /**< @brief The subnet mask. */
ModbusIP mb;

View File

@@ -40,31 +40,32 @@
*/
template<>
BatteryState<ModbusIP>::BatteryState() {
addStrategy("System Output RMS A-B", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("System Output RMS B-C", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("System Output RMS C-A", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("System Output RMS A-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("System Output RMS B-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("System Output RMS C-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("System Output RMS A-B", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("System Output RMS B-C", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("System Output RMS C-A", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("System Output RMS A-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("System Output RMS B-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("System Output RMS C-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("System Output RMS Current Phase A", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output RMS Current Phase B", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output RMS Current Phase C", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output RMS Current Phase A", new RampStrategy(10.0f, 50.0f, 1000));
addStrategy("System Output RMS Current Phase B", new RampStrategy(10.0f, 50.0f, 1000));
addStrategy("System Output RMS Current Phase C", new RampStrategy(10.0f, 50.0f, 1000));
addStrategy("System Output Frequency", new SingleValueStrategy(60.0F, 2.0f, 1000));
addStrategy("System Output Power Factor Phs A", new SingleValueStrategy(93.0F, 5.0f, 1000));
addStrategy("System Output Power Factor Phs B", new SingleValueStrategy(93.0F, 5.0f, 1000));
addStrategy("System Output Power Factor Phs C", new SingleValueStrategy(93.0F, 5.0f, 1000));
addStrategy("System Output Power Factor Phs A", new SingleValueStrategy(93.0f, 5.0f, 1000));
addStrategy("System Output Power Factor Phs B", new SingleValueStrategy(93.0f, 5.0f, 1000));
addStrategy("System Output Power Factor Phs C", new SingleValueStrategy(93.0f, 5.0f, 1000));
addStrategy("System Output Power Phase A", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output Power Phase B", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output Power Phase C", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output Apparent Power Phase A", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output Apparent Power Phase B", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output Apparent Power Phase C", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output Power Phase A", new RampStrategy(10.0f, 50.0f, 1000));
addStrategy("System Output Power Phase B", new RampStrategy(10.0f, 50.0f, 1000));
addStrategy("System Output Power Phase C", new RampStrategy(10.0f, 50.0f, 1000));
addStrategy("System Output Apparent Power Phs A", new RampStrategy(10.0f, 50.0f, 1000));
addStrategy("System Output Apparent Power Phs B", new RampStrategy(10.0f, 50.0f, 1000));
addStrategy("System Output Apparent Power Phs C", new RampStrategy(10.0f, 50.0f, 1000));
addStrategy("Battery Time Remaining", new RampStrategy(0.0F, 0.3f, 1000));
addStrategy("Battery Time Remaining", new RampStrategy(0.0f, 3.0f, 1000));
addStrategy("Percentage Load", new RampStrategy(0.0f, 5.0f, 1000));
}
/**
@@ -95,95 +96,123 @@ State<ModbusIP>* BatteryState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
case 4:
return new BypassState<ModbusIP>();
break;
default:
default:
break;
}
float rating = getPointValue(equipment, "Px Rating");
float load = getPointValue(equipment, "Px Load");
float real_load = rating * (load/100.f);
Strategy_Behavior* ramp_strat = nullptr;
}
float Battery_time = getPointValue(equipment, "Battery Time Remaining");
float Bat_Percent = Battery_time /4.80f;
float select = 1.0f;
if (Bat_Percent > 98.0f){
setPointValue(equipment, "UPS Battery Status2", 0.0f);
select = 1.0f;
}
if (Bat_Percent > 20.0f) {
setPointValue(equipment, "UPS Battery Status1", 2.0f);
setPointValue(equipment, "Battery Low", 0.0f);
select = 1.0f;
}
if (Bat_Percent <= 20.0f && Bat_Percent >= 5.0f){
setPointValue(equipment, "UPS Battery Status1", 3.0f);
setPointValue(equipment, "Battery Low", 1.0f);
select = 0.8f;
}
if (Bat_Percent < 5.0f){
setPointValue(equipment, "UPS Battery Status1", 4.0f);
select = 0.05f;
}
float rating = getPointValue(equipment, "Px Rating");
float load = getPointValue(equipment, "Px Load");
float real_load = (rating) * (load/100.0f);
Strategy_Behavior* ramp_strat = nullptr;
//Output strategies
float Out_Vab = getPointValue(equipment, "System Output RMS A-B");
ramp_strat = getStrategy("System Output RMS Current Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load/Out_Vab);
float Out_Vbc = getPointValue(equipment, "System Output RMS B-C");
ramp_strat = getStrategy("System Output RMS Current Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load/Out_Vbc);
float Out_Vca = getPointValue(equipment, "System Output RMS C-A");
ramp_strat = getStrategy("System Output RMS Current Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load/Out_Vca);
float Out_Vab = getPointValue(equipment, "System Output RMS A-B");
ramp_strat = getStrategy("System Output RMS Current Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load*select);
float Out_Vbc = getPointValue(equipment, "System Output RMS B-C");
ramp_strat = getStrategy("System Output RMS Current Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load*select);
float Out_Vca = getPointValue(equipment, "System Output RMS C-A");
ramp_strat = getStrategy("System Output RMS Current Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load*select);
float Out_Van = getPointValue(equipment, "System Output RMS A-N");
float Out_Ia = getPointValue(equipment, "System Output RMS Current Phase A");
float Out_PFa = getPointValue(equipment, "System Output Power Factor Phs A");
ramp_strat = getStrategy("System Output Power Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Van * Out_Ia);
ramp_strat = getStrategy("System Output Apparent Power Phs A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Van * Out_Ia * Out_PFa);
float Out_Vbn = getPointValue(equipment, "System Output RMS B-N");
float Out_Ib = getPointValue(equipment, "System Output RMS Current Phase B");
float Out_PFb = getPointValue(equipment, "System Output Power Factor Phs B");
ramp_strat = getStrategy("System Output Power Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vbn * Out_Ib);
ramp_strat = getStrategy("System Output Apparent Power Phs B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vbn * Out_Ib * Out_PFb);
float Out_Vcn = getPointValue(equipment, "System Output RMS C-N");
float Out_Ic = getPointValue(equipment, "System Output RMS Current Phase C");
float Out_PFc = getPointValue(equipment, "System Output Power Factor Phs C");
ramp_strat = getStrategy("System Output Power Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vcn * Out_Ic);
ramp_strat = getStrategy("System Output Apparent Power Phs C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vcn * Out_Ic * Out_PFc);
float Out_Van = getPointValue(equipment, "System Output RMS A-N");
float Out_Ia = getPointValue(equipment, "System Output RMS Current Phase A");
float Out_PFa = getPointValue(equipment, "System Output Power Factor Phs A");
ramp_strat = getStrategy("System Output Power Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Van * Out_Ia);
ramp_strat = getStrategy("System Output Apparent Power Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Van * Out_Ia * Out_PFa);
float Out_Vbn = getPointValue(equipment, "System Output RMS B-N");
float Out_Ib = getPointValue(equipment, "System Output RMS Current Phase B");
float Out_PFb = getPointValue(equipment, "System Output Power Factor Phs B");
ramp_strat = getStrategy("System Output Power Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vbn * Out_Ib);
ramp_strat = getStrategy("System Output Apparent Power Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vbn * Out_Ib * Out_PFb);
float Out_Vcn = getPointValue(equipment, "System Output RMS C-N");
float Out_Ic = getPointValue(equipment, "System Output RMS Current Phase C");
float Out_PFc = getPointValue(equipment, "System Output Power Factor Phs C");
ramp_strat = getStrategy("System Output Power Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vcn * Out_Ic);
ramp_strat = getStrategy("System Output Apparent Power Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vcn * Out_Ic * Out_PFc);
float Battery_time = getPointValue(equipment, "Battery Time Remaining");
float Bat_Percent = Battery_time /4.80f;
if (Bat_Percent > 98.0f){
setPointValue(equipment, "UPS Battery Status2", 0.0f);
}
if (Bat_Percent > 20.0f) {
setPointValue(equipment, "UPS Battery Status1", 2.0f);
setPointValue(equipment, "Battery Low", 0.0f);
}
if (Bat_Percent <= 20.0f && Bat_Percent >= 5.0f){
setPointValue(equipment, "UPS Battery Status1", 3.0f);
setPointValue(equipment, "Battery Low", 1.0f);
}
if (Bat_Percent < 5.0f){
setPointValue(equipment, "UPS Battery Status1", 4.0f);
}
setPointValue(equipment, "System Output Power", (real_load * Out_Vab)/1000.0f);
setPointValue(equipment, "System Output Apparent Power", (real_load* Out_Vab * 0.9f)/1000.0f);
// Apply any strategies defined for the standby state
_applyStrategies(equipment);
return nullptr;
}
/**
* @brief Logic to execute once when entering the Battery state.
* Sets the "Run Status" for all EC fans to 1 to indicate they are active.
* @param equipment Pointer to the Equipment instance.
*/
template<>
void BatteryState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
}
/**
* @brief Logic to execute once when entering the Battery state.
* Sets the "Run Status" for all EC fans to 1 to indicate they are active.
* @param equipment Pointer to the Equipment instance.
*/
template<>
void BatteryState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Battery State...");
setPointValue(equipment, "System Input RMS A-B", 0.0f);
setPointValue(equipment, "System Input RMS B-C", 0.0f);
setPointValue(equipment, "System Input RMS C-A", 0.0f);
setPointValue(equipment, "System Input RMS A-N", 0.0f);
setPointValue(equipment, "System Input RMS B-N", 0.0f);
setPointValue(equipment, "System Input RMS C-N", 0.0f);
setPointValue(equipment, "System Input RMS Current Phase A", 0.0f);
setPointValue(equipment, "System Input RMS Current Phase B", 0.0f);
setPointValue(equipment, "System Input RMS Current Phase C", 0.0f);
setPointValue(equipment, "System Input Frequency", 0.0f);
setPointValue(equipment, "System Input Power Factor Phs A", 0.0f);
setPointValue(equipment, "System Input Power Factor Phs B", 0.0f);
setPointValue(equipment, "System Input Power Factor Phs C", 0.0f);
setPointValue(equipment, "System Input Power Phase A", 0.0f);
setPointValue(equipment, "System Input Power Phase B", 0.0f);
setPointValue(equipment, "System Input Power Phase C", 0.0f);
setPointValue(equipment, "System Input Apparent Power Phs A", 0.0f);
setPointValue(equipment, "System Input Apparent Power Phs B", 0.0f);
setPointValue(equipment, "System Input Apparent Power Phs C", 0.0f);
setPointValue(equipment, "Bypass Input Voltage RMS A-B", 0.0f);
setPointValue(equipment, "Bypass Input Voltage RMS B-C", 0.0f);
setPointValue(equipment, "Bypass Input Voltage RMS C-A", 0.0f);
setPointValue(equipment, "Bypass Input Voltage RMS A-N", 0.0f);
setPointValue(equipment, "Bypass Input Voltage RMS B-N", 0.0f);
setPointValue(equipment, "Bypass Input Voltage RMS C-N", 0.0f);
setPointValue(equipment, "Bypass Input Frequency", 0.0f);
setPointValue(equipment, "Bypass Power Phase A", 0.0f);
setPointValue(equipment, "Bypass Power Phase B", 0.0f);
setPointValue(equipment, "Bypass Power Phase C", 0.0f);
setPointValue(equipment, "UPS Loading Status", 6.0f);
setPointValue(equipment, "UPS Battery Status2", 2.0f);
// You could also update a Modbus register to show the "standby" state
setPointValue(equipment, "Bypass Input Voltage RMS A-B", 0.0f);
setPointValue(equipment, "Bypass Input Voltage RMS B-C", 0.0f);
setPointValue(equipment, "Bypass Input Voltage RMS C-A", 0.0f);
setPointValue(equipment, "Bypass Input Voltage RMS A-N", 0.0f);
setPointValue(equipment, "Bypass Input Voltage RMS B-N", 0.0f);
setPointValue(equipment, "Bypass Input Voltage RMS C-N", 0.0f);
setPointValue(equipment, "Bypass Input Frequency", 0.0f);
setPointValue(equipment, "Bypass Power Phase A", 0.0f);
setPointValue(equipment, "Bypass Power Phase B", 0.0f);
setPointValue(equipment, "Bypass Power Phase C", 0.0f);
setPointValue(equipment, "UPS Loading Status", 6.0f);
setPointValue(equipment, "UPS Battery Status2", 2.0f);
// You could also update a Modbus register to show the "standby" state
}

View File

@@ -42,72 +42,72 @@ template<>
BypassState<ModbusIP>::BypassState() {
//Input System
addStrategy("System Input RMS A-B", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("System Input RMS B-C", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("System Input RMS C-A", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("System Input RMS A-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("System Input RMS B-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("System Input RMS C-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("System Input RMS A-B", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("System Input RMS B-C", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("System Input RMS C-A", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("System Input RMS A-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("System Input RMS B-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("System Input RMS C-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("System Input RMS Current Phase A", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input RMS Current Phase B", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input RMS Current Phase C", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input RMS Current Phase A", new RampStrategy(0.0f, 25.0f, 1000));
addStrategy("System Input RMS Current Phase B", new RampStrategy(0.0f, 25.0f, 1000));
addStrategy("System Input RMS Current Phase C", new RampStrategy(0.0f, 25.0f, 1000));
addStrategy("System Input Frequency", new SingleValueStrategy(60.0F, 2.0f, 1000));
addStrategy("System Input Frequency", new SingleValueStrategy(60.0f, 2.0f, 1000));
addStrategy("System Input Power Factor Phs A", new SingleValueStrategy(93.0F, 5.0f, 1000));
addStrategy("System Input Power Factor Phs B", new SingleValueStrategy(93.0F, 5.0f, 1000));
addStrategy("System Input Power Factor Phs C", new SingleValueStrategy(93.0F, 5.0f, 1000));
addStrategy("System Input Power Factor Phs A", new SingleValueStrategy(93.0f, 5.0f, 1000));
addStrategy("System Input Power Factor Phs B", new SingleValueStrategy(93.0f, 5.0f, 1000));
addStrategy("System Input Power Factor Phs C", new SingleValueStrategy(93.0f, 5.0f, 1000));
addStrategy("System Input Power Phase A", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input Power Phase B", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input Power Phase C", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input Apparent Power Phase A", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input Apparent Power Phase B", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input Apparent Power Phase C", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input Power Phase A", new RampStrategy(0.0f, 50.0f, 1000));
addStrategy("System Input Power Phase B", new RampStrategy(0.0f, 50.0f, 1000));
addStrategy("System Input Power Phase C", new RampStrategy(0.0f, 50.0f, 1000));
addStrategy("System Input Apparent Power Phs A", new RampStrategy(0.0f, 50.0f, 1000));
addStrategy("System Input Apparent Power Phs B", new RampStrategy(0.0f, 50.0f, 1000));
addStrategy("System Input Apparent Power Phs C", new RampStrategy(0.0f, 50.0f, 1000));
//Bypass System
addStrategy("Bypass Input Voltage RMS A-B", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("Bypass Input Voltage RMS B-C", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("Bypass Input Voltage RMS C-A", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("Bypass Input Voltage RMS A-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("Bypass Input Voltage RMS B-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("Bypass Input Voltage RMS C-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("Bypass Input Voltage RMS A-B", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("Bypass Input Voltage RMS B-C", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("Bypass Input Voltage RMS C-A", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("Bypass Input Voltage RMS A-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("Bypass Input Voltage RMS B-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("Bypass Input Voltage RMS C-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("Bypass Input Frequency", new SingleValueStrategy(60.0F, 2.0f, 1000));
addStrategy("Bypass Input Frequency", new SingleValueStrategy(60.0f, 2.0f, 1000));
addStrategy("Bypass Input Power Phase A", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("Bypass Input Power Phase B", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("Bypass Input Power Phase C", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("Bypass Input Power Phase A", new RampStrategy(0.0f, 25.0f, 1000));
addStrategy("Bypass Input Power Phase B", new RampStrategy(0.0f, 25.0f, 1000));
addStrategy("Bypass Input Power Phase C", new RampStrategy(0.0f, 25.0f, 1000));
//Output System
addStrategy("System Output RMS A-B", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("System Output RMS B-C", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("System Output RMS C-A", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("System Output RMS A-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("System Output RMS B-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("System Output RMS C-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("System Output RMS A-B", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("System Output RMS B-C", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("System Output RMS C-A", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("System Output RMS A-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("System Output RMS B-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("System Output RMS C-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("System Output RMS Current Phase A", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output RMS Current Phase B", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output RMS Current Phase C", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output RMS Current Phase A", new RampStrategy(0.0f, 25.0f, 1000));
addStrategy("System Output RMS Current Phase B", new RampStrategy(0.0f, 25.0f, 1000));
addStrategy("System Output RMS Current Phase C", new RampStrategy(0.0f, 25.0f, 1000));
addStrategy("System Output Frequency", new SingleValueStrategy(60.0F, 2.0f, 1000));
addStrategy("System Output Frequency", new SingleValueStrategy(60.0f, 2.0f, 1000));
addStrategy("System Output Power Factor Phs A", new SingleValueStrategy(93.0F, 5.0f, 1000));
addStrategy("System Output Power Factor Phs B", new SingleValueStrategy(93.0F, 5.0f, 1000));
addStrategy("System Output Power Factor Phs C", new SingleValueStrategy(93.0F, 5.0f, 1000));
addStrategy("System Output Power Factor Phs A", new SingleValueStrategy(93.0f, 5.0f, 1000));
addStrategy("System Output Power Factor Phs B", new SingleValueStrategy(93.0f, 5.0f, 1000));
addStrategy("System Output Power Factor Phs C", new SingleValueStrategy(93.0f, 5.0f, 1000));
addStrategy("System Output Power Phase A", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output Power Phase B", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output Power Phase C", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output Apparent Power Phase A", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output Apparent Power Phase B", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output Apparent Power Phase C", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output Power Phase A", new RampStrategy(0.0f, 50.0f, 1000));
addStrategy("System Output Power Phase B", new RampStrategy(0.0f, 50.0f, 1000));
addStrategy("System Output Power Phase C", new RampStrategy(0.0f, 50.0f, 1000));
addStrategy("System Output Apparent Power Phs A", new RampStrategy(0.0f, 50.0f, 1000));
addStrategy("System Output Apparent Power Phs B", new RampStrategy(0.0f, 50.0f, 1000));
addStrategy("System Output Apparent Power Phs C", new RampStrategy(0.0f, 50.0f, 1000));
addStrategy("Battery Time Remaining", new RampStrategy(480.0F, 0.3f, 1000));
addStrategy("DC Bus Voltage", new SingleValueStrategy(518.0F, 5.0f, 1000));
addStrategy("Battery Time Remaining", new RampStrategy(480.0f, 0.3f, 1000));
addStrategy("DC Bus Voltage", new SingleValueStrategy(518.0f, 5.0f, 1000));
}
/**
@@ -143,85 +143,85 @@ State<ModbusIP>* BypassState<ModbusIP>::update(Equipment<ModbusIP>* equipment) {
}
float rating = getPointValue(equipment, "Px Rating");
float load = getPointValue(equipment, "Px Load");
float real_load = rating * (load/100.f);
float real_load = (rating) * (load/100.0f);
Strategy_Behavior* ramp_strat = nullptr;
//Input strategies
float In_Vab = getPointValue(equipment, "System Input RMS A-B");
ramp_strat = getStrategy("System Input RMS Current Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load/In_Vab);
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load);
float In_Vbc = getPointValue(equipment, "System Input RMS B-C");
ramp_strat = getStrategy("System Input RMS Current Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load/In_Vbc);
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load);
float In_Vca = getPointValue(equipment, "System Input RMS C-A");
ramp_strat = getStrategy("System Input RMS Current Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load/In_Vca);
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load);
float In_Van = getPointValue(equipment, "System Input RMS A-N");
float In_Ia = getPointValue(equipment, "System Input RMS Current Phase A");
float In_PFa = getPointValue(equipment, "System Input Power Factor Phs A");
ramp_strat = getStrategy("System Input Power Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Van * In_Ia);
ramp_strat = getStrategy("Bypass Power Phase A");
ramp_strat = getStrategy("Bypass Input Power Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Van * In_Ia);
ramp_strat = getStrategy("System Input Apparent Power Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Van * In_Ia * In_PFa);
ramp_strat = getStrategy("System Input Apparent Power Phs A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Van * In_Ia * 0.9f);
float In_Vbn = getPointValue(equipment, "System Input RMS B-N");
float In_Ib = getPointValue(equipment, "System Input RMS Current Phase B");
float In_PFb = getPointValue(equipment, "System Input Power Factor Phs B");
ramp_strat = getStrategy("System Input Power Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Vbn * In_Ib);
ramp_strat = getStrategy("Bypass Power Phase B");
ramp_strat = getStrategy("Bypass Input Power Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Vbn * In_Ib);
ramp_strat = getStrategy("System Input Apparent Power Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Vbn * In_Ib * In_PFb);
ramp_strat = getStrategy("System Input Apparent Power Phs B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Vbn * In_Ib * 0.9f);
float In_Vcn = getPointValue(equipment, "System Input RMS C-N");
float In_Ic = getPointValue(equipment, "System Input RMS Current Phase C");
float In_PFc = getPointValue(equipment, "System Input Power Factor Phs C");
ramp_strat = getStrategy("System Input Power Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Vcn * In_Ic);
ramp_strat = getStrategy("Bypass Power Phase C");
ramp_strat = getStrategy("Bypass Input Power Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Vcn * In_Ic);
ramp_strat = getStrategy("System Input Apparent Power Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Vcn * In_Ic * In_PFc);
ramp_strat = getStrategy("System Input Apparent Power Phs C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Vcn * In_Ic * 0.9f);
//Output strategies
float Out_Vab = getPointValue(equipment, "System Output RMS A-B");
ramp_strat = getStrategy("System Output RMS Current Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load/Out_Vab);
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load);
float Out_Vbc = getPointValue(equipment, "System Output RMS B-C");
ramp_strat = getStrategy("System Output RMS Current Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load/Out_Vbc);
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load);
float Out_Vca = getPointValue(equipment, "System Output RMS C-A");
ramp_strat = getStrategy("System Output RMS Current Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load/Out_Vca);
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load);
float Out_Van = getPointValue(equipment, "System Output RMS A-N");
float Out_Ia = getPointValue(equipment, "System Output RMS Current Phase A");
float Out_PFa = getPointValue(equipment, "System Output Power Factor Phs A");
ramp_strat = getStrategy("System Output Power Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Van * Out_Ia);
ramp_strat = getStrategy("System Output Apparent Power Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Van * Out_Ia * Out_PFa);
ramp_strat = getStrategy("System Output Apparent Power Phs A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Van * Out_Ia * 0.9f);
float Out_Vbn = getPointValue(equipment, "System Output RMS B-N");
float Out_Ib = getPointValue(equipment, "System Output RMS Current Phase B");
float Out_PFb = getPointValue(equipment, "System Output Power Factor Phs B");
ramp_strat = getStrategy("System Output Power Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vbn * Out_Ib);
ramp_strat = getStrategy("System Output Apparent Power Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vbn * Out_Ib * Out_PFb);
ramp_strat = getStrategy("System Output Apparent Power Phs B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vbn * Out_Ib * 0.9f);
float Out_Vcn = getPointValue(equipment, "System Output RMS C-N");
float Out_Ic = getPointValue(equipment, "System Output RMS Current Phase C");
float Out_PFc = getPointValue(equipment, "System Output Power Factor Phs C");
ramp_strat = getStrategy("System Output Power Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vcn * Out_Ic);
ramp_strat = getStrategy("System Output Apparent Power Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vcn * Out_Ic * Out_PFc);
ramp_strat = getStrategy("System Output Apparent Power Phs C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vcn * Out_Ic * 0.9f);
float Battery_time = getPointValue(equipment, "Battery Time Remaining");
float Bat_Percent = Battery_time /4.80f;
@@ -239,11 +239,12 @@ State<ModbusIP>* BypassState<ModbusIP>::update(Equipment<ModbusIP>* equipment) {
if (Bat_Percent < 5.0f){
setPointValue(equipment, "UPS Battery Status1", 4.0f);
}
setPointValue(equipment, "System Output Power", (real_load * In_Vab)/1000.0f);
setPointValue(equipment, "System Output Apparent Power", (real_load* In_Vab * 0.9f)/1000.0f);
// Apply any strategies defined for the standby state
_applyStrategies(equipment);
return nullptr;
}
/**
* @brief Logic to execute once when entering the Bypass state.
* Sets the "Run Status" for all EC fans to 1 to indicate they are active.
@@ -252,9 +253,10 @@ State<ModbusIP>* BypassState<ModbusIP>::update(Equipment<ModbusIP>* equipment) {
template<>
void BypassState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Battery State...");
Serial.println("Enter Bypass State...");
setPointValue(equipment, "UPS Loading Status", 4.0f);
setPointValue(equipment, "UPS Battery Status2", 3.0f);
setPointValue(equipment, "Percentage Load", 0.0f);
// You could also update a Modbus register to show the "standby" state
}

View File

@@ -40,60 +40,60 @@
*/
template<>
RunningState<ModbusIP>::RunningState() {
addStrategy("System Input RMS A-B", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("System Input RMS B-C", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("System Input RMS C-A", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("System Input RMS A-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("System Input RMS B-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("System Input RMS C-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("System Input RMS A-B", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("System Input RMS B-C", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("System Input RMS C-A", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("System Input RMS A-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("System Input RMS B-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("System Input RMS C-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("System Input RMS Current Phase A", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input RMS Current Phase B", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input RMS Current Phase C", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input RMS Current Phase A", new RampStrategy(0.0f, 25.0f, 1000));
addStrategy("System Input RMS Current Phase B", new RampStrategy(0.0f, 25.0f, 1000));
addStrategy("System Input RMS Current Phase C", new RampStrategy(0.0f, 25.0f, 1000));
addStrategy("System Input Frequency", new SingleValueStrategy(60.0F, 2.0f, 1000));
addStrategy("System Input Frequency", new SingleValueStrategy(60.0f, 2.0f, 1000));
addStrategy("System Input Power Factor Phs A", new SingleValueStrategy(93.0F, 5.0f, 1000));
addStrategy("System Input Power Factor Phs B", new SingleValueStrategy(93.0F, 5.0f, 1000));
addStrategy("System Input Power Factor Phs C", new SingleValueStrategy(93.0F, 5.0f, 1000));
addStrategy("System Input Power Factor Phs A", new SingleValueStrategy(93.0f, 0.5f, 1000));
addStrategy("System Input Power Factor Phs B", new SingleValueStrategy(93.0f, 0.5f, 1000));
addStrategy("System Input Power Factor Phs C", new SingleValueStrategy(93.0f, 0.5f, 1000));
addStrategy("System Input Power Phase A", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input Power Phase B", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input Power Phase C", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input Apparent Power Phase A", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input Apparent Power Phase B", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input Apparent Power Phase C", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Input Power Phase A", new RampStrategy(0.0f, 50.0f, 1000));
addStrategy("System Input Power Phase B", new RampStrategy(0.0f, 50.0f, 1000));
addStrategy("System Input Power Phase C", new RampStrategy(0.0f, 50.0f, 1000));
addStrategy("System Input Apparent Power Phs A", new RampStrategy(0.0f, 50.0f, 1000));
addStrategy("System Input Apparent Power Phs B", new RampStrategy(0.0f, 50.0f, 1000));
addStrategy("System Input Apparent Power Phs C", new RampStrategy(0.0f, 50.0f, 1000));
addStrategy("System Output RMS A-B", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("System Output RMS B-C", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("System Output RMS C-A", new SingleValueStrategy(480.0F, 5.0f, 1000));
addStrategy("System Output RMS A-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("System Output RMS B-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("System Output RMS C-N", new SingleValueStrategy(270.0F, 5.0f, 1000));
addStrategy("System Output RMS Current Phase A", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output RMS Current Phase B", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output RMS Current Phase C", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output RMS A-B", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("System Output RMS B-C", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("System Output RMS C-A", new SingleValueStrategy(480.0f, 5.0f, 1000));
addStrategy("System Output RMS A-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("System Output RMS B-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("System Output RMS C-N", new SingleValueStrategy(270.0f, 5.0f, 1000));
addStrategy("System Output Frequency", new SingleValueStrategy(60.0F, 2.0f, 1000));
addStrategy("System Output Power Factor Phs A", new SingleValueStrategy(93.0F, 5.0f, 1000));
addStrategy("System Output Power Factor Phs B", new SingleValueStrategy(93.0F, 5.0f, 1000));
addStrategy("System Output Power Factor Phs C", new SingleValueStrategy(93.0F, 5.0f, 1000));
addStrategy("System Output Power Phase A", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output Power Phase B", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output Power Phase C", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output Apparent Power Phase A", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output Apparent Power Phase B", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("System Output Apparent Power Phase C", new RampStrategy(10.0F, 5.0f, 1000));
addStrategy("Battery Time Remaining", new RampStrategy(480.0F, 1.0f, 1000));
addStrategy("DC Bus Voltage", new SingleValueStrategy(518.0F, 5.0f, 1000));
addStrategy("System Output RMS Current Phase A", new RampStrategy(0.0f, 25.0f, 1000));
addStrategy("System Output RMS Current Phase B", new RampStrategy(0.0f, 25.0f, 1000));
addStrategy("System Output RMS Current Phase C", new RampStrategy(0.0f, 25.0f, 1000));
addStrategy("System Output Frequency", new SingleValueStrategy(60.0f, 2.0f, 1000));
addStrategy("System Output Power Factor Phs A", new SingleValueStrategy(93.0f, 5.0f, 1000));
addStrategy("System Output Power Factor Phs B", new SingleValueStrategy(93.0f, 5.0f, 1000));
addStrategy("System Output Power Factor Phs C", new SingleValueStrategy(93.0f, 5.0f, 1000));
addStrategy("System Output Power Phase A", new RampStrategy(10.0f, 50.0f, 1000));
addStrategy("System Output Power Phase B", new RampStrategy(10.0f, 50.0f, 1000));
addStrategy("System Output Power Phase C", new RampStrategy(10.0f, 50.0f, 1000));
addStrategy("System Output Apparent Power Phs A", new RampStrategy(10.0f, 50.0f, 1000));
addStrategy("System Output Apparent Power Phs B", new RampStrategy(10.0f, 50.0f, 1000));
addStrategy("System Output Apparent Power Phs C", new RampStrategy(10.0f, 50.0f, 1000));
addStrategy("DC Bus Voltage", new SingleValueStrategy(518.0f, 5.0f, 1000));
addStrategy("Battery Time Remaining", new RampStrategy(480.0f, 1.0f, 1000));
addStrategy("Percentage Load", new RampStrategy(100.0f, 5.0f, 1000));
addStrategy("System Output Power", new SingleValueStrategy(0.0f, 5.0f, 1000));
addStrategy("System Output Apparent Power", new SingleValueStrategy(0.0f, 5.0f, 1000));
}
/**
@@ -130,78 +130,81 @@ State<ModbusIP>* RunningState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
float rating = getPointValue(equipment, "Px Rating");
float load = getPointValue(equipment, "Px Load");
float real_load = (rating*1000.0f) * (load/100.f);
float real_load = (rating) * (load/100.0f);
Strategy_Behavior* ramp_strat = nullptr;
//Input strategies
float In_Vab = getPointValue(equipment, "System Input RMS A-B");
ramp_strat = getStrategy("System Input RMS Current Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load/In_Vab);
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load);
float In_Vbc = getPointValue(equipment, "System Input RMS B-C");
ramp_strat = getStrategy("System Input RMS Current Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load/In_Vbc);
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load);
float In_Vca = getPointValue(equipment, "System Input RMS C-A");
ramp_strat = getStrategy("System Input RMS Current Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load/In_Vca);
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load);
setPointValue(equipment, "System Output Power", (real_load * In_Vab)/1000.0f);
setPointValue(equipment, "System Output Apparent Power", (real_load* In_Vab * 0.9f)/1000.0f);
float In_Van = getPointValue(equipment, "System Input RMS A-N");
float In_Ia = getPointValue(equipment, "System Input RMS Current Phase A");
float In_PFa = getPointValue(equipment, "System Input Power Factor Phs A");
ramp_strat = getStrategy("System Input Power Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Van * In_Ia);
ramp_strat = getStrategy("System Input Apparent Power Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Van * In_Ia * (In_PFa/100.0f));
ramp_strat = getStrategy("System Input Apparent Power Phs A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Van * In_Ia * 0.9f);
float In_Vbn = getPointValue(equipment, "System Input RMS B-N");
float In_Ib = getPointValue(equipment, "System Input RMS Current Phase B");
float In_PFb = getPointValue(equipment, "System Input Power Factor Phs B");
ramp_strat = getStrategy("System Input Power Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Vbn * In_Ib);
ramp_strat = getStrategy("System Input Apparent Power Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Vbn * In_Ib * (In_PFb/100.0f));
ramp_strat = getStrategy("System Input Apparent Power Phs B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Vbn * In_Ib * 0.9f);
float In_Vcn = getPointValue(equipment, "System Input RMS C-N");
float In_Ic = getPointValue(equipment, "System Input RMS Current Phase C");
float In_PFc = getPointValue(equipment, "System Input Power Factor Phs C");
ramp_strat = getStrategy("System Input Power Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Vcn * In_Ic);
ramp_strat = getStrategy("System Input Apparent Power Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Vcn * In_Ic * (In_PFc/100.0f));
ramp_strat = getStrategy("System Input Apparent Power Phs C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(In_Vcn * In_Ic * 0.9f);
//Output strategies
float Out_Vab = getPointValue(equipment, "System Output RMS A-B");
ramp_strat = getStrategy("System Output RMS Current Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load/Out_Vab);
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load);
float Out_Vbc = getPointValue(equipment, "System Output RMS B-C");
ramp_strat = getStrategy("System Output RMS Current Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load/Out_Vbc);
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load);
float Out_Vca = getPointValue(equipment, "System Output RMS C-A");
ramp_strat = getStrategy("System Output RMS Current Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load/Out_Vca);
static_cast<RampStrategy*>(ramp_strat)->setTarget(real_load);
float Out_Van = getPointValue(equipment, "System Output RMS A-N");
float Out_Ia = getPointValue(equipment, "System Output RMS Current Phase A");
float Out_PFa = getPointValue(equipment, "System Output Power Factor Phs A");
ramp_strat = getStrategy("System Output Power Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Van * Out_Ia);
ramp_strat = getStrategy("System Output Apparent Power Phase A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Van * Out_Ia * (Out_PFa/100.0f));
ramp_strat = getStrategy("System Output Apparent Power Phs A");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Van * Out_Ia * 0.9f);
float Out_Vbn = getPointValue(equipment, "System Output RMS B-N");
float Out_Ib = getPointValue(equipment, "System Output RMS Current Phase B");
float Out_PFb = getPointValue(equipment, "System Output Power Factor Phs B");
ramp_strat = getStrategy("System Output Power Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vbn * Out_Ib);
ramp_strat = getStrategy("System Output Apparent Power Phase B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vbn * Out_Ib * (Out_PFb/100.0f));
ramp_strat = getStrategy("System Output Apparent Power Phs B");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vbn * Out_Ib * 0.9f);
float Out_Vcn = getPointValue(equipment, "System Output RMS C-N");
float Out_Ic = getPointValue(equipment, "System Output RMS Current Phase C");
float Out_PFc = getPointValue(equipment, "System Output Power Factor Phs C");
ramp_strat = getStrategy("System Output Power Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vcn * Out_Ic);
ramp_strat = getStrategy("System Output Apparent Power Phase C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vcn * Out_Ic * (Out_PFc/100.0f));
ramp_strat = getStrategy("System Output Apparent Power Phs C");
static_cast<RampStrategy*>(ramp_strat)->setTarget(Out_Vcn * Out_Ic * 0.9f);
float Battery_time = getPointValue(equipment, "Battery Time Remaining");
float Bat_Percent = Battery_time /4.80f;

View File

@@ -86,9 +86,60 @@ State<ModbusIP>* StandbyState<ModbusIP>::update(Equipment<ModbusIP>* equipment)
*/
template<>
void StandbyState<ModbusIP>::enterState(Equipment<ModbusIP>* equipment) {
// Logic to run when the equipment enters this state
Serial.println("Enter Standby State...");
setPointValue(equipment, "UPS Loading Status", 2.0f);
// Logic to run when the equipment enters this state
Serial.println("Enter Standby State...");
setPointValue(equipment, "UPS Loading Status", 2.0f);
setPointValue(equipment, "System Input RMS A-B", 0.0f);
setPointValue(equipment, "System Input RMS B-C", 0.0f);
setPointValue(equipment, "System Input RMS C-A", 0.0f);
setPointValue(equipment, "System Input RMS A-N", 0.0f);
setPointValue(equipment, "System Input RMS B-N", 0.0f);
setPointValue(equipment, "System Input RMS C-N", 0.0f);
setPointValue(equipment, "System Input RMS Current Phase A", 0.0f);
setPointValue(equipment, "System Input RMS Current Phase B", 0.0f);
setPointValue(equipment, "System Input RMS Current Phase C", 0.0f);
setPointValue(equipment, "System Input Frequency", 0.0f);
setPointValue(equipment, "System Input Power Factor Phs A", 0.0f);
setPointValue(equipment, "System Input Power Factor Phs B", 0.0f);
setPointValue(equipment, "System Input Power Factor Phs C", 0.0f);
setPointValue(equipment, "System Input Power Phase A", 0.0f);
setPointValue(equipment, "System Input Power Phase B", 0.0f);
setPointValue(equipment, "System Input Power Phase C", 0.0f);
setPointValue(equipment, "System Input Apparent Power Phs A", 0.0f);
setPointValue(equipment, "System Input Apparent Power Phs B", 0.0f);
setPointValue(equipment, "System Input Apparent Power Phs C", 0.0f);
setPointValue(equipment, "Bypass Input Voltage RMS A-B", 0.0f);
setPointValue(equipment, "Bypass Input Voltage RMS B-C", 0.0f);
setPointValue(equipment, "Bypass Input Voltage RMS C-A", 0.0f);
setPointValue(equipment, "Bypass Input Voltage RMS A-N", 0.0f);
setPointValue(equipment, "Bypass Input Voltage RMS B-N", 0.0f);
setPointValue(equipment, "Bypass Input Voltage RMS C-N", 0.0f);
setPointValue(equipment, "Bypass Input Frequency", 0.0f);
setPointValue(equipment, "Bypass Power Phase A", 0.0f);
setPointValue(equipment, "Bypass Power Phase B", 0.0f);
setPointValue(equipment, "Bypass Power Phase C", 0.0f);
setPointValue(equipment, "System Output RMS A-B", 0.0f);
setPointValue(equipment, "System Output RMS B-C", 0.0f);
setPointValue(equipment, "System Output RMS C-A", 0.0f);
setPointValue(equipment, "System Output RMS A-N", 0.0f);
setPointValue(equipment, "System Output RMS B-N", 0.0f);
setPointValue(equipment, "System Output RMS C-N", 0.0f);
setPointValue(equipment, "System Output RMS Current Phase A", 0.0f);
setPointValue(equipment, "System Output RMS Current Phase B", 0.0f);
setPointValue(equipment, "System Output RMS Current Phase C", 0.0f);
setPointValue(equipment, "System Output Frequency", 0.0f);
setPointValue(equipment, "System Output Power Factor Phs A", 0.0f);
setPointValue(equipment, "System Output Power Factor Phs B", 0.0f);
setPointValue(equipment, "System Output Power Factor Phs C", 0.0f);
setPointValue(equipment, "System Output Power Phase A", 0.0f);
setPointValue(equipment, "System Output Power Phase B", 0.0f);
setPointValue(equipment, "System Output Power Phase C", 0.0f);
setPointValue(equipment, "System Output Apparent Power Phs A", 0.0f);
setPointValue(equipment, "System Output Apparent Power Phs B", 0.0f);
setPointValue(equipment, "System Output Apparent Power Phs C", 0.0f);
setPointValue(equipment, "System Output Power", 0.0f);
setPointValue(equipment, "System Output Apparent Power", 0.0f);
}
/**

View File

@@ -21,10 +21,10 @@
* @{
*/
#include <ModbusIP_ESP8266.h>
const char *ssid = "wifi_ssid"; /**< @brief The SSID of the WiFi network. */
const char *password = "wifi_password"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(192, 168, 1, 234); /**< @brief The static IP address for the device. */
IPAddress gateway(192, 168, 1, 1); /**< @brief The gateway IP address. */
const char *ssid = "QTS_CDR_Arduino"; /**< @brief The SSID of the WiFi network. */
const char *password = "123abc456"; /**< @brief The password for the WiFi network. */
IPAddress local_IP(172, 17, 33, 187); /**< @brief The static IP address for the device. */
IPAddress gateway(172, 17, 33, 1); /**< @brief The gateway IP address. */
IPAddress subnet(255, 255, 255, 0); /**< @brief The subnet mask. */
ModbusIP mb;
@@ -60,75 +60,76 @@
*/
modbusMap mb_map[] =
{
{HR, 9, 0, "Px State"}, //1-standby, 2 Running (Normal - charging), 3 Battery, 4 Bypass
{HR, 10, 0, "Px Load"}, //% Internal Fault code from Modscan
{HR, 11, 0, "Px Rating"}, //kVA Internal Fault code from Modscan
{HR, 9, 0, "Px State"}, //1-standby, 2 Running (Normal - charging), 3 Battery, 4 Bypass
{HR, 10, 0, "Px Load"}, //% Internal Fault code from Modscan
{HR, 11, 0, "Px Rating"}, //kVA Internal Fault code from Modscan
{DI, 11, 0, "Output Overload"},
{DI, 20, 0, "Bypass Not Ready"},
{DI, 239, 0, "Internal Comms Failure"},
{DI, 244, 0, "System Shutdown-EPO"},
{DI, 245, 0, "Fuse Failure"},
{DI, 247, 0, "System Fan Failure"},
{DI, 249, 0, "System Output Off"},
{DI, 254, 0, "UPS Output on Bypass"},
{DI, 263, 0, "Battery Low"},
{DI, 11, 0, "Output Overload"},
{DI, 20, 0, "Bypass Not Ready"},
{DI, 239, 0, "Internal Comms Failure"},
{DI, 244, 0, "System Shutdown-EPO"},
{DI, 245, 0, "Fuse Failure"},
{DI, 247, 0, "System Fan Failure"},
{DI, 249, 0, "System Output Off"},
{DI, 254, 0, "UPS Output on Bypass"},
{DI, 263, 0, "Battery Low"},
{IR_10x, 1, 0, "System Input RMS A-B"},
{IR_10x, 2, 0, "System Input RMS B-C"},
{IR_10x, 3, 0, "System Input RMS C-A"},
{IR_10x, 4, 0, "System Input RMS A-N"},
{IR_10x, 5, 0, "System Input RMS B-N"},
{IR_10x, 6, 0, "System Input RMS C-N"},
{IR_10x, 7, 0, "System Input RMS Current Phase A"},
{IR_10x, 8, 0, "System Input RMS Current Phase B"},
{IR_10x, 9, 0, "System Input RMS Current Phase C"},
{IR_10x, 10, 0, "System Input Frequency"},
{IR_10x, 11, 0, "System Input Power Factor Phs A"},
{IR_10x, 12, 0, "System Input Power Factor Phs B"},
{IR_10x, 13, 0, "System Input Power Factor Phs C"},
{IR_10x, 14, 0, "System Input Power Phase A"},
{IR_10x, 15, 0, "System Input Power Phase B"},
{IR_10x, 16, 0, "System Input Power Phase C"},
{IR_10x, 17, 0, "System Input Apparent Power Phs A"},
{IR_10x, 18, 0, "System Input Apparent Power Phs B"},
{IR_10x, 19, 0, "System Input Apparent Power Phs C"},
{IR_10x, 23, 0, "Bypass Input Voltage RMS A-B"},
{IR_10x, 24, 0, "Bypass Input Voltage RMS B-C"},
{IR_10x, 25, 0, "Bypass Input Voltage RMS C-A"},
{IR_10x, 26, 0, "Bypass Input Voltage RMS A-N"},
{IR_10x, 27, 0, "Bypass Input Voltage RMS B-N"},
{IR_10x, 28, 0, "Bypass Input Voltage RMS C-N"},
{IR_10x, 29, 0, "Bypass Input Frequency"},
{IR_10x, 30, 0, "Bypass Power Phase A"},
{IR_10x, 31, 0, "Bypass Power Phase B"},
{IR_10x, 32, 0, "Bypass Power Phase C"},
{IR_10x, 38, 0, "System Output RMS A-B"},
{IR_10x, 39, 0, "System Output RMS B-C"},
{IR_10x, 40, 0, "System Output RMS C-A"},
{IR_10x, 41, 0, "System Output RMS A-N"},
{IR_10x, 42, 0, "System Output RMS B-N"},
{IR_10x, 43, 0, "System Output RMS C-N"},
{IR_10x, 44, 0, "System Output RMS Current Phase A"},
{IR_10x, 45, 0, "System Output RMS Current Phase B"},
{IR_10x, 46, 0, "System Output RMS Current Phase C"},
{IR_10x, 50, 0, "System Output Frequency"},
{IR_10x, 51, 0, "System Output Power Factor Phs A"},
{IR_10x, 52, 0, "System Output Power Factor Phs B"},
{IR_10x, 53, 0, "System Output Power Factor Phs C"},
{IR_10x, 54, 0, "System Output Power Phase A"},
{IR_10x, 55, 0, "System Output Power Phase B"},
{IR_10x, 56, 0, "System Output Power Phase C"},
{IR_10x, 57, 0, "System Output Apparent Power Phs A"},
{IR_10x, 58, 0, "System Output Apparent Power Phs B"},
{IR_10x, 59, 0, "System Output Apparent Power Phs C"},
{IR_10x, 60, 0, "System Output Power"},
{IR_10x, 61, 0, "System Output Apparent Power"},
{IR, 164, 0, "UPS Loading Status"},
{IR_10x, 175, 0, "DC Bus Voltage"},
{IR, 180, 0, "Battery Time Remaining"},
{IR, 183, 0, "UPS Battery Status1"},
{IR, 184, 0, "UPS Battery Status2"},
{IR, 1, 0, "System Input RMS A-B"},
{IR, 2, 0, "System Input RMS B-C"},
{IR, 3, 0, "System Input RMS C-A"},
{IR, 4, 0, "System Input RMS A-N"},
{IR, 5, 0, "System Input RMS B-N"},
{IR, 6, 0, "System Input RMS C-N"},
{IR, 7, 0, "System Input RMS Current Phase A"},
{IR, 8, 0, "System Input RMS Current Phase B"},
{IR, 9, 0, "System Input RMS Current Phase C"},
{IR_10x, 10, 0, "System Input Frequency"},
{IR, 11, 0, "System Input Power Factor Phs A"}, //0.01
{IR, 12, 0, "System Input Power Factor Phs B"},
{IR, 13, 0, "System Input Power Factor Phs C"},
{IR_10x, 14, 0, "System Input Power Phase A"},
{IR_10x, 15, 0, "System Input Power Phase B"},
{IR_10x, 16, 0, "System Input Power Phase C"},
{IR_10x, 17, 0, "System Input Apparent Power Phs A"},
{IR_10x, 18, 0, "System Input Apparent Power Phs B"},
{IR_10x, 19, 0, "System Input Apparent Power Phs C"},
{IR, 23, 0, "Bypass Input Voltage RMS A-B"},
{IR, 24, 0, "Bypass Input Voltage RMS B-C"},
{IR, 25, 0, "Bypass Input Voltage RMS C-A"},
{IR, 26, 0, "Bypass Input Voltage RMS A-N"},
{IR, 27, 0, "Bypass Input Voltage RMS B-N"},
{IR, 28, 0, "Bypass Input Voltage RMS C-N"},
{IR_10x, 29, 0, "Bypass Input Frequency"},
{IR_10x, 30, 0, "Bypass Power Phase A"},
{IR_10x, 31, 0, "Bypass Power Phase B"},
{IR_10x, 32, 0, "Bypass Power Phase C"},
{IR, 38, 0, "System Output RMS A-B"},
{IR, 39, 0, "System Output RMS B-C"},
{IR, 40, 0, "System Output RMS C-A"},
{IR, 41, 0, "System Output RMS A-N"},
{IR, 42, 0, "System Output RMS B-N"},
{IR, 43, 0, "System Output RMS C-N"},
{IR, 44, 0, "System Output RMS Current Phase A"},
{IR, 45, 0, "System Output RMS Current Phase B"},
{IR, 46, 0, "System Output RMS Current Phase C"},
{IR_10x, 50, 0, "System Output Frequency"},
{IR, 51, 0, "System Output Power Factor Phs A"},
{IR, 52, 0, "System Output Power Factor Phs B"},
{IR, 53, 0, "System Output Power Factor Phs C"},
{IR_10x, 54, 0, "System Output Power Phase A"},
{IR_10x, 55, 0, "System Output Power Phase B"},
{IR_10x, 56, 0, "System Output Power Phase C"},
{IR_10x, 57, 0, "System Output Apparent Power Phs A"},
{IR_10x, 58, 0, "System Output Apparent Power Phs B"},
{IR_10x, 59, 0, "System Output Apparent Power Phs C"},
{IR, 60, 0, "System Output Power"},
{IR, 61, 0, "System Output Apparent Power"},
{IR, 164, 0, "UPS Loading Status"},
{IR, 175, 0, "DC Bus Voltage"},
{IR, 179, 0, "Percentage Load"},
{IR, 180, 0, "Battery Time Remaining"},
{IR, 183, 0, "UPS Battery Status1"},
{IR, 184, 0, "UPS Battery Status2"},
};
//Size of modbus map used in FOR cycles, automatically calculated.