Custom I/O
Contents
rPLC allows to spawn custom input and output tasks for unsupported-out-of-the-box I/O protocols.
Let us review an example of a custom I/O which handles GPIO bus on Raspberry Pi-compatible boards which simply routes GPIO #1 input signal to GPIO output #3 and GPIO #2 input to GPIO #4.
plc.yml
version: 1
context:
fields:
in1: BOOL
in2: BOOL
out1: BOOL
out2: BOOL
main.rs
Note
As well as program threads, I/O threads can not have names longer than 14 symbols.
use rplc::prelude::*;
use rppal::gpio::Gpio;
use std::time::Duration;
mod plc;
const GPIO_IN1: u8 = 1;
const GPIO_IN2: u8 = 2;
const GPIO_OUT1: u8 = 3;
const GPIO_OUT2: u8 = 4;
#[plc_program(loop = "500ms")]
fn pinroute() {
let mut ctx = plc_context_mut!();
ctx.out1 = ctx.in1;
ctx.out2 = ctx.in2;
}
fn gpio_input_spawn() {
let pin_in1 = Gpio::new().unwrap().get(GPIO_IN1).unwrap().into_input();
let pin_in2 = Gpio::new().unwrap().get(GPIO_IN2).unwrap().into_input();
rplc::tasks::spawn_input_loop(
"gpio",
Duration::from_millis(500),
Duration::default(),
move || {
let in1 = pin_in1.is_high();
let in2 = pin_in2.is_high();
let mut ctx = plc_context_mut!();
ctx.in1 = in1;
ctx.in2 = in2;
},
);
}
fn gpio_output_spawn() {
let mut pin_out1 = Gpio::new().unwrap().get(GPIO_OUT1).unwrap().into_output();
let mut pin_out2 = Gpio::new().unwrap().get(GPIO_OUT2).unwrap().into_output();
rplc::tasks::spawn_output_loop(
"gpio",
Duration::from_millis(500),
Duration::default(),
move || {
let (out1, out2) = {
let ctx = plc_context!();
(ctx.out1, ctx.out2)
};
pin_out1.write(out1.into());
pin_out2.write(out2.into());
},
);
}
fn main() {
init_plc!();
gpio_input_spawn();
gpio_output_spawn();
pinroute_spawn();
run_plc!();
}
Cargo.toml
[package]
name = "custom_io_rpi_gpio"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rplc = "0.3.0"
rppal = "0.14.1"
[build-dependencies]
rplc = "0.3.0"
build.rs
fn main() {
rplc::builder::generate("plc.yml").unwrap();
}