Skip to main content

Crate pamoja_can

Crate pamoja_can 

Source
Expand description

CAN for the pamoja SDK: the frames, J1939, and a node on a bus.

CAN is the bus that connects the moving parts of a machine: motor controllers, servos, battery management, and the engines, gensets, and farm equipment that speak J1939 on top of it. It is how a robot or a vehicle’s pieces talk to each other reliably over a short, noisy two-wire link, which is why it is the SDK’s path to actuators and to the diesel-and-hydraulic world of rural machinery.

The byte layer needs no controller and no allocation:

  • CanId - a standard 11-bit or extended 29-bit identifier, always masked to width.
  • Frame - a classic CAN 2.0 frame, a CAN-FD frame at the discrete CAN-FD lengths, or a remote frame, with len_to_dlc and dlc_to_len for the length encoding CAN-FD uses above eight bytes.
  • J1939Id - the priority, parameter group, and addresses J1939 packs into a 29-bit identifier, decoded from one and composed back into one.
  • Signals - the eight data bytes of a J1939 frame, read and written by the offsets its parameter group publishes, starting every signal as not available.

The controller hardware handles the wire itself (arbitration, bit timing, the frame CRC); this is the identifier and payload layer above it, the part an application actually reasons about.

With the bus feature, bus::CanBus is one node’s place on a bus: a bus simulated inside the program, or with the linux feature, a kernel interface such as can0 through SocketCAN. A node hears every frame the others send and none of its own, and keeps the ones its bus::Filters pass, by identifier or by J1939 parameter group.

§Examples

use pamoja_can::{CanId, Frame, J1939Id, Signals};

// A classic frame: the motor controller at identifier 0x20A told to run at 500 rpm,
// sent big-endian as its protocol asks.
let command = Frame::new(CanId::standard(0x20A), &500u16.to_be_bytes())?;
assert_eq!(command.dlc(), 2);

// A J1939 broadcast: a genset's engine controller, at source address 0, reports its
// speed in EEC1, parameter group 61444. The speed sits in bytes 4 and 5 of the payload,
// offset 3 counting from zero, at 0.125 rpm per bit, and every signal the controller does
// not report stays marked not available.
const EEC1: u32 = 61_444;
let mut payload = Signals::new();
payload.set_u16(3, (1500.0 / 0.125) as u16);
let report = Frame::new(J1939Id::broadcast(3, EEC1, 0).to_id(), payload.as_bytes())?;

// A listener reads the group from the identifier and the speed from the payload.
let heard = J1939Id::from_id(report.id()).expect("an extended identifier");
assert_eq!(heard.pgn(), EEC1);
assert!(heard.is_broadcast());
let speed = report.signals().and_then(|signals| signals.u16(3)).expect("a speed");
assert_eq!(f64::from(speed) * 0.125, 1500.0);

Modules§

bus
One CAN bus, joined by each node on it.
priority
The priorities J1939 conventionally assigns.

Structs§

CanId
A CAN arbitration identifier.
Frame
A CAN frame: an identifier and its data.
J1939Id
The fields a J1939 message packs into its 29-bit identifier.
Signals
The eight data bytes of a J1939 frame.

Enums§

CanError
What can go wrong building a CAN frame.

Constants§

BROADCAST_ADDRESS
The destination address that means every node on the bus.
NOT_AVAILABLE
The byte a J1939 sender writes for a signal it is not reporting.

Functions§

dlc_to_len
Maps a data-length code to the number of bytes it represents.
len_to_dlc
Maps a data length to the data-length code that represents it.