CANBed Dual problems -- multiple problems!

I am writing a very simple CAN bridge (or relay) on the new CANBed Dual, which has an RP2040 and GD32E103CBT6 as the CAN controller, using the Arduino development environment. (See example code below).

Problems (in order of importance):

  1. CAN messages appear to be garbled. I am just doing a basic CAN.read() (see below), and I know that all the messages on the vehicle bus have a length <= 8. But I read crazy CAN IDs (like 369100705) and length values (like 66).

  2. Somewhat randomly, the main loop() completely bogs down because the CAN.reads() can sometimes take approximately 11-13 seconds. Sometimes it returns quickly (which is what I expect), but I canā€™t figure out why it sometimes has good behavior, or what makes it have the slow behavior!

  • This even happens where there is no CAN traffic at all.
  • This even happens when I have wired the board in loopback configuration (CAN0L to CAN1L and CAN0H to CAN1H)
  1. About 50% of the time, the board fails to flash. I think this may be related to the mounting/unmounting of the RP filesystem. I then have to mess with the reset button, unplug/replug USB cables

  2. Sometimes the board will not reset when I press the reset button. This is related to (3), since one of the things I try to get the board to recover is to reset it manually. The only thing that seems to work is to unplug the board for ~10 seconds, and then it will let me flash (and reset with the button properly)ā€¦ at least for a while until the problem happens again.

Generally, the CAN library at GitHub - Longan-Labs/CANBedDual_Arduino_Lib: Arduino Library for CANBed Dual seems to be very poorly written, and Iā€™m not sure it actually works.

Questions:

  • Anything obviously busted with my code?
  • Has anyone gotten this board to read legitimate CAN messages?
  • Does anyone know what code is running on the GD32E103CBT6? Then at least I could figure out to fix the busted CANBedDual_Arduino_Lib code. Or maybe I should just program it and skip the RP2040ā€¦

Thanks!!

Example code:

/*  Relay messages between CAN and Serial.

    Uses two CANBed V1.2d's connected by Serial to form a CAN bridge.

    CANBedDual: https://www.longan-labs.cc/1030019.html
     - Docs: https://docs.longan-labs.cc/1030019/
     - Arduino library: https://github.com/Longan-Labs/CANBedDual_Arduino_Lib

    TODO:
    - Consider down-clocking (eg to 50 MHz) to reduce power usage
*/

#include <Wire.h>
#include <stdio.h>
#include "canbed_dual.h"

#define RELAY_DEBUG 1

CANBedDual CAN0(0);
CANBedDual CAN1(1);

unsigned long startMillis = 0;
unsigned long byteCount = 0;

void setup() {
  if (RELAY_DEBUG) {
    Serial.begin(115200);  // USB serial port for debug
    while(!Serial);        // Block on the debug port
    Serial.println("Debug serial OK!");
  }

  // Setup: pin 18 is the little blue LED (not the green power LED)
  pinMode(18, OUTPUT);

  // ??? Setup: Wire1/I2C is the underlying interface to the CAN controllers
  Wire1.setSDA(6);
  Wire1.setSCL(7);
  Wire1.begin();

  CAN0.init(500000);  // CAN0 baudrate: 500kb/s
  CAN1.init(500000);  // CAN1 baudrate: 500kb/s
  if (RELAY_DEBUG) Serial.println("Initialized CAN");
}

bool ledToggle = false;

void loop() {
  // CAN message fields
  unsigned long id = 0;
  int ext = 0;
  int rtr = 0;
  int fd = 0;
  int len = 0;
  unsigned char data[64];

  unsigned long nowMillis = millis();
  if (nowMillis - startMillis >= 1000) {
    Serial.print("bytes per second: "); Serial.println(byteCount);
    startMillis += 1000;
    byteCount = 0;
    ledToggle = !ledToggle;
    if (ledToggle) digitalWrite(18, HIGH);
    else digitalWrite(18, LOW);
  }

  if (CAN1.read(&id, &ext, &rtr, &fd, &len, data)) {
    if (RELAY_DEBUG) {
      Serial.print("CAN1 ");
      Serial.print(id); Serial.print(" ");
      Serial.print(ext); Serial.print(" ");
      Serial.print(rtr); Serial.print(" ");
      Serial.print(fd); Serial.print(" ");
      Serial.println(len);
    }
    byteCount += len;
    CAN0.send(id, ext, rtr, fd, len, data);
  }
if (CAN0.read(&id, &ext, &rtr, &fd, &len, data)) {
    if (RELAY_DEBUG) {
      Serial.print("CAN0 ");
      Serial.println(id);
    }
    byteCount += len;
    CAN1.send(id, ext, rtr, fd, len, data);
  }
}

