element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Members
    Members
    • Benefits of Membership
    • Achievement Levels
    • Members Area
    • Personal Blogs
    • Feedback and Support
    • What's New on element14
  • Learn
    Learn
    • Learning Center
    • eBooks
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Dev Tools
    • Manufacturers
    • Raspberry Pi
    • RoadTests & Reviews
    • Avnet Boards Community
    • Product Groups
  • Store
    Store
    • Visit Your Store
    • Choose Another Store
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
Arduino
  • Products
  • More
Arduino
Blog Arduino MKR CAN Shield Review - part 2: Interrupt and Filter
  • Blog
  • Forum
  • Documents
  • Events
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Arduino requires membership for participation - click to join
Blog Post Actions
  • Subscribe by email
  • More
  • Cancel
  • Share
  • Subscribe by email
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Jan Cumps
  • Date Created: 26 Jun 2019 10:34 AM Date Created
  • Views 1154 views
  • Likes 3 likes
  • Comments 0 comments
  • mkr_shields
  • can_bus
  • automotive
  • mcp2515
  • can_shield
  • arduino
  • can
Related
Recommended

Arduino MKR CAN Shield Review - part 2: Interrupt and Filter

Jan Cumps
Jan Cumps
26 Jun 2019

A follow up project with the Arduino MKR CAN Shield.

In this post, I try to offload as much effort as possible to the CAN IC, and reduce the load on the Arduino microcontroller.

image

 

CAN Receive with Interrupts

 

The CAN controller, the Microchip MCP2515Microchip MCP2515, has several features that handle traffic management in hardware.

The first one I review here, the read interrupt, takes care that the controller doesn't have to check if data is arriving.

Instead of looping and polling all the time, the Arduino can spend its precious resources on other activities, or can go to a low power mode.

When traffic arrives, the CAN controller sends a signal on its trigger pin.

That pin is watched by the Arduino (the CAN library from Sandeep Mistry takes care of that).

 

My task, as user of the library, is to:

  • inform that I want to use the interrupt, and
  • provide an interrupt service handler.

 

The interrupt is activated by adding this piece of code:

 

  // register the receive callback
  CAN.onReceive(onReceive);

 

The interrupt function will be called when data arrives on the bus:

 

void onReceive(int packetSize) {
  // received a packet
  Serial.print("Received ");

  if (CAN.packetExtended()) {
    Serial.print("extended ");
  }

  if (CAN.packetRtr()) {
    // Remote transmission request, packet contains no data
    Serial.print("RTR ");
  }

  Serial.print("packet with id 0x");
  Serial.print(CAN.packetId(), HEX);

  if (CAN.packetRtr()) {
    Serial.print(" and requested length ");
    Serial.println(CAN.packetDlc());
  } else {
    Serial.print(" and length ");
    Serial.println(packetSize);

    // only print packet data for non-RTR packets
    while (CAN.available()) {
      Serial.print((char)CAN.read());
    }
    Serial.println();
  }

  Serial.println();
}

 

This isn't my code. It's the CANReceiverCallback example from the library I'm using.

In that example, the loop() method does nothing. That's because it doesn't have to do anything. All is handled by the interrupt.

 

void loop() {
  // do nothing
}

 

This is an excellent way to prove that the mechanism works.

In a real project, you may want to minimise the logic in the interrupt handler, and handle the majority of the processing in the loop().

That, in combination with sleeping whenever possible, can result in a well-behaving, low power design.

 

Add Hardware Filtering

 

The CAN controller has an additional hardware feature. It can filter inbound messages and only pass them to the Arduino if they match the filter's scope.

Together with the interrupt, this is a powerful combination.

Ther microcontroller just has to read the data. It already knows that that data is intended for it.

 

image

 

In the first section, the microcontroller received an interrupt for each message appearing on the bus. It had to check the message ID of each data chunk and decide if it was of interest.

If the message wasn't intended for our design, we spent precious clock ticks to find that out. And if we were in low power mode, we woke up for nothing.

In this example with filters, the hardware capabilities of the CAN controller are put to optimal use. The controller only has to spend clock ticks if the message is relevant.

 

The change to the code is minimal. Add this snippet before the interrupt handler registration:

 

  // Set ID Filter 
  if (!CAN.filter(0x01)) {
    Serial.println("Setting CAN ID filter failed!");
    while (1);
  }

 

The screen capture above shows the project in action.

I used the Microchip CAN AnalyzerMicrochip CAN Analyzer to inject messages on the bus.

What you see on the image is the result of shooting two in-scope messages. Not shown, but tested by me, is that messages with a different ID are nicely ignored.

 

Road Test Blog
part 1: First trials
part 2: Inject CAN Messages
part 3: Analyzer as Test Tool
part 4: Analyze the Physical layer of CAN Bus
Related Blog
part 1: tryout
part 2: Communication between 2 Devices
part 3a: Design a Bus Driver PCB
part 3b: Design a Bus Driver PCB - Schematics and Custom Components
part 3c: Design a Bus Driver PCB - Layout
part 3d: Design a Bus Driver PCB - Test
Arduino MKR CAN Shield Review - part 1: Log BUS Traffic
Arduino MKR CAN Shield Review - part 2: Interrupt and Filter
  • Sign in to reply
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2023 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • Facebook
  • Twitter
  • linkedin
  • YouTube