Realisation Document - CAN PERSONAL PROJECT Gergana Avrionova | T-A-RB01 | 30.05.2025 Table of Contents Introduction ..................................................................................................................... 6 Hardware ........................................................................................................................ 6 Realised Work (What I Did) ............................................................................................. 7 Research and Planning ............................................................................................... 7 Hardware Setup ........................................................................................................... 7 Software Development ................................................................................................ 7 Node Design and Message Protocol ............................................................................ 7 Added advanced Filtering ................................................................................................ 8 Interrupt-Based Message Handling ................................................................................. 8 Final Result ..................................................................................................................... 9 Troubleshooting ............................................................................................................ 10 Brake Button from Node 2 Stopped Responding When Full CAN Bus Was Connected .................................................................................................................................. 10 Problem 2: 180° Servo Didn’t Move Despite Receiving Steering Angle Messages .... 11 Interrupt Mode Only Triggered Once ......................................................................... 11 Indicators Only Updated When New Message Was Received ................................... 12 Engine Servo SUDDENLY Stopped After Brief Acceleration ...................................... 12 Steering Servo Unresponsive Without Delay ............................................................. 12 References.................................................................................................................... 14 PAGE 1 Versions Version 1.0 Date 24.04.2025 1.1 30.05.2025 1.2 19.06.2025 Author(s) Gergana Avrionova Gergana Avrionova Gergana Avrionova Amendments Creation of the document Added more to Realised Work – advanced filtering and interrupt explanations. Added section in Troubleshooting for the interrupt problem I encountered. Added more to Troubleshooting, Created Final Working Result, Conclusion and Reflection Status Reviewed Reviewed In Review Table 1. Current Version PAGE 2 Communication Version 1.0 Date 24.04.2025 1.1 30.05.2025 1.2 20.06.2025 To Jan Dobbelsteen René Bakx Jan Dobbelsteen René Bakx Jan Dobbelsteen René Bakx and and and Table 2. Communication PAGE 3 Table of Tables Table 1. Current Version ................................................................................................. 2 Table 2. Communication ................................................................................................. 3 Table 3. Glossary Table .................................................................................................. 5 PAGE 4 Glossary Term Definition MCP2515 A stand-alone CAN controller chip that interfaces with microcontrollers via SPI to send and receive CAN messages. MCP2551 A CAN transceiver chip that converts digital CAN controller signals into differential bus signals. SPI (Serial A synchronous serial communication protocol used for shortPeripheral distance communication between microcontrollers and Interface) peripherals. I²C (Inter- A two-wire serial communication protocol often used to connect Integrated Circuit) sensors (e.g., BMP280) to microcontrollers. Baud Rate The rate at which data is transmitted over a communication channel, measured in bits per second (bps). millis() A non-blocking Arduino function that returns the number of milliseconds since the program started — often used for nonblocking timing logic. Pull-down A resistor used to ensure a digital pin reads LOW when no active Resistor signal is applied, preventing floating states. Table 3. Glossary Table PAGE 5 Introduction This project explores the implementation of Controller Area Network (CAN) communication to simulate real-world automotive communication between sensors, actuators, and control units. The objective is to design a functional proof of concept (PoC) that showcases reliable, real-time data exchange across a CAN bus using Arduino-based hardware. Hardware The following hardware components were used to build and test the CAN-based automotive simulation system. Each component plays a specific role in simulating a realworld vehicle environment, including sensing, user input, actuation, and communication. Microcontrollers and Communication Interfaces - 3× Arduino Uno R3 — Each board acts as a CAN node (sensor node, input node, actuator node). 3× CANdiy Shield v2.0 — Arduino shields featuring: - MCP2515 (CAN controller) - MCP2551 (CAN transceiver) - RJ45 ports for CAN bus connections - On-board termination resistor options Sensors - 1× BMP280 Sensor — Measures temperature and pressure; connected to Node 1 via I²C. 1× Rotary Encoder — Simulates steering wheel angle; connected to Node 1 via digital pins. Input Devices - 4× Push Buttons — Simulate: - Brake pedal (supports short and long press logic) - Gas pedal (simple activation) - Turn signals (left/right) Actuators - 1× 180° Servo Motor — Simulates steering mechanism on Node 3. 1× Continuous Rotation Servo (360° Servo) — Simulates speed changes based on gas/brake input. 2× LEDs — Represent turn signal indicators for left and right. PAGE 6 Connectivity and Support Components - RJ45 Ethernet Cables (x2) — Connect the CAN nodes in a daisy-chain configuration. Breadboards & Jumper Wires — Used for prototyping and circuit connections. 10kΩ Resistor (x1) — Added as a pull-down resistor to stabilize the brake button input. 2× 330Ω Resistors for the LEDs. Power Supply — Standard USB or external power source for Arduino boards. Realised Work (What I Did) RESEARCH AND PLANNING - Defined core research questions regarding CAN architecture, communication principles, and automotive applications (Project Debriefing, 2025) Studied existing documentation on CAN, including arbitration, message prioritisation, and error handling (CAN Analysis and Advice, 2025) Evaluated and benchmarked different CAN libraries, selecting the Seed Studio library for its robust features and compatibility. (CAN Analysis and Advice, 2025) HARDWARE SETUP - Selected Arduino Uno boards with CANdiy v2.0 Shields for hardware prototyping Design Document CAN_v2. (Design Document CAN, 2025) Implemented correct bus wiring with RJ45 cables and termination resistors. SOFTWARE DEVELOPMENT Developed and integrated key modules for the following components: - Sensors: Rotary encoder (steering angle), BMP280 sensor (temperature & pressure). Inputs: Gas and brake pedals, turn signal switches. CAN Communication: Built a CanBusHandler for sending and receiving CAN messages Actuation: Integrated response logic for LEDs and servos to simulate dashboard and vehicle reactions. NODE DESIGN AND MESSAGE PROTOCOL Defined three logical nodes to separate functionality: - Node 1: Sensor data acquisition. Node 2: Driver input handling. Node 3: Actuation and display. PAGE 7 Assigned unique CAN IDs and message formats to ensure priority and synchronization. Added advanced Filtering To improve the efficiency and reliability of CAN message handling, I implemented advanced filtering using the MCP2515’s built-in mask and filter registers. This allows the receiver node to only process relevant messages, reducing CPU load and minimising the chance of incorrect message handling. The configuration separates filters across both receive buffers (RXB0 and RXB1). RXB0 is assigned to critical sensor data like steering angle and brake status, while RXB1 handles pressure, temperature, gas pedal, and turn signal messages. Each filter matches a specific CAN ID, ensuring that only necessary messages are received and processed by the corresponding logic in the receiver. RXB0, the higher priority buffer, is linked to one mask and two message acceptance filters. Initially, the incoming message is processed through the RXB0 mask and filters. RXB1, the lower priority buffer, has one mask but four acceptance filters. The message is applied to the RXB0 mask and filters first, and because RXB0 has fewer acceptance filters, its matching criteria are more stringent, reflecting its higher priority. When a message arrives, the RXBnCTRL[3:0] register bits reveal which acceptance filter allowed the reception and whether the received message is a Remote Transfer Request. (Microchip Technology Inc., 2019) This design was implemented in the CanReceiver.cpp module. It improves modularity, debugging clarity, and responsiveness by preventing the receiver from being overwhelmed by unrelated messages. Additionally, it simplifies the logic in the update() function by making incoming message types predictable and well-structured, enabling targeted response actions. Interrupt-Based Message Handling To further optimise responsiveness, I added an external interrupt tied to the MCP2515’s INT pin. This interrupt (configured in main.cpp) triggers whenever a new CAN message is received. Instead of continuously polling for new messages, the system now reacts immediately to incoming data by setting a flag (flagRecv) handled in the main loop. This not only reduces processor load but also minimizes latency, making real-time reactions—such as braking or steering—faster and more reliable. PAGE 8 Final Result The final implementation successfully demonstrated reliable Controller Area Network (CAN) communication between three Arduino-based nodes, simulating real-world automotive subsystems: sensor acquisition, driver input, and actuation (See the video in Realisation Evidences). All core functionalities were achieved: - - - Sensor Node (Node 1) accurately measured temperature, pressure, and steering input via a BMP280 sensor and rotary encoder. These values were transmitted over the CAN bus. Input Node (Node 2) successfully captured user inputs through brake, gas, and turn signal buttons. Short and long presses were correctly detected for the brake pedal, and the system handled user interaction reliably after resolving hardware stability using pull-down resistors. Actuation Node (Node 3) correctly responded to CAN messages, activating the appropriate actuators: o Turn indicators blinked with the correct timing and behaved predictably following logic decoupling from message polling. o The engine simulation via a continuous rotation servo reflected acceleration and deceleration commands, including reliable braking when speed = 0. o The 180° steering servo responded accurately to steering angle commands after switching to a non-blocking timing system using millis() and replacing the faulty servo hardware. Additionally, the system incorporated: - Advanced filtering using MCP2515 mask and filter registers to prioritize critical messages and reduce unnecessary processing. Interrupt-based message handling, enabling immediate response to CAN traffic and improved system responsiveness, particularly for time-sensitive inputs such as braking. The system was validated in a full-bus configuration, with all three nodes actively sending and receiving messages. Message flow, processing order, and actuator behavior matched the design specifications. Through iterative debugging, both hardware and software reliability were improved significantly. The result is a robust and modular CAN-based simulation platform, representative of automotive electronic control unit (ECU) communication. The system serves as a strong proof of concept for real-time message exchange, prioritization, and responsiveness in embedded networked environments. Further design considerations and potential improvements are discussed in more detail in the accompanying Design Document (Avrionova, 2025). PAGE 9 Troubleshooting RECEIVER NOT RECEIVING CAN MESSAGES During testing, the receiver using the Seeed Studio MCP2515 CAN library was unable to receive messages from the sender, even though both devices were properly wired and initialized without error. The CAN.checkReceive() function consistently returned no available messages, and the serial monitor only displayed the "CAN init ok!" message. Cause: Incompatibility between CAN FD and CAN 2.0 After examining both the sender and receiver setups, I found that: - The sender was using an MCP2518FD CAN controller, which supports CAN FD (Flexible Data Rate). The receiver was using the MCP2515, which supports only classic CAN 2.0 (up to 8 bytes, no FD features). While the sender was transmitting only 8 bytes (within CAN 2.0 limits), it was doing so using a CAN FD frame format, which includes additional bits that the MCP2515 cannot interpret. This caused the MCP2515 to silently discard all incoming FD frames because they do not comply with the classic CAN 2.0 format. To fix the issue, the sender code was modified to also use the MCP2515 chip and the same library (mcp2515_can.h) as the receiver. BRAKE BUTTON FROM NODE 2 STOPPED RESPONDING WHEN FULL CAN BUS WAS CONNECTED When the full CAN system was connected, the brake button on Node 2 stopped functioning — no output was detected in the serial monitor, and no CAN messages were sent for short or long brake presses. Other buttons on the same node worked without issue. This was a hardware-level electrical issue caused by a floating input pin on the Arduino. When a button is connected with only the pull-down internal resistor of the Arduino, the input pin can float, especially when the CAN bus introduces additional power noise or voltage drift due to shared ground and bus capacitance. In this case, the brake button’s input pin likely drifted around the undefined voltage region, preventing a clean HIGH/LOW signal change. PAGE 10 Adding a 10kΩ pull-down resistor between the button input pin and ground stabilized the signal. This resistor ensures that when the button is unpressed, the pin is firmly held at LOW instead of floating. When pressed, the pin is pulled HIGH cleanly. This resolved the issue entirely, restoring reliable detection of both short and long presses. PROBLEM 2: 180° SERVO DIDN’T MOVE DESPITE RECEIVING STEERING ANGLE MESSAGES Although the rotary encoder on Node 1 correctly sent the steering angle over the CAN bus, and Node 3 successfully received the message (confirmed via serial logs), the 180° servo motor didn’t visibly move in response. It appeared to “receive” data but made no physical motion. Initially, it seemed like the servo wasn't receiving commands, but it turned out the issue was related to timing. Servo motors require a stable PWM signal for a brief period to move to a new position. When updating positions in a fast-running loop without pausing, the servo doesn't have enough time to process the signal before the next command comes in or is skipped. A short delay() (e.g. delay(20)) was added after sending a new position to the servo. This allowed the servo time to physically react and move accordingly. With this delay, the servo started responding correctly to the incoming steering angles. Using delay() is not ideal in real-time systems like this. It blocks the entire processor, which can interrupt the timing of other tasks or message handling — especially in a multi-node CAN system where timing and responsiveness are crucial. I’m currently exploring ways to replace delay() with a non-blocking timing mechanism based on millis(). INTERRUPT MODE ONLY TRIGGERED ONCE While implementing interrupt-based CAN message handling, I encountered an issue where only the first CAN message would be processed successfully, and then the receiver would stop responding to new messages. The interrupt would trigger once, but no further updates were received, even though the sender was still broadcasting messages. After reviewing examples from the Seeed Studio MCP2515 CAN library, I discovered that the problem was caused by not calling the CAN.checkReceive() function inside the main loop, even when using interrupt mode. Although the interrupt correctly flagged that a message was available, the receive buffer was not properly cleared or checked for additional data, which effectively blocked further processing. PAGE 11 The library demonstrates that even when using interrupts, a loop checking CAN.checkReceive() is still necessary to process all available messages. Without this, the IRQ line remains active and the ISR stops triggering after the first event. By integrating this logic into my code—specifically, a while (CAN_MSGAVAIL == CAN.checkReceive()) loop inside the interrupt handler section—I resolved the issue and ensured that all pending CAN messages are read and handled properly. This adjustment restored full functionality and allowed the receiver to reliably respond to multiple incoming messages using interrupts. INDICATORS ONLY UPDATED WHEN NEW MESSAGE WAS RECEIVED The left and right indicator LEDs blinked at a much slower rate than intended, despite being configured with a 200 ms blink interval. The cause was the update() function, which is responsible for toggling the indicators. The function was placed inside the conditional block that checks for new CAN messages. As a result, the indicators only updated when new messages were received—approximately once per second—leading to the observed delay. The indicator update logic was moved outside of the CAN message availability check, allowing it to run continuously within the main loop. This change ensured that the blinking behavior followed the expected timing, independent of message reception frequency. ENGINE SERVO SUDDENLY STOPPED AFTER BRIEF ACCELERATION The continuous rotation servo motor, simulating engine speed, would accelerate briefly and then stop unexpectedly, even though messages were being sent periodically and it should have continue rotating with the last received speed. The cause of that was that the servo update occurred only when new CAN messages were received (same as the indicators problem). In the absence of new data, no command was issued, which defaulted the speed to zero, halting the servo’s rotation. An update() function was added to the engine control class and called continuously within the main loop, like the indicator logic. Additionally, the setSpeed() function was updated to explicitly write a value of 90 to the servo (neutral stop position) whenever a speed of 0 was received. This ensured consistent behavior even during periods with no new data. STEERING SERVO UNRESPONSIVE WITHOUT DELAY The 180° steering servo motor failed to respond to incoming angle commands unless a delay() function was introduced in the main loop (to enable time for it to get to position). However, using delay() caused undesirable blocking behaviour in the system. PAGE 12 Initial Attempted Solution: The servo timing logic was restructured using a non-blocking millis()-based approach, but the issue persisted. The problem was ultimately traced to a hardware fault in the servo itself. It did not reliably process PWM signals, even with correct timing logic. Replacing the servo with a new unit resolved the issue entirely. The new servo responded immediately and consistently to steering angle commands using the nonblocking timing logic. Conclusion and Reflection This project demonstrated the core principles of CAN communication in a multi-node embedded system, simulating interactions among automotive sensors, controls, and actuators. Through iterative development and rigorous debugging, the system evolved from basic message passing to a sophisticated, interrupt-driven architecture with advanced message filtering. The experience highlighted technical and practical challenges in embedded systems engineering, particularly regarding timing, hardware reliability, and communication protocols. It reinforced the importance of clean architecture, modular design, and incremental testing. While the current setup functions reliably, the project has also highlighted areas for future improvement, which are outlined in the Design Document for potential future development. This project served as both a technical milestone and a learning experience, solidifying theoretical knowledge through practical application in a realistic automotive scenario. PAGE 13 References Microchip Technology Inc. (2019). MCP2515 stand-alone CAN controller with SPI interface (Rev. J) [Data sheet]. https://ww1.microchip.com/downloads/en/DeviceDoc/MCP2515-Stand-Alone-CANController-with-SPI-20001801J.pdf Avrionova, G. (2025). Design Document CAN_v2.2. Fontys University of Applied Sciences. Internal project documentation. PAGE 14
0
You can add this document to your study collection(s)
Sign in Available only to authorized usersYou can add this document to your saved list
Sign in Available only to authorized users(For complaints, use another form )