element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • 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 Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
    About the element14 Community
  • 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
      •  Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      •  Vietnam
      • 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
  • Settings
On the Line
  • Challenges & Projects
  • Design Challenges
  • On the Line
  • More
  • Cancel
On the Line
Forum SolarSense - Part 2 - Can Arduino CAN?
  • News
  • Projects
  • Forum
  • DC
  • Leaderboard
  • Files
  • Members
  • More
  • Cancel
  • New
Join On the Line to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • Replies 7 replies
  • Subscribers 36 subscribers
  • Views 251 views
  • Users 0 members are here
Related

SolarSense - Part 2 - Can Arduino CAN?

arvindsa
arvindsa 1 month ago

I spent a lot of time last month cleaning up my projects. I almost lost lost track of time. Now to convert the POC I made into a reliable data collection powerhouse, ArduinoQ running Zephyr on STM32 is new to me. Linux part i can handle.

Recap:

I’m developing a smart solar monitoring system that uses a clean reference panel to eliminate weather effects and directly quantify dust-induced losses in real time. With edge AI and environmental sensing, the goal is to predict the right moment to cleanbefore efficiency drops enough to matter.

  • SolarSense - Part 1 - Introduction, The POC Built and The Plan

Setting Up Arduino Q

I downloaded AppLab quickly from the official website, connected the Arduino Q via a USB-C and blasted away through the configuration screen. In this regard, it was easy, although the update took time. 

image

And it is always an Ritual that i need to blink an LED whenever i get a new hardware and so I used the example. I have to admit it, Using Zephyr , An Python Code and RPC connection between them just to blink LED is like using cannon to Kill a mosquito.

image

Internet Research to Answer the Question

After Looking at some Internet on how to get CAN to work, I came to a conclusion that ArduinoQ cannot run the CAN Controller on the STM32

  • https://forum.arduino.cc/t/arduino-uno-q-canfd-controller-use/1414493 
  • https://forum.arduino.cc/t/uno-q-can-library/1416035 
  • https://forum.arduino.cc/t/trying-to-get-fdcan-working-on-the-uno-q/1431867 

And so the challenge begins. If i cannot easily interface the CAN Peripheral on STM32 then my next idea became to have an additional board like Teensy 3.2 or my Nucleo F303Re which as a CAN Peripheral as a bridge between ArduinoQ and the MAX33041E. Then the number of bridges made me uneasy. Imagine Q's Qualcomm Chip -> Q's STM32 Chip -> Nucleo F303RE -> MAX33041E -> CAN Bus. It was ridiculous. I looked if i can break the Qualcomm's Bridge and somehow run the STM32 using STM32HAL. I came to know that the Linux installation contains OpenOCD and Zephyr's Documentation that the Physical connection between MPU and MCU is LPUART managed by an arduino-router service on the linux

image

Taking Control of the STM32 from the hands of Qualcomm Chip

Step 1: Disable arduino-router Service

I connected to the ArduinoQ's terminal via SSH ssh arduino@<boardname>.local where boardname is the name you gave it while setup. The Password is again the same as you gave in the setup

sudo cp /etc/systemd/system/arduino-router.service \
        /home/arduino/arduino-router.service.bak
sudo rm /etc/systemd/system/arduino-router.service
sudo systemctl mask arduino-router
sudo systemctl daemon-reload
sudo pkill -9 -f arduino-router
 

image

I ensured that i restarted the Q to ensure that the service does not pop up back again.

Step 2: Setting up the STM32MX Project

From the Schematics of Arduino Q here: https://docs.arduino.cc/resources/schematics/ABX00162-schematics.pdf , I got the full chip code - STM32U585AII6TR, set up the project on STM32MX with the clock and just LPUART, LED, CAN

image

image\

The clock values as as below

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState       = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource  = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM       = 1;
RCC_OscInitStruct.PLL.PLLN       = 10;
RCC_OscInitStruct.PLL.PLLR       = 1;   // 16 * 10 / 1 = 160 MHz

I generated the code, starting with a simple blink. btw, Flash latency must be FLASH_LATENCY_4 at VOS1 / 160 MHz — anything lower causes a hard fault on the first cache miss.

Step 3: The Blinking Ritual

The onboard LED is on PH10, active-HIGH

image

/* MX_GPIO_Init USER CODE section */
__HAL_RCC_GPIOH_CLK_ENABLE();

GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin   = GPIO_PIN_10;
GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull  = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);

/* Main loop */
HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_10);
HAL_Delay(500);

Step 4: Setting up the LPUART1

/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */

/* USER CODE BEGIN 2 */
char tx_buf[64];
/* USER CODE END 2 */

/* Main loop */
int len = snprintf(tx_buf, sizeof(tx_buf), "hello from STM32\r\n");
HAL_UART_Transmit(&hlpuart1, (uint8_t *)tx_buf, len, 100);

#!/usr/bin/env python3
import serial, sys

ser = serial.Serial('/dev/ttyHS1', 209700, timeout=5)
print(f"Listening on /dev/ttyHS1 at 209700 baud...")
try:
    while True:
        line = ser.readline()
        if line:
            print(line.decode('utf-8', errors='replace').strip())
except KeyboardInterrupt:
    ser.close()

Step 5: Now ArduinoQ CAN

The STM32 has CAN pins on PA11 (RX) / PA12 (TX). Before connecting to a real bus, verify the peripheral and transceiver with an external loopback test. External loopback drives the TX pin through the transceiver while simultaneously receiving
the frame internally. The STM32 provides its own ACK, so it keeps transmitting even with no termination resistor or other node on the bus. And Ensure that the Jumpers are all in default positions as https://www.analog.com/media/en/technical-documentation/data-sheets/MAX33041ESHLD.pdf except for JU11, you need to switch it to the 3.3V side so that it can receive the power from Arduino Q's 3.3V

