CAN in vehicle

Thread Starter

Kittu20

Joined Oct 12, 2022
484
Hello everyone,

I'm looking for someone who can provide a general explanation about CAN communication networks. My focus is on understanding its application within vehicles. After looking information from various websites, it appears to be widely used in vehicle.

To illustrate, consider a vehicle network with a microcontroller featuring inbuilt CAN. This setup includes two headlights, four door locks, and a temperature sensor, each equipped with its transceiver IC. All these components are interconnected through the CAN bus. I'm particularly keen on gaining a better understanding of how these elements communicate using the CAN protocol.

Specifically, I'd like insights into what the CAN frame, CAN IDs, and CAN messages would be in this context. Any explanation on these aspects would be greatly appreciated.
 
Last edited:

Thread Starter

Kittu20

Joined Oct 12, 2022
484
I've been following a link https://en.m.wikipedia.org/wiki/CAN_bus with valuable information, but I'm currently facing challenges in translating the theoretical knowledge into real application.

In my example, I have a total of five nodes, including the microcontroller. Each node is designated for specific tasks - one for controlling the left headlight, another for the right headlight, one for the left door lock, and one for the right door lock.

My understanding is that each node should have its unique CAN ID, and the CAN frame should consist this ID along with relevant data.

For instance, if we wish to control the left headlight, the master controller should send a CAN frame containing the appropriate CAN ID and data to take the action.

Could you confirm if I am on right track
 

Ian0

Joined Aug 7, 2020
10,277
I've been following a link https://en.m.wikipedia.org/wiki/CAN_bus with valuable information, but I'm currently facing challenges in translating the theoretical knowledge into real application.

In my example, I have a total of five nodes, including the microcontroller. Each node is designated for specific tasks - one for controlling the left headlight, another for the right headlight, one for the left door lock, and one for the right door lock.

My understanding is that each node should have its unique CAN ID, and the CAN frame should consist this ID along with relevant data.

For instance, if we wish to control the left headlight, the master controller should send a CAN frame containing the appropriate CAN ID and data to take the action.

Could you confirm if I am on right track
Yes - that's about it. The "source address" is the lowest 8 bits in the 29-bit ID code.
The next 16 bits will be a "PGN" which has something to do with headlights. There is a list of them - I found it the other day using Google, so it can't be hard to find. Unfortunately, I didn't keep the link.
The CAN 8 data bytes will contain the instruction as to what to do with the headlights.
 

LowQCab

Joined Nov 6, 2012
4,309
Attached are several Folders containing information that I have gathered on CAN Networking as utilized by
a Mega-Squirt Fuel-Injection-Computer.
They are contained in a single Zip-File.
There's more to CAN than You might imagine.
There are several different common Protocols that may, or may not be, utilized in your particular system.
There are also several different Bit-Rates that can be employed, even in the same Network.

CAN Networks are also used in some industrial/manufacturing environments, not just Cars and Trucks.
.
.
.
 

Attachments

Thread Starter

Kittu20

Joined Oct 12, 2022
484
. There is a list of them
This structure reminded me of a scenario I2C where multiple slave devices operate over two signals.

In this analogy, where multiple nodes communicate with a central node over two signals, namely CAN High and CAN Low.

CAN-bus-frame-with-stuff-bit-and-correct-CRC.png
 

Thread Starter

Kittu20

Joined Oct 12, 2022
484
Yes - that's about it. The "source address" is the lowest 8 bits in the 29-bit ID code.
The next 16 bits will be a "PGN" which has something to do with headlights. There is a list of them -
There may be multiple nodes connected to CAN bus I'm curious about the process of deciding the ID for a node in a CAN communication setup. Does the programmer assign any magic number for this ID, and if so, is it based on any specific criteria or is there a standardized method?
 

Ian0

Joined Aug 7, 2020
10,277
There may be multiple nodes connected to CAN bus I'm curious about the process of deciding the ID for a node in a CAN communication setup. Does the programmer assign any magic number for this ID, and if so, is it based on any specific criteria or is there a standardized method?
I think you have to find a number that hasn't been used, but I don't know quite how you would do that.
I dealing with it on Victron products, and it is possible to log into the product via bluetooth and change its number - but unfortunately, that doesn't help you.
 

LowQCab

