Arduino programs, called sketches, are written in C++, with a beginner-friendly set of functions (the Arduino API) added on top. You can use plain C anywhere in the same sketch. A standard GCC compiler then turns your code into machine code for the microcontroller.
You open the Arduino IDE, type pinMode(13, OUTPUT);, press Upload, and an LED starts blinking. The code reads almost like plain English, so it’s fair to ask: which programming language is used in Arduino, and do you have to learn something new just for it?
Arduino programming at a glance:
Good news: you don’t. Let’s break down what is really happening under that friendly code.
No. There is no standalone Arduino compiler or syntax. Think of the “Arduino language” as C++ wearing a friendly jacket.
pinMode(), digitalWrite(), analogRead() and Serial.println()Arduino.h for you, generates function prototypes so you can call a function before defining it, and wraps your code in a hidden main()Every sketch needs two functions: setup() and loop(). Here is the classic Blink example, which makes the onboard LED flash:
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // runs once at power-up or reset
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // LED on
delay(1000); // wait 1000 ms
digitalWrite(LED_BUILTIN, LOW); // LED off
delay(1000); // wait 1000 ms
}Let’s decode what each piece does:
setup() runs once when the board powers up or resets. Use it for pin modes, Serial.begin() and sensor initialization.loop() runs forever, over and over. Your main logic lives here.pinMode() tells the microcontroller whether a pin is an input or an output.digitalWrite() drives a pin HIGH (the board’s logic voltage) or LOW (0 V).delay() pauses the program for the given number of milliseconds.main() functionSpot anything missing? There is no main(), yet every C and C++ program starts there. Arduino tucks it inside the core library. Here is a simplified view:
// Simplified view of what the Arduino core runs for you
int main(void) {
init(); // configure timers, ADC and other core hardware
setup(); // your one-time setup code
for (;;) { // endless loop
loop(); // your repeating code
}
return 0;
}setup() and loop().main().The reason is simple: microcontrollers have very little memory and need fast, predictable code. Once you understand how a microcontroller works (flash, SRAM, registers and peripherals), the choice makes sense.
In one line: the IDE converts your sketch into C++, compiles it with GCC and sends the machine code to the board over USB. Think of it as a relay race with six runners (shown here for an AVR board such as the Uno R3):
.ino files into one C++ file, adds #include and generates function prototypes.avr-g++ and avr-gcc turn your code, the libraries you included and the Arduino core into object files..elf file.avr-objcopy extracts a .hex file containing the final machine code.avrdude sends the .hex file over USB, and the bootloader writes it into flash memory.main(), calls setup() once and then repeats loop() forever.Pro tip: want to watch the relay race? Open the IDE preferences (Settings on macOS), turn on verbose output for compilation and upload, then press Upload. You’ll see the real
avr-g++andavrdudecommands scroll past.
Other chip families use their own compilers and uploaders (such as Arm GCC and esptool), but the flow stays the same.
Arduino code is C++ with a friendly layer, and embedded C is the same family of languages used closer to the hardware. You can mix both in a single sketch. Here is Blink again, this time talking to the ATmega328P’s registers directly (Uno R3 and Nano):
// Register-level blink (ATmega328P: Uno R3, Nano)
void setup() {
DDRB |= (1 << DDB5); // PB5 (Arduino pin 13) as output
}
void loop() {
PORTB ^= (1 << PORTB5); // toggle PB5
delay(1000);
}digitalWrite() does extra work (pin lookup and safety checks), so it is slower and uses more flash.DDRB and PORTB are AVR names. An ESP32 or STM32 board uses different registers, so this exact code will not move across.Wondering how much of each language shows up in a real sketch? Here is the breakdown.
int, float, char, byte, boolif/else, for, while, switchstruct&, |, ^, ~, <<, >>) for flags and registers#define, #include, #ifdefSerial, Servo, Wire and LiquidCrystal are objects with methods. Serial.begin(9600) is a method call.LiquidCrystal lcd(12, 11, 5, 4, 3, 2); creates an object and passes its pin settings in one line.Serial.print() accepts integers, floats, characters and strings.std::vector or std::string out of the box. Arm and ESP32 based cores generally give you far more.new, malloc() and the String class can fragment the tiny heap on a 2 KB board.| Function | What it does | Example |
|---|---|---|
| pinMode(pin, mode) | Sets a pin as INPUT, OUTPUT or INPUT_PULLUP | pinMode(7, INPUT_PULLUP); |
| digitalWrite(pin, value) | Drives a digital pin HIGH or LOW | digitalWrite(13, HIGH); |
| digitalRead(pin) | Reads HIGH or LOW from a pin | int state = digitalRead(2); |
| analogRead(pin) | Reads an analog voltage (0 to 1023 on the Uno’s 10-bit ADC) | int raw = analogRead(A0); |
| analogWrite(pin, value) | Outputs PWM (0 to 255) on supported pins | analogWrite(9, 128); |
| delay(ms) | Pauses the program (blocking) | delay(500); |
| millis() | Milliseconds since the board started | unsigned long t = millis(); |
| Serial.begin(baud) | Starts serial communication for debugging | Serial.begin(9600); |
The language stays C/C++, but data type sizes and memory limits change with the chip. For the full picture, see data types in C++.
int size: 16 bits on classic AVR boards (Uno R3, Nano, Mega) and 32 bits on Arm and ESP32 based boards (Uno R4, Due, Nano ESP32). So int count = 40000; overflows on an Uno R3 but works on an Uno R4.double precision: same as float (32 bits) on AVR, but 64 bits on most 32-bit boards.uint8_t, int16_t and uint32_t. They mean the same thing on every board.Yes, with one distinction. Some languages run on the board, while others run on your computer and only talk to the board.
asm for timing-critical routines.For a wider look at the trade-offs, see Python in embedded systems.
Important: in these setups the board still runs C++ firmware (for example, StandardFirmata). Your computer is remote-controlling it, not replacing it.
| Board | Chip | Language support |
|---|---|---|
| Uno R3, Nano, Mega 2560 | AVR (8-bit) | C/C++ |
| Uno R4 Minima and WiFi | Renesas RA4M1 (Arm Cortex-M4) | C/C++ |
| Nano RP2040 Connect | RP2040 | C/C++ and MicroPython |
| Nano ESP32 | ESP32-S3 | C/C++ and MicroPython |
| GIGA R1 WiFi, Portenta H7 | STM32H747 (dual-core) | C/C++ and MicroPython |
| UNO Q | Qualcomm QRB2210 + STM32U585 | C/C++ (microcontroller side) and Python (Linux side) |
Board support keeps growing, so check Arduino’s documentation before you buy. If you are still choosing a first board, read which Arduino board is best for beginners.
No. A few functions and a breadboard are enough to begin. When you want to go deeper, this path works well, and C programming from basic to advanced covers the language side step by step:
if/else, loops and switchServo, Wire, SPI and Serialmillis(), state machines and interrupts instead of delay()pinMode(): the pin stays an input, so your LED stays dim or off. Set the mode in setup().delay(): it freezes everything else. Use millis() for timing.millis() in an int: a 16-bit int overflows after about 33 seconds. Use unsigned long, which wraps after roughly 49.7 days.= instead of ==: if (x = 5) assigns instead of compares, so the condition is always true.Serial.begin() or mismatching the baud rate: you get no output or garbled characters.String on small boards: it can fragment memory and cause odd resets. Prefer char arrays on AVR.setup() (runs once) and loop() (runs forever), wrapped by a hidden main().So, which programming language is used in Arduino? C++, with plain C welcome, wrapped in a friendly API that lets you blink an LED in minutes. Keep peeking under the hood, and the same skills will carry you to STM32, ESP32 and professional firmware work.
Both, but mostly C++. Sketches compile as C++, so you can use C syntax freely along with C++ features such as classes and objects.
A sketch is an Arduino program. It is saved with the .ino extension and must contain setup() and loop().
They are close cousins. Arduino code is C++ with a friendly abstraction layer, while professional embedded C often works directly with registers, vendor libraries and an RTOS. Skills transfer easily in both directions.
Yes, in two ways. MicroPython runs on the board itself on selected models, and the UNO Q runs Python on its Linux side. On classic boards such as the Uno R3, Python can only control the board from a computer while the board runs C++ firmware.
It is an excellent first step for understanding GPIO, timers, ADC and communication protocols. Employers also expect solid embedded C/C++, datasheet reading, debugging skills and experience with microcontrollers beyond the Arduino ecosystem.
Indian Institute of Embedded Systems – IIES