KevinOConnor / can2040

Software CAN bus implementation for rp2040 micro-controllers
GNU General Public License v3.0
636 stars 63 forks source link

Need a working example for Remote frame transmission and reception #21

Closed Varghesemela closed 1 year ago

Varghesemela commented 1 year ago

Hello people, I am trying to establish a communication using 2 RPi Picos (VP230) and 1 Arduino UNO (MCP2515) on the same bus. I have tried to run the basic example that was provided on different sources. It works for me for basic transmission. I also have a Picoscope on which i am reading the data where i can see that the transmission on the bus.

Also i would like to implement Remote frame transmission and reception but i feel there is lack of documentation on this aspect. It would be great if someone could provide an example code or their own implementation. Thanks

For reference, this is my implementation of main.c:

include

include

include

include

include

include <pico/stdlib.h>

include <pico/multicore.h>

include <hardware/pio.h>

include <hardware/dma.h>

include <hardware/uart.h>

include <hardware/flash.h>

include <hardware/watchdog.h>

include <pico/bootrom.h>

include <hardware/irq.h>

include

include "hardware/clocks.h"

include <hardware/regs/intctrl.h>

include "can2040.h"

define CANMSG_DATA_LEN(msg) ((msg)->dlc > 8 ? 8 : (msg)->dlc)

typedef struct can2040 CANHandle; typedef struct can2040_msg CANMsg;

static CANHandle cbus; bool flag = 0; uint8_t data_len = 0; uint8_t rbuf[8]; volatile bool cb_called = false; volatile uint32_t cb_notify; struct can2040_msg tx_msg, rx_msg;

/// format CAN message as a string

char msg_to_str(struct can2040_msg msg) {

static char buf[64], buf2[8];

sprintf(buf, "[ %lu ] [ %lu ] [ ", msg->id, msg->dlc);
for (uint32_t i = 0; i < msg->dlc && i < 8; i++) {
sprintf(buf2, "%u ", msg->data[i]);
strcat(buf, buf2);
}
strcat(buf, " ] ");

if (msg->id & CAN2040_ID_RTR) {
strcat(buf, "R");
}

if (msg->id & CAN2040_ID_EFF) {
strcat(buf, "X");
}

return buf;

}

static void can2040_cb(CANHandle cd, uint32_t notify, CANMsg msg) { cb_called = true; cb_notify = notify;

if (notify == CAN2040_NOTIFY_RX) {
rx_msg = *msg;
}

return; }

static void PIO0_IRQHandler(void) { can2040_pio_irq_handler(&cbus); }

void canbus_setup(void) { uint32_t pio_num = 0; uint32_t bitrate = 250000; uint32_t gpio_rx = 1, gpio_tx = 0;

// Setup canbus
can2040_setup(&cbus, pio_num);
can2040_callback_config(&cbus, can2040_cb);

// Start canbus
can2040_start(&cbus, clock_get_hz(clk_sys), bitrate, gpio_rx, gpio_tx);

// Enable irqs
irq_set_exclusive_handler(PIO0_IRQ_0_IRQn, PIO0_IRQHandler);
NVIC_SetPriority(PIO0_IRQ_0_IRQn, 1);
NVIC_EnableIRQ(PIO0_IRQ_0_IRQn);

}

int main(){ stdio_init_all();

sleep_ms(1000);
printf("Starting Initialization of CAN\n");
canbus_setup();
printf("Initialized CAN\n");

sleep_ms(1000);
while (true) {

    uint8_t command = getchar_timeout_us(0);
    if(command == 'u' || command == 'U'){
        CANMsg txmsg = {0};
        txmsg.dlc = 8;
        txmsg.id = 0x202;
        txmsg.data[0] = 0xDE;
        txmsg.data[1] = 0xAD;
        txmsg.data[2] = 0xBE;
        txmsg.data[3] = 0xEF;
        txmsg.data[4] = 0xDE;
        txmsg.data[5] = 0xAD;
        txmsg.data[6] = 0xBE;
        txmsg.data[7] = 0xEF;
        if(can2040_check_transmit(&cbus)){
            int res = can2040_transmit(&cbus, &txmsg);
            printf("Returned: %d\n", res);
        }
        printf("not transmittin\n");

    }
    else if(command == 't'){
        for(int i=0; i<8; i++){
            printf("%X ", rx_msg.data[i]);
        }
        printf("\n");
    }

    if (cb_called) {

    cb_called = false;
    printf("callback called\n");

    switch (cb_notify) {
    // received message
    case CAN2040_NOTIFY_RX:
        printf("cb: received msg: %s\n", msg_to_str(&rx_msg));
        for(int i=0; i<8; i++){
            printf("%X ", rbuf[i]);
        }
        printf("\n");
        break;

    // message sent ok
    case CAN2040_NOTIFY_TX:
        printf("cb: message sent ok\n");
        break;

    // error
    case CAN2040_NOTIFY_ERROR:
        printf("cb: an error occurred\n");
        break;

    // unknown
    default:
        printf("cb: unknown notification = %lu\n", cb_notify);
    }
}
}

}

KevinOConnor commented 1 year ago

You can use Klipper as a "usb to can bus" adapter with the rp2040 - see https://github.com/KevinOConnor/can2040/blob/master/docs/Tools.md . As described in that page, you can then use candump and cansend to send and receive can bus messages - including "remote" messages.

"Remote" frame transmission and reception is the same as normal messages - the only difference is that the can2040_msg id field has the CAN2040_ID_RTR bit set and there are no data bytes in the message (though the dlc field is still available).

-Kevin

Varghesemela commented 1 year ago

Thanks Kevin for the update. I actually got my setup working. But it feels quite weird to me that the Arduino Library (from autowp) for mcp2515 works on 500KBps while the can2040 works on 250KBps on the same can bus. Also i am able to work with the request frames, but after receiving some data for a couple of times to the rp2040, the bus shows up as busy when i query using can2040_check_transmit(&cbus) and stays that way.

Varghesemela commented 1 year ago

Hi @KevinOConnor, I have used the can2040 in my custom project and i am trying to establish communication over the bus. I also have another Pico that is running the original project of yours. My custom project is able to read every time a data is sent on the bus, but fails to transmit anything back to the bus. Every time i check can2040_check_transmit(&cbus) it always returns back as busy. The other pico that is running the default project can2040 works fine. Do you have any idea or suggestion on what could be the problem?

KevinOConnor commented 1 year ago

Unfortunately I can't provide assistance on using can2040. My suggestion would be to try running known working code on your hardware and work back from there. https://github.com/KevinOConnor/can2040/blob/master/docs/Tools.md

-Kevin

Varghesemela commented 1 year ago

Hi, It was just a silly mistake. The canbus instance was defined static in another library and was failing when i tried accessing it in the main file