◈ CircuitBench ▶ Open simulator

Arduino C++ Tutorial

Arduino sketches are written in C++ with a few simplifications. This tutorial covers what you need to write code in the CircuitBench code panel. Every example can be pasted in and run.

Program structureVariables and typesDigital input and outputAnalog and PWMControl flowFunctionsSerial monitorTiming with millis()LibrariesDebugging tips

Program structure

Every sketch has two required functions. setup() runs once at start. loop() runs over and over forever.

void setup() {
  pinMode(13, OUTPUT);      // configure pin 13 as an output
}
void loop() {
  digitalWrite(13, HIGH);   // LED on
  delay(1000);              // wait 1000 ms
  digitalWrite(13, LOW);    // LED off
  delay(1000);
}

Statements end with a semicolon, blocks use curly braces, and // starts a comment (a note for humans that the computer ignores).

Load the Blink an LED example, press Start, then change 1000 to 200 and start again. What changed?

Variables and types

TypeHoldsExample
intWhole numberint count = 5;
floatDecimal numberfloat v = 3.3;
booltrue / falsebool on = true;
byte0–255byte level = 200;
longBig whole numberlong t = millis();
StringTextString s = "hi";

Use const for values that never change, such as pin numbers: const int LED_PIN = 9;. Naming pins makes code far easier to read.

A variable is like a labelled box that holds a value. The type says what kind of thing the box can hold.

Digital input and output

pinMode(pin, mode) sets a pin to OUTPUT, INPUT or INPUT_PULLUP. digitalWrite(pin, HIGH/LOW) sets an output and digitalRead(pin) reads an input.

const int BTN = 2, LED = 13;
void setup() {
  pinMode(BTN, INPUT_PULLUP);
  pinMode(LED, OUTPUT);
}
void loop() {
  // pressed button connects the pin to GND, so it reads LOW
  digitalWrite(LED, digitalRead(BTN) == LOW ? HIGH : LOW);
}
Every line that ends in ; needs its semicolon, and every { needs a matching }. Missing ones are the most common beginner mistake.

Analog input and PWM

analogRead(pin) returns 0–1023 on an Uno (0–4095 on an ESP32) for 0 V to the reference voltage. analogWrite(pin, 0–255) outputs PWM on pins marked with a tilde (~). map(x, inMin, inMax, outMin, outMax) rescales a range.

void loop() {
  int knob = analogRead(A0);
  analogWrite(9, map(knob, 0, 1023, 0, 255));  // knob dims the LED
}

Control flow

Use if / else to decide, for to repeat a known number of times and while to repeat until a condition changes. Comparison operators are == != < > <= >=; combine tests with && (and), || (or) and ! (not).

for (int i = 0; i < 5; i++) {
  Serial.println(i);
}
if (temp > 30 && fan == false) {
  fan = true;
}

Functions

Functions group code you reuse. Give them a return type (void if none), a name and parameters.

void blink(int pin, int ms) {
  digitalWrite(pin, HIGH); delay(ms);
  digitalWrite(pin, LOW);  delay(ms);
}
void loop() { blink(13, 250); }

The serial monitor

Call Serial.begin(9600) in setup(), then Serial.println(value) to print. Output appears in the SERIAL MONITOR panel, the best way to inspect sensor values while the program runs. Text typed into the input box is available with Serial.read().

Timing without blocking

delay() freezes everything else. To do several things at once, compare against millis(), the milliseconds since start.

unsigned long last = 0;
void loop() {
  if (millis() - last >= 500) {
    last = millis();
    digitalWrite(13, !digitalRead(13));   // toggle every 500 ms
  }
  // other code keeps running here
}

Libraries

Libraries add ready-made features. Include them at the top of the sketch with #include. Common ones: Servo.h for servos, DHT.h for the DHT22, Adafruit_NeoPixel.h for pixel strips and LiquidCrystal_I2C.h for the LCD. See the output components for working examples.

Debugging tips

Challenge: make an LED blink faster the harder you turn a potentiometer. (Hint: use analogRead for the delay.)

Next: understand the hardware in Electronics Basics or wire something up from the component library.