Home Contents | # Using µBus Devices | Lua | Application Notes

## ABSTRACT

Using input/output devices that use the µBus Packet Protocol (MUPP) with the V4 controller series.

## SCOPE

This application note applies to the range of Multi-IO products:

eemio | 8 Relays, 8 Optocouplers, 150W Power Supply
fpmio | 16 Transistor Out, 16 Logic In
cnmio | 4 Relays, 4 Optocouplers, DIN-Rail case

## INTERFACING

All IO modules attach using a serial interface. Most modules are available in two models, µBus and RS485.

µBus is a proprietary interface using a 10-way flat-ribbon cable. It is meant for short range inside a common enclosure. The V4 Controller has a µBus connector, while the V4½ does not support µBus.

RS485 is the industry standard serial interface that allows wiring lengths of up to 1200m.

## INITIALIZATION

Each IO module has a unique network address in the range of 1 to 255. This address is configured on the module, using DIP or rotary switches. See the module specific documentation for locating these switches. When attaching multiple modules to a single bus, make sure each module has a unique address configured.

To use a modue with Lua, it needs to be registered with the GPIO subsystem (See gpio.register()).

#include <lua/gpio.h> gpio.register(grpid, GPGRP_MUPP, device, address)

grpid is a user selected identifier that is later used to access the registered module. This value must be 256 or larger. It is recommended to start at 1000.
device indicates the name of the serial port used. For example, the RS485 interface of the V4½ controller is "/dev/ttyS1" while the µBus connector of the V4 controller is named "/dev/mubus".
address specifies the network address that was configured on the IO module.

The following example registers device number 1 on the RS485 interface of a V4½ controller:

#include <lua/gpio.h> gpio.register(1001, GPGRP_MUPP, "/dev/ttyS1", 1)

Note that a group number of 1001 was chosen, to keep a clean numbering system.

Once registered, the operating system starts polling the node and will report an event when the device is detected on the bus.

## OUTPUTS

Outputs can be turned on or off, can emit a pulse and can be made to blink. Pulse and blinking are handled by the module itself. This makes sure that a pulse will complete as requested, even if the bus connection fails during the pulse time.

This is an overview of the commands available for output control:

- gpio.out()
- gpio.pulse()
- gpio.blink()

For example, let's emit a one-second pulse on output 0 of the device number 1 that was registered in the example above:

gpio.pulse(1001, 0, 1000)

## INPUTS

Inputs are automatically polled and buffered by the operating system as fast as the bus goes (This is usually 19200 bits per second.) The application can read the state of a single input by calling gpio.input() or it can read all inputs of a node as a binary pattern with gpio.inputs().

These commands return the input state of the last poll round, and therefore take negligible execution time on their own. Be aware however, that the returned state might already be a few ms old.

As an example, this prints the state of the first input of the device number 1 that was registered in the example above:

print(gpio.input(1001, 0))

## EDGE DETECTION

Reading inputs directly is simple and straightforward. It has a disadvantage however. If an input changes from off -> on -> off between two readings, the intermediate on state will be invisible to the application. This is no problem for some use cases, but will be bad for others.

In order to detect all input state changes, each module does automatic edge detection on its own. Rising and falling edges on an input are detected and reported to the application via gpio events.

Inputs are debounced, so there is a minimum pulse with of a few tens of milliseconds for a state change to be detected.

Any inputs for which edge detection is required must be registered by calling gpio.watch(). For example, to watch the first four inputs of the device number 1 that was registered in the example above. call:

gpio.watch(1001, 0, GPIO_WATCH_ANY) gpio.watch(1001, 1, GPIO_WATCH_ANY) gpio.watch(1001, 2, GPIO_WATCH_ANY) gpio.watch(1001, 3, GPIO_WATCH_ANY)

## EVENTS

Event driven programming allows the application to detect events of interest in an automatic way.

- A module is detected on the bus
- Communication with a module fails
- An input changes state

### Event handler initialization

To start processing events, a gpio event handler must be registered (See gpio.new()). There is always exactly one gpio event handler per application which handles all gpio events.

gpevh = gpio.new(app, gpio_event)

app is the global application event handler instance, for details, see the event:poll() command.
gpio_event is the name of a user defined callback function that will be called whenever an event needs to be reported. The callback has one argument, a table describing the event.

### Module detection or failure reporting

Whenever a module is detected on the bus, and also when communication fails, the event report looks like this.

Name | Description
--- | ---
group | GPGRP_MUPP
type | This is GPIO_ACTIVE to report a detected node and GPIO_INACTIVE to detect a failed communication.
value | The group number under which the module was registered. Sticking to our example above, this would be 1001 in that case.

### Input event reporting

When a module is detected, the initial state of the inputs is reported first, to get a clean start.

Name | Description
--- | ---
group | The group number under which the module was registered. Sticking to our example above, this would be 1001 in that case.
type | This is either GPIO_OFF or GPIO_ON to indicate the state of the input.
pin | The pin number of the input (starting at zero for the first pin).

Then, each time an input changes state, the change is reported.

Name | Description
--- | ---
group | The group number under which the module was registered. Sticking to our example above, this would be 1001 in that case.
type | This is either GPIO_FALLING to indicate a change from on to off, or GPIO_RISING to indicate a change from off to on.
pin | The pin number of the input (starting at zero for the first pin).
rising | The number of rising edges since the last report. This is a 16bit value that rolls over to 0 after 65535.
falling | The number of falling edges since the last report. This is a 16bit value that rolls over to 0 after 65535.

## SAMPLE PROJECT

There is a sample project that shows registering a device and polling for input changes.

The project assumes a V4½ controller with a module connected to the RS485 interface on ttyS1. To use a V4, change the device name at the top of the main.lua file.

You can view the example main lua file, download example project MuppDemo or browse the project contents online.