Skip to content

Releases: XavSPM/RevpiEpics

RevPiEpics v0.2.1

23 Mar 16:13
9118037

Choose a tag to compare

Release Notes - RevPiEpics v0.2.1

What's New: Architecture, Flexibility, and Autosave

1. Internal Architecture Refactoring (IOMap)

The monolithic IOMap object has been refactored into a cleaner object-oriented hierarchy. Analog inputs/outputs now use the AnalogIOMap class, which reduces the memory footprint for simple binary signals and removes numerous redundant conditional checks.

2. Native Autosave Integration (softioc.autosave)

It is now possible to enable automatic backup of EPICS configuration states:

  • Global Activation: In RevPiEpics.init(..., autosave=True, autosave_dir="/tmp/save").
  • Granular Control: When creating an analog PV, you can specify autosave_multiplier=True or autosave_offset=True to specifically save these parameters to the .softsav file.
  • The standard autosave=... parameter for primary variables is fully supported out of the box (e.g., autosave=["PREC", "EGU", "VAL"]).

3. Simplified Software Scaling (Float PVs)

The previous behavior that generated an integer "DIVISOR" PV has been safely removed. The system now strictly relies on a :MULTIPLIER and an :OFFSET. Both PVs are now exported as Floating-point Records (aOut). They fully accept standard decimal computations (e.g. 0.1 instead of dividing by 10) and negative values.

4. Direct Scaling Parameter Setup

When building an analog I/O, developers can disregard PiCtory's system hardware defaults and manually inject the soft EPICS startup configuration straight from python:
RevPiEpics.builder("IN1", initial_multiplier=1.5, initial_offset=20.0)

5. Enriched Object API

The RecordWrapper Python object returned by RevPiEpics.builder(...) when targeting an analog module now structurally integrates its child scaling records. You can dynamically drive tracking parameters from Python execution logic: my_sensor.offset.set(10).


AIO Engine Core Mechanics (Reminder)

Delegated Mathematical Computation (SoftIOC)

At initialization, the system imports the software parameters mapped in PiCtory to establish an absolute factory baseline. The new scalable conversion is managed entirely by live synchronized computations across the soft PV backend (pvsync.py).

Real-time EPICS Editing

An operator can freely modify the mapped Soft PVs (like caput IN2_1:MULTIPLIER 0.5) to instantly adjust the underlying behavior:

  • Reading (IN): Inverse calculation from the initial raw binary value scaling back to base zero, subsequently layered dynamically beneath the new EPICS ratio.
  • Writing (OUT): Resolves the SCADA request according to the EPICS layer, then translates and applies the factory hardware ratio to pipeline directly to the Digital-to-Analog hardware converter.

What's Changed

  • Enhance AIO integration with autosave, logging, and documentation updates by @XavSPM in #3

Full Changelog: 0.2.0...0.2.1

RevpiEpics v0.2.0

16 Jun 09:02
4e1765a

Choose a tag to compare

RevpiEpics v0.2.0 - Major API Refactor 🚀

🎉 What's New

This major release brings a complete API refactor for simpler and more intuitive usage, along with improved support for asynchronous programming.

✨ Key Improvements

  • 🔄 API Refactor: Migration from instance-based API to static methods
  • ⚡ Enhanced Asyncio Support: Native integration with AsyncioDispatcher
  • ⏱️ Cycletime Control: Customizable configuration of IO loop cycle time
  • 🔧 Custom Functions: Add user tasks to the main loop with add_loop_task()
  • 📚 Enhanced Documentation: Complete examples for cothread and asyncio
  • 🛠️ Simplified Installation: Detailed instructions for virtual environments

🆕 New Features

  • add_loop_task(): Allows adding custom functions to the main IO loop
  • Practical Examples: Complete implementations for cothread and asyncio
  • RevPi Commander Compatibility: System installation with --break-system-packages

📋 Usage Examples

Simple Usage

from softioc import builder
from revpiepics import RevPiEpics

builder.SetDeviceName("TEST")
RevPiEpics.init(debug=True, cycletime=200)

# Create PVs
ai1 = RevPiEpics.builder("OutputStatus_2_i06")
ai2 = RevPiEpics.builder("OutputStatus_1_i06", "Out1Status")
ao1 = RevPiEpics.builder(io_name="OutputValue_1_i06", pv_name="Out1", DESC="Output 1", EGU="mV")

# Start IOC and IO loop
RevPiEpics.start()

With Custom Function (add_loop_task)

from softioc import builder
from revpiepics import RevPiEpics

builder.SetDeviceName("TEST")
RevPiEpics.init(debug=True, cycletime=200)

ai1 = RevPiEpics.builder(io_name="OutputValue_1_i06", pv_name="Out1")
ai2 = RevPiEpics.builder(io_name="InputValue_1_i06", pv_name="In1")
counter = builder.aIn('COUNTER')

def update_logic():
    """Function executed at each IO loop cycle"""
    # Copy input value to output with offset
    ai1.set(ai2.get() + 100)
    
    # Increment counter
    counter.set(counter.get() + 1)

# Add function to IO loop
RevPiEpics.add_loop_task(update_logic)

# Start IOC and IO loop with custom function
RevPiEpics.start()

With Cothread

from softioc import builder
from revpiepics import RevPiEpics
import cothread

builder.SetDeviceName("TEST")
RevPiEpics.init()

ai1 = RevPiEpics.builder(io_name="OutputValue_1_i06", pv_name="Out1")
ai2 = RevPiEpics.builder(io_name="InputValue_1_i06", pv_name="Int1")

def update():
    while True:
        ai1.set(ai2.get() + 100)
        cothread.Sleep(1)

cothread.Spawn(update)
RevPiEpics.start()

With Asyncio

from softioc import builder, asyncio_dispatcher
from revpiepics import RevPiEpics
import asyncio

dispatcher = asyncio_dispatcher.AsyncioDispatcher()
builder.SetDeviceName("TEST")
RevPiEpics.init()

ai1 = RevPiEpics.builder(io_name="OutputValue_1_i06", pv_name="Out1")
ai2 = RevPiEpics.builder(io_name="InputValue_1_i06", pv_name="Int1")

async def update():
    while True:
        ai1.set(ai2.get() + 100)
        await asyncio.sleep(1)

dispatcher(update)
RevPiEpics.start(dispatcher=dispatcher)

⚠️ Breaking Changes

  • Initialization is now done with RevPiEpics.init() instead of RevPiEpics()
  • The start() method is now static
  • No need to manually call builder.LoadDatabase() and softioc.iocInit()

🔧 Migration

  1. Replace RevPiEpics() with RevPiEpics.init()
  2. Use RevPiEpics.builder() directly (static method)
  3. Call RevPiEpics.start() instead of instance.start()
  4. Remove manual calls to builder.LoadDatabase() and softioc.iocInit()

🐛 Bug Fixes

  • Improved IO type management
  • Optimized update loop
  • Better initialization error handling

📖 Documentation

  • Complete examples for cothread and asyncio
  • Detailed installation instructions
  • Advanced PV configuration

Compatibility: Revolution Pi (Connect 5/4/S/SE, Core S/SE) + AIO Extension Modules
Requirements: 64-bit OS, PiCtory configuration
Dependencies: pythonSoftIOC, revpimodio2