CAN Bus, Buffer, timing issue?

I'm currently running a Nano plugged up to a cheap 8mhz Can Bus transceiver and Cory Fowlers fantastic can bus library.

This sniffs the "generic dash" information placed on the CAN Bus from my Link (aftermarket ECU). The goal to have CAN Bus data displayed on a series of 7 segment displays such that I or my Nav can read the engine /gearbox statistics.

I'm running the Cory Fowler Can Bus library such that I can interface to the 8mhz crystal on the CAN Bus adapter.

My problem is that as soon as I introduce any delay (such as writing to the 7 segments) I only receive the first row of data (frame 0), or two (frame 1) of a series of 12 rows in total.

This makes update of any gauges for which the data is not in the first frame or two impossible (for which a great deal of my gauges are based).

I can replicate the fault by simply using Cory's example code (linked below) and introducing a delay.

I've include copy of the output from both the non delayed and delayed can bus data, using Cory's example code. (attached). The first column represents the frame number.

I would have thought it's some form of buffer issue, however the can bus adapter doesn't drop interrupt pin 2 for several hundred main loop iterations (I introduced an else counter should int 2 not be raised) before it again reads frame 0 or frame 1.

It's got me stumped as to how it's even being timed to pull these first specific frames other than perhaps a buffer issue that is somehow timed to the Link ECU calculating the can bus values to be transmitted?

All suggestions appreciated!

curious... is 0x3E8 the only CAN ID on the bus (hard to believe that!) or have you applied some kind on filter....?

sherzaad:
curious... is 0x3E8 the only CAN ID on the bus (hard to believe that!) or have you applied some kind on filter....?

No filtering.

Benching with only the ECU, Nano and my Pi based telemetry transmitter (listen only) on the bus. Even were it in the race car there is nothing else on that bus (other than an AIM datalogger/dash and wideband O2)

https://nzmotorracing.co.nz/wp-content/uploads/2017/08/Daniel-Powell-770x470.jpg

OK.

Reading your post #1 and #3 again I'm not clear on what you are trying to achieve... if it's not to much to ask, could you post like a block diagram of what you are trying to connect together?

I'm not clear on how you would construct a block diagram displaying a sample script that works however has is not reading all data. I simply wish to capture ALL or at least a majority of the data on the bus.

Currently the data on the canbus isn't being captured by my Nano. I can prove this with my Pi on the same canbus, which captures ALL frames sequentially. I have also proved that a majority of the data can be captured on the Nano so long as the program is so short as to have no usable function. One of the attachments in the first post demonstrates output from the sample receive code with an almost sequential numbering of frames (but still the odd dropped frame).

In my own program, which adds two bytes together, breaks the sum into individual digits, then displays it in either 7 Segment, a larger 7 Segment, a 8x8 matrix, or neopixels, is only capturing the first two in the sequence of 12 (frame 0 and 1), at best, frames. Often resulting in an output of only frame 0's, as demonstrated in the attachment in the first post. As such none of my ECU values post frame 0 are ever displayed.

I can simplify and demonstrate this as a timing issue by inserting a delay into the existing sample receive from the Cory Flowlers library. The output of which is the second attachment included in the first post.

However I can also demonstrate that an interrupt isn't being generated by adding an else and counter to the end of the "if(!digitalRead(CAN0_INT))" if statement in the sample code. As such if an int isn't raised, it performs and serial prints a counter. This counter ends up in high 100's , as in hundreds of loops of the main loop, before being reset (interrupt being generated).
This in itself confuses me as I would have thought an interrupt would be produced on anything in the buffer, that being anything on the bus.... which it clearly is not capturing.

