155 lines
5.5 KiB
Java
155 lines
5.5 KiB
Java
/*
|
|
* %W% %E% Dymik739
|
|
* Email: dymik739@109.86.70.81
|
|
*
|
|
* Copyright (C) 2023 FIOT Dev Team
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/**
|
|
* Class that represents a vent installed in the house.
|
|
* This device acts as a reactive load.
|
|
*
|
|
* @author Dymik739
|
|
* @since 0.3
|
|
*/
|
|
public class Vent extends Appliance {
|
|
/**
|
|
* Power draw limit set by the digital controller, designed by a KPI
|
|
* student. Built with the JK-triggers, may malfunction sometimes.
|
|
* Exceeding this limit may damage the engine, so it's hard limited.
|
|
*/
|
|
private float maxPower = 80.0f;
|
|
|
|
/**
|
|
* Current rotor revolutions per minute.
|
|
* Can also be defined as angular velocity or kinetic energy
|
|
* accumulated in the device.
|
|
*/
|
|
private float rpm = 0.0f;
|
|
|
|
/**
|
|
* Defines inertia of the rotor.
|
|
* Allows the rotor to withstand forces changing it's angular speed.
|
|
*/
|
|
private final float rotorInertia = 2.0f;
|
|
|
|
/**
|
|
* Target RPM the vent is tuned to maintain.
|
|
* Rotor draws full power until it reaches this speed, after that it
|
|
* draws only as much power as needed to maintain this speed.
|
|
*
|
|
* Might be tweaked up to match the exact RPM required, as the target
|
|
* RPM is more than actual RPM while running due to additional forces
|
|
* and failures in design of the microcontroller (it was also designed
|
|
* using JK-triggers as they were the ones that student used in their
|
|
* coursework last year).
|
|
*/
|
|
private final float maxRPM = 2013.0f;
|
|
|
|
/**
|
|
* Constructor for this class.
|
|
*
|
|
* @param plugged defines if the device is plugged into the power
|
|
* network right away
|
|
*/
|
|
public Vent(boolean plugged) {
|
|
super(plugged);
|
|
super.setType("Vent");
|
|
}
|
|
|
|
/**
|
|
* Method for simulating the device behaviour.
|
|
* As was stated before in the class docs, this device has reactive
|
|
* properties when it comes to loading the network. This means, it
|
|
* doesn't only change it's power usage during operation, but also
|
|
* follows some real-world physics laws while running.
|
|
*
|
|
* First, it uses the power, limited by a device microcontroller,
|
|
* to gain angular velocity, measured in RPM. Right before it reaches
|
|
* it's target RPM, the power draw falls with the exponential decrement
|
|
* law (can be seen from the graph in --vent-monitoring-graph mode).
|
|
*
|
|
* Once it meets the target RPM, it draws power to only maintain it's
|
|
* speed (the power goes to withstand air forces trying to slow the
|
|
* fan - and the attached rotor - down).
|
|
*
|
|
* After the power cuts off, the fan keeps rotating due to it's inertia
|
|
* and, when plugged back in, starts getting back up to it's target speed
|
|
* according to it's current RPM. The power draw from the network always
|
|
* meets the power used to gain angular velocity of the rotor.
|
|
*
|
|
* Also, as this vent is forcing the air through, the blades experience
|
|
* the air drag - it always tries to slow the fan down. As such, the
|
|
* air rag force is always calculated and depends of the RPM, which
|
|
* is proportional to the force being put on the blades.
|
|
*
|
|
* And the engineering level is kind of weird: on one hand, they
|
|
* engineer a smark device that can manage the RPM and limit the power
|
|
* to the rotor, but on the other hand they're unable to deal with
|
|
* reverse polarity the rotor generates while running, so they've
|
|
* just soldered a single diode on the wire and thus limited possible
|
|
* power down to just 80W! At least, the vent is still functional, so
|
|
* I guess it's good enough...
|
|
*
|
|
* @param seconds delta time to simulate for
|
|
*/
|
|
public void step(float seconds) {
|
|
// electric current usage
|
|
if (super.getPowerState()) {
|
|
rpm += max(min(((int) (maxRPM - rpm) * rotorInertia), maxPower), 0)
|
|
* 10 / rotorInertia * seconds;
|
|
}
|
|
|
|
// air drag (always present)
|
|
rpm -= (rpm / 20) / rotorInertia * seconds;
|
|
}
|
|
|
|
/**
|
|
* Method for calculating current power consumption of this device.
|
|
* Calculations are similar to the step() method above.
|
|
*
|
|
* @return current power consumption of this device
|
|
*/
|
|
public float getPowerConsumption() {
|
|
if (super.getPowerState()) {
|
|
return max(min(rotorInertia*(maxRPM - rpm), maxPower), 0);
|
|
} else {
|
|
return 0f;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Getter for RPM.
|
|
*
|
|
* @return current RPM
|
|
*/
|
|
public float getRPM() {
|
|
return rpm;
|
|
}
|
|
|
|
/**
|
|
* Method for ptinting out this device state in a nice way.
|
|
*
|
|
* @return string representation of this device state
|
|
*/
|
|
@Override
|
|
public String toString() {
|
|
return String.format("Vent(%s, %4.1fW, %4.0f RPM)",
|
|
super.getPowerState() ? "on" : "off", getPowerConsumption(),
|
|
rpm);
|
|
}
|
|
}
|