CAN Bus Java Documentation with Custom Sensors

Hi guys,

Is there anyone who can provide information on any WPIlib documentation on communicating with custom sensors (IR, Ultrasonic, LIDAR, etc.) between the Robo-rio and the CAN Bus? Our team can’t seem to find any specific documentation on this stuff other than some basic send/receive methods.

Thanks in advance!

David

There aren’t any simple wrapper classes for general-purpose CAN communication in WPILib, mostly because every device is a little different. However, you can technically call the FRCNetworkCommunication functions directly. It would look something like this, but you need to fill in the blanks for device-specific things. I’m also not sure if the message tokenization stuff will interfere with it.


import edu.wpi.first.wpilibj.IterativeRobot;
import edu.wpi.first.wpilibj.can.CANExceptionFactory;
import edu.wpi.first.wpilibj.can.CANJNI;

import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.Arrays;

public class Robot extends IterativeRobot {
    /* Check the datasheets for your device for the arbitration IDs of the
        messages you want to send.  By convention, this is a bitstring
        containing the model number, manufacturer number, and api number. */
    private static final int MESSAGE1_ARB_ID = 0x1;
    private static final int MESSAGE2_ARB_ID = 0x2;

    /*  Device ID, from 0 to 63. */
    private static final int DEVICE_NUMBER = 1;

    private IntBuffer status = ByteBuffer.allocateDirect(4).asIntBuffer();
    private IntBuffer messageId = ByteBuffer.allocateDirect(4).asIntBuffer();
    private ByteBuffer data = ByteBuffer.allocateDirect(8);
    private ByteBuffer timestamp = ByteBuffer.allocate(4);

    /**
     * Send a message once when the robot program starts
     */
    public void robotInit() {
        /* Again, see the datasheet for the device you're using.  It should
            specify what data to put here. */
        data.clear();
        data.putFloat(3.14f);
        data.putInt(3);
        data.putChar('a');

        /* Alternatively, instead of CAN_SEND_PERIOD_NO_REPEAT, you can specify
            a period in milliseconds to automatically send the message over
            and over again. */
        status.clear();
        CANJNI.FRCNetworkCommunicationCANSessionMuxSendMessage(
                MESSAGE1_ARB_ID | DEVICE_NUMBER,
                data,
                CANJNI.CAN_SEND_PERIOD_NO_REPEAT,
                status
        );
        CANExceptionFactory.checkStatus(status.get(0), MESSAGE1_ARB_ID);
    }

    /**
     * Check for an incoming message periodically, and print it out if one
     * arrives.
     */
    @Override
    public void teleopPeriodic() {
        /* To receive a message, put the message ID you're looking for in this
            buffer.  CANJNI...ReceiveMessage  will not block waiting for it,
            but just return null if it hasn't been received yet. */
        messageId.clear();
        messageId.put(0, MESSAGE2_ARB_ID | DEVICE_NUMBER);

        status.clear();
        ByteBuffer data = CANJNI.FRCNetworkCommunicationCANSessionMuxReceiveMessage(
                messageId,
                CANJNI.CAN_MSGID_FULL_M,
                timestamp,
                status
        );

        if (data != null) {
            CANExceptionFactory.checkStatus(status.get(0), MESSAGE1_ARB_ID);
            System.out.println("Received a message: " + Arrays.toString(data.array()));
        }
    }
}

Thanks!

Do you know if there’s anyway to actually use the data from the sensors (as like a variable) and manipulate it? Or can we only just print these messages?

Thomas’s example demonstrates how to send and receive CAN frames (nice job!). What goes into and out of the frames depends on what CAN device you want to talk to. Wpilib uses this to implement support for …
CAN Talon SRX
CAN Jaguar
…but you can write your own logic to support other CAN devices (As long as they are legal).

Did you have something specific in mind?

Also if you’re just trying to get more analog channels easily, you can wire to the analog input of the Talon SRX and grab its decoded analog value over CAN bus. See software reference manual for details.

Good point. Our team was playing around with reading data from custom sensors (not the motor controllers) like LIDAR, IR etc. I guess we have to write our own logic to support this?

Are these CAN sensors or analog sensors?