Connect to and control machines using MACI API and platform services
Replace your PLC or DCS by building control apps to connect to and control machines.
    /// Ramp machine speed down until temperature is safe.
    float currentRpm = targetRpm->GetValue();
    targetRpm->SetValue(currentRpm - 10.0);

    // Enable command runner for scheduling commands and monitoring trigger
    // expressions.
    CommandRunnerPtr pRunner = CreateCommandRunner("runner");

    ReInt32Ptr temperature = CreateInt32("Current_Temperature");
    ReFloatPtr maxTemp = CreateInt32("maximum_temperature");
    ReFloatPtr targetRpm = CreateInt32("complete_start");


    ExpressionPtr errorExpr = temperature > maxTemp;
    ExpressionPtr normalExpr = temperature <= maxTemp;

    CommandPtr command = pRunner->CreateCommand("OverTemperature",              // Name
                                             errorExpr,                         // Target Launch Expression
                                             normalExpr,                        // Exit Expression
                                             COMMAND_FUNCTION(OverTemperature), // Execute Expression
                                             10);                               // Command Execute Cycle

bool CVendingMachine::Initialize()
    ReDoublePtr input = CreateDouble("input", true, false);
    ReDoublePtr output = CreateDouble("output", true, false);
    ReDoublePtr target = CreateDouble("target");

    // Update PID Controller with input of current actual RPM
    // Update VFD drive increment/decrement target with output of PID controller.


    // Delta T = 0.03
    // P = 0.02
    // I = 0.00
    // D = 0
    // These paramaters can be updated from engineering interface to finely tune
    // PID controller performance. 
    PIDControllerPtr pid = CPIDController::Create(factory,
void CVendingMachine::InitialStateExecute(void)

void CVendingMachine::NickelStateExecute(void)

bool CVendingMachine::Initialize()
    // Create input objects
    m_pCoin = CreateFloat("InputCoin", true, false);

    // Create state machine
    m_pVendingMachine = CreateStateMachine("VendingMachineMain");

    m_pVendingMachine->CreateState("InitialState", STATE_EXECUTE(InitialStateExecute));
    m_pVendingMachine->CreateState("InputNickel", STATE_EXECUTE(NickelStateExecute));
    m_pVendingMachine->CreateState("InputDime", STATE_EXECUTE(DimeStateExecute));
    // Quarter and terminating states clipped for example

    // Define Starting and Emergency States

    // Create transition expressions
    ExpressionPtr valueCoin = CValue::Create(m_pCoin);

    ExpressionPtr valueFive = CValue::Create(m_pVendingMachine, 0.05f);
    ExpressionPtr coinEqualsFive = valueCoin == valueFive;

    ExpressionPtr valueTen = CValue::Create(m_pVendingMachine, 0.10f);
    ExpressionPtr coinEqualsTen = valueCoin == valueTen;

    ExpressionPtr valueMaxValue = CValue::Create(m_pMaxValue);
    ExpressionPtr currentValue = CValue::Create(m_pCurrentValue);

    ExpressionPtr greaterEqualSeventyFive = currentValue >= valueMaxValue;

    ExpressionPtr valueTrue = CValue::Create(m_pVendingMachine, true);
    ExpressionPtr equalsTrue = valueTrue == valueTrue;

    // Initialize transitions from Initial State
    m_pVendingMachine->CreateTransition("IStoIN", "InitialState", "InputNickel", coinEqualsFive);
    m_pVendingMachine->CreateTransition("IStoID", "InitialState", "InputDime", coinEqualsTen);
    m_pVendingMachine->CreateTransition("IStoIQ", "InitialState", "InputQuarter", coinEqualsTwentyFive);

    // Initialize transitions from Input Nickel
    m_pVendingMachine->CreateTransition("INtoTS", "InputNickel", "TerminatingState", greaterEqualSeventyFive);
    m_pVendingMachine->CreateTransition("INtoID", "InputNickel", "InputDime", coinEqualsTen);
    m_pVendingMachine->CreateTransition("INtoIQ", "InputNickel", "InputQuarter", coinEqualsTwentyFive);

    // Initialize transitions from Input Dime
    m_pVendingMachine->CreateTransition("IDtoTS", "InputDime", "TerminatingState", greaterEqualSeventyFive);
    m_pVendingMachine->CreateTransition("IDtoIN", "InputDime", "InputNickel", coinEqualsFive);
    m_pVendingMachine->CreateTransition("IDtoIQ", "InputDime", "InputQuarter", coinEqualsTwentyFive);

    return true;
void CNetExample::RpmUpdate()
    printf("Motor RPM has been updated. RPM = [%f]", motorRpm->GetValue());

bool CNetExample::Initialize()
    // Define Net Types
    motorRpm = CreateFloat("motorRpm");

    // Use EVENT_HANDLER macro with RegisterEvent(delegate) to define an async
    // event handler for motor rpm updates.

    motorTarget = CreateFloat("targetRpm");

    // Write update without needing to know how to connect to the target device.
    return true;
The Remuv connectivity layer is driven by the configuration layer. Once network device configuration has been defined, developers do not need to worry about the connection details of the device they are connected to. The network object internally updates and maintains meta data describing the quality of the fieldbus data.

Existing automation technologies are closed ecosystems. Solutions are vendor dependent where hardware and software are tightly coupled. MACI provides open control models and services for building scalable and highly interoperable automation solutions. Remuv provides your engineers the infrastructure they need to deliver products.
  • Communication patterns
  • Machine control patterns
  • Control algorithms (P.I.D loops)
  • Units management
  • Alarm & event normalization
  • Services
  • Control Logic Engine
  • Deployment Agents
  • Network Layer
  • Configuration
  • Utilities
  • Network debugging
  • Engineering Interfaces
  • Historical Logging
The RACE platform accelerates system development and deployment time. Explore how Remuv has stacks up against traditional automation technologies.

Hardware Agnostic

Currently if you are trying to build a control system solution, you must develop system requirements then select a specific hardware vendor. You must use the vendor's development suite to create your control logic to enable machine automation.
If you need to switch to a new vendor, you will have to rewrite a lot of your control logic to comply with your new hardware.
RACE is built using open source tools and languages. The platform is developed using cross-platform principles that allow us to target Windows, Linux, and Mac OSX. The Remuv services are capable of running on any hardware that supports Windows, Linux, or Mac OSX.

Contextual Data Mining & Scraping

Big data analytics is the process of examining large data sets containing a variety of data types -- i.e., big data -- to uncover hidden patterns, unknown correlations, market trends, customer preferences and other useful business information. The analytical findings can lead to more effective marketing, new revenue opportunities, better customer service, improved operational efficiency, competitive advantages over rival organizations and other business benefits.
Large data lakes filled with logged data points generated by machines, sensors and drives can be used to identify predictive maintenance patterns, optimized machine set points and complete automation feedback loops.
Currently data is collected by plugging into the factory network to harvest data. Output from sensors and motors are continually recorded, this complicates the data analyst or machine learning scientist's job because they generally do not know exactly what the system was doing when the data point was recorded.
Data with context. Data from the factory floor can now be propagated up through RACE and then sent to the data lake via a strongly typed data interface. This transport enables the RACE control logic to attach context to the data. RACE is data-centric, meaning the system is developed around data and conveniently normalizes data to a common protocol enabling data to be easily shipped service to service.

Universal Device Interface

Sensors, motors, drives, controllers and other devices all communicate across a wide variety of protocols. Interfacing with these devices requires supporting the proprietary protocol.
Many PLC controllers and systems do not support an extensive list of ethernet communication protocols. This limits what system architects are able to build as they are limited to using sensors and drives that natively interface with their controller(s).
RACE provides a device abstraction layer via a collection of edge servers supporting an unbound number of communication protocols. Data is normalized from proprietary protocol formats to a common language spoken throughout RACE. Once inside RACE, data can easily be shipped to any external consumer. The network layer abstracts protocols as drivers, there is one driver or connector for each communication protocol.
  • CANopen
  • EtherNet/IP
  • Ethercat
  • Modbus RTU
  • Modbus TCP
  • Build support for additional protocols using Remuv's dynamic interface.

Data Logging

Historical record logging is a requirement in many systems. Every message sent and every network I/O update may need to be recorded for audit transparency.
Data is not always relevant. However, PLCs are often not powerful enough to process incoming data, decide if it should be logged, then log it. This creates a requirement for a separate data logging device that records every network IO sample.
Remuv's network layer implements a highly customizable set of netWorker services that manage network items. Logging verbosity is easily configured at the item level. APIs are additionally available to configure network logging options. There is a separate logging service that brokers and organizes logs generated by other RACE services.

System & Control Debugging

A fundamental requirement of any software application is the ability to troubleshoot errors. Even more beneficial are systems which provide live monitoring to evaluate how the system is currently performing. The Windows task manager is a perfect example, when you press ctrl+alt+del you are provided an interface to monitor system resource usages and programs currently running on the machine. Task manager even allows you to make changes, which affect system behavior. Similar resources are available for control systems.
Most control system debug interfaces require special software to view the controllers. Once connection to the controller has been made, the options to view what the control logic is actually doing is very limited. Technicians can at best simply view the registers (variables) on the controller and observe the current values. To understand what the system is actually doing, these variable values must be cross referenced with code.
RACE provides a web based debug interface accessible from any computer, with a web browser, on the RACE network. The debug interface will provide the following monitoring and interaction interfaces:
  • Control logic execution:
    • Visualize running state machines.
      • Observe current state.
      • Inspect how the system arrived at current state (path history)
      • Observe where the system could go next.
    • Control engine tree visualization
  • Network Topography
    • Visualize network devices and their items.
    • View & Update configuration items for each network device or item on a device.
    • View data being received at the network layer real time.
  • Monitor RACE services.

System Availability

Control system reliability and up-time are critical. Outages can have serious safety, property and cash consequences.
Designing fail over PLC systems requires a lot of controller to controller handshaking. Reliable high-availability PLC systems are expensive to design and often require special controllers (hardware).
RACE has built-in support for deploying high availability solutions without requiring developers to write any extra code. The number of backup services is described by the system configuration file. When a service fails or "crashes" there will be another service that will switch from "idle" to "active" and seamlessly take over.

Change Management (Solution Versioning)

When developing software applications, it is important to track revisions. Version control systems exist for software languages, these systems track changes on a line-to-line and file-by-file basis. It is very easy to document changes between revisions.
PLC software applications cannot be tracked using any standard version control system, this is due to the development environments and the file types used to save the applications. These issues make for a nightmare trying to document the logic changes across control system releases.
RACE control solutions are written using modern and widely supported languages that have native support for tracking changes in source code. Remuv utilizes build systems that easily facilitate versioning software releases.

Developer Availability

Developer turnover is a problem that no company will ever be able to stamp out. Recruiting, hiring, and integration are expensive processes that companies have to wade through when building teams.
PLC developers are more rare and often specialize in only a few different PLC models, thus shrinking the available talent pool.
Remuv's platform is built upon C++, one of the most common languages in the world. The RACE API is simple and usable by even the most junior programmers. One of Remuv's goals is to provide a platform that is usable by as many developers as possible. To support this goal, more language bindings for C, JAVA, C# and more will soon be available. More language bindings will only increase the size of the pool of developers who find RACE a very easy to use platform.