Skip to Content

Arduino CLI for Arduino PLC: compile and upload on Windows and Linux

Install Arduino CLI, add the Industrial Shields boards and program an M-Duino or Ardbox from the terminal
October 27, 2026 by
Arduino CLI for Arduino PLC: compile and upload on Windows and Linux

Arduino CLI is the official command line tool of Arduino. With it you can program an Arduino PLC (M-Duino or Ardbox) without opening the IDE: add the Industrial Shields boards URL, install the industrialshields:avr platform, then run arduino-cli compile and arduino-cli upload with the FQBN of your model. The commands are the same on Windows and Linux; only the installation and the serial port name change.

This guide covers the full flow on both systems: install, board package, FQBN of each model, compile, upload over USB and serial monitor. At the end you have the avrdude method, which uses the tools that the Arduino IDE 2 already installed.

When is the command line better than the Arduino IDE?

The IDE is the easiest way to write and test a sketch. The command line is better when the same build has to repeat without clicks: a script that programs a batch of PLCs at the end of the line, a build server, a remote PC reached over SSH, or an AI assistant that compiles and flashes for you.

ToolWhat it doesUse it when
Arduino IDE 2Editor, compiler, uploader and serial monitor in one windowYou write and debug the program
Arduino CLIInstalls cores and libraries, compiles and uploads from a terminalYou repeat builds, use scripts or work without a desktop
avrdudeOnly writes an already compiled .hex file to the PLCYou received a .hex and only need to flash it

The IDE 2 uses Arduino CLI inside, with the same default data folder. A core that you install from one of them is available in the other.

What you need

  • An Arduino PLC from the M-Duino or Ardbox families, powered as its datasheet says, and its USB cable.
  • A PC with Windows 10 or 11, or with a Linux distribution (Ubuntu, Debian or similar). Arduino CLI also has builds for Linux ARM, so a Raspberry Pi works too.
  • Internet access the first time, to download Arduino CLI, the Industrial Shields boards and the compiler.
  • The URL of the Industrial Shields boards package:
    https://apps.industrialshields.com/main/arduino/boards/package_industrialshields_index.json

How do you install Arduino CLI on Windows?

  1. Open the official Arduino CLI installation page and download the Windows 64 bit MSI installer or ZIP file.
  2. With the MSI, run the installer. With the ZIP, extract arduino-cli.exe to a folder of your choice, for example C:\arduino-cli, and add that folder to the Path environment variable (search "environment variables" in the Start menu, then Environment Variables > Path > Edit > New).
  3. Open a new Command Prompt or PowerShell window and check the installation:
arduino-cli version

If Windows answers that the command is not recognized, the folder is not in Path yet. Close the terminal and open a new one after you edit Path; you do not need to restart the PC.

How do you install Arduino CLI on Linux?

The official install script downloads the latest version to the folder in BINDIR. The folder must exist before you run it:

mkdir -p ~/.local/bin
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR=~/.local/bin sh
arduino-cli version

If the shell does not find arduino-cli, add the folder to PATH and open a new terminal:

echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc

To use the USB serial port without sudo, add your user to the dialout group (Debian, Ubuntu and Raspberry Pi OS) and log out and in again:

sudo usermod -aG dialout $USER

How do you add the Industrial Shields boards to Arduino CLI?

These commands are the same in the Windows terminal and in the Linux shell. The first one creates the configuration file; if it already exists, skip it.

arduino-cli config init
arduino-cli config add board_manager.additional_urls https://apps.industrialshields.com/main/arduino/boards/package_industrialshields_index.json
arduino-cli core update-index
arduino-cli core search industrialshields
arduino-cli core install industrialshields:avr

core install downloads the Industrial Shields AVR core, the avr-gcc compiler and avrdude. Run arduino-cli core list to see the installed version, and arduino-cli core upgrade later to update it.

PlatformPLC families
industrialshields:avrM-Duino, Ardbox and Spartan (ATmega2560 and ATmega32u4)
industrialshields:esp32ESP32 PLC and the other ESP32 based families

Which FQBN does each M-Duino and Ardbox model use?

The FQBN (Fully Qualified Board Name) tells Arduino CLI the package, the platform, the family and the model: industrialshields:avr:<family>:cpu=<model>. It is the same choice that you make in the IDE under Tools > Board and Tools > Model, and it selects the pin names (Q0_0, I0_0, R1...) of your PLC.

PLCFQBN
M-Duino 21+industrialshields:avr:mduino:cpu=mduino21plus
M-Duino 42+industrialshields:avr:mduino:cpu=mduino42plus
M-Duino 57R+industrialshields:avr:mduino:cpu=mduino57rplus
M-Duino 58+industrialshields:avr:mduino:cpu=mduino58plus
Ardbox Analog HF+ with RS-485industrialshields:avr:ardbox:cpu=ardboxanaloghfplus485
Ardbox Relay HF+ with RS-485industrialshields:avr:ardbox:cpu=ardboxrelayhfplus485

To see every family and the model options of yours:

arduino-cli board listall industrialshields
arduino-cli board details -b industrialshields:avr:mduino

The WiFi/BT, GPRS, LoRa and DALI versions have their own family (for example mduinowifi or ardboxlora), each with its own list of models: check it with board details.

Create and compile a sketch

Create the sketch folder and replace the content of the .ino file with this example. It switches digital output Q0.0 every second and prints the state on the USB serial port:

arduino-cli sketch new BlinkQ00
// Toggle digital output Q0.0 every second and print its state on the USB serial port.
void setup() {
  Serial.begin(115200);
  pinMode(Q0_0, OUTPUT);
}

void loop() {
  static bool on = false;
  on = !on;
  digitalWrite(Q0_0, on ? HIGH : LOW);
  Serial.println(on ? "Q0.0 ON" : "Q0.0 OFF");
  delay(1000);
}

Compile it for your model, for example an M-Duino 42+:

arduino-cli compile --fqbn industrialshields:avr:mduino:cpu=mduino42plus BlinkQ00

The output ends with the flash and RAM that the program uses. In our build with the Industrial Shields AVR core 1.2.1, this sketch used 2,850 bytes of the 253,952 available on the M-Duino 42+, and 4,318 bytes of the 28,672 available on the Ardbox Analog HF+.

On an Ardbox Relay the outputs are relays, so the pin is R1 instead of Q0_0. If you compile the example as it is for that model, the compiler stops with "Q0_0 was not declared in this scope". That error is the FQBN doing its job: each model only knows its own pin names.

Upload the sketch over USB

Connect the PLC and find its serial port:

arduino-cli board list

On Windows the port is COM plus a number (also visible in Device Manager > Ports (COM & LPT)). On Linux it is usually /dev/ttyACM0 or /dev/ttyUSB0. The list may name the board by the Arduino inside the PLC (Mega 2560 or Leonardo); upload with the Industrial Shields FQBN anyway.

# Windows
arduino-cli upload -p COM5 --fqbn industrialshields:avr:mduino:cpu=mduino42plus BlinkQ00

# Linux
arduino-cli upload -p /dev/ttyACM0 --fqbn industrialshields:avr:mduino:cpu=mduino42plus BlinkQ00

You can also compile and upload in one step with arduino-cli compile --upload -p <port> --fqbn <fqbn> BlinkQ00.

Ardbox: its ATmega32u4 has native USB. To start the bootloader, Arduino CLI first opens the port at 1200 baud, and then the PLC can come back on a different port number for a few seconds. Arduino CLI waits for that new port and uploads there. If the upload fails, close any serial monitor that keeps the port open and try again.

Check the program with the serial monitor

arduino-cli monitor -p COM5 -c baudrate=115200

On Linux, use -p /dev/ttyACM0. You should see "Q0.0 ON" and "Q0.0 OFF" every second, and the Q0.0 LED of the PLC change at the same time. Press Ctrl+C to exit.

Alternative: upload a .hex file with avrdude

If you already have the compiled file, avrdude writes it to the PLC without compiling. Arduino CLI saves the .hex next to the sketch with the --export-binaries option (-e), in BlinkQ00/build/industrialshields.avr.mduino/. In the Arduino IDE 2 the same file comes from Sketch > Export Compiled Binary.

You do not need to install avrdude: the Industrial Shields core installs it, for the IDE 2 and for Arduino CLI, in this folder (the version number depends on the core):

Systemavrdude and its configuration file
Windows%LOCALAPPDATA%\Arduino15\packages\industrialshields\tools\avrdude\6.3.0-arduino17\bin\avrdude.exe
...\6.3.0-arduino17\etc\avrdude.conf
Linux~/.arduino15/packages/industrialshields/tools/avrdude/6.3.0-arduino17/bin/avrdude
.../6.3.0-arduino17/etc/avrdude.conf

