5.8 KiB
Examples
Real-world Slang programs demonstrating common patterns.
Temperature Control
Basic thermostat that controls an air conditioner based on room temperature:
device ac = "db";
device roomGasSensor = "d0";
const TARGET_TEMP = 22c;
const HYSTERESIS = 1;
loop {
yield();
let temp = roomGasSensor.Temperature;
if (temp > TARGET_TEMP + HYSTERESIS) {
ac.On = true;
} else if (temp < TARGET_TEMP - HYSTERESIS) {
ac.On = false;
}
}
Note: The IC10 chip is assumed to be inserted in the air conditioner's IC slot.
Two-Axis Solar Panel Tracking
Handles two-axis solar panel tracking based on the sun's position:
device sensor = "d0";
const H_PANELS = hash("StructureSolarPanelDual");
loop {
setBatched(H_PANELS, "Horizontal", sensor.Horizontal);
setBatched(H_PANELS, "Vertical", sensor.Vertical + 90);
yield();
}
Note: Assumes the daylight sensor is mounted with its port looking 90 degrees east of the solar panel's data port, an offset can be added on the horizontal angle if needed.
Day/Night Lighting
Controls grow lights during the day and ambient lights at night:
device greenhouseSensor = "d0";
const daylightSensor = hash("StructureDaylightSensor");
const growLight = hash("StructureGrowLight");
const wallLight = hash("StructureLightLong");
loop {
yield();
let solarAngle = lb(daylightSensor, "SolarAngle", "Average");
let isDaylight = solarAngle < 90;
sb(growLight, "On", isDaylight);
sb(wallLight, "On", !isDaylight);
}
Pressure Relief Valve
Controls a volume pump based on pressure readings for emergency pressure relief:
device volumePump = "d0";
device pipeSensor = "d1";
const MAX_PRESSURE = 10_000;
const R = 8.314;
loop {
yield();
let pressure = pipeSensor.Pressure;
if (pressure > MAX_PRESSURE) {
// Use PV=nRT to calculate the amount of mols we need to move
// n = PV / RT
let molsToMove = (pressure - MAX_PRESSURE) *
pipeSensor.Volume / (R * pipeSensor.Temperature);
// V = nRT / P
let setting = molsToMove * R * pipeSensor.Temperature / pressure;
volumePump.Setting = setting;
volumePump.On = true;
} else {
volumePump.On = false;
}
}
Greenhouse Environment Controller
Complete greenhouse control with pressure, temperature, and lighting:
device self = "db";
device emergencyRelief = "d0";
device greenhouseSensor = "d1";
device recycleValve = "d2";
const MAX_INTERIOR_PRESSURE = 80;
const MAX_INTERIOR_TEMP = 28c;
const MIN_INTERIOR_PRESSURE = 75;
const MIN_INTERIOR_TEMP = 25c;
const daylightSensor = 1076425094;
const growLight = hash("StructureGrowLight");
const wallLight = hash("StructureLightLong");
const lightRound = hash("StructureLightRound");
let shouldPurge = false;
loop {
yield();
let interiorPress = greenhouseSensor.Pressure;
let interiorTemp = greenhouseSensor.Temperature;
shouldPurge = (
interiorPress > MAX_INTERIOR_PRESSURE ||
interiorTemp > MAX_INTERIOR_TEMP
) || shouldPurge;
emergencyRelief.On = shouldPurge;
recycleValve.On = !shouldPurge;
if (
shouldPurge && (
interiorPress < MIN_INTERIOR_PRESSURE &&
interiorTemp < MIN_INTERIOR_TEMP
)
) {
shouldPurge = false;
}
let solarAngle = lb(daylightSensor, "SolarAngle", "Average");
let isDaylight = solarAngle < 90;
sb(growLight, "On", isDaylight);
sb(wallLight, "On", !isDaylight);
sb(lightRound, "On", !isDaylight);
}
Advanced Furnace Pressure Control
Automates multi-furnace pump control based on dial setting for pressure target:
const FURNACE1 = 1234;
const DIAL1 = 1123;
const ANALYZER1 = 1223;
const FURNACE2 = 1235;
const DIAL2 = 1124;
const ANALYZER2 = 1224;
const FURNACE3 = 1236;
const DIAL3 = 1124;
const ANALYZER3 = 1225;
const R = 8.314;
fn handleFurnace(furnace, dial, analyzer) {
let pressure = furnace.Pressure;
let targetPressure = max(dial.Setting, 0.1) * 1000;
if (abs(targetPressure - pressure) <= 0.1) {
furnace.On = false;
return;
}
let molsToMove = max(furnace.TotalMoles, 1) * (
(targetPressure / pressure) - 1
);
// V = nRT / P
if (molsToMove > 0) {
// Calculate volume required
if (analyzer.Pressure == 0) {
// No more gas to add
furnace.On = false;
return;
}
let volume = molsToMove * R * analyzer.Temperature / analyzer.Pressure;
furnace.On = true;
furnace.SettingOutput = 0;
furnace.SettingInput = volume;
return;
}
// Calculate volume required
let volume = (-molsToMove) * R * furnace.Temperature / pressure;
furnace.On = true;
furnace.SettingInput = 0;
furnace.SettingOutput = volume;
return;
}
loop {
yield();
handleFurnace(FURNACE1, DIAL1, ANALYZER1);
handleFurnace(FURNACE2, DIAL2, ANALYZER2);
handleFurnace(FURNACE3, DIAL3, ANALYZER3);
}
Note: This example does not handle edge cases such as insufficient gas in the input network or overfilling the furnace/pipe network.
Common Patterns
Waiting for a Condition
fn waitForDeviceToTurnOff(device) {
while (device.On) {
yield();
}
}
See Also
- Getting Started — First steps with Slang
- Language Reference — Complete syntax guide
- Built-in Functions — System calls and math functions