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.
| Tool | What it does | Use it when |
|---|---|---|
| Arduino IDE 2 | Editor, compiler, uploader and serial monitor in one window | You write and debug the program |
| Arduino CLI | Installs cores and libraries, compiles and uploads from a terminal | You repeat builds, use scripts or work without a desktop |
| avrdude | Only writes an already compiled .hex file to the PLC | You 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?
- Open the official Arduino CLI installation page and download the Windows 64 bit MSI installer or ZIP file.
- With the MSI, run the installer. With the ZIP, extract
arduino-cli.exeto a folder of your choice, for exampleC:\arduino-cli, and add that folder to the Path environment variable (search "environment variables" in the Start menu, then Environment Variables > Path > Edit > New). - 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.
| Platform | PLC families |
|---|---|
industrialshields:avr | M-Duino, Ardbox and Spartan (ATmega2560 and ATmega32u4) |
industrialshields:esp32 | ESP32 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.
| PLC | FQBN |
|---|---|
| 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-485 | industrialshields:avr:ardbox:cpu=ardboxanaloghfplus485 |
| Ardbox Relay HF+ with RS-485 | industrialshields: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):
| System | avrdude 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.
| Option | Meaning |
|---|---|
-C | avrdude configuration file. Without it, avrdude may not know the protocol |
-p | Microcontroller: atmega2560 on M-Duino, atmega32u4 on Ardbox |
-c | Upload protocol of the bootloader: wiring on M-Duino, avr109 on Ardbox |
-P | Serial port (COM5, /dev/ttyACM0...) |
-b | Speed: 115200 on M-Duino, 57600 on Ardbox |
-D | Skip the full chip erase before writing, as the Arduino IDE also does |
-U flash:w:file.hex:i | Write 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.
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.
More about programming Arduino PLCs
- How to install Industrial Shields boards in the Arduino IDE
- How to configure the serial port on industrial Arduino IDE
- Node-RED vs CODESYS vs Arduino IDE: which to pick
- Choosing an industrial controller
Choose the model and the I/O mix in the Arduino PLC family, for example the M-Duino 42 or the Ardbox Analog.