image

FDCAN_FilterTypeDef sFilterConfig;
sFilterConfig.IdType       = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex  = 0;
sFilterConfig.FilterType   = FDCAN_FILTER_MASK;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1    = 0x000;
sFilterConfig.FilterID2    = 0x000;  // mask=0 → accept all standard frames
HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig);
HAL_FDCAN_Start(&hfdcan1);

// User Loop
FDCAN_TxHeaderTypeDef txHeader;
uint8_t canTxData[8] = {0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04};
txHeader.Identifier         = 0x123;
txHeader.IdType             = FDCAN_STANDARD_ID;
txHeader.TxFrameType        = FDCAN_DATA_FRAME;
txHeader.DataLength         = FDCAN_DLC_BYTES_8;
txHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
txHeader.BitRateSwitch      = FDCAN_BRS_OFF;
txHeader.FDFormat            = FDCAN_CLASSIC_CAN;
txHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
txHeader.MessageMarker      = 0;

HAL_StatusTypeDef tx_status =
    HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, canTxData);
HAL_Delay(10);

FDCAN_RxHeaderTypeDef rxHeader;
uint8_t canRxData[8];
int len;

if (tx_status != HAL_OK) {
    len = snprintf(tx_buf, sizeof(tx_buf), "CAN TX ERR %d\r\n", (int)tx_status);
} else if (HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO0) > 0) {
    HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &rxHeader, canRxData);
    len = snprintf(tx_buf, sizeof(tx_buf), "CAN OK id=0x%03lX d=%02X%02X%02X%02X\r\n",
                   (unsigned long)rxHeader.Identifier,
                   canRxData[0], canRxData[1], canRxData[2], canRxData[3]);
} else {
    len = snprintf(tx_buf, sizeof(tx_buf), "CAN FAIL no rx\r\n");
}
HAL_UART_Transmit(&hlpuart1, (uint8_t *)tx_buf, len, 100);

and we get the CAN OK id=0x123 d=DEADBEEF on the serial output. And on the Oscilloscope I get the beautiful differential signal. 

image

Finally we made the ArduinoQ CAN.

Final Notes

Arduino Q looking at the specs seems promising but there are lot of usability issues with the software and they should have given an easy connection to STM32 for power users. None the less, I managed to overcome the limitation Zephyr OS gave - Ability to use the CAN peripheral on the STM32 and in that process, i unleashed full potential of the STM32. Next will be to actually connect an Receiver side to the CAN Bus and establish and transfer some poetry. 

  • Sign in to reply
  • Cancel

Top Replies

  • arvindsa
    arvindsa 1 month ago in reply to saramic +1
    Once you killed the router, You should get a response "Killed", check with "sudo systemctl status arduino-router" Status should be masked and there should not be any indication that it is running. Restart…
  • arvindsa
    arvindsa 1 month ago in reply to saramic +1
    arduino@asa-q1:~$ sudo systemctl status arduino-router [sudo] password for arduino: ○ arduino-router.service Loaded: masked (Reason: Unit arduino-router.service is masked.) Drop-In: /run/systemd/generator…
  • embeddedguy
    embeddedguy 1 month ago

    Finally, you are using the scope. Glad.Slight smile

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • arvindsa
    arvindsa 1 month ago in reply to embeddedguy

    :D Yes, With touchscreen replacing the knobs and buttons of a benching DSO, I'm still figuring out how to get some functions done. Were you able to use yours? 

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • embeddedguy
    embeddedguy 1 month ago in reply to arvindsa

    Nope. I am waiting for yours review.Laughing

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • saramic
    saramic 1 month ago

    glad you got to a point where you got around the RouterBridge, I tried many time, I got to your mask command but maybe needed a restart there and then?

    sudo systemctl mask arduino-router
    sudo systemctl daemon-reload           // not sure I did this
    sudo pkill -9 -f arduino-router        // this just kept coming back

    that said - I did mange to just get the bridge working and haven't really looked back - still I am yet to connect the MAX3304 shield

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • arvindsa
    arvindsa 1 month ago in reply to saramic

    Once you killed the router, You should get a response "Killed", check with "sudo systemctl status arduino-router" Status should be masked and there should not be any indication that it is running. Restart is not necessary, i restarted my Q to make sure there is no setting in the arduino that reverses me masking the router. It did not. You can share the result of the "sudo systemctl status arduino-router" 

    Once the bridge is disabled, then the serial port is free to be accessed by a python code. Do install 

    sudo apt update
    sudo apt install python3-pip
    pip3 install pyserial --break-system-packages
    

    After that you can use the python code in the Step 4. Or if you prefer rust use ... sorry i dont know rust.. the appropriate function to open /dev/ttyHS1 and stream the data from and to it. Essentially this becomes your custom bridge between MCU and MPU


    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • arvindsa
    arvindsa 1 month ago in reply to saramic

    arduino@asa-q1:~$ sudo systemctl status arduino-router
    [sudo] password for arduino:
    ○ arduino-router.service
         Loaded: masked (Reason: Unit arduino-router.service is masked.)
        Drop-In: /run/systemd/generator/arduino-router.service.d
                 └─10-imola.conf
         Active: inactive (dead)

    this is output of my Q currently. 

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • DAB
    DAB 1 month ago

    Very good post.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
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 © 2026 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.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube