Basics

Core concepts and fundamental usage of RevPiModIO.

Programming Paradigms

RevPiModIO supports two complementary programming approaches:

Cyclic Programming - Execute a function at regular intervals, similar to PLC programming.

  • Best for deterministic timing, state machines, and time-critical control

  • Runs your function every cycle (typically 20-50ms)

  • See Cyclic Programming for details

Event-Driven Programming - Register callbacks triggered by hardware state changes.

  • Best for user interactions, sporadic events, and system integration

  • Consumes CPU only when events occur

  • See Event Programming for details

Both approaches can be combined in a single application. See Advanced for examples.

Getting Started

Basic Instantiation

Create a RevPiModIO instance to access your hardware:

import revpimodio2

rpi = revpimodio2.RevPiModIO(autorefresh=True)

# Your code here

rpi.exit()

Configuration Parameters

rpi = revpimodio2.RevPiModIO(
    autorefresh=True,    # Auto-sync process image (recommended)
    monitoring=False,    # Read-only mode
    syncoutputs=True,    # Load output values on init
    debug=False          # Enable debug messages
)

autorefresh - Automatically reads inputs and writes outputs. Set to True for most applications.

monitoring - Read-only mode. Use when monitoring without controlling hardware.

syncoutputs - Load current output values on startup. Prevents outputs from resetting.

debug - Enable debug logging for troubleshooting.

Cycle Timing

Default update rates depend on your hardware:

  • Core 1: 40ms (25Hz)

  • Core3/Connect: 20ms (50Hz)

  • NetIO: 50ms (20Hz)

Adjust cycle time to match your needs:

rpi = revpimodio2.RevPiModIO()
rpi.cycletime = 100  # Set to 100ms
rpi.autorefresh_all()

Important: Faster cycle times consume more CPU. Choose the slowest cycle time that meets your requirements. Default values will fit most needs.

Error Handling

Configure I/O error threshold:

maxioerrors = 10  # Raise exception after 10 errors

# Check error count
if rpi.core.ioerrorcount > maxioerrors:
    print("Warning: I/O errors detected")

Core Objects

rpi.io - Input/Output Access

Access all configured IOs from piCtory:

# Direct attribute access
value = rpi.io.button.value
rpi.io.led.value = True

# String-based access
rpi.io["button"].value

# Check existence
if "sensor" in rpi.io:
    print(rpi.io.sensor.value)

# Iterate all IOs
for io in rpi.io:
    print(f"{io.name}: {io.value}")

IO Properties

Each IO object has these properties:

  • .name - IO name from piCtory

  • .value - Current value (read/write)

  • .address - Byte address in process image

  • .type - IO type (INPUT=300, OUTPUT=301, MEMORY=302)

  • .defaultvalue - Default value from piCtory

rpi.core - System Control

Access Revolution Pi system features:

LED Control

# Using constants
rpi.core.A1 = revpimodio2.GREEN
rpi.core.A2 = revpimodio2.RED
rpi.core.A3 = revpimodio2.OFF

# Individual colors
rpi.core.a1green.value = True
rpi.core.a1red.value = False

System Status

# CPU information
temp = rpi.core.temperature.value
freq = rpi.core.frequency.value

# piBridge status
cycle_time = rpi.core.iocycle.value
errors = rpi.core.ioerrorcount.value

Watchdog

# Toggle watchdog
rpi.core.wd_toggle()

# Watchdog IO object
rpi.core.wd.value = True

See Advanced for complete watchdog management examples.

rpi.device - Device Access

Access specific hardware devices:

# By name
dio = rpi.device.DIO_Module_1

# By position
first = rpi.device[0]

# Iterate
for device in rpi.device:
    print(device.name)

Signal Handling

Graceful Shutdown

Handle SIGINT and SIGTERM for clean program termination:

rpi = revpimodio2.RevPiModIO(autorefresh=True)

# Enable signal handling
rpi.handlesignalend()

# Run main loop
rpi.mainloop()

Custom Signal Handler

Implement custom cleanup logic:

def cleanup(signum, frame):
    print("Shutting down...")
    rpi.setdefaultvalues()
    rpi.exit()

rpi.handlesignalend(cleanup)
rpi.mainloop()

Simple Examples

Read Input, Control Output

import revpimodio2

rpi = revpimodio2.RevPiModIO(autorefresh=True)

# Read input and control output
if rpi.io.button.value:
    rpi.io.led.value = True
else:
    rpi.io.led.value = False

rpi.exit()

LED Control

import revpimodio2

rpi = revpimodio2.RevPiModIO(autorefresh=True)

# Control status LEDs
rpi.core.A1 = revpimodio2.GREEN
rpi.core.A2 = revpimodio2.RED

rpi.exit()

Iterate All IOs

import revpimodio2

rpi = revpimodio2.RevPiModIO(autorefresh=True)

# Print all IOs and their values
for io in rpi.io:
    print(f"{io.name}: {io.value}")

rpi.exit()

Best Practices

Use Descriptive IO Names

Configure descriptive names in piCtory:

# Good - Clear intent
if rpi.io.emergency_stop.value:
    rpi.io.motor.value = False

# Poor - Generic names
if rpi.io.I_15.value:
    rpi.io.O_3.value = False

Always Clean Up

Always call rpi.exit() to clean up resources:

rpi = revpimodio2.RevPiModIO(autorefresh=True)

try:
    # Your code here
    pass
finally:
    rpi.exit()

Check IO Existence

Verify IOs exist before accessing:

if "optional_sensor" in rpi.io:
    value = rpi.io.optional_sensor.value
else:
    print("Sensor not configured")

See Also