I also have issue with the frame that is being picked up by the Nano. It's not a random frame, nor is it sequential, from the 12 frames sent by the ECU. It's almost always 0, with an occasional frame 1. The larger the delay introduced in the sample code, the more propensity it has to only select frame 0.
My very rudimentary suspicion is that the data on the bus has a short delay while the ECU generates all fields and then places data on the bus in a series of writes, then recalcs. The short delay means the first thing in the buffer is frame 0. However I'm a backyard hack and my suspicions probably lack the sense of anyone wise enough not to bring a butter knife (Nano) to this gunfight.

ok... all that text hurt my head! :slight_smile:

anyway.... what I don't understand is WHY you are using another board (the Nano) when you already are working with a PI!!!

are you lacking IO an the PI or something???

For me, given that the PI is a beast compared to a nano, I would be implementing everything on it!

I come to an arduino forum for assistance on an arduino issue, and your best advice is not to use an arduino?

This is an integrated dash (as in F1 steering wheel) I can't wait 30 seconds after every start, stall, every power cycle for the Pi to boot and my gauges to work. In terms of integrated radio telemetry this isn't an issue, as such I use a Pi for this task.

I'm working with the Nano because it is a small, as such easily integrated into the steering wheel, and a well supported micro-controller.

Arduino is also a platform that I'd like to learn as such have picked a project that I believe that it should handle, as in a single threaded simple data collection, some very simple byte manipulation and display.

Back to the issue at hand.

The Nano clearly isn't lacking in clock cycles otherwise I wouldn't get hundreds of main loops completing without a pin 2 CAN Bus interrupt.

Given that it's dropping frames from the buffer without a read I'd guess it's either an issue with the 8mhz CAN Bus adapter (probable), a problem inherent to the arduino SPI bus (doubtful), or an issue with the libraries I'm using.

I've somewhat resolved the issue.
By using an interrupt rather than checking that pin 2 was low it's collecting considerably more data (or at least cycling through the frames). In any case it's working with a refresh rate that'll be good for all but RPM alerts.
I suspect that when I get it in the race car I'll need to improve performance such that RPM can be displayed in millisecond response, at which time I think it's time for a 16mhz can bus controller and a teensy (or ESP8266).

RedMist:
My problem is that as soon as I introduce any delay (such as writing to the 7 segments) I only receive the first row of data (frame 0), or two (frame 1) of a series of 12 rows in total.

When you say "delay" do you mean actual use of delay(value), or something that takes a bit of time to run?

If you are using delay(value), I would suggest you look at the blink without delay example and update your display at 10hz or some other rate.

It is also possible that you might need to create a more complex CAN receive routine that waits for all the CAN data and then immediately updates the display when all the info is received.

coryjfowler:
When you say "delay" do you mean actual use of delay(value), or something that takes a bit of time to run?

If you are using delay(value), I would suggest you look at the blink without delay example and update your display at 10hz or some other rate.

It is also possible that you might need to create a more complex CAN receive routine that waits for all the CAN data and then immediately updates the display when all the info is received.

Cory, thank you so much for the reply. I'm simply attempting to construct a dash for my Link ECU powered race car... and I suspect I'm asking too much of the Nano and CAN Bus adapter.

I used delay() in your example script to replicate writing out to the 7 Segs. It just standardized the code without introducing my completely bolloxed coding. I realize that it was rough and ready, and on reflection it's better served by simply introducing a counter.

void loop()
{
    if(!digitalRead(2))                         // If pin 2 is low, read receive buffer
    {
      Serial.print ("Counter = ");
      Serial.println(countUp);
      countUp = 1;
      CAN0.readMsgBuf(&len, rxBuf);              // Read data: len = data length, buf = data byte(s)
      rxId = CAN0.getCanId();                    // Get message ID
      Serial.print("ID: ");
      Serial.print(rxId, HEX);
      Serial.print("  Data: ");
      for(int i = 0; i<len; i++)                // Print each byte of the data
      {
        if(rxBuf[i] < 0x10)                     // If data byte is less than 0x10, add a leading zero
        {
          Serial.print("0");
        }
        Serial.print(rxBuf[i], HEX);
        Serial.print(" ");
      }
      Serial.println();
    }
    else 
    {
     countUp++;
    }
    
}

