Detailed Description
Functional Description
The IOU09 has 8 analog inputs, grouped in 4 groups of 2 channels each. Each group has an integrated sensor power supply, separate connector and a separate galvanic isolation to the host system.
The two channels of a group are sampled simultaneously, so they must use the same sampling rate. However, the gain can be set individually per channel.
Supported sample rates
- 61,0351 Hz (default)
- 122,0703 Hz
- 244,140 Hz
- 488,281 Hz
- 976,562 Hz
- 1953,125 Hz
- 3906,250 Hz
Note
Due to internal limitations, only one group can be sampled with the highest sample rate. The other groups must use a lower sample rate. However, it is possible to sample all groups with 1953,125 Hz or lower.
Trying to sample more than one group with 3906,250 Hz may result in firmware restarts or lost samples.
Supported gains
Each channel can be individually configured with one of the following gain values:
- 1 (default)
- 2
- 4
- 8
- 16
- 32
- 64
- 128
Measurement Types and Ranges
Each channel can measure either voltage or current. The measurement type is just defined by the wiring of the input connector.
Electrical characteristics:
- Voltage input: 100 kOhm impedance
- Current input: 50 Ohm shunt resistor to ground
Warning
Do not connect voltage and current input pin of the same channel at the same time.
The following table shows the nominal input ranges, for different gain settings:
| Measurement Type | Gain | Nominal Input Range |
|---|---|---|
| Voltage - via Ux pin | 1 | +/-10 V |
| Current - via Ix pin | 1 | +/-20 mA |
| Voltage - via Ux pin | 2 | +/-5 V |
| Current - via Ix pin | 2 | +/-10 mA |
| Voltage - via Ux pin | 4 | +/-2.5 V |
| Current - via Ix pin | 4 | +/-5 mA |
| Voltage - via Ux pin | 8 | +/-1.25 V |
| Current - via Ix pin | 8 | +/-2.5 mA |
| Voltage - via Ux pin | 16 | +/-0.625 V |
| Current - via Ix pin | 16 | +/-1.25 mA |
| Voltage - via Ux pin | 32 | +/-0.3125 V |
| Current - via Ix pin | 32 | +/-0.625 mA |
| Voltage - via Ux pin | 64 | +/-0.15625 V |
| Current - via Ix pin | 64 | +/-0.3125 mA |
| Voltage - via Ux pin | 128 | +/-0.078125 V |
| Current - via Ix pin | 128 | +/-0.15625 mA |
The API delivers measurement values scaled to the nominal input range, i.e. a value of 1.0 represents the maximum of the nominal input range, and a value of -1.0 represents the minimum of the nominal input range.
Behavior on Out-of-Range Input
The ADCs can measure up to the nominal input range * 1.2, i.e. up to +/-12 V for voltage measurement with gain 1, or up to +/-24 mA for current measurement with gain 1.
If the input voltage or current exceeds the maximum input range, the measured value is saturated to the maximum value of the range. For example, if a voltage of +13 V is applied to a channel with gain 1, the measured value is +1.2.
Sensor Supply
Each group has a 24 V/50 mA sensor supply output, which can be used to power external sensors.
Anti-Aliasing Filter
Each channel has a built-in low-pass filter to suppress aliasing effects. The aliasing filter is selected automatically according to the sample rate.
Connection
Each analog group has its own connector with the following pinout:
| Pin | Symbol | Description |
|---|---|---|
| 1 | +24V | Supply Voltage Output |
| 2 | Ux | First voltage input of the group |
| 3 | Ix | First current input of the group |
| 4 | Ux+1 | Second voltage input of the group |
| 5 | Ix+1 | Second current input of the group |
| 6 | GND | Ground |
LED Indicators
Each channel has a LED which can display the following states:
- Yellow: channel is almost zero (between -0.1 and +0.1 of nominal range)
- Red: channel overrange (above +1.0 or below -1.0 of nominal range)
- Green otherwise
API Description
The IOU09 implements the AnalogInTypeB function block, that presents all 8 channels within one function block instance.
The function block offsers:
- Configuration of sample rate and gain per channel
- Start/Stop of sampling per channel
- Data stream with sampled values
- Reading the last sampled value of all channels (without starting a stream)
Using the io4edge API to access the Analog Input Function
First, install the io4edge client library.
Want to have a quick look to the examples? See our Github repository.
First, install the io4edge client library.
Want to have a quick look to the examples? See our Github repository.
Connect to the Analog Input Function
To access the Analog Inputs, create a Client and save it to the variable c. Pass as address either a service address or an ip address with port. Example:. Example:
- As a service address:
S101-IOU09-USB-EXT-1-anain - As an IP/Port: e.g.
192.168.201.1:10000
We need this client variable for all further access methods.
import (
"fmt"
"os"
"strconv"
"time"
log "github.com/sirupsen/logrus"
"github.com/ci4rail/io4edge-client-go/v2/pkg/protobufcom/common/functionblock"
anain "github.com/ci4rail/io4edge-client-go/v2/pkg/protobufcom/functionblockclients/analogintypeb"
fspb "github.com/ci4rail/io4edge_api/analogInTypeB/go/analogInTypeB/v1"
)
func main() {
const timeout = 0 // use default timeout
c, err = anain.NewClientFromUniversalAddress(("S101-IOU09-USB-EXT-1-anain", timeout)
if err != nil {
log.Fatalf("Failed to create anain client: %v\n", err)
}
...
To access the analog inputs, create a Client and save it to the variable ana_client. Pass as address either a service address or an ip address with port. Examples:
- As a service address:
S101-IOU09-USB-EXT-1-anain - As an IP/Port:
192.168.201.1:10000
We need this client variable for all further access methods.
import io4edge_client.analogintypeb as ana
import io4edge_client.functionblock as fb
def main():
ana_client = ana.Client("S101-IOU09-USB-EXT-1-anain")
...
Configuring Channels
To configure a one or more channels, provide a "channel configuration" array to the UploadConfiguration method. Each entry in the array defines the configuration for one channel. The gain can be set individually per channel, but the sample rate must be the same for both channels of a group. If it is not, the latest sample rate for the group is used.
The gain value must exactly match one of the supported gain values.
The sample does not need to exactly match one of the supported sample rates, the closest supported sample rate is used.
Channels that are not included in the configuration array are not changed.
// configure channel 0 with sample rate 122.0703 Hz and gain 1
// configure channel 1 with sample rate 122.0703 Hz and gain 2
err = c.UploadConfiguration([]*fspb.ChannelConfig{
{
Channel: 0,
SampleRate: 122.0703,
Gain: 1,
},
{
Channel: 1,
SampleRate: 122.0703,
Gain: 2,
},
})
if err != nil {
...
}
# configure channel 0 with sample rate 122.0703 Hz and gain 1
# configure channel 1 with sample rate 122.0703 Hz and gain 2
config = ana.Pb.ConfigurationSet()
config.channelConfig.add(channel=0, sample_rate=122.0703, gain=1)
config.channelConfig.add(channel=1, sample_rate=122.0703, gain=2)
ana_client.upload_configuration(config)
Reading the latest Sampled Values
For slow or DC measurements, it may be sufficient to read the latest sampled values without starting a stream.
Still, the channels are sampled continuously with the configured sample rate and gain, and the latest sampled value is always available.
values, err := c.Values()
if err != nil {
...
}
for i, val := range values {
fmt.Printf("Current value channel %d: %.4f\n", i, val)
}
values = ana_client.value()
ch = 0
for value in values:
print(f"Ch{ch}: {value: .3f}")
ch += 1
Streamed Sampling
In data logger applications, you may want to record the waveforms on the analog inputs.
Start a Stream
Therefore, the API provides functions to start a Stream. You can select which channels include in the stream.
// start stream
err = c.StartStream(
anain.WithFBStreamOption(functionblock.WithBucketSamples(400)),
anain.WithFBStreamOption(functionblock.WithBufferedSamples(800)),
anain.WithChannelMask(0x03), // include channel 0 and 1 in stream
)
ana_client.start_stream(
0x03, # include channel 0 and 1 in stream
fb.Pb.StreamControlStart(
bucketSamples=400,
keepaliveInterval=1000,
bufferedSamples=800,
low_latency_mode=False,
),
)
Receive Samples from Stream
Then, Samples are generated with the configured sample rate in the stream, each sample contains one more values.
- A timestamp of the sample
- The base channel number of the values (e.g. 0 for channel 0 and 1, 2 for channel 2 and 3, etc.)
- Measured values
For efficiency, multiple samples are gathered and sent as one Bucket to the host.
To read samples from the stream:
...
for {
// read next bucket from stream
sd, err := c.ReadStream(time.Second * 1)
if err != nil {
log.Errorf("ReadStreamData failed: %v\n", err)
} else {
samples := sd.FSData.GetSamples()
fmt.Printf("got stream data seq=%d ts=%d\n", sd.Sequence, sd.DeliveryTimestamp)
for i, sample := range samples {
fmt.Printf(" #%d: ts=%d ch %d", i, sample.Timestamp, sample.BaseChannel)
for _, value := range sample.Value {
fmt.Printf(" %.4f", value)
}
fmt.Printf("\n")
}
}
}
while True:
generic_stream_data, stream_data = ana_client.read_stream()
print(
f"Received stream data {datetime.datetime.now()} {generic_stream_data.deliveryTimestampUs}, {generic_stream_data.sequence}"
)
for sample in stream_data.samples:
print(
" #%d: ts=%d ch %d %s"
% (n, sample.timestamp, sample.baseChannel, sample.value) # note that sample.value is a list
)
n += 1
Warning
At the moment, timestamps are expressed in microseconds relative to the start of the IOU09. Future client libraries will map the time to the host's time domain.
Controlling the Stream
The stream behavior can be fine-tuned to the application needs. If you do not specify any parameters, the default values are used.
- The
BucketSamplesparameter (default:25) defines the number of samples per bucket. If the bucket containsBucketSamples, it is sent to the client. - The
KeepAliveIntervalparameter (default:1000) defines the maximum time in ms between two buckets. If the bucket is not full, it is sent after the configured interval. - The
BufferedSamplesparameter (default:50) defines the number of samples that can be buffered in the device. If the buffer is full, the oldest samples are overwritten. As a rule of thumb,BufferedSamplesshould be at least two times theBucketSamples. Select a higher number if your reception process is slow to avoid buffer overruns.
// configure stream to send the bucket at least once a second
// configure the maximum samples per bucket to 400
// configure the buffered samples to 800
err = c.StartStream(
anain.WithFBStreamOption(functionblock.WithKeepaliveInterval(1000)),
anain.WithFBStreamOption(functionblock.WithBucketSamples(400)),
anain.WithFBStreamOption(functionblock.WithBufferedSamples(800)),
anain.WithChannelMask(0x03), // include channel 0 and 1 in stream
)
The stream behavior can be fine-tuned to the application needs:
-
The
bucketSamplesparameter defines the number of samples per bucket. If the bucket containsbucketSamples, it is sent to the client. -
The
keepAliveIntervalparameter defines the maximum time in ms between two buckets. If the bucket is not full, it is sent after the configured interval. -
The
bufferedSamplesparameter defines the number of samples that can be buffered in the device. If the buffer is full, the oldest samples are overwritten. As a rule of thumb,bufferedSamplesshould be at least two times thebucketSamples. Select a higher number if your reception process is slow to avoid buffer overruns.
ana_client.start_stream(
0x03, # include channel 0 and 1 in stream
fb.Pb.StreamControlStart(
bucketSamples=400,
keepaliveInterval=1000,
bufferedSamples=800,
low_latency_mode=False,
),
)