Electronic – Using CAN bus tranceivers with custom data link layer

1-wirecani2cprotocoluart

We needed a noise immune, low cost, multidrop, multi master (realtime and distributed) protocol and there is only CAN bus seems to meet with these requirements.

Since there are no can controllers (data link layer hardware) for very low cost MCU's (such as STM32F0) and no easy-to-use API we could find to get started we can not consider CAN bus as a default communication stack of our projects.

So I think I can implement a really tiny layer that will allow implementing any protocol (like Modbus) over UART over CAN physical layer while taking advantage of data collision detection by using 1 starting byte as a bait.

Additionally, I suppose any I2C or 1-Wire hardware can directly use a CAN transmitter for its bus protocol with a simple diode-resistor hack, similar to 1-wire <-> uart diode-resistor hack.

I suspect I'm missing something since this approach is both bringing many advantages with a relatively small effort although there is no implementation I could find for this purpose.

Are there any hidden consequences on this survey?

Edit

1-Wire (with UART hack) is not working over MCP2551 CAN transceiver, since the transceiver starts feeding itself with zero (dominant) at the end point (the 1-Wire side) which prevents any device from writing "1" on the bus till the transceiver's "permanent TXD detection" function takes over the control. So, it's useless from the point of view of "simple 1-wire range extender". Which means a CAN bus transceiver's RXD/TXD pins can not be converted to an open drain line with a simple 1-wire/uart converter hack, so it will not work either with an I2C bus.

Edit-2

Using 1 byte as a bait is not performant since we have to use only 1 bit as zero, which means we have to use 100 bit just for addressing if we plan to connect 100 device on the same bus because although we could detect someone else is talking at the same time but we can not detect the priority (eg. if node#0b101 and node#0b011 talks at the same time, we will read 0b001 which is just the same response when node#0b011 and node#0b001 talks. So node#011 will never know if it has the priority or not.) So this is impossible if we don't use a bit banging technique and read the RX port bit by bit. Which makes no sense because it's reinventing CAN bus as mentioned.

Best Answer

  1. Many small and cheap microcontroller have CAN built in. Look at some of the PIC 18 with "8" in their part number. You only need to add the physical CAN transceiver, like a MCP2551.
  2. If you just want a differential signal, then you can use a number of differential line drivers/receivers. There is nothing wrong with using CAN transceivers for this, RS-485 or others are options too.

Overall, I'd use CAN all the way. You will need a line drivers/receivers one way or another. CAN transceivers are as good as any, but then it's easier to use the rest of CAN. The main difference with CAN is that the lower levels of the protocol have been well thought out and are available at low cost integrated directly in many microcontrollers. RS-485 throws you a electrical spec, then you're on your own.

It's a lot more difficult to get all the details of a multi-drop bus right and robust than most people realize. Use CAN. It's all been worked out and done for you. You send whole packets at the firmware level. The hardware takes care of collision detection, retry, and CRC checksum generation and validation. These are all things you want, and with CAN you get them practially for free.