CAN bus - how to not miss packets? - Page 1
Forum section: electronics / general

author: e100
author_rank: Frequent Contributor
timestamp: February 11, 2017, 08:43:28 am
content: I'm using the MCP2515 CAN bus controller that has a 2 message receive buffer. I'm running it at 10 kbps so my micro cannot be busy doing other things (such as reading a temperature sensor) for more than about 25 ms otherwise packets will be missed.The MCP2515 talks through SPI, so reading the data via an interrupt isn't an option.My code is currently sprinkled with polling checks so see if the MCP2515 has data in its Rx buffer. It sort of works but it's not very elegant.Do systems running at higher baud rates (cars use 500 kbps) use some kind of synchronised time slot protocol whereby there are quiet periods set for when sensors are being read and then talkative periods when the micros are exchanging data?

author: hans
author_rank: Super Contributor
timestamp: February 11, 2017, 08:53:47 am
content: You really need interrupts. The MCP2515 can generate those, but you need an additional wire to the MCU to signal that. It's true you can't send the interrupt over SPI, but then also it shouldn't.The MCP2515 has the INT Pin which I suppose is re-programmable, and additional RXxBF/TXxRTS pins.If you're running SPI at 10kbps that will cause problems at high bus loads.If you're running the CAN bus at 10kbps; then that is quite slow.Large CAN busses do not use synchronization. The beauty of CAN is that any device can put a message on the bus at any time, but due to dominant bits during message ID phase the most important messages will be send first.But to be honest, you probably want to set up acceptance masks and filters in order to reduce the number of data via SPI.

author: e100
author_rank: Frequent Contributor
timestamp: February 11, 2017, 09:09:16 am
content: Quote from: hans on February 11, 2017, 08:53:47 amThe MCP2515 has an INT (data available) hardware line, but if I use that to generate an interrupt then I cannot use SPI within the interrupt to get the data.I'm using 3 filters to look for 3 packet IDs but sometimes packets arrive when the micro is busy and with only 2 receive buffers data gets missed.

author: Rerouter
author_rank: Super Contributor
timestamp: February 11, 2017, 09:17:37 am
content: Perhaps cut your other tasks into smaller slices, so the longest wait time on the system is still smaller than the time it takes to overwrite your buffer,For reading temperature sensors, most micros do the conversion of ADC's in the hardware and write a flag when done, if a digital sensor, most 1 wire or I2C ones have quite a lengthy timeout window, equally some micros I2C interfaces need you to only fill the buffer and tell it to write, and has a buffer for read, allowing you to let the hardware do your heavy lifting.Same goes for TTL serial out if your sending data that way, use the hardware buffer for your read and write operations.This way you dont need to use interrupts, just make the first thing you check that status pin of the chip before starting a new task. otherwise plod on through the state machine

author: voltsandjolts
author_rank: Unknown
timestamp: February 11, 2017, 09:55:59 am
content: Quote from: e100 on February 11, 2017, 09:09:16 amYes you can and thats exactly what you should do but you must implement SPI transfers using interrupts.The MCP2515 interrupt handler starts the first SPI transfer, sets up the SPI interrupt, disables the MCP2515 interrupt then exits. That takes a few microseconds.After the first SPI transfer completes you get another interrupt to handle that...and so on until all the SPI transfers are done.Then (in the last SPI transfer interrupt) enable the MCP interrupt again ready for next message.

author: JPortici
author_rank: Super Contributor
timestamp: February 11, 2017, 10:35:28 am
content: i don't understand why you can't use the interrupt. yes you can, you absolutely can (and should)

author: Lunasix
author_rank: Regular Contributor
timestamp: February 11, 2017, 10:45:15 am
content: And never use delay loop (except for some us and when it can't be avoided) in software. If a function can not respond and should wait, return and call it later, when result will be available. Use DMA when necessary. 25ms is no more real time for me.

author: SKPang
author_rank: Unknown
timestamp: February 11, 2017, 10:47:18 am
content: I would definitely use interrupt.Increase the clock speed of your SPI so that when an interrupt occurs, inside your ISR it will read the MCP2515 quickly and exit.

author: kaz911
author_rank: Super Contributor
timestamp: February 11, 2017, 11:58:22 am
content: you could also change to TI Tiva w/CAN - there you can have filters in "hardware" so an interrupt is only generated on the packets you are interested in.

author: JPortici
author_rank: Super Contributor
timestamp: February 11, 2017, 12:53:53 pm
content: i didn't want to mention it because maybe he doesn't want to change hardware (and this "problem" sounds like it is in software anyway, given the geological eras between events)but yes, you could use any MCU with a can controller built in. there are thousands of them, even from simple 8 bitters

author: e100
author_rank: Frequent Contributor
timestamp: February 11, 2017, 02:59:59 pm
content: This is on an Arduino Mega2560. I tried using SPI within the interrupt but the micro would freeze after a few seconds, after processing a dozen or so messages. I kind of assumed that SPI isn't allowed within an interrupt. Looks like I was wrong.This is the library I'm usinghttps://github.com/coryjfowler/MCP_CAN_lib.I shall try to create a minimal test case that does nothing except receive messages.

author: JPortici
author_rank: Super Contributor
timestamp: February 11, 2017, 03:25:05 pm
content: don't assume, check with the debugger. Oh of course, you cant. Ditch the arduino crap altogether and get full control of the chip

author: jnz
author_rank: Frequent Contributor
timestamp: February 11, 2017, 05:25:03 pm
content: Definitely interrupts. 10kbps on CAN is WAY slow.If you are having issues with 10k CAN, you are programming poorly. You should be able to poll SPI to cover that. My guess is you are writing blocking code and have a software technique problem more than a hardware problem.I don't like that the 2515/25625 have 2 receive buffers, but with a hardware interrupt you should be fine.Can't run SPI from an ISR, I agree, is reason to dump that chip! That said, my above point stands and if you are smart about it, the ISR should set a flag and it will be handled in your main context.

author: e100
author_rank: Frequent Contributor
timestamp: February 11, 2017, 06:46:50 pm
content: My buggy code. Sometimes the receive message interrupt occurred while another part of the code was already in the process of sending a message out through the same MCP2515.My current fix is to temporarily disable interrupts before sending a message and re enable them afterwards. I'm not sure this is the correct way to do this, but it's working.

author: jnz
author_rank: Frequent Contributor
timestamp: February 11, 2017, 10:58:39 pm
content: Quote from: e100 on February 11, 2017, 06:46:50 pmI don't know that chip or arduino, but I've had similar issues in PIC where interrupt while in an interrupt wasn't working, the solution in that last case was to enable priority interrupts and specific somethings high and low.