1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use profirust::dp;
use profirust::fdl;
use profirust::phy;
// Bus Parameters
const MASTER_ADDRESS: u8 = 3;
const BUS_DEVICE: &'static str = "/dev/ttyUSB0";
const BAUDRATE: profirust::Baudrate = profirust::Baudrate::B500000;
fn main() -> ! {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
.format_timestamp_micros()
.init();
log::info!("PROFIBUS Multi-Application Example");
let mut dp_scanner = dp::scan::DpScanner::new();
let mut dp_master = dp::DpMaster::new(vec![]);
// Options generated by `gsdtool` using "wagob757.gsd"
let options = profirust::dp::PeripheralOptions {
// "WAGO 750-343" by "WAGO Kontakttechnik GmbH"
ident_number: 0xb757,
// Global Parameters:
// - DP-Watchdog-Base...............: 10 ms
// - Restart on K-Bus Failure.......: POWER ON RESET
// - Device Diagnosis...............: enabled
// - Process Data Representation....: MOTOROLA (MSB-LSB)
// - Response to PROFIBUS DP Failure: Substitude Values are switched
// - Response to K-Bus Failure......: PROFIBUS communication stops
//
// Selected Modules:
// [0] 750-343 No PI Channel
// [1] 750-504 4 DO/24 V DC/0.5 A
// - Terminal is physically....: plugged
// - Substitude Value Channel 1: 0
// - Substitude Value Channel 2: 0
// - Substitude Value Channel 3: 0
// - Substitude Value Channel 4: 0
// [2] 750-402 4 DI/24 V DC/3.0 ms
// - Terminal is physically: plugged
// [3] 750-469 2 AI/TC/OCM
// - Terminal is physically: plugged
// - Diagnosis Channel 1...: disabled
// - Diagnosis Channel 2...: disabled
user_parameters: Some(&[
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2b, 0x00, 0x21, 0x02, 0x00, 0x21, 0x01, 0x00,
0x20, 0x53, 0x01, 0x06,
]),
config: Some(&[0x00, 0x20, 0x10, 0x51]),
// Set max_tsdr depending on baudrate and assert
// that a supported baudrate is used.
max_tsdr: match BAUDRATE {
profirust::Baudrate::B9600 => 60,
profirust::Baudrate::B19200 => 60,
profirust::Baudrate::B93750 => 60,
profirust::Baudrate::B187500 => 60,
profirust::Baudrate::B500000 => 100,
profirust::Baudrate::B1500000 => 150,
profirust::Baudrate::B3000000 => 250,
profirust::Baudrate::B6000000 => 350,
profirust::Baudrate::B12000000 => 550,
b => panic!("Peripheral \"WAGO 750-343\" does not support baudrate {b:?}!"),
},
fail_safe: true,
..Default::default()
};
let mut buffer_inputs = [0u8; 5];
let mut buffer_outputs = [0u8; 1];
let mut buffer_diagnostics = [0u8; 64];
let handle_io_wago = dp_master.add(
dp::Peripheral::new(8, options, &mut buffer_inputs[..], &mut buffer_outputs[..])
.with_diag_buffer(&mut buffer_diagnostics[..]),
);
let mut fdl = fdl::FdlActiveStation::new(
fdl::ParametersBuilder::new(MASTER_ADDRESS, BAUDRATE)
// We use a rather large T_slot time because USB-RS485 converters
// can induce large delays at times.
.slot_bits(4000)
.max_retry_limit(3)
// .token_rotation_bits(512)
.build(),
);
// Read more about timing considerations in the SerialPortPhy documentation.
let sleep_time = std::time::Duration::from_micros(3500);
log::info!("Connecting to the bus...");
let mut phy = phy::SerialPortPhy::new(BUS_DEVICE, fdl.parameters().baudrate);
fdl.set_online();
dp_master.enter_operate();
loop {
fdl.poll_multi(
profirust::time::Instant::now(),
&mut phy,
&mut [&mut dp_master, &mut dp_scanner],
);
let dp_events = dp_master.take_last_events();
if dp_events.cycle_completed {
let io = dp_master.get_mut(handle_io_wago);
if io.is_running() {
log::debug!("WAGO Inputs: {:?}", io.pi_i());
if io.pi_q_mut()[0] == 0x55 {
io.pi_q_mut()[0] = 0xAA;
} else {
io.pi_q_mut()[0] = 0x55;
}
}
}
let scanner_event = dp_scanner.take_last_event();
match scanner_event {
Some(dp::scan::DpScanEvent::PeripheralFound(desc)) => {
log::info!("Discovered peripheral #{}:", desc.address);
log::info!(" - Ident: 0x{:04x}", desc.ident);
log::info!(" - Master: {:?}", desc.master_address);
}
Some(dp::scan::DpScanEvent::PeripheralLost(address)) => {
log::info!("Lost peripheral #{}.", address);
}
_ => (),
}
std::thread::sleep(sleep_time);
}
}