produces

ID: 3E8  Data: 00 00 00 00 67 00 66 00 
Counter = 1.00
ID: 3E8  Data: 01 00 FB 03 64 00 00 00 
Counter = 1.00
ID: 3E8  Data: 02 00 00 00 00 00 96 00 
Counter = 1.00
ID: 3E8  Data: 04 00 00 00 90 01 1A 04 
Counter = 1.00
ID: 3E8  Data: 06 00 00 00 00 00 00 00 
Counter = 1.00
ID: 3E8  Data: 09 00 00 00 00 00 00 00 
Counter = 1.00
ID: 3E8  Data: 0B 00 00 00 00 00 00 00 
Counter = 1.00
ID: 3E8  Data: 03 00 96 00 F5 04 00 00 
Counter = 35386.00
ID: 3E8  Data: 00 00 00 00 67 00 66 00

You'll note that it's in the main loop and missing every second, or more frame (first data byte is frame number) When it raises pin 2 it'll loop 35,386 times and when pin 2 is lowered again receives from the buffer frame 0 every time. Which makes receiving late frames like frame 9 (oil temp and pressure) very rare, as such attempting to place all this data into an array or similar before processing is useless as I'm simply not receiving over half the frames on the bus. I have confirmed that these frames are on the bus with my Pi/ PiCan2.
By generating an interrupt routine I can receive these frames more regularly, but again rarely. I suspect that the interrupt routine simply allows for a more random frame start "selection" and as such is still dropping a vast majority of data, just allowing for a more random frame selection.
What I don't understand is that if I'm overflowing the 2515 buffers then why is there not a continuous series of buffered interrupt's being performed, or why is pin 2 not constantly low?
Is it possible that this is a problem with reading both buffers in the 2515?
Please forgive my inability to describe this in a more cohesive coding manner. I've only been coding for a very limited time and am using the dash as a project to fire neurons and gain some skills in micros. I think I've bitten off more than I can chew with my first mouthful.

By comparing the timing on receipt of frames on the Pi with the timing received on the Nano I think I may have simply pointed to an issue with not enough grunt.
It appears that the Link ECU waits 500ms before planting 12 frames on the bus at 1ms increments. Hence the reason for pin two not remaining low. However the buffers on the Nano are dumping huge amounts of data.

// demo: CAN-BUS Shield, receive data
#include <mcp_can.h>
#include <SPI.h>

float countUp = 1;
long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
unsigned long rcvTime;


MCP_CAN CAN0(10);                               // Set CS to pin 10


void setup()
{
  Serial.begin(115200);
  CAN0.begin(CAN_500KBPS, MCP_8MHz);                      // init can bus : baudrate = 500k
  pinMode(2, INPUT);                            // Setting pin 2 for /INT input
  Serial.println("MCP2515 Library Receive Example...");
}

void loop()
{
  CAN0.readMsgBuf(&len, rxBuf);              // Read data: len = data length, buf = data byte(s)
  if (sizeof(rxBuf) == 8)
  {
    rcvTime = millis();
    Serial.print(rcvTime);
    rxId = CAN0.getCanId();                    // Get message ID

    Serial.print(" ID: ");
    Serial.print(rxId, HEX);
    Serial.print("  Data: ");
    for (int i = 0; i < len; i++)             // Print each byte of the data
    {
      Serial.print(rxBuf[i], HEX);
      Serial.print(" ");
    }
    Serial.println();
  }
  else
  {
    Serial.println ("Buffer size too small");
  }



}

The result below, I believe, demonstrates that I simply can't pick up data at 500kBPs with a transmit rate of 2Hz. (the slowest I can introduce data onto the bus). I've even lowered the bus data rate to 125kBPs with a similar issue.