M-Duino (ATmega2560, protocol wiring, 115200 baud), on Linux:

AVRDUDE=~/.arduino15/packages/industrialshields/tools/avrdude/6.3.0-arduino17
$AVRDUDE/bin/avrdude -C $AVRDUDE/etc/avrdude.conf -p atmega2560 -c wiring -P /dev/ttyACM0 -b 115200 -D -U flash:w:BlinkQ00.ino.hex:i

Ardbox (ATmega32u4, protocol avr109, 57600 baud): first open the port at 1200 baud to start the bootloader, then run avrdude on the port that appears. The port can change, so check it again. On Linux:

stty -F /dev/ttyACM0 1200
arduino-cli board list
$AVRDUDE/bin/avrdude -C $AVRDUDE/etc/avrdude.conf -p atmega32u4 -c avr109 -P /dev/ttyACM0 -b 57600 -D -U flash:w:BlinkQ00.ino.hex:i

On Windows, mode COM5 BAUD=1200 opens the port at 1200 baud in the same way.

OptionMeaning
-Cavrdude configuration file. Without it, avrdude may not know the protocol
-pMicrocontroller: atmega2560 on M-Duino, atmega32u4 on Ardbox
-cUpload protocol of the bootloader: wiring on M-Duino, avr109 on Ardbox
-PSerial port (COM5, /dev/ttyACM0...)
-bSpeed: 115200 on M-Duino, 57600 on Ardbox
-DSkip the full chip erase before writing, as the Arduino IDE also does
-U flash:w:file.hex:iWrite the file to the flash memory, in Intel HEX format

The Windows version of each step, with screenshots of Path and Device Manager, is in upload a sketch to an Arduino PLC from the Windows command line, and the Linux version in upload a sketch to an M-Duino or Ardbox from the Linux shell.

How this guide was checked. On 27 October 2026 we downloaded the Industrial Shields boards index from the URL above and the AVR core 1.2.1 that it lists (SHA-256 checksum correct), and we compiled the example with that core and the avr-gcc 7.3.0 of Ubuntu 24.04 (the core installs its own 7.3.0 build), for M-Duino 21+, 42+, 57R+ and 58+ and for Ardbox Analog HF+ (Ardbox Relay HF+ with R1). The FQBN, protocols, speeds and paths come from the boards.txt and platform.txt files of that core. The arduino-cli commands follow the official Arduino CLI documentation and were not run in that environment, and the upload steps were not run on a PLC for this guide.

From blinking an output to running a machine. In the Modbus VFD simulator, an M-Duino reads and writes a variable frequency drive over Modbus RTU and controls its speed. In the HVAC case study, one M-Duino 58 controls an air handling unit for an OEM.

Open the Modbus VFD simulatorRead the HVAC case study

FAQ about Arduino CLI and Arduino PLCs

Do I need the Arduino IDE to use Arduino CLI?

No. Arduino CLI installs the core, the compiler and avrdude by itself. If you also have the IDE 2, both use the same installed cores.

Why does the upload fail with "Permission denied" on Linux?

Your user cannot open the serial port. Add it to the dialout group with sudo usermod -aG dialout $USER and log out and in again.

Why does the compiler not know Q0_0 or I0_0?

The FQBN is not an Industrial Shields one (for example arduino:avr:mega) or the model is wrong. Use industrialshields:avr:mduino:cpu=... or industrialshields:avr:ardbox:cpu=... with your exact model.

Can I program an M-Duino from a Raspberry Pi?

Yes. Arduino CLI has Linux ARM builds, and the Industrial Shields index includes the compiler and avrdude for ARM 32 and 64 bit Linux. The steps are the same as on a Linux PC.

Can I upload over Ethernet instead of USB?

Yes, with a binary file and a remote reset. The process is explained in upload a sketch to a PLC using Ethernet, step 2: binary file.

​Search in our Blog

Arduino CLI for Arduino PLC: compile and upload on Windows and Linux
October 27, 2026
Share this post

Looking for your ideal Programmable Logic Controller?

Take a look at this product comparison with other industrial controllers Arduino-based. 

We are comparing inputs, outputs, communications and other features with the ones of the relevant brands.

PLC Comparison