You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
4.4 KiB
116 lines
4.4 KiB
//! Steuerung für die Ventilinseln
|
|
//!
|
|
//! Verbindet sich dynamisch mit einer Ventilinsel, die am Bus unter beliebiger Adresse gefunden
|
|
//! wurde. Es wird eine bekannte Parametrierung vorausgesetzt.
|
|
//!
|
|
//! Zur demo ist hier eine CPV14 mit CPV14-GE-DI02-8 Anschaltung vorgesehen.
|
|
|
|
use profirust::dp;
|
|
|
|
// "Festo CPV-DI02" by "Festo AG&Co."
|
|
const VALVE_TERMINAL_IDENT_NUMBER: u16 = 0x0a35;
|
|
|
|
pub struct ValveTerminal {
|
|
peripheral: dp::PeripheralHandle,
|
|
address: profirust::Address,
|
|
valve_states: [bool; 8],
|
|
}
|
|
|
|
impl ValveTerminal {
|
|
pub fn new(dp_master: &mut dp::DpMaster, baudrate: profirust::Baudrate) -> Self {
|
|
// Als erstes wird die Ventilinsel mit einer Standard-Adresse parametriert. Die Adresse
|
|
// wird dann später geändert, sobald ein tatsächliches Gerät auf dem Bus gefunden wurde.
|
|
let default_address = 42;
|
|
|
|
// Options generated by `gsdtool` using "cpv_0A35.gse"
|
|
let options = profirust::dp::PeripheralOptions {
|
|
// "Festo CPV-DI02" by "Festo AG&Co."
|
|
ident_number: 0x0a35,
|
|
|
|
// Global Parameters:
|
|
// (none)
|
|
//
|
|
// Selected Modules:
|
|
// [0] Base module:16DO
|
|
// - monitor U-Load.........: active
|
|
// - monitor failure CP-Line: inactive
|
|
// - fault mode.............: reset outputs
|
|
// - fault state 2 byte.....: 0
|
|
user_parameters: Some(&[0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00]),
|
|
config: Some(&[0x21]),
|
|
|
|
// Set max_tsdr depending on baudrate and assert
|
|
// that a supported baudrate is used.
|
|
max_tsdr: match baudrate {
|
|
profirust::Baudrate::B9600 => 20,
|
|
profirust::Baudrate::B19200 => 20,
|
|
profirust::Baudrate::B93750 => 20,
|
|
profirust::Baudrate::B187500 => 20,
|
|
profirust::Baudrate::B500000 => 20,
|
|
profirust::Baudrate::B1500000 => 25,
|
|
profirust::Baudrate::B3000000 => 50,
|
|
profirust::Baudrate::B6000000 => 100,
|
|
profirust::Baudrate::B12000000 => 200,
|
|
b => panic!("Peripheral \"Festo CPV-DI02\" does not support baudrate {b:?}!"),
|
|
},
|
|
|
|
fail_safe: false,
|
|
..Default::default()
|
|
};
|
|
let buffer_inputs = vec![0u8; 0].leak();
|
|
let buffer_outputs = vec![0u8; 2].leak();
|
|
let buffer_diagnostics = vec![0u8; 16].leak();
|
|
let handle = dp_master.add(
|
|
dp::Peripheral::new(default_address, options, buffer_inputs, buffer_outputs)
|
|
.with_diag_buffer(buffer_diagnostics),
|
|
);
|
|
|
|
Self {
|
|
peripheral: handle,
|
|
address: default_address,
|
|
valve_states: [false; 8],
|
|
}
|
|
}
|
|
|
|
/// Überprüfen ob ein gefundenes Gerät eine Ventilinsel von unserem Typ ist
|
|
pub fn check_ident(&self, ident: u16) -> bool {
|
|
ident == VALVE_TERMINAL_IDENT_NUMBER
|
|
}
|
|
|
|
/// Gibt `true` zurück wenn die Ventilinsel an der aktuell parametrierten Adresse erfolgreich
|
|
/// kommuniziert.
|
|
pub fn is_running(&self, dp_master: &mut dp::DpMaster) -> bool {
|
|
let peripheral = dp_master.get_mut(self.peripheral);
|
|
peripheral.is_running()
|
|
}
|
|
|
|
pub fn init_at_address(&mut self, address: profirust::Address, dp_master: &mut dp::DpMaster) {
|
|
if address != self.address {
|
|
let peripheral = dp_master.get_mut(self.peripheral);
|
|
peripheral.reset_address(address);
|
|
peripheral.pi_q_mut().fill(0u8);
|
|
self.valve_states = [false; 8];
|
|
}
|
|
}
|
|
|
|
pub fn update_valve_states(&mut self, valve_states: &[bool]) {
|
|
if self.valve_states != valve_states {
|
|
self.valve_states.copy_from_slice(valve_states);
|
|
log::info!("Ventile: {:?}", valve_states);
|
|
}
|
|
}
|
|
|
|
pub fn update(&mut self, dp_master: &mut dp::DpMaster, events: &dp::DpEvents) {
|
|
let peripheral = dp_master.get_mut(self.peripheral);
|
|
if peripheral.is_running() && events.cycle_completed {
|
|
let pi_q = peripheral.pi_q_mut();
|
|
pi_q.fill(0);
|
|
for (i, valve) in self.valve_states.iter().enumerate() {
|
|
let bit_index = i * 2;
|
|
let bit_value = if *valve { 1 } else { 0 };
|
|
pi_q[bit_index / 8] |= bit_value << (bit_index % 8);
|
|
}
|
|
}
|
|
}
|
|
}
|