Senbrix monitor view - four ladder rungs and an OutdoorTemp watch cell showing 19.9

This ladder switches a fan using the weather from the internet. It takes four rungs and one C# method. C# fetches Seoul’s temperature from a weather API and writes it to D0, and the ladder compares that value and decides.

What you need

ItemDetails
ProjectA PLC-track project (ladder + C#)
Runtime connectionConnected to a runtime through the connection icon at the bottom. The screens in this post come from a runtime running on a PC
InternetThe device running the runtime must be able to reach outside addresses
Output addressAn output for the fan relay. This example uses OUT1 on the ZPi-IO8R main board, which is P5

How it fits together

  • C# calls the weather API every 60 seconds and writes the temperature to D0.R.
  • The ladder turns on TooHot at 28℃ or above and Cooled at 26℃ or below, then uses those two bits to switch the fan.

C# fetches values from the outside world, and the ladder decides what to do with them. The two share one memory cell, D0.

1. Symbols

Symbols page - FanOn P5, TooHot M10, Cooled M11, OutdoorTemp D0.R

NameAddressDescription
OutdoorTempD0.ROutdoor temperature in ℃, written by C#
TooHotM10Temperature ≥ 28
CooledM11Temperature ≤ 26
FanOnP5Fan output

The temperature has a decimal part, so the address ends in .R. .R is a float and takes two words (D0 and D1). The ladder and C# both read and write values like 19.9 under the same name, OutdoorTemp.

2. Ladder

Ladder page - compare contacts drive TooHot and Cooled, and SETOUT and RSTOUT control FanOn in four rungs

RungContactOutput
Too hotOutdoorTemp>=28fTooHot coil
Cooled downOutdoorTemp<=26fCooled coil
Fan onTooHotSETOUT(FanOn)
Fan offCooledRSTOUT(FanOn)

The first two rungs put a comparison straight into the contact slot. When the condition holds, the contact conducts and the coil turns on. When you build, this contact becomes a C# expression like (Scan.D[0].R>=28f).

The lower two rungs are a latch. SETOUT holds an output on once it is set, and RSTOUT clears it. The turn-on threshold (28℃) and the turn-off threshold (26℃) are different, so between 26 and 28℃ neither fires and the fan keeps its previous state. It won’t flicker on and off near a single threshold.

Right after startup OutdoorTemp is 0, so Cooled comes on first and the fan starts off.

3. C#

Code page - App.cs with a Loop that calls Open-Meteo and writes to OutdoorTemp

using System.Net.Http;
using System.Text.Json;

namespace Senbrix.Generated;

public partial class App : PlcApp
{
    // Seoul. Open-Meteo needs no API key.
    const string Url = "https://api.open-meteo.com/v1/forecast"
                     + "?latitude=37.57&longitude=126.98&current=temperature_2m";

    static readonly HttpClient Http = new() { Timeout = TimeSpan.FromSeconds(5) };
    long _last;

    // Runs on its own task, so waiting on the network never stalls the ladder.
    protected override void Loop()
    {
        if (Environment.TickCount64 - _last < 60_000) return;   // refresh every 60 s
        _last = Environment.TickCount64;

        try
        {
            using var doc = JsonDocument.Parse(Http.GetStringAsync(Url).Result);
            OutdoorTemp = doc.RootElement.GetProperty("current")
                             .GetProperty("temperature_2m").GetSingle();
        }
        catch { }   // keep the last value; an unhandled exception would end this task
    }
}

A few notes on the code.

  • Setup() and Loop() run on their own task, separate from the ladder cycle, so waiting for a network response doesn’t delay the 10 ms ladder cycle.
  • The runtime calls Loop() repeatedly. Left alone, it would hit the API nonstop, so it checks Environment.TickCount64 for 60 seconds and returns right away otherwise.
  • If the connection drops or nothing comes back within 5 seconds, an exception is thrown. Swallowing it with try/catch leaves OutdoorTemp at its previous value.
  • An exception that leaves Loop() quietly ends this whole task. The temperature stops updating while the ladder keeps running, which makes the problem hard to notice.

4. Build, deploy and monitor

Press Build, then Deploy, then Monitor. When the status bar shows that the deploy finished and the runtime is running, the monitor overlay appears on the ladder.

Monitor view - the OutdoorTemp watch cell shows 19.9, and the Cooled coil and the RSTOUT rung are energized

Place an '' OutdoorTemp watch cell next to the ladder and you can read the value directly. On 2026-10-02 Seoul’s temperature started at 19.8℃ and changed to 19.9℃ a few minutes later. Even though we ask every 60 seconds, the API refreshes its value every 15 minutes, so the temperature doesn’t change on every call.

On screen you should see:

  • The OutdoorTemp<=26f contact conducts and the Cooled coil is on.
  • RSTOUT(FanOn) on the Fan off rung conducts, so the fan is off.
  • The TooHot rung is off, as expected at a temperature well below 28℃.

To see the fan turn on, the temperature has to pass 28℃. To see it at the current temperature, lower both the turn-on and turn-off values below it (for example 18 and 16). TooHot then comes on, Cooled stays off, and SETOUT(FanOn) conducts. If you change only the turn-on value, the Fan off rung sits lower and wins, so the fan stays off. Change both.

Going further

  • To change the location, edit only latitude and longitude in Url.
  • To use other values, write humidity or wind speed into a D register the same way and change only the comparisons in the ladder. The structure stays the same: Loop() fetches the value and the ladder decides.