[beagleboard] Re: Running CANbus on BBB w/ Chipsee BBB-EXP-C 7" display cape

OK, first I should point out that specific to the beaglebone is not necessary. Linux is Linux, socketCAN is socketCAN.

Second, the github project for socketCAN / can-utils has example code. But I found that for me personally the examples were rather terse reading.

https://github.com/linux-can/can-utils

Thirdly, I found once I started learning more about socketCAN, that I could google keywords like “frame->can_id” ( struct can_frame frame; ) that I could find example code, that would help me understand things better.

Last, but not least. all but excessive google sessions on every variation of different keywords to find out what I needed to understand. All that, and I’m still learning.

This link http://fabiobaltieri.com/2013/07/23/hacking-into-a-vehicle-can-bus-toyothack-and-socketcan/ Helped me understand various things early on, and gave me some rough ideas as to how I could reverse engineer the protocol our external CAN device uses. While at the same time, my buddy a long time oldschool electronics engineer, reversed the protocol by hand to find out which protocol it was, the actual meanings of various fields. Close enough to where I have a much better understanding of things like, what the can_id fields actually means for our protocol. Then stuff like the basics of how the frame->data payload(s) are structured.

In short, the protocol our device uses is much more complex than the one your PLC seems to be using. It’s NEMA 2000 fast packet, and the data most of the time spans multiple CAN frames. For each PGN.Where as your PLC only seems to use single frames per payload. I do not recognize the protocol offhand though . . . seems like it could be based on SAE J1939, but the can_id fields do not look familiar to me.

Anyway, here is a very simple socketCAN example app I wrote to get my own feet wet.

#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <net/if.h>
#include <sys/ioctl.h>

static int sock;

static int can_init(char *ifname){

    struct sockaddr_can addr;
    struct ifreq ifr;

    sock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if (sock < 0){
        perror("Unable to create socket.");
        exit(1);
    }

    memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
    strncpy(ifr.ifr_name, ifname, IFNAMSIZ);

    if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
        perror("SIOCGIFINDEX");
        exit(1);
    }

    memset(&addr, 0, sizeof(addr));
    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;
    if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0){
        perror("Unable to bind to socket");
        exit(1);
    }

    return 0;
}

static void read_can_frame(void){

    struct can_frame frame;
    int nbytes;
    int i;

    nbytes = read(sock, &frame, sizeof(struct can_frame));

    if (nbytes < 0) {
            perror("can raw socket read");
            exit(1);
    }
    printf("  Recv :  %03X      ", frame.can_id);

    for (i = 0; i < frame.can_dlc; i++){

        printf(" %02X", frame.data[i]);
    }

    printf("\n");
}

int main(int argc, char *argv[]) {

    can_init("vcan0");

    while(1){
        read_can_frame();
    }

    return 0;
}

The output is very similar to candump, except that is does not check for:

frame->can_id & CAN_ERR_FLAG, frame->can_id & CAN_EFF_FLAG, 
frame->can_id & CAN_SFF_FLAG

Or mask out the frame->can_id like is done in candump. Thus the 
can_id fields will show differently than is shown from the
candump output. This was pointed out to me by another person, 
after which I was able to correct my test code.

As for GUI apps go. Qt will probably do a good job for you. I’ve never really used it much, and only for simple things on Windows. While toying with it. After watching this series of videos when bored one week . . .

https://www.youtube.com/watch?v=aMUh9DmFLto