Hi,

I received a CANBedDual a few days ago, and Iā€™ve been able to run a simple example script (from the same longan git repo) looping one CAN bus to the other (but it really need the 120ohms termination resistors).

I have not yet tested other cases for now, but I may try to implement a slcan firmware (not sure if there is support for dual can bus in the slcan protocol).

But I agree that if the hardware seems nice, the software and documentation are not great (there is actually no real doc on seeedstudio product page, the schematic linked there is not the correct one, etc).

Iā€™d also like to find the source code for the CAN controller (GD32E103CBT6), Iā€™ve created an issue for this. It seems itā€™s not upgradable via the RP2040, but there are SWD pins available.

(BTW I also wonder what are the relations between seeedstudio and longan labsā€¦)

David

Cool ā€“ glad to hear someone else is trying to use this thing! I still havenā€™t had any response from Longan labs support (though they say theyā€™ll get back to you in 24 hours). Not a good sign.

I was also able to get the loopback code workingā€¦ My problems started when I started trying to read real CAN messages! Very curious to hear whether that works for you.

Hi,
I wonder if I could ask you guys for help, since you seem to have gotten further than I have just getting this board to work. Iā€™ve sent the same question to SeeedStudio and Longan, but Iā€™m not the patient kind :).

When I try to set up the Arduino IDE for this board, I get the error message ā€œarchive size differs from size specified in indexā€, see below. Consequently, I cannot compile the example code. Iā€™m using Arduino IDE 2.0.0. When I use Arduino 1.8.10 the error is ā€œCRC doesnā€™t matchā€.

I get the same message when I try to install version 1.0.1. When I select version 1.0.0 it works, but only the CANBed 2040 device is supported (not the Dual).

Tool longan-rp2040:[email protected] already installed
Tool longan-rp2040:[email protected] already installed
Tool longan-rp2040:[email protected] already installed
Tool longan-rp2040:[email protected] already installed
Tool longan-rp2040:[email protected] already installed
Tool longan-rp2040:[email protected] already installed
Downloading packages
longan-rp2040:[email protected]
Installing platform longan-rp2040:[email protected]
Failed to install platform: longan-rp2040:longan-rp2040.
Error: 13 INTERNAL: Cannot install platform: installing platform longan-rp2040:[email protected]: testing local archive integrity: testing archive size: fetched archive size differs from size specified in index: 14111817 != 14114816

Please advise.
Cees.

My problem is a little different. Iā€™m using the Module based on GD32E103 and two older 5v arduinos and I can get it to send messages but if one drops offline (unplug or reflash) everything just seems to stop working and it takes some random hard resets between the modules to get data flowing again.

Cees: I think I remember having some sort of trouble like that. I might have downloaded the zip file and manually unzipped it in the Arduino directories. You notice the archive size is just off by one byte!

Just a general update: Iā€™ve continued to have problems with the CANBed Dual, and have basically given up hope of getting support from Longan (no response after multiple emails).

Does anyone knows how to configure the CANFD sample point, such as SEG1态SEG2态BRP ?
I couldnā€™t find any infomation in GD32E103CBT6 datasheet.
Thanks.

Thanks Than,

I had to revert to Arduino 1.8.19 for the board installation to succeed.

When I compile the example, CAN20_SendRecv, I get the following warnings. Is this normal?

*WARNING: library Wire claims to run on rp2040 architecture(s) and may be incompatible with your current board which runs on longan-rp2040 architecture(s).*
*<command-line>: warning: ISO C++11 requires whitespace after the macro name*
(this ISO warning is repeated 26 times)
*Sketch uses 62984 bytes (3%) of program storage space. Maximum is 2093056 bytes.*
*Global variables use 11712 bytes (4%) of dynamic memory, leaving 250432 bytes for local variables. Maximum is 262144 bytes.*
*Resetting COM7*
*Converting to uf2, output size: 139776, start address: 0x2000*
*Flashing D: (RPI-RP2)*
*Wrote 139776 bytes to D:/NEW.UF2*