Joined Nov 6, 2012
4,309
There may be multiple nodes connected to CAN bus I'm curious about the process of deciding the ID for a node in a CAN communication setup. Does the programmer assign any magic number for this ID, and if so, is it based on any specific criteria or is there a standardized method?
.
Generally, "You" don't decide,
the manufacturer of the equipment normally assigns the IDs,
or a "range" of recognized, or proprietary, ID's,
when the Software is written.
.
.
.
 

Thread Starter

Kittu20

Joined Oct 12, 2022
484
I dealing with it on Victron products, and it is possible to log into the product via bluetooth and change its number - but unfortunately, that doesn't help you.
.
Generally, "You" don't decide,
the manufacturer of the equipment normally assigns the IDs,
How we determine within a CAN message frame whether we intend to write data to the node or read data from it. I wanted to discuss a technical aspect related to CAN message frames. In the context of our system with two nodes – one controlling headlights and the other reading temperature. Node 1 has ID = 0x15, Node 2 has ID 0x20

How we represent the intention to write or read in the CAN message Frame ?
 
Last edited:

Ian0

Joined Aug 7, 2020
10,277
How we determine within a CAN message frame whether we intend to write data to the node or read data from it. I wanted to discuss a technical aspect related to CAN message frames. In the context of our system with two nodes – one controlling headlights and the other reading temperature. Node 1 has ID = 0x15, Node 2 has ID 0x20

How we represent the intention to write or read in the CAN message Frame ?
You can't read. All you can do is send a request, then wait for the answer.
 

Thread Starter

Kittu20

Joined Oct 12, 2022
484
You can't read. All you can do is send a request, then wait for the answer.
meaning when a node sends a message, every other node on the network receives it. Each node then decides independently whether to ignore or act upon the message based on its programming and the message content.
 

Ian0

Joined Aug 7, 2020
10,277
One big advantage of CAN over RS485 is that the hardware decided whether to receive the message, not the software. That removes a big software overhead in receiving and discarding unwanted messages.
 

Thread Starter

Kittu20

Joined Oct 12, 2022
484
One big advantage of CAN over RS485 is that the hardware decided whether to receive the message, not the software. That removes a big software overhead in receiving and discarding unwanted messages.
I'm looking ways to simulate CAN behavior using MPLAB.

Do you have any experience or suggestions on using the CAN module in MPLAB for simulator?
 

Ian0

Joined Aug 7, 2020
10,277
I'm looking ways to simulate CAN behavior using MPLAB.

Do you have any experience or suggestions on using the CAN module in MPLAB for simulator?
Afraid not - I have done all my CAN software on ARMs, either NXP or Renesas.
I'm about to use a MCP2518, but I haven't started on it yet.
 

Thread Starter

Kittu20

Joined Oct 12, 2022
484
Afraid not - I have done all my CAN software on ARMs, either NXP or Renesas.
I'm about to use a MCP2518, but I haven't started on it yet.
Thank you for your quick response!

Could you kindly share any basic code you might have for CAN project in ARM .

I believe having a code will helpful as we can proceed with further discussion.
 

Ian0

Joined Aug 7, 2020
10,277
All I have is a CAN receive interrupt handler and routines for setting up the interface. Those will be different for each CAN module, and are probably provided free in MPLAB.
 

Thread Starter

Kittu20

Joined Oct 12, 2022
484
All I have is a CAN receive interrupt handler and routines for setting up the interface. Those will be different for each CAN module, and are probably provided free in MPLAB.
I'm quite curious to explore the depths of your code, particularly the segment related to CAN message frame implementation for different nodes. Taking a closer look at your code would undoubtedly enhance my understanding, and having the flexibility to seek clarification in case of any doubts would be immensely beneficial.

Could you please share the relevant code ?
 

nsaspook

Joined Aug 27, 2009
13,578
I can share some of my 'work in progress' code for a simple ID based command parser for CAN on the PIC18 Q84. The CAN ID numbers are unique to this network so they are just made-up.
https://forum.allaboutcircuits.com/...rge-controller-datalogger.194146/post-1854534

C:
/*
 * simple CAN FD transfers using blocking TX and interrupts for RX
 */
#ifndef CANFD_H
#define    CANFD_H

#ifdef    __cplusplus
extern "C" {
#endif

#include "qconfig.h"
#include "mateQ84.X/mxcmd.h"
#include "modbus_master.h"
#include "batmon.h"

#define DATA_DEBUG
#define NO_NODE_ID
#define NODE_ID_SHIFT    4

#ifdef CAN_REMOTE
#define LCD_MIRROR
#endif

#define USE_FD    // select classic or FD
#define CANFD_BYTES     64
#define CANFD_NBUF      3
#define CAN_RX_TRIES    8
#define CAN_REC_BUFFERS    4
#define CAN_LOW_BUF     0
#define CAN_HIGH_BUF    1
#define CAN_INFO_BUF    2
#define CAN_ERROR_BUF    3
#define CAN_MIRRORS    4

#define    EMON_M    0x1    // FM80 host
#define EMON_SL    0x2    // remote display lower data
#define EMON_SU    0x3    // remote display upper data
#define EMON_MR    0x4    // LCD mirror data [0..3]]
#define EMON_TM    0xA    // remote time from time server
#define EMON_DS    0xB    // remote display server
#define EMON_ER    0xF    // error reporting
#define EMON_CO    0xC    // configuration reporting
#define EMON_DA    0xD    // 64 byte binary blob

#define MIRR0R_BUF    CANFD_NBUF-1 // LCD mirror CANBUS buffer
#define LCD_BUF_SIZ    22

    typedef struct {
        uint32_t rec_count;
        bool rec_flag;
    } can_rec_count_t;

    typedef struct {
        volatile uint8_t blob[CANFD_BYTES];
        volatile bool tx_flag, rx_flag;
    } blob_type;

    /*
     * testing blob data feature for logs
     */
    union blob_log {
        blob_type blob;
        mx_logpage_t log;
    };

    extern volatile can_rec_count_t can_rec_count;
    extern CAN_MSG_OBJ msg[3];
    extern volatile uint8_t rxMsgData[CAN_REC_BUFFERS][CANFD_BYTES];
    extern time_t can_timer;
    extern struct tm *can_newtime;

    void TXQNotFullHandler(void);
    void Can1FIFO1NotEmptyHandler(void);

    extern char info_buffer[MAX_B_BUF], log_buffer[MAX_B_BUF];
    void can_fd_tx(void);
    void can_setup(void);
    void can_fd_lcd_mirror(const uint8_t, char *);
    void can_mirror_print(void);
    void can_blob_set(blob_type*);
    blob_type* can_blob_get(blob_type*);
    bool get_blob_tx(void);
    bool get_blob_rx(void);

#ifdef    __cplusplus
}
#endif

#endif    /* CANFD_H */

A receive CAN message interrupt handler.
C:
/*
 * process the FIFO data into msg structure
 * interrupt context ISR
 */
