Unable to send a message CAN from a PC with Linux (Ubuntu) to a module CANable (usb to can) with C++ code

73 Views Asked by At

I am using a C++ library with the following code:

#include <linux/can.h>
#include <linux/can/raw.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstring>
#include <net/if.h>
#include <sys/ioctl.h>
#include <vector>
#include <iostream>
#include <stdexcept>
#include <cstdio>

class Can {
private:
    int socket_fd;
    struct sockaddr_can addr;
    struct ifreq ifr;

public:
    Can() {
        system("modprobe can");
        system("modprobe can-dev");
        system("modprobe can-raw");
        system("modprobe slcan");

        system("sudo slcand -o -c -s8 /dev/ttyACM1 can0"); //have to install slcand
        //-s8 is the speed of the CAN bus 1Mbit/s
        system("sudo ip link set can0 up"); //turnign

        // Creation of the socket CAN
        if ((socket_fd = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
            throw std::runtime_error("Failed to create socket");
        }

        // Bind the socket to one of the interfaces (vcan0 or canx x=0,1):
        struct ifreq ifr;
        struct sockaddr_can addr;

        const char *ifname = "can0";

        // Configuration du socket
        strcpy(ifr.ifr_name, ifname);
        ioctl(socket_fd, SIOCGIFINDEX, &ifr);

        addr.can_family = AF_CAN;
        addr.can_ifindex = ifr.ifr_ifindex;

        if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
            throw std::runtime_error("Failed to bind socket");
        }
    }

    ~Can() {
        close(socket_fd);
    }

    void sendCanMessage(int can_id, const std::vector<uint8_t>& data) {
        struct can_frame frame;
        frame.can_id = can_id;
        frame.can_dlc = data.size();
        std::memcpy(frame.data, data.data(), data.size());

        if (write(socket_fd, &frame, sizeof(frame)) != sizeof(frame)) {
            throw std::runtime_error("Failed to send CAN message");
        }
    }

    void receiveCanMessage() {
        struct can_frame frame;
        int nbytes = read(socket_fd, &frame, sizeof(struct can_frame));
        if (nbytes < 0) {
            throw std::runtime_error("CAN read error");
        } else if (nbytes == sizeof(struct can_frame)) {
            std::cout << "Received CAN message with ID: 0x" << std::hex << frame.can_id << std::dec << " Data: ";
            for (int i = 0; i < frame.can_dlc; i++) {
                std::cout << std::hex << static_cast<int>(frame.data[i]) << " ";
            }
            std::cout << std::endl;
        } else {
            throw std::runtime_error("Incomplete CAN frame received");
        }
    }
};

int main() {
    try {
        Can canInterface;

        std::vector<uint8_t> data(8, 0x0F);
        
        canInterface.sendCanMessage(0x123, data);

        std::cout << "En attente de la réception d'un message CAN..." << std::endl;
        canInterface.receiveCanMessage();

    } catch (const std::exception& e) {
        std::cerr << "Une erreur est survenue : " << e.what() << std::endl;
        return 1;
    }

    return 0;
}

My main goal is to send a CAN message from my PC which is on Linux to a CAN bus trough a CANable module. When I run the code, I get the following error: write: Input/output error

It seems that there is a problem with the method "write". The module CANable works properly, it can send and receive CAN msg (I test it with the linux Terminal).

I am completely new to the protocol CAN. Thanks to all of those who reply in advance.

0

There are 0 best solutions below