Closed agmui closed 1 year ago
Check your cmake CMakeLists.txt
Okay, so I found out I was just dumb and did not include one of the files correctly and the whole code was compiled. However, the signal coming out of tx was just constant high and I double checked with an oscope to see what was going on. I then copied the code here and the output for some reason was coming out of GPIO 0 and not 5. Also for the ESC I am using it requires that I have a bitrate of 1Mbps but on the oscope the pico it did not seem like it was outputting 1Mbps. In the code I put this bitrate = 1000000
but it did not seem like the signal was the same frequency as another microcontroller that was outputting the correct signal.
Copy the setup code on this page. https://github.com/KevinOConnor/can2040/blob/master/docs/API.md
I tried using that one but no output came out of gpio 5 itwas just high like the other code. I don't know if its just me or the board is broken but im semi confident that the code is fine because I just copyed and paisted the example code.
What board and what can transceiver?
(blue) pi pico -> SN65HVD230 (yellow) arduino uno -> mcp2515 (purple: only working one) robomasters devlempment board type A
Here are each of the signals on the oscope. I just thought I would include it.
All set to the same bit rate and connected by a single ground plane?
Yea, I put in the code to all be the same gnd, data, id, and bitrate.
Should I post my code?
Sure
#include <stdio.h>
#include "pico/stdlib.h"
#include "can2040.h"
typedef struct can2040 CANHandle;
typedef struct can2040_msg CANMsg;
static CANHandle can1;
static void can2040_cb1(CANHandle *cd, uint32_t notify, CANMsg *msg) {
printf("can1 callback called. id: &d", notify);
}
static void PIO1_IRQHandler(void) {
can2040_pio_irq_handler(&can1);
}
void canbus_setup() {
uint32_t sys_clock = 125000000, bitrate = 1000000;//250000;
// Setup canbus
can2040_setup(&can1, 1);
can2040_callback_config(&can1, can2040_cb1);
// Enable irqs
irq_set_exclusive_handler(PIO1_IRQ_0, PIO1_IRQHandler);
irq_set_priority(PIO1_IRQ_0, 1);
irq_set_enabled(PIO1_IRQ_0, true);
// Start canbus
can2040_start(&can1, sys_clock, bitrate, 8, 10);
}
int main() {
stdio_init_all();
sleep_ms(10);
printf("Startup delay over\n");
printf("Starting Initialization of CAN\n");
canbus_setup();
printf("Initialized CAN1\n");
sleep_ms(1000);
while (true) {
CANMsg msg = {0};
msg.dlc = 8;
msg.id = 0x200;
msg.data[0] = 0x01;
msg.data[1] = 0x01;
msg.data[2] = 0x01;
msg.data[3] = 0x01;
msg.data[4] = 0x01;
msg.data[5] = 0x01;
msg.data[6] = 0x01;
msg.data[7] = 0x01;
int res = can2040_transmit(&can1, &msg);
printf("Sending! returned: %d\n", res);
// sleep_ms(1000);
sleep_ms(10);
}
}
cmake:
# Generated Cmake Pico project file
cmake_minimum_required(VERSION 3.13)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
# Initialise pico_sdk from installed location
# (note this can come from environment, CMake cache etc)
set(PICO_SDK_PATH "/home/agmui/cs/Robomasters/pico/pico-sdk")
# Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)
project(test C CXX ASM)
# Initialise the Raspberry Pi Pico SDK
pico_sdk_init()
# Add executable. Default name is the project name, version 0.1
add_executable(test
can.c
can2040.c
)
pico_set_program_name(test "test")
pico_set_program_version(test "0.1")
pico_enable_stdio_uart(test 1)
pico_enable_stdio_usb(test 1)
# Add the standard library to the build
target_link_libraries(test
pico_stdlib)
# Add the standard include files to the build
target_include_directories(test PRIVATE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts or any other standard includes, if required
/home/agmui/cs/Robomasters/pico/pico-sdk/src/rp2040/
/home/agmui/cs/Robomasters/pico/pico-sdk/src/rp2_common/cmsis/stub/CMSIS/Core/Include/
/home/agmui/cs/Robomasters/pico/pico-sdk/src/rp2_common/cmsis/stub/CMSIS/Device/RaspberryPi/RP2040/Include/
)
# Add any user requested libraries
target_link_libraries(test
hardware_spi
hardware_pio
)
pico_add_extra_outputs(test)
#include <SPI.h>
#include <mcp2515.h>
struct can_frame canMsg1;
struct can_frame canMsg2;
MCP2515 mcp2515(10);
void setup() {
canMsg1.can_id = 0x200;
canMsg1.can_dlc = 8;
canMsg1.data[0] = 0x01;
canMsg1.data[1] = 0x01;
canMsg1.data[2] = 0x01;
canMsg1.data[3] = 0x01;
canMsg1.data[4] = 0x01;
canMsg1.data[5] = 0x01;
canMsg1.data[6] = 0x01;
canMsg1.data[7] = 0x01;
while (!Serial);
Serial.begin(115200);
mcp2515.reset();
mcp2515.setBitrate(CAN_1000KBPS,MCP_20MHZ);
mcp2515.setNormalMode();
Serial.println("Example: Write to CAN");
}
void loop() {
mcp2515.sendMessage(&canMsg1);
//mcp2515.sendMessage(&canMsg2);
Serial.println("Messages sent");
delay(100);
}
I don't remember if I had the same data values as in the picture but it's the id that really matters.
Can you set the robomaster to read packets and only the rp2040 to send?
I don't have it all set up at the moment and I will see if I can get that set up but I doubt it would work. When I try to get the rp2040 to talk to the robotmasters ESC nothing happens same with the Arduino. I also tried to get the Arduino to read the rp2040 and nothing happened.
Are all the physical connections good? Do you have terminating resistors?
I'm like pretty sure they are all good.
Try this
int main() {
canbus_setup();
struct can2040_msg message;
message.id = 161;
message.dlc = 4;
while(1)
{
for(int i = 0; i < 255; i++)
{
int send = -1;
message.data32[0] = i;
while( send != 0)
{
send = can2040_transmit(&cbus, &message);
}
}
}
}
If you want to check the software (and/or hardware connectivity) one possibility is to download Klipper, compile it for the rp2040 (via make menuconfig
) with "USB to CAN bridge" support, flash the rp2040 with that code, and attach the resulting device to a linux machine. That will cause the device to act as a standard Linux "usb to can" adapter. You can then send and receive messages using the standard linux "candump" and "cansend" commands.
https://www.klipper3d.org/CANBUS.html
https://github.com/Klipper3d/klipper
-Kevin
Ok, so i finally got the usb to can set up on the pico but when I run cansend can0 200#DEADBEEF
on the oscilloscope it just shows high on GPIO 5 relative to ground and same for GPIO 4.
I'm not sure what would cause the issues here. However, there were several fixes recently that could impact testing of the code, in particular with multiple retransmits. (Issue #14 and PR #15 and PR #16.) So, you may wish to update to the latest code.
Also, I've added a page to document some available tools: https://github.com/KevinOConnor/can2040/blob/master/docs/Tools.md . As noted in that document, make sure there is a fully functional canbus (with at least one other device) even for testing.
-Kevin
Thank you so much, I will try that when I get back and see what will happen with the new code.
Hello,
It looks like there hasn't been any recent updates on this github ticket. We prefer to only list tickets as "open" if they are actively being worked on. Feel free to provide an update on this ticket. Otherwise the ticket will be automatically closed in a few days.
Best regards,
~ Your friendly GitIssueBot
PS: I'm just an automated script, not a human being.
I'm going through similar issues, trying out Klipper in USB to CAN bridge mode. I'm not sure how to specify the pins in menuconfig. I can't find any examples of how to set this string, which seems to also include the CAN bitrate as well.
EDIT: solved this. I had missed one of the menu options in menuconfig. I also figured out the USB to CAN interface being presented was gs_usb
and not slcan
. Once all that was sorted out, I can send/receive CAN over the RP2040. Next up -- compile my own application.
So I know it has been a while but I had finally figured out what went wrong. Turns out I am just dumb and never thought to wire up the CAN transceiver(SN65HVD230) to the pico. The picture above of the oscilloscope was just the signal from the uart port.
The reason why I plugged the oscilloscope into the uart port was because it was the only pin that was giving off a signal so I thought it was the correct pin. Because at the time pins 4 and 5, the rx and tx pins I set in the code, were only showing high and nothing at all. Only yesterday I thought about connecting the CAN transceiver to the pico did everything finally work properly.
Also regarding the CMake issue I normally exclusively code in python and have little to no experience in c++ so CMake was very new to me. Only when I decided to sit down and properly learn about CMake did everything compile.
I am very new to embedded development do only in hindsight I realized how dumb I was.
Anyways here is my CMake file and example code. Its probably not the best but it is what compiles for me.
# Generated Cmake Pico project file
cmake_minimum_required(VERSION 3.13)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
# Initialise pico_sdk from installed location
# (note this can come from environment, CMake cache etc)
set(PICO_SDK_PATH "/home/agmui/cs/pico/pico-sdk")
set(PICO_BOARD pico CACHE STRING "Board type")
# Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)
if (PICO_SDK_VERSION_STRING VERSION_LESS "1.4.0")
message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.4.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
endif()
project(rm_pico_dev C CXX ASM)
# Initialise the Raspberry Pi Pico SDK
pico_sdk_init()
# Add executable. Default name is the project name, version 0.1
add_executable(rm_pico_dev canbus.cpp )
pico_set_program_name(rm_pico_dev "canbus")
pico_set_program_version(rm_pico_dev "0.1")
pico_enable_stdio_uart(rm_pico_dev 0)
pico_enable_stdio_usb(rm_pico_dev 1)
# Add the standard library to the build
target_link_libraries(rm_pico_dev
pico_stdlib)
# Add the standard include files to the build
target_include_directories(rm_pico_dev PRIVATE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts or any other standard includes, if required
)
add_library(can2040 can2040.c can2040.h)
target_link_libraries(can2040 pico_stdlib
pico_base_headers
hardware_dma
cmsis_core
)
target_link_libraries(rm_pico_dev
can2040
)
# Add any user requested libraries
target_link_libraries(rm_pico_dev
hardware_pio
pico_base_headers
hardware_dma
cmsis_core
)
pico_add_extra_outputs(rm_pico_dev)
c++ code:
This is just the copied code from the example
#include <stdio.h> #include "pico/stdlib.h" #include "hardware/pio.h" extern "C"{ #include "can2040.h" } #include "RP2040.h"
typedef struct can2040_msg CANMsg; static struct can2040 cbus;
static void can2040_cb(struct can2040 cd, uint32_t notify, struct can2040_msg msg) { // Add message processing code here... }
static void PIOx_IRQHandler(void) { can2040_pio_irq_handler(&cbus); }
void canbus_setup(void) { uint32_t pio_num = 0; uint32_t sys_clock = 125000000, bitrate = 500000; uint32_t gpio_rx = 4, gpio_tx = 5;
// Setup canbus
can2040_setup(&cbus, pio_num);
can2040_callback_config(&cbus, can2040_cb);
// Enable irqs
irq_set_exclusive_handler(PIO0_IRQ_0_IRQn, PIOx_IRQHandler);
NVIC_SetPriority(PIO0_IRQ_0_IRQn, 1);
NVIC_EnableIRQ(PIO0_IRQ_0_IRQn);
// Start canbus
can2040_start(&cbus, sys_clock, bitrate, gpio_rx, gpio_tx);
}
int main() { stdio_init_all(); canbus_setup();
const uint LED_PIN = PICO_DEFAULT_LED_PIN;
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
while (true) {
CANMsg msg = {0};
msg.dlc = 8;
msg.id = 0x200;
msg.data[0] = 0x01;
msg.data[1] = 0x01;
msg.data[2] = 0x01;
msg.data[3] = 0x01;
msg.data[4] = 0x01;
msg.data[5] = 0x01;
msg.data[6] = 0x01;
msg.data[7] = 0x01;
int res = can2040_transmit(&cbus, &msg);
printf("Sending! returned: %d\n", res);
printf("LED ON!\n");
gpio_put(LED_PIN, 1);
sleep_ms(250);
printf("LED OFF!\n");
gpio_put(LED_PIN, 0);
sleep_ms(250);
sleep_ms(1000);
}
return 0;
}
Here is the repo with the code:
[repo](https://github.com/agmui/rm_pico_dev/tree/c881497b965e519618b53bb8f6eedbbe90d0aa54)
Hey, First, I would like to say how great this project is. I was trying to run this project the other day on a pi pico connected to a Waveshare SN65HVD230 CAN Board. I followed the example code shown but CMake threw this error
I saw in the previous issue that you could put PIO0_IRQ_0 and I tried that but when I built it and used an oscilloscope I only got noise. Is this because I am compiling wrong through CMake and not just using the command shown in the guide?
Here is my code: