Colibri Runtime

From Stm32World Wiki
Jump to navigation Jump to search

The Colibri Runtime is the custom firmware that is running on Colibri MCUs, an application in Colibri Zephyr orchestrating the hardware resources, I/O drivers and Lua user scripts.

Initially, a single Lua script is supported. But more might follow.

User Program Requirements

The user program/script MUST contain the following functions;

Limits in Lua

Host API

 event(event_id, value)
 publish(event, value)
 subscribe(event_type, value)
 unsubscribe(event_type)
 
 is_type(event_id, event_type)

Event Types

 TIME_PERIOD
 COUNTER
 ERROR_CODE
 MEASURED_VALUE
 COMPUTED_VALUE
 SETPOINT
 MIN_VALUE
 MAX_VALUE
 LOW_THRESHOLD
 HIGH_THRESHOLD
 RUN_INDICATION
 ALARM_INDICATION
 RGB_SET

Example 1 - Blinky

  -- do..end is called an "explicit lexical scope", and needed to
  -- allow for so called "upvalues", that is the variables in that scope
  -- which will persist over invocations from the system.

  do
    local next=0
    local state=0
    local period_id
    
    -- local functions are not visible to the host system.
    local function tick(now)
      if next < now then
        -- publish() is the main way to interact with the system
        -- Event type RGB_SET is making a request to set the RGB LED to the color value
        -- in the second argument, and that value is equal to (r << 16 | g << 8 | b)
        -- Negative colors are predefined colors, currently;
        --   -1  OK       (typically Green)
        --   -2  WARNING  (typically Yellow)
        --   -3  ERROR    (typically Red)
        --   -4  INFO     (typically Cyan)
        publish( RGB_SET, -state)
        state = (state + 1) % 5
        next = now + 300
      end
    end
    
    -- Called once after program has been loaded into memory.
    -- To be called periodically, subscription to a TIME_PERIOD
    -- event should be established.
    function init()
      period_id = subscribe(TIME_PERIOD, 250)
    end
  
    -- Entry point for all events. All interaction with the
    -- system and I/O subsystem are handled through events.
    -- This is to ensure future-compatibility, so that firmware
    -- doesn't need to be upgraded when new I/O modules are 
    -- introduced.
    function event(event_id, value)
      if event_id == period_id then
        tick(value)
      end
    end
  
    -- terminating() is called just before the program is terminated 
    -- and removed from memory
    function terminating()
      publish(RGB_SET, 0)
    end
  end

Example 2 - Toggle SSR in slot 5 output 1 at 1Hz and output 2 at 5Hz

  -- do..end is called an "explicit lexical scope", and needed to
  -- allow for so called "upvalues", that is the variables in that scope
  -- which will persist over invocations from the system.

  do
    local state1 = 0
    local state2 = 0
    local counter1 = 0
    
    -- local functions are not visible to the host system.
    local function tick()
      -- publish to slot 5, channel 2, and the value
      publish( create_io( 5, 2, state2 ) )
      state2 = !state2

      if counter1 = 0 then
        -- publish to slot 5, channel 1, and the value
        publish( create_io( 5,1, state1 ) )
        state1 = !state1
      end
      counter1 = ( counter1 + 1 ) % 5
    end
    
    -- Called once after program has been loaded into memory.
    function init()
      -- request the 5Hz
      period_id = subscribe( TIME_PERIOD, 200 )
    end
  
    -- Entry point for all events. All interaction with the
    -- system and I/O subsystem are handled through events.
    -- This is to ensure future-compatibility, so that firmware
    -- doesn't need to be upgraded when new I/O modules are 
    -- introduced.
    function event( event, value )
      if event_type( event ) == period_type then
        tick()
      end
    end
  
    -- terminating() is called just before the program is terminated 
    -- and removed from memory
    function terminating()
      publish( RGB_SET, 0 )
    end
  end

Example 3 - Set Analog Output 1 in Slot 4

Example 4 - Raise an Alarm condition

Example 5 - Get Analog Input 2 in slot 1

Example - Level check

Check every minute if Analog Input 2 in slot 2 is >10mA, if so set SSR output 1, and if input < 5mA turn it off.

Example - PID implementation in Lua

Example - Interface Colibri PID1

Colibri PID1 has a co-processor on the I/O module, which measures temperature on Pt1000 input and use PID algorithm to regulate that with Analog Output. The program in that I/O module is fixed, but it has a lot of parameters that can be set.

 SetP - Setpoint in ˚C
 Cycle - Sample frequency in ms
 P - Proportional constant
 I - Integral time
 D - Derivative time
 MD - Max Derivative value
 Min - Minimum value, default 0
 Max - Maximum value, default 100

It also reports both Input (in ˚C) and Output (in Max/Min values) on each Cycle, if cycle is slower than I/O subsystem update time (typ 10ms).


Historical

The Colibri Runtime is the custom firmware that is running on Colibri MCUs, an application in Colibri Zephyr orchestrating the hardware resources, WebAssembly engines with I/O drivers and user programs.

NOTE: running in individual WebAssembly instances turned out to be more stressful than useful, so that thread has been closed but kept on this Wiki for historical purposes.

Development

Colibri EEPROM Layout

Colibri WebAssembly Notes