Published on

Arduino IDE?

Authors
  • avatar
    Name
    Johanness Nilsson
    Mastodon

Nah…

The Arduino IDE has no LSP. No fuzzy finding. No git integration. The autocomplete is a joke that's always late to the punchline. It's a g'damn Java Swing app from 2005 that somehow survived into the present day.

There arose a need to improve some process controls connected to servos on this bespoke industrial machinery i've been working on, so now i'm writing firmware for Teknic ClearCore motion controllers—industrial grade hardware that drives ClearPath servos. Teknic provides a few paths to development: a native C++ SDK if you're the kind of code cowboy who wants to wrangle your own toolchain, Microchip Studio if you enjoy trading one proprietary IDE for another, or their Arduino board package. The Arduino path is lowest resistance—Teknic already did the work of packaging the toolchain, board definitions, and upload scripts. You get their libraries pre-configured and arduino-cli gives you command-line access to all of it.

But using the Arduino toolchain doesn't mean you're stuck with a joke-ass jerk-off toy IDE.

Code that controls precision machinery deserves a proper development environment. i had a look around and didn't find much discussion that aligned with the way i like to do things, so i wired up my Neovim to the Arduino toolchain—full LSP support, Telescope integration, the works. Let's dive in and i'll explain the path to get there as we go.

The Stack

  • LazyVim as the Neovim base
  • arduino-cli for compilation and uploads
  • clangd + arduino-language-server for LSP
  • Arduino-Nvim plugin for Telescope integration
  • NixOS managing the whole thing declaratively

Nix Packages

First i added the tooling to my neovim.nix extraPackages:

# Arduino Development
arduino-cli
clang-tools   # provides clangd
arduino-language-server

Plugin Config

Create lua/plugins/arduino.lua:

return {
  {
    "yuukiflow/Arduino-Nvim",
    dependencies = {
      "nvim-telescope/telescope.nvim",
      "neovim/nvim-lspconfig",
    },
    ft = "arduino",
    config = function()
      require("arduino-nvim").setup({})
    end,
  },
}

Keybindings are built in:

  • <leader>ac — compile
  • <leader>au — upload
  • <leader>am — serial monitor
  • <leader>al — library manager (Telescope)
  • <leader>ag — board picker
  • <leader>ap — port picker

LSP Setup

That lives in lsp-nixos.lua, so I added the following:

clangd = {
  mason = false,
  filetypes = { "c", "cpp", "objc", "objcpp", "cuda" },
},
arduino_language_server = {
  mason = false,  -- there is a reason for this, but later...
  cmd = {
    "arduino-language-server",
    "-cli", "arduino-cli",
    "-clangd", "clangd",
    "-cli-config", vim.fn.expand("~/.arduino15/arduino-cli.yaml"),
  },
  filetypes = { "arduino" },
},

i added both to my Mason exclusion list so it doesn't try to install its own copies. more on the weird idomatic behavior or Mason in NixOS in a later post.

arduino-cli Init

After rebuilding:

arduino-cli config init
arduino-cli core update-index
arduino-cli core install arduino:avr    # standard boards
arduino-cli core install arduino:samd   # ARM boards

ClearCore Setup

ClearCore uses a custom board manager:

arduino-cli config add board_manager.additional_urls \
  https://raw.githubusercontent.com/Teknic-Inc/ClearCore-Arduino-wrapper/refs/heads/master/package_clearcore_index.json

This URL may change, but at the time of writing was correct.
The base repo is on github

After you have added the board_manager.additional_urls you can run:

arduino-cli core update-index
arduino-cli core install ClearCore:sam
$:
Downloading packages...
arduino:arm-none-eabi-gcc@7-2017q4 downloaded
arduino:bossac@1.9.1-arduino1 downloaded
arduino:CMSIS@4.5.0 downloaded
ClearCore:sam@1.7.1 downloaded
Installing arduino:arm-none-eabi-gcc@7-2017q4...
Configuring tool....
arduino:arm-none-eabi-gcc@7-2017q4 installed
Installing arduino:bossac@1.9.1-arduino1...
Configuring tool....
arduino:bossac@1.9.1-arduino1 installed
Installing arduino:CMSIS@4.5.0...
Configuring tool....
arduino:CMSIS@4.5.0 installed
Installing platform ClearCore:sam@1.7.1...
Configuring platform....
Platform ClearCore:sam@1.7.1 installed

Verify with:

arduino-cli board listall | rg clearcore
# Teknic ClearCore ClearCore:sam:clearcore

Project Setup

Every Arduino project needs a sketch.yaml in the root for the LSP to work:

mkdir ~/projects/motor_control
cd ~/projects/motor_control
arduino-cli sketch new motor_control

cat > sketch.yaml <<EOF
default_fqbn: ClearCore:sam:clearcore
default_port: /dev/ttyACM0
EOF

nvim motor_control.ino

Open the file, :LspInfo should show arduino_language_server attached. Type Serial. and autocomplete suggestions appear.

Troubleshooting

Permission denied on serial port:

sudo usermod -a -G dialout $USER
# log out and back in

LSP not attaching:

  • Check sketch.yaml exists
  • :set ft? should show arduino
  • :LspLog for errors

"No treesitter parser for this buffer":

Arduino files are C++ under the hood, but there's no dedicated treesitter parser for the arduino filetype. Register the cpp parser in lua/config/options.lua (or anywhere that loads early):

vim.treesitter.language.register("cpp", "arduino")

This needs to run before files are opened, so don't put it in a plugin's config function that's lazy-loaded on ft = "arduino".

ClearCore not detected:

lsusb | grep -i teknic
# should show: ID 16d0:08a0 MCS Teknic ClearCore

If not, add udev rules to your NixOS config:

services.udev.extraRules = ''
  SUBSYSTEM=="tty",
  ATTRS{idVendor}=="16d0",
  ATTRS{idProduct}=="08a0",
  MODE="0666",
  GROUP="dialout"
'';

Resources


Work With Us

If you made it this far, you're probably the kind of person who can't leave broken things alone ‒if a tool fights you, you engineer a better tool. The kind who enjoys methodical work as much as engineering new methods. If you're in the L.A. area, let's grab a pint and I'll tell you about what I'm working on at Terraform Industries.

We're building machines that turn sunlight and air into fuel—applying software brains to hardware problems where the stakes are higher than a deploy button.

We need people who care about the craft. Mechanical technicians, controls engineers, firmware devs, fabricators and anyone who'd rather spend their days making atoms move than pixels shift.

If that sounds like you, send a one page introduction. Skip the cover letter fluff. Tell us what you've built and why you care.