To respond to your issue. Iā€™ve tinkered with various Arduino CAN shields in the past and found that many serial.print calls in succession may cause the Arduino to stall or hang. Itā€™s as if either side cannot keep up.
Iā€™m currently testing a ā€˜pingpongā€™ program, sending can frames back and forth between the two ports with a 100 us wait in between. Itā€™s managing 88 frames per second in either direction.
Iā€™m using the following to report back to the Serial Momitor:

 sprintf (sLogLine, "Time: %lu, Sent 0: %04d, Received 1: %04d, Sent 1: %04d, Received 0: %04d, Diff: %03d, Cycle (us): %04d", startTime, sentFrames0, receivedFrames1, sentFrames1, receivedFrames0, difference, (96+96+2*waitTime));
      Serial.println(sLogLine);

Itā€™s been running for hours.
Hope this helps.

Cees: yes I get that error/warning too.

Have you connected it to a real CAN bus yet? I was also able to get loopback working ( the device can read its own messages), but I got gibberish from real messages. (and I need to read more like 500 messages per second)

No not on a real CAN bus yet.
Are you sure youā€™re not actually reading extended CAN frames, with their 29 bit ID versus 11 bit? The ID you mentioned is within the 29 bit range, and the extended ID bits could overwrite the data length bitsā€¦

Update. My laptop ran out of juice while I was away. On restart (with the board plugged in) the board did start again, but the CAN0 TX LED was fainter than the rest. And shortly after, the CAN messages stopped. So the code still ran -looped and reported to serial- but no CAN messages going back and forth.
I pressed Reset and all is back to how it should be.
Strange behaviour. My bet is the GD32E103CBT6 MCU-turned-CAN-controller is the weak link.

Hereā€™s the code of my pingpong program.
Iā€™ve stripped out the delay, so theoretically the max throughput should be determined by the bit rate (500 kbps in this case). That would be 4,000 fps for an 8 byte frame in one direction, or 2,000 in alternating directions (pingpong).
Iā€™m getting only 104 fpsā€¦

  while ((millis() - startTime) <= 1000) {      // during one second, do
    if(CAN1.read(&id, &ext, &rtr, &fd, &len, dtaGet)) {
      receivedFrames1++;      
      CAN1.send(0x01, 0, 0, 0, 8, str);
      sentFrames1++;
      //delayMicroseconds(waitTime);
    }
    if(CAN0.read(&id, &ext, &rtr, &fd, &len, dtaGet)) {
      receivedFrames0++;      
      CAN0.send(0x01, 0, 0, 0, 8, str);
      sentFrames0++;
      //delayMicroseconds(waitTime);  // one 8 byte frame is 112 bits in total, and takes approx. 224 us at 500kb/s
      // max throughput should be 2,000 fps
    }
  }

Iā€™ve done another test, where I was just sending frames. This had to be placed in a separate function called at the end of setup(), instead of using the loop().
In any case, I got max 450 fps out. The waitTime value had to be 12 us or more. Below that, the board would no longer respond to the serial port: the Serial Monitor would not start and the board could no longer be programmed. If you encounter this: unplug your board from the USB and reconnect it with the boot button pressed. This will mount it as a D: drive and you can upload a new sketch.

450 fps may be acceptable one-way. But for the typical use case of relaying messages, receive and resend, the rate is only 104 fps. Even then, the board often hangs, requiring a power cycle (ON/OFF) to come back.

This product is super-crap. Bought 2 of these, none of them work. Same issues as @than. Their board library doesnā€™t work on newer Arduino IDE.

It works on the bench with CAN0 attached to CAN1 but it doesnā€™t on the car.


    Serial.println();
    Serial.print("CAN1: 0x");
    Serial.print(id, HEX);
    Serial.print(", ");
    Serial.print(ext);
    Serial.print(", ");
    Serial.print(rtr);
    Serial.print(", ");
    Serial.print(fd);
    Serial.print(", ");
    Serial.print(len);
    Serial.print(",");

    for (int i = 0; i < len; i++)
    {
      sprintf(msgString, " %.2X", dtaGet[i]);
      Serial.print(msgString);
    }

CAN0: 0x6160600, 7, 0, 161, 32, 07 16 06 00 07 00 A1 20 40 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
CAN0: 0x60007A1, 32, 0, 15, 66, 07 00 07 A1 20 00 0F 42 40 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 07 A1 20 00 0F 42 40 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
CAN1: 0x16060007, 161, 0, 32, 15, 17 06 00 07 A1 00 20 0F 40 01 00 00 00 00 00
CAN0: 0x6160600, 7, 0, 161, 32, 07 16 06 00 07 00 A1 20 40 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

The source for the GD32 is on their Github: GitHub - Longan-Labs/GD32_I2C_CAN_FIRMWARE: GD32E103CBT6/GD32C103CBT6 I2C TO CAN FIRMWARE.

I see quite a few issues in this firmware that could be responsible for some of the issues posted in this thread:

  • The I2C clock is set to only 100KHz even though the chip supports 1000.
  • CAN is initialized with default values (2.0: 500k, FD: 1M) before receiving the I2C config/init. In my experience this would certainly crash/cause errors on an automotive bus. It may also be why it only works in loopback?
  • Only 4 out of 28 supported filters are implemented.

With all that said, I think the hardware is quite nice. Sure, itā€™s mostly Chinese domestic chips but with the right software they should do the job. Re-soldering TJA1042s instead is also not a big deal. I actually think they have excellent potential.

Iā€™ve started re-working the firmware addressing some of the above on my repo: GitHub - superwofy/GD32_I2C_CAN_FIRMWARE however, I didnā€™t receive my boards yet so have not been able to test. Itā€™s very much work-in-progress.

3 Likes

What is the process to update the GD32 firmware on the CANBed Dual? Iā€™m having similar issues as above in the thread, hoping this can address them

Did you figure this out yet? Iā€™m looking out to do the same, and have
built superwofyā€™s version of fw, but unsure how to continue from here.

edit: I have soldered a 4pin header to the bottom, that seems to be
the way, but I suppose something should be done to also reset/boot
it correctly for flashing? There might be UART bootloader on gd32,
available on same pins that are connected to the pins of rp2040 for i2c
already. Atleast if itā€™s somekind of a clone for stm32f103, or close by.
So it wouldnā€™t be impossible to use rp2040 as a bridge I guess.

I never was able to figure out the process for updating the firmware (but Iā€™m pretty much convinced the issues with the board are in fact the firmware). If you figure it out and can share details of the process that would be a great, great help

@superwofy - Any luck burning your firmware to the board?

Any further updates to this?
I only just bought a couple of boards last month and the few trials I have done in car have so far worked. I am intending on using it as a CAN relay though so not quite sure what thoughput I will need for good operation in the car. The comments above re message thorughput is concerning.

I somehow managed to break the thing I had for uploading the firmware(BMP), and Iā€™m waiting for a better(jlink edu) replacement. I didnā€™t succeed flashing it with stlink v3.
My intention with this is the same. To use it first as a simple bridge, with logging on rp2040 via i2c from gd32e103.
So the firmware by ā€œLongan-Labsā€ is no good for me*. And Iā€™m mostly developing on linux, so the keil project these firmwares(by LL and superwofy) atm. use is somewhat unusable for me. My next step is to replace that w/cmake&gcc. Or even go with zephyr and rewrite the whole thing(not much, to be honest).

^ ==working on the firmware is ā€œon holdā€ for a week, or two I guess, for me that is.

*) itā€™s really so bad(code/ā€˜qualityā€™) I didnā€™t at first believe it was a real thing being soldā€¦

edit: thereā€™s some info here about the process of burning new firmware:

I was having issues reading can with canbed dual and found this thread.
Eventually I figured out that there is a bug in the provided library file canbed_dual.cpp

It forces a read of 8 bytes, so if a message is less than 8 bytes this hangs forever.

//Problematic code:
if(dtaLen <= 32)
{
CANI2C.beginTransmission(0x41);
CANI2C.write(canNum ? 0x17 : 0x07);
CANI2C.endTransmission();

    CANI2C.requestFrom(0x41, 8);

    for(int i=0; i<8; i++)
    {
        str[i]= CANI2C.read();
    }
}

//Should be changed to
if(dtaLen <= 32)
{
CANI2C.beginTransmission(0x41);
CANI2C.write(canNum ? 0x17 : 0x07);
CANI2C.endTransmission();

    CANI2C.requestFrom(0x41, dtaLen );

    for(int i=0; i<dtaLen ; i++)
    {
        str[i]= CANI2C.read();
    }
}