4248 ID: 3E8  Data: 0 0 0 0 67 0 65 0 
4251 ID: 3E8  Data: 4 0 0 0 90 1 1A 4 
4255 ID: 3E8  Data: 1 0 FD 3 64 0 0 0 
4258 ID: 3E8  Data: 
4260 ID: 3E8  Data: 
4262 ID: 3E8  Data: 
4263 ID: 3E8  Data: 
4265 ID: 3E8  Data: 
4268 ID: 3E8  Data: 
4270 ID: 3E8  Data: 
4272 ID: 3E8  Data: 
4274 ID: 3E8  Data: 
4275 ID: 3E8  Data: 
4277 ID: 3E8  Data: 
4279 ID: 3E8  Data: 
4281 ID: 3E8  Data: 
4283 ID: 3E8  Data: 
4285 ID: 3E8  Data: 
4286 ID: 3E8  Data: 
4288 ID: 3E8  Data: 
4290 ID: 3E8  Data: 
4292 ID: 3E8  Data: 
4294 ID: 3E8  Data: 
4296 ID: 3E8  Data: 
4297 ID: 3E8  Data: 
4299 ID: 3E8  Data: 
4301 ID: 3E8  Data: 
4303 ID: 3E8  Data: 
4305 ID: 3E8  Data: 
4306 ID: 3E8  Data: 
4308 ID: 3E8  Data: 
4311 ID: 3E8  Data: 
4313 ID: 3E8  Data: 
4315 ID: 3E8  Data: 
4317 ID: 3E8  Data: 
4318 ID: 3E8  Data: 
4320 ID: 3E8  Data: 
4322 ID: 3E8  Data: 
4324 ID: 3E8  Data: 
4326 ID: 3E8  Data: 
4328 ID: 3E8  Data: 
4329 ID: 3E8  Data: 
4331 ID: 3E8  Data: 
4333 ID: 3E8  Data: 
4335 ID: 3E8  Data: 
4337 ID: 3E8  Data: 
4339 ID: 3E8  Data: 
4340 ID: 3E8  Data: 
4342 ID: 3E8  Data: 
4344 ID: 3E8  Data: 
4346 ID: 3E8  Data: 
4348 ID: 3E8  Data: 
4349 ID: 3E8  Data: 
4352 ID: 3E8  Data: 
4354 ID: 3E8  Data: 
4356 ID: 3E8  Data: 
4358 ID: 3E8  Data: 
4360 ID: 3E8  Data: 
4361 ID: 3E8  Data: 
4363 ID: 3E8  Data: 
4365 ID: 3E8  Data: 
4367 ID: 3E8  Data: 
4369 ID: 3E8  Data: 
4371 ID: 3E8  Data: 
4372 ID: 3E8  Data: 
4374 ID: 3E8  Data: 
4376 ID: 3E8  Data: 
4378 ID: 3E8  Data: 
4380 ID: 3E8  Data: 
4382 ID: 3E8  Data: 
4383 ID: 3E8  Data: 
4385 ID: 3E8  Data: 
4387 ID: 3E8  Data: 
4389 ID: 3E8  Data: 
4391 ID: 3E8  Data: 
4392 ID: 3E8  Data: 
4395 ID: 3E8  Data: 
4397 ID: 3E8  Data: 
4399 ID: 3E8  Data: 
4401 ID: 3E8  Data: 
4403 ID: 3E8  Data: 
4404 ID: 3E8  Data: 
4406 ID: 3E8  Data: 
4408 ID: 3E8  Data: 
4410 ID: 3E8  Data: 
4412 ID: 3E8  Data: 
4414 ID: 3E8  Data: 
4415 ID: 3E8  Data: 
4417 ID: 3E8  Data: 
4419 ID: 3E8  Data: 
4421 ID: 3E8  Data: 
4423 ID: 3E8  Data: 
4425 ID: 3E8  Data: 
4426 ID: 3E8  Data: 
4428 ID: 3E8  Data: 
4430 ID: 3E8  Data: 
4432 ID: 3E8  Data: 
4434 ID: 3E8  Data: 
4435 ID: 3E8  Data: 
4438 ID: 3E8  Data: 
4440 ID: 3E8  Data: 
4442 ID: 3E8  Data: 
4444 ID: 3E8  Data: 
4446 ID: 3E8  Data: 
4447 ID: 3E8  Data: 
4449 ID: 3E8  Data: 
4451 ID: 3E8  Data: 
4453 ID: 3E8  Data: 
4455 ID: 3E8  Data: 
4457 ID: 3E8  Data: 
4458 ID: 3E8  Data: 
4460 ID: 3E8  Data: 
4462 ID: 3E8  Data: 
4464 ID: 3E8  Data: 
4466 ID: 3E8  Data: 
4468 ID: 3E8  Data: 
4469 ID: 3E8  Data: 
4471 ID: 3E8  Data: 
4473 ID: 3E8  Data: 
4475 ID: 3E8  Data: 
4477 ID: 3E8  Data: 
4478 ID: 3E8  Data: 
4481 ID: 3E8  Data: 
4483 ID: 3E8  Data: 
4485 ID: 3E8  Data: 
4487 ID: 3E8  Data: 
4489 ID: 3E8  Data: 
4490 ID: 3E8  Data: 
4492 ID: 3E8  Data: 
4494 ID: 3E8  Data: 
4496 ID: 3E8  Data: 
4498 ID: 3E8  Data: 
4500 ID: 3E8  Data: 
4501 ID: 3E8  Data: 
4503 ID: 3E8  Data: 
4505 ID: 3E8  Data: 
4507 ID: 3E8  Data: 
4509 ID: 3E8  Data: 
4511 ID: 3E8  Data: 
4512 ID: 3E8  Data: 
4514 ID: 3E8  Data: 
4516 ID: 3E8  Data: 
4518 ID: 3E8  Data: 
4520 ID: 3E8  Data: 
4521 ID: 3E8  Data: 
4524 ID: 3E8  Data: 
4526 ID: 3E8  Data: 
4528 ID: 3E8  Data: 
4530 ID: 3E8  Data: 
4532 ID: 3E8  Data: 
4533 ID: 3E8  Data: 
4535 ID: 3E8  Data: 
4537 ID: 3E8  Data: 
4539 ID: 3E8  Data: 
4541 ID: 3E8  Data: 
4543 ID: 3E8  Data: 
4544 ID: 3E8  Data: 
4546 ID: 3E8  Data: 
4548 ID: 3E8  Data: 
4550 ID: 3E8  Data: 
4552 ID: 3E8  Data: 
4554 ID: 3E8  Data: 
4555 ID: 3E8  Data: 
4557 ID: 3E8  Data: 
4559 ID: 3E8  Data: 
4561 ID: 3E8  Data: 
4563 ID: 3E8  Data: 
4564 ID: 3E8  Data: 
4567 ID: 3E8  Data: 
4569 ID: 3E8  Data: 
4571 ID: 3E8  Data: 
4573 ID: 3E8  Data: 
4575 ID: 3E8  Data: 
4576 ID: 3E8  Data: 
4578 ID: 3E8  Data: 
4580 ID: 3E8  Data: 
4582 ID: 3E8  Data: 
4584 ID: 3E8  Data: 
4586 ID: 3E8  Data: 
4587 ID: 3E8  Data: 
4589 ID: 3E8  Data: 
4591 ID: 3E8  Data: 
4593 ID: 3E8  Data: 
4595 ID: 3E8  Data: 
4597 ID: 3E8  Data: 
4598 ID: 3E8  Data: 
4600 ID: 3E8  Data: 
4602 ID: 3E8  Data: 
4604 ID: 3E8  Data: 
4606 ID: 3E8  Data: 
4608 ID: 3E8  Data: 
4610 ID: 3E8  Data: 
4612 ID: 3E8  Data: 
4614 ID: 3E8  Data: 
4616 ID: 3E8  Data: 
4618 ID: 3E8  Data: 
4619 ID: 3E8  Data: 
4621 ID: 3E8  Data: 
4623 ID: 3E8  Data: 
4625 ID: 3E8  Data: 
4627 ID: 3E8  Data: 
4629 ID: 3E8  Data: 
4630 ID: 3E8  Data: 
4632 ID: 3E8  Data: 
4634 ID: 3E8  Data: 
4636 ID: 3E8  Data: 
4638 ID: 3E8  Data: 
4640 ID: 3E8  Data: 
4641 ID: 3E8  Data: 
4643 ID: 3E8  Data: 
4645 ID: 3E8  Data: 
4647 ID: 3E8  Data: 
4649 ID: 3E8  Data: 
4651 ID: 3E8  Data: 
4653 ID: 3E8  Data: 
4655 ID: 3E8  Data: 
4657 ID: 3E8  Data: 
4659 ID: 3E8  Data: 
4661 ID: 3E8  Data: 
4662 ID: 3E8  Data: 
4664 ID: 3E8  Data: 
4666 ID: 3E8  Data: 
4668 ID: 3E8  Data: 
4670 ID: 3E8  Data: 
4672 ID: 3E8  Data: 
4673 ID: 3E8  Data: 
4675 ID: 3E8  Data: 
4677 ID: 3E8  Data: 
4679 ID: 3E8  Data: 
4681 ID: 3E8  Data: 
4683 ID: 3E8  Data: 
4684 ID: 3E8  Data: 
4686 ID: 3E8  Data: 
4688 ID: 3E8  Data: 
4690 ID: 3E8  Data: 
4692 ID: 3E8  Data: 
4694 ID: 3E8  Data: 
4696 ID: 3E8  Data: 
4698 ID: 3E8  Data: 
4700 ID: 3E8  Data: 
4702 ID: 3E8  Data: 
4704 ID: 3E8  Data: 
4705 ID: 3E8  Data: 
4707 ID: 3E8  Data: 
4709 ID: 3E8  Data: 
4711 ID: 3E8  Data: 
4713 ID: 3E8  Data: 
4715 ID: 3E8  Data: 
4716 ID: 3E8  Data: 
4718 ID: 3E8  Data: 
4720 ID: 3E8  Data: 
4722 ID: 3E8  Data: 
4724 ID: 3E8  Data: 
4726 ID: 3E8  Data: 
4727 ID: 3E8  Data: 
4729 ID: 3E8  Data: 
4731 ID: 3E8  Data: 
4733 ID: 3E8  Data: 
4736 ID: 3E8  Data: 
4737 ID: 3E8  Data: 
4739 ID: 3E8  Data: 
4741 ID: 3E8  Data: 
4743 ID: 3E8  Data: 
4745 ID: 3E8  Data: 
4747 ID: 3E8  Data: 
4749 ID: 3E8  Data: 0 0 0 0 67 0 65 0 
4752 ID: 3E8  Data: 3 0 96 0 EE 4 0 0 
4755 ID: 3E8  Data: 1 0 FD 3 64 0 0 0

I think I'm pissing in the wind with the 8mhz can bus adapter. Or anything without a decent buffer.

I couldn't collect all frames on the canbus. As such dumped the Nano, 2515 and library.
I now collect all frames with a ESP32, SN65HVD230 and a ESPCAN library.

I have a question about sending two messages from different IDs in sender example to recieve example, so If I send messages without delay, the recieving IDs aro not in sync. I have ID 0x380 and ID 0x288 sending data
but on reciever side I get random number of messages from same ID and then random from different, attached image explains my problem. But when I add delay at the end of send message, it is better but then responsive is bad.