Hacker News new | past | comments | ask | show | jobs | submit login

Has anyone used both I2C and other protocols like PJON or CAN and can compare?



I've used I2C and CAN.

I2C is electrically far more fragile than CAN. CAN is robust against all sorts of electrical faults. While you might not be able to transmit data, you won't fry the controller, and once the fault is removed it comes back.

I2C is often more tolerant of unexpected traffic on the bus. There are far too many ECUs that will put a vehicle into limp mode (limit speed drastically) if they detect unexpected CAN traffic, even traffic not directed to them. Protocol-wise I2C is significantly simpler to get right.


That's a very useful analysis, thanks!


To add to this, I2C is more common between a controller and 'slaves' which are architecturally simpler, for instance single output sensors often have I2C as their comms interface.

CAN is really meant for distributed embedded systems where you are having to implement full blown communication between equally complex nodes.

CAN is indeed much more robust both at a physical layer with a differential line and at a transfer layer with all sorts of error detection and mitigation mechanisms.


I see, thanks. I'm asking mostly from a model airplane perspective, where you have a receiver, GPS, mag, transmitter, etc. Right now they use UART, with only the mag using I2C, but CAN sounds like a better solution, especially given the amount of electrical noise you get from the motors/servos.


You could go for a realism factor and adopt MIL-STD-1553 or ARINC 429.


No LOL, but that made me giggle.


It doesn't have wide adoption yet, but it's coming! https://uavcan.org/


Oooh, that's very exciting! Worth it just for the standardized connectors, pinouts are such a mess right now, no two of them are the same.


The closest comparable protocol IMO would be SPI-- which generally requires more wiring and more "slave management" (addressing a certain slave device is typically done via dedicated chip-select connection, while sharing data lines). Potential data rates are significantly higher (>1MBit/s) But SPI is even less specified, and you will sometimes encounter slaves with diverging/exotic requirements (regarding chip select/clock timing behavior, actual protocol structure on bit level, etc.). This is also typically full duplex unlike both others.

I2C is highly suitable as an interface to a bunch of registers, while being still very simple (especially wiring/addressing) and easy to get to work. Slave devices are also typically more consistent in behavior/requirements than with SPI.

CAN is by far the most complex of these; it is not intended for connecting components on a single board, but instead to connect discrete components. It typically needs transceivers (separate from your controller), and has typically the most rigid timing requirements for participants. Multiple bitrates are possible, and the protocol already comes with mechanisms for clock synchronization, CRC checking, message retransmission on error and basic protocol structure (11/29bitID + up to 8 data bytes per message). Actual useful bandwith is often the worst with this protocol, also because overhead is very significant (think ~150bits on the bus for every message containing 8byte data+29bit ID) Max Bus baudrate is typically 1Mbit but 250K is most common, while higher rate extensions exist (CAN-FD).

Never used PJON before, but AFAICT its more of a software stack on top of existing protocols (while also defining a custom physical layer). This one is MUCH less pervasive than the other three from my experience.


I would say that while CAN is much more complex as a protocol, it is far simpler from the point of view of the software interface: CAN works by sending and receiving atomic messages, and usually there's a straightforward messagebox protocol with the control which can be used. I2C on the other hand required a very complex (and timing-sensitive) interface between the software and the peripheral, due many details of the protocol being underspecified and varying from device to device. SPI is far simpler than the other two, even though there are many variations (usually just a matter of tweaking some bits in the peripheral).


I can see your point, but I disagree with the "CAN software interface is typically simpler"-- in my experience, there is often a significantly larger API surface with CAN than with I2C on microcontrollers, and you are forced to deal with it because otherwise NOTHING works; examples are bit timing configuration, parameters for behavior when messages are not acknowledged, picking the right frame format, etc.

While with I2C, chances are much better that your microcontroller manufacturer just provides you with a HAL_I2C_Mem_Write function, and you just use defaults everywhere, without understanding or caring, and things just work™.

But all this probably depends a lot on specific platform...


I've had the opposite experience: each I2C device has its own way of using the constructs of the protocol, and you need to customise your code for each one, even though they all generally basically implement the same concepts. e.g. how do you address the register (after you've addressed the device), how do you read vs write, how do you read multiple bytes, empty a FIFO, what does an ACK or NAK mean? And I2c means you need the software to decide this on every. single. byte. And woe betide you if the software chose wrong or takes too long to decide, because then the bus is wedged and nothing will happen. And that's before you get into buggy implementations, either in the micro (STM32s have had multiple different buggly I2C peripherals), or on the device. I've had multiple hair-pullingly bad bugs in I2C where it mostly worked fine until some edge case or another caused the whole thing to lock up unpredictably, causing bugs which ranged from subtle to hardware destroying. It's absolutely the furthest from 'just work' I've seen at this level.

On the other hand, CAN is mildly more difficult to configure initially (usually you need to understand the message box protocol if you want maximum efficiency), but it's then pretty damn bulletproof, and far less actual code to worry about.


I think at worst it is a wash. Having used various device on both, CAN is more regular. The complexity you attribute to CAN is there with I2C just poorly documented, devices resetting for no reason, etc. I think CAN is preferable, and you can even use it on short runs without the physical interfaces.


That's helpful, thank you. CAN does sound much more heavy-weight, though I guess it might be a good fit when you have multiple MCUs (not just sensors to connect to one MCU).


CAN is intended for real-time applications, i.e. with bounded latency. Its also intended for use in noisy environments, hence the differential signalling. Both these characteristics are required for automotive applications.

I2C is relatively susceptible to noise in comparison to CAN. I2C is also very simple to interface with from both a h/w and s/w perspective. CAN, having timing requirements requires more thought on the s/w side.

UARTs are also simple to use and can be used in multi-drop protocols for using multiple devices and can also give good range and noise rejection in some variants (i.e. RS485, RS422, etc).

SPI is for on-board, relatively high-speed use with a handful of devices (maximum) but offers limited noise rejection.

There are also other simple protocols (e.g. one-wire) but they're less popular these days.

PJON on the other hand is pretty much unknown and is a very much higher level protocol that isn't really comparable to CAN-bus.


PJON is more an abstraction over a bunch of different protocols.

CAN is for off board comms.

I2C should really never leave the board.

I've actually seen a blend though, where someone hooked a couple CAN transceivers to bridge an I2C bus off board (a simple LED board had to be 3 meters away from the micro controller). At the end of the day they should have just put a micro controller on the other end and ran CAN over it, as they still had a bunch of glitches anyway.


CAN is used for more robust communication at a longer distance, whereas I2C is typically used for inter-chip communication on the same PCB.

Never heard of PJON.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: