Menu

CAN Bus Library MCP2515 and USB - CAN Bus Tool

Angel Mier
2021-10-07
2022-01-03
  • Angel Mier

    Angel Mier - 2021-10-07

    I always wanted to communicate various microcontrollers in a reliable network, and wanted that it works whit GCB. In my spare time I started working in a library to use CAN Bus easily and cheaply, I used some available boards whit the Microchip MCP2515 Can controller and an NXP/Phillips TJA1015 Can Transceiver, in my country I can get it for something like $5 US Dollars, so I think you can get them cheaply.
    It can communicate whit the CAN Bus specification v2.0A and v2.0B (it is v2.0B Passive and Active), have 2 Rx Buffers whit 2 masks and 6 filters, 3 Tx buffers and can handle bit rates from 5kbps to 1mbps.
    The library at the moment can:
    • Transmit messages whit any Tx buffer
    • Read Messages whit any Rx buffer
    • Set Filters and masks for Rx messages
    • Get Buffer Status
    • Set the bitrate between 5,10,20,31,33,40,50,80,100,125,200,250,1000 KBPS
    • Clear Rx Interrupts
    • Use CAN Standard ID’s and Extended ID’s
    • Change working modes (Config, Normal, Listen, Loopback and Sleep)

    The first can frame that came out of the library 😊

    Also, in the development of the library (and whit the help of the USB library) I made a useful device; it’s a tool for sniffing CAN Bus communications (it can send data frames too!), it logs all activity in the bus, read only the messages and stay or act inconspicuous, or acknowledge them and act like another controller in the bus, in this last mode you cand send a CAN frame that you set in the application. It is made whit one of the boards and a PIC 18F4550.

    This is a look of the simplicity of the tool, nothing fancy:

    The Windows Application communicating thru USB:

    My beautiful Device Under Test a BMW F850GS model year 2020 (It happens that I have a CAN Bus easy access in the harness for testing):

    The device and the app Sniffing the CAN Bus data 😊 BMW Motorrad uses a 500kbps bus (actually BMW uses mostly standard ID frames instead of the extended ones, but I think that I see one or two extended, I didn’t fire up the bike only turn on the ignition.)


    The device connected to the CAN Bus thru one of the connectors of the harness

    The test rigs (not pretty) two Pic 18f45k50 and the “tool”

    In the current state, the app can save the CAN bus log in a ccv format for further analysis, I added some logs of the bike sniffing, in the log called “bike off hazard lights on.ccv” I turned on the hazard lights and then turned off the ignition, in a brief period (like 1 min) all of the computers turned off except for the Body Controller that keeps actuating the lights and keeps informing of that, in that way I can isolate that one identifier and data.

    This project is a work in progress, in the attachments I add the current code of the library in case someone want to take a sneak pick. I still going to add a little bit more of functionality to the library, the tool and the App. Also, I will share the code of the 3 things and some easy and advanced demos, Stay tuned.
    So, as always, forget my bad English and have a great day everyone.

    Angel.

     

    Last edit: Angel Mier 2021-10-07
  • Anobium

    Anobium - 2021-10-07

    A wonderful project and your library is very good - clear and use of development conventions is also very good.

    Let us know how you move forward from Alpha to Release!

     
  • Angel Mier

    Angel Mier - 2021-10-07

    Update: Symple demo codes.

    Send a Frame

    '''A program  for GCGB and GCB the demonsations......
    '''--------------------------------------------------------------------------------------------------------------------------------
    '''This program sends a CAN Bus standard frame whit the status of one button in it simpliest way.
    '''
    '''@author     Angel Mier
    '''@licence    GPL
    '''@version    1.0
    '''@date       10/07/2021
    '''********************************************************************************
    
    ; ----- Configuration
     #chip 18F45k50, 48
    #include <CanBus.h>
    
     #option explicit
    
    ; ----- Constants
    
    
    ; ----- Define Hardware settings
       // CanBus
       #define CanBus_HardwareSPI   'Just because we can, we are going to use Hardware SPI this time, coment for sft.
       #define CanBus_DI       PORTB.0          ' Data in | MISO
       #define CanBus_DO       PORTB.3          ' Data out | MOSI
       #define CanBus_SCK      PORTB.1          ' Clock Line  sck
    
       #define CanBus_INT      PORTB.2          ' Interrupt command line
       #define CanBus_CS       PORTB.4          ' Chip select line
    
       #define CanBus_BitRate 1000  'bit rate in kbps, Options: 5,10,20,31,33,40,50,80,100,125,200,250,1000
    
    
    #define Button PORTa.2  'Our most precious button
    dir Button in
    
    ; ----- Variables
    dim Buffern as Byte
    dim ForceExt as BIT
    dim ID as Long
    dim RTR as BIT
    dim DLC as Byte
    dim ButtonStatus as BIT
    ; ----- Quick Command Reference:
    
    
    ; ----- Main body of program commences here.
    'Variable details
     Buffern  = 0     'we will use the TX0 Bufer, we have 3
     ID       = 0x400 'Our Frame ID will be  1024 (you can enter it in decimal or hex) its a Standard id and the library will detect it accordingly
     ForceExt = 0     'we can force to send a lower value as an extended id (29 bits instead of 11 for standard) in this case we are going to use a standard id
     RTR      = 0     'we arent asking for data so we dont going to use a Remote Request Frame
     DLC      = 1     'how many bytes of data we will send? the CAN bus v2.0 standard allows a maximum of 8 in a frame
    
    'change to normal mode
    CanBus_NormalMode
    
    'lets inform of our actual status.
    ButtonStatus = Button
    CanBus_SendMessage (Buffern,ForceExt,ID,RTR,DLC,ButtonStatus)
    
    
     Do
    
    'our button has been tampered? :-)
    if ButtonStatus <> Button then
    ButtonStatus = Button
    'lets send our frame trouhg the bus and be a happy module
    CanBus_SendMessage (Buffern,ForceExt,ID,RTR,DLC,ButtonStatus)
    end if
    
    'rince and repeat...
            Loop
    
            end
    
    ; ----- Support methods.  Subroutines and Functions
    

    Read a Frame

    '''A program  for GCGB and GCB the demonsations......
    '''--------------------------------------------------------------------------------------------------------------------------------
    '''This program reads a CAN Bus standard frame whit the status of one button and turns a led.
    '''
    '''@author     Angel Mier
    '''@licence    GPL
    '''@version    1.0
    '''@date       10/07/2021
    '''********************************************************************************
    
    ; ----- Configuration
     #chip 18F45k50, 48
    #include <CanBus.h>
    
     #option explicit
    
    ; ----- Constants
    
    
    ; ----- Define Hardware settings
       // CanBus
    '  #define CanBus_HardwareSPI       //Disable Coment for Hardware SPI, change pins accordingly
       #define CanBus_DI       PORTE.0          ' Data in | MISO
       #define CanBus_DO       PORTE.1          ' Data out | MOSI
       #define CanBus_SCK      PORTE.2          ' Clock Line  sck
    
       #define CanBus_INT      PORTB.2          ' Interrupt command line
       #define CanBus_CS       PORTB.3          ' Chip select line
    
       #define CanBus_BitRate 1000  'bit rate in kbps, Options: 5,10,20,31,33,40,50,80,100,125,200,250,1000
    
    
    #define Led PORTa.1  'a happy led
    dir Led out
    Led = 0
    
    ; ----- Variables
    dim Buffern as Byte
    dim Ext as BIT
    dim RTR as BIT
    dim DLC as Byte
    dim ID as Long
    dim ExpectedID as Long
    dim Rx0Full as BIT
    ; ----- Quick Command Reference:
    
    
    ; ----- Main body of program commences here.
    'Variable details
     Buffern    = 0     'we will use the RX0 Bufer, we have 2
     ExpectedID = 0x400 'Our expected Frame ID will be  1024 (you can enter it in decimal or hex)
    'ID                  What ID we receive?
    'Ext                 do we receive an extended ID?
    'RTR                 do we receive a Remote Request Frame?
    'DLC                 how many bytes of data we receive?
    'Rx0Full             did the mail arrive?
    
    'change to normal mode
    CanBus_NormalMode
    
    
     Do
    
    'read the Rx0 buffer status
    CanBus_GetBufferSatus Rx0Full
    
    if Rx0Full = 1 then
    'lets read the frame!
    CanBus_ReadMessage Buffern, Ext, ID, RTR, DLC
    
    'WARNING: in this example we are filtering the data whit the microcontroler and wasting resources, the library have the capability to do mask and message filtering on the CAN controller
    '         and get interrupts whitout any sacrificies; But this is a simple Hello world program.
    
    'is our frame the one expected?
    if ID = ExpectedID then
    'lets command that led.
    Led = Not CanBus_ReadBuffer(1).0 'we are reading a BYTE and only want the first bit (maybe some one send us another number), I'm using "Not" because my button relaxed state is 1
    end if
    end if
    
    'rince and repeat...
            Loop
    
            end
    
    ; ----- Support methods.  Subroutines and Functions
    

    Stay tuned

     
  • mmotte

    mmotte - 2021-10-08

    Angel,

    Very nice code. Well commented, thank you.

    I don't know much about CAN_BUS but this this library makes it a useful tool and you don't need to know much. I understand that CAN is used in cars(and motorcylces?) and industrial control. I have worked on an Old Dynapath (late 1990's)CNC controller that used CAN for the I/O bus. At that time I was wondering how to explore the CAN_bus never pursued it. You have given the ability to log it here.

    So you are using an external bus controller and level driver. I see some of the PIC chips have CAN in their description. Do you know if they have the CAN controller built in? I will look.

    Thanks again
    Mike W9YS

     
  • Angel Mier

    Angel Mier - 2021-10-08

    hi, first thank you for your comments, its true, that you can start without knowing much about CAN, but you will maybe start making some minor mistakes, i further recomend you reading this page first: https://www.kvaser.com/can-protocol-tutorial/ its easy, concise, and available in video if you dont want to read.
    for the pic's whit embedded CAN: in the process of making this library i also read some datasheets of pic series that ended in 80 and 88 if i'm not mistaken, like the 18f4580, and it actualy looks that are very similar or almost identical to the mcp2550, just that the registers are internal in the pic instead of accessing by spi obviously, even the registers and bits have the same names. may be it well be not that hard to adapt the library to it, but and big but, i dont have access to that microcontroller localy :-( also, you will need any ways a canbus transceiver like the TJA1015 mentioned earlier.

    the CAN bus is a beautifull protocol, very reliable, and almost bullet proff, as you say its also used in automation and motion control (i also like a lot CNC's, made my own little ones) they normaly use at top of the CAN bus protocol, a transfer layer called CANopen; there are several transfer layers, in example: CANopen, CANaerospace, UAVCAN, CANkingdom, etc. every one tailored to their specific needs, its important to remark that these layers run atop of the can bus and there arent included in the can bus specification, actualy a simple way to view it is, that they are the way you are going to comunicate in a ordered manner following certain rules. i recommend you to avoid this layer at the beginning and fully immerse you in the raw can bus specification that consist in the physical and data link layer, the beauty and simplicity of CAN bus resides there.

    greetings.

    Angel

     

    Last edit: Angel Mier 2021-10-08
  • Anobium

    Anobium - 2022-01-03

    Angel - I am testing the new build and I am getting some failures.

    I have installed the CANBUS.H library and I get the following errors.

    Canbus.h - ' date: 10/06/2021 Alpha (For a sneak peak)

    Errors

    "C:\temp\GCB@Syn\GreatCowBASIC\demos\CANbus_Solutions\2Advanced Demos\CANbus Adv module  18f4550.gcb"
    CANbus Adv module  18f4550.gcb (83): Error: Syntax Error
    CANbus Adv module  18f4550.gcb (153): Error: Syntax Error
    CANbus Adv module  18f4550.gcb (197): Error: Variable BUTTSTAT was not explicitly declared
    
    "C:\temp\GCB@Syn\GreatCowBASIC\demos\CANbus_Solutions\2Advanced Demos\CANbus LCD module  18f45k50.gcb"
    CANbus LCD module  18f45k50.gcb (91): Error: Syntax Error
    CANbus LCD module  18f45k50.gcb (144): Error: Syntax Error
    

    Maybe I do not have the latest .h file?

     
  • Angel Mier

    Angel Mier - 2022-01-03

    Hi Evan, you are right, that errors are because some subroutines aren’t present in the old header file.

    The latest library it’s on your GitHub repo:
    https://github.com/Anobium/Great-Cow-BASIC-Library-Development/blob/master/CANbus/CanBus.h

    Latest library is from 10/19/2021
    I tested it on AVR and works on hardware and software SPI (on hardware mode, just don’t use the chip select hardware pin, use another one)

    Also in “CANbus Adv module 18f4550.gcb” one variable have a typo, already corrected and pull request made.

    Compiled all the examples with no errors on my end.

    I will update my first post to add the links to the latest library and files.

    I wish you a great 2022.
    Best regards, Angel.

     
  • Anobium

    Anobium - 2022-01-03

    Thank you for the updates and info.

    Your library will be included in the next release, along with your demos.

    Again, thank you,

    Evan

     

Log in to post a comment.