void Can1FIFO1NotEmptyHandler(void)
{
    uint8_t tries = 0;
    static uint8_t half = CAN_LOW_BUF;

    INT_TRACE; // GPIO interrupt scope trace

    while (true) {
        can_rec_count.rec_count++;
        if (CAN1_ReceiveFrom(FIFO1, &msg[half])) //receive the message
        {
            memcpy(&msg[MIRR0R_BUF], &msg[half], sizeof(CAN_MSG_OBJ));

// other code removed

            if ((msg[MIRR0R_BUF].msgId & 0xf) == EMON_TM) {
                memcpy((void *) &can_timer, msg[MIRR0R_BUF].data, sizeof(time_t)); // load 32-bit linux time from canbus packet
                EB->fm80_time = can_timer; // save remote Unix time from canbus packets
                can_newtime = localtime(&can_timer);
                update_time(can_newtime, EB);
                /*
                 * update the FM80 time and data message values with a proper checksum
                 * this is sent to the FM80 but am unsure if it changes anything on the device
                 */
                myVar.Word = EB->time;
                cmd_time[5] = myVar.structBytes.Byte1; // store time
                cmd_time[4] = myVar.structBytes.Byte2;
                myVar.Word = calc_checksum((uint8_t *) & cmd_time[1], CMD_CRC_LEN);
                cmd_time[7] = myVar.structBytes.Byte1; // store crc
                cmd_time[6] = myVar.structBytes.Byte2;
                myVar.Word = EB->date;
                cmd_date[5] = myVar.structBytes.Byte1;
                cmd_date[4] = myVar.structBytes.Byte2;
                myVar.Word = calc_checksum((uint8_t *) & cmd_date[1], CMD_CRC_LEN);
                cmd_date[7] = myVar.structBytes.Byte1;
                cmd_date[6] = myVar.structBytes.Byte2;
                if (B.canbus_online && B.FM80_online) {
                    C.tm_ok = true; // FM80 time date data valid to send flag
                }
                break;
            }
#ifdef CAN_REMOTE
            if ((msg[MIRR0R_BUF].msgId & 0xf) == EMON_MR + LCD0) {
                memcpy((void *) &s_buffer[LCD0][0], msg[MIRR0R_BUF].data, LCD_BUF_SIZ); // load LCD mirror packet
                mirror_print[LCD0] = true;
                break;
            }
            if ((msg[MIRR0R_BUF].msgId & 0xf) == EMON_MR + LCD1) {
                memcpy((void *) &s_buffer[LCD1][0], msg[MIRR0R_BUF].data, LCD_BUF_SIZ); // load LCD mirror packet
                mirror_print[LCD1] = true;
                break;
            }
            if ((msg[MIRR0R_BUF].msgId & 0xf) == EMON_MR + LCD2) {
                memcpy((void *) &s_buffer[LCD2][0], msg[MIRR0R_BUF].data, LCD_BUF_SIZ); // load LCD mirror packet
                mirror_print[LCD2] = true;
                break;
            }
            if ((msg[MIRR0R_BUF].msgId & 0xf) == EMON_MR + LCD3) {
                memcpy((void *) &s_buffer[LCD3][0], msg[MIRR0R_BUF].data, LCD_BUF_SIZ); // load LCD mirror packet
                mirror_print[LCD3] = true;
                break;
            }
#endif
        }
        if (++tries >= CAN_RX_TRIES) {
            break;
        }
    }
}
This sends the LCD text buffer from the main controller to a remote controllers display to mirror that text on the remote screen
C:
/*
 * send LCD line buffer data via CANBUS to remote displays
 */
void can_fd_lcd_mirror(const uint8_t r, char *strPtr)
{
#ifndef CAN_REMOTE    // don't repeat a received message
    if (!B.FM80_io) {
        CAN_MSG_OBJ Transmission; //create the CAN message object
        Transmission.field.brs = CAN_BRS_MODE; //Transmit the data bytes at data bit rate
        Transmission.field.dlc = DLC_64; // 64 data bytes
        Transmission.field.formatType = CAN_FD_FORMAT; // CAN FD frames
        Transmission.field.frameType = CAN_FRAME_DATA; // Data frame
        Transmission.field.idType = CAN_FRAME_EXT; // EXT ID
        Transmission.msgId = EMON_MR + r + (B.node_id << NODE_ID_SHIFT); // packet type ID of client
        Transmission.data = (uint8_t*) strPtr; //transmit the data from the data bytes
        if (CAN_TX_FIFO_AVAILABLE == (CAN1_TransmitFIFOStatusGet(TXQ) & CAN_TX_FIFO_AVAILABLE))//ensure that the FIFO has space for a message
        {
            CAN1_Transmit(TXQ, &Transmission); //transmit frame
        }
        Transmission.msgId = (EMON_DA + (B.node_id << NODE_ID_SHIFT)); // BLOB data packet type ID
        Transmission.data = (uint8_t*) & blob; //transmit the data from the data bytes
        if (CAN_TX_FIFO_AVAILABLE == (CAN1_TransmitFIFOStatusGet(FIFO3) & CAN_TX_FIFO_AVAILABLE))//ensure that the FIFO has space for a message
        {
            CAN1_Transmit(FIFO3, &Transmission); //transmit frame
        }
        blob.tx_flag = false;
    }
#endif
#ifdef CAN_REMOTE_ERR
    if (CAN1_IsRxErrorActive()) {
    }
#endif
}
These three displays are synchronized by CAN messages.
1699724050328.png
 

Thread Starter

Kittu20

Joined Oct 12, 2022
484
I would like someone help with this network shown in picture I created where have a one microcontroller with inbuilt can, each node consists with the trans receiver IC, one control the left headlight, one control the right headlight and one monitor the temperature so it's have their specific ID so how all node communicate

IMG-20231112-WA0003.jpg
 
Top