CAN Bus Dying for Unknown Reason

Status
Not open for further replies.

dresio

Member
I am developing a decently long program for a project and currently the CAN bus is being very finicky. I have a completely working system, but if I call an empty if statement that doesn't even evaluate to true it breaks the entire thing. When I reduced the size of the code (the full thing is 2k+ lines) I can replicate the issue not with an if statement, but a print statement instead.
Please disregard some of the bad naming convention as I had to change how different systems work to make it smaller. Near the end of the main loop, the print statement that breaks it all can be seen, but it should also be noted that sometimes if the system isn't connected to something it allows it to run.
I have attached my source code to this post, and it runs on the teensy 3.6 with 2 teensy 3.2s listening to the data but not sending anything. I don't believe it could be the teensy 3.2s breaking it because they don't send anything. I have it hooked up to an oscilloscope to confirm data and when the print statement is commented out, the bus just goes blank.
Any help is greatly appreciated as I have spent countless hours trying to work around this issue.

Edit: To enable can either type -rc then -ef in the serial port or set both enableFins and radioControl to true.
More Info:
Using Arduino IDE with Teensyduino
Using SN65HVD230DR CANbus Transceiver (https://www.digikey.com/en/products/detail/texas-instruments/SN65HVD230DR/404367)
I would send wiring but it is built in to a PCB and it normally operates just fine. If you guys want details I can try and find the schematics.
Thanks!
Daniel
 

Attachments

  • CAN_Bus_Error.zip
    5.1 KB · Views: 80
Last edited:
does the loop completely halt? i noticed you're running a non standard baudrate (100000), keep notes that, like on another post someone had issue with 95000 not working, changing the rate a bit helped it work. Unfortunately we don't have your hardware, maybe you can confirm flexcan.h can read/write the bus at very minimum only and show that it still fails then you can go futher into your code.
 
I can confirm that the loop doesn't halt. When testing on the hardware I have an LED blink every 0.5 seconds so I can ensure the process is still running. I am not sure why but it seems like CAN networks typically work at these even number intervals as the example has it running at 500000. When digging through the library, I found this comment:
Code:
/*
 * \brief Initializes the CAN bus to the given settings
 *
 * \param baud - Set the baud rate of the bus. Only certain values are valid 50000, 100000, 125000, 250000, 500000, 1000000
 * \param mask - A default mask to use for all mailbox masks. Optional.
 * \param txAlt - 1 to enable alternate Tx pin (where available)
 * \param rxAlt - 1 to enable alternate Rx pin (where available)
 *
 * \retval none
 *
 */

On that note I did forget to mention that I am using the alternative pins for the can bus. I don't think that should have an effect but it is something that we had to declare.
 
yeah it could be a non standard bitrate (since you said 500000 worked?)

on the other thread someone else had issue with 95000 not working. when i told him to try 95238, his network functioned correctly after. if you have a spare esp32 (or anyone else reading this thread) load up my esp32_can and Serial.print(Can0.setBaudrate(100000)) and the "actual" bitrate will be printed after calculated. 100000 is desired but it's the actual one you need for teensy, if its not standard rate you will see it offset to one that is correct
 
I have not been able to confirm the baud rate over the ESP32 but I do have one on hand that I should be able to test later tonight. The main issue though is the baud rate of 100000 does work sometimes, but seems to break with random code additions. I have managed to break it by commenting out a print statement, incrementing a variable in the main loop, and calling a function that returns an integer from the state machine in the attached code. My understanding may be off but I thought that if it works once then it shouldn't be an issue with the baud rate.
 
I may have found something, although it isn't much. I added a segment of code at the end of SendSpeedPacket function that prints data if the buffer is overflowing and it looks like it is! I have no clue why this is happening though. It only happens sometimes, but not all times. I went into the library and upped the number of mailboxes and that seemed to delay the time to the canbus crash but didn't allow the data to go through still. Code for that function is seen below.
Code:
void Comms::SendSpeedPacket(float leftFreq, float rightFreq)
{
  CAN_message_t  msg;
  msg.ext = 0;
  msg.id = MAIN_DATA_ID;
  msg.len = 8;

  long leftLong = leftFreq * 1000;
  long rightLong = rightFreq * 1000;

  for (int i = 0; i < 4; i++)
  {
    msg.buf[i] = leftLong & 0b11111111;
    leftLong >>= 8;
  }
  for (int i = 4; i < 8; i++)
  {
    msg.buf[i] = rightLong & 0b11111111;
    rightLong >>= 8;
  }

  if (msg.flags.overrun)
    Serial1.println("Message Buffer Overflow in Send Speed Packet");

  Can0.write(msg);
}
 
Ok, I found the problem! I had seen use cases where 8 integers could be used and assumed it would work with 2 byte ints. However the transmit limit is 8 bytes of data. After splitting it up I found it working just fine again, but I have another question now, why did this ever work? With the code originally attached it allows data to transmit, and is technically sending more bytes then the limit and was receiving it just fine.
 
the array for the message struct is 8 bytes, writing past it causes undefined behaviour. this probably wouldn't have happened if you used CANFD as it's buffer is 64 bytes :)

msg.flags.overrun is useless for transmits, it's used for reception indication of overrun condition
 
Status
Not open for further replies.
Back
Top