Your First Sketch: Blink
By the end of this lesson you will have written Blink, the "Hello, World" of electronics, line by line. You will understand what each function does, print messages to the Serial Monitor, count blinks with a variable, and build your own light patterns with a function.
You only need the board and a USB cable. The LED marked L on the board, connected to pin 13, is the one we will blink.
Step 1: The empty sketch
Open the IDE and choose File > New Sketch. You will see the two functions every sketch needs:
void setup() {
// put your setup code here, to run once
}
void loop() {
// put your main code here, to run repeatedly
}A function is a named block of code. void means the function does not give back a value. The curly brackets { } mark where the function starts and ends.
Think of a school day. setup() is the morning assembly: it happens once. loop() is the class timetable that repeats period after period, except that on a microcontroller the timetable never ends while there is power.
Step 2: Write Blink
Type this sketch yourself rather than copying it. Typing builds memory, and you will make (and fix) small mistakes, which is how you learn.
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // pin 13 will send out voltage
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // 5 V on the pin: LED on
delay(1000); // wait 1000 ms (1 second)
digitalWrite(LED_BUILTIN, LOW); // 0 V on the pin: LED off
delay(1000); // wait another second
}Click Upload. After a few seconds, the L LED should switch on for one second and off for one second, for ever.
What each line does
| Code | Meaning |
|---|---|
LED_BUILTIN | A name for the pin of the board's own LED; it is 13 on the UNO |
pinMode(pin, OUTPUT) | Sets a pin to drive voltage out, instead of reading voltage in |
digitalWrite(pin, HIGH) | Puts the pin at the board's high voltage (5 V on an UNO) |
digitalWrite(pin, LOW) | Puts the pin at 0 V (GND) |
delay(1000) | Pauses the whole program for 1000 milliseconds |
; | Ends each statement, like a full stop ends a sentence |
// | Starts a comment: notes for humans that the compiler ignores |
C++ is case-sensitive. digitalWrite works; DigitalWrite and digitalwrite do not. Most beginner errors are a wrong capital letter or a missing semicolon.
Step 3: Make it talk
Blinking is nice, but you cannot see why code behaves as it does. The Serial Monitor lets the board send text to your computer. Add three lines:
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600); // start serial at 9600 baud
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
Serial.println("LED on");
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
Serial.println("LED off");
delay(1000);
}Upload, then click the Serial Monitor icon (top right) and set the speed at the bottom to 9600 baud. You should see a new line every second:
LED on LED off LED on LED off
The pattern continues for ever. Serial.begin(9600) sets the communication speed; the number in the Serial Monitor must match it, or you will see strange symbols. You will learn much more in The Serial Monitor.
Step 4: Count the blinks
A variable is a named box that stores a value. Let us count how many times the LED has blinked. The variable must be created outside loop(), so it keeps its value between repeats.
unsigned long blinkCount = 0; // created once, keeps its value
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
while (!Serial && millis() < 3000) { } // wait up to 3 s for the Serial Monitor
}
void loop() {
blinkCount = blinkCount + 1;
Serial.print("Blink number ");
Serial.println(blinkCount);
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}Blink number 1 Blink number 2 Blink number 3 Blink number 4
The count keeps rising, one line per second. unsigned long is a whole-number type that cannot be negative and can count beyond four billion, so it will not run out.
The while (!Serial && millis() < 3000) { } line waits up to three seconds for the Serial Monitor to connect, so the first lines are not lost on boards like the UNO R4 that talk over USB directly. If no monitor connects, the sketch carries on after three seconds.
Step 5: Your own pattern with a function
You can write your own functions to avoid repeating code. This one blinks the LED a given number of times at a given speed. With it, you can send the famous SOS signal: three short, three long, three short.
void blinkTimes(int times, int onMs) {
for (int i = 0; i < times; i++) {
digitalWrite(LED_BUILTIN, HIGH);
delay(onMs);
digitalWrite(LED_BUILTIN, LOW);
delay(200); // short gap between flashes
}
}
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
while (!Serial && millis() < 3000) { }
}
void loop() {
Serial.println("S");
blinkTimes(3, 200); // short flashes
Serial.println("O");
blinkTimes(3, 600); // long flashes
Serial.println("S");
blinkTimes(3, 200);
Serial.println("-- pause --");
delay(2000);
}S O S -- pause -- S O S -- pause --
int times and int onMs are parameters: values you pass into the function when you call it. blinkTimes(3, 600) means "three flashes, each 600 ms long". The for loop repeats its block times times, counting i from 0.
How long does one loop take?
You can work out timing by adding the delays. In the SOS loop, each short flash takes 200 + 200 = 400 ms, and each long flash takes 600 + 200 = 800 ms. One full loop is 3 × 400 + 3 × 800 + 3 × 400 + 2000 = 6800 ms, which is 6.8 seconds. Being able to calculate timing like this is a real embedded skill.
A problem with delay()
While delay() runs, the board does nothing else. It cannot read a button, check a sensor or blink a second LED at a different speed. For first sketches this is fine. In Timing with millis() you will learn how to do several things at once without delay().
Common mistakes
- Capital letters wrong.
pinmodeorDigitalWritecause "was not declared in this scope" errors. - Missing semicolon. The error often points to the line after the real mistake.
- Counter variable inside
loop(). It would be created again and reset to 0 on every pass. Declare it at the top. - Baud rate mismatch between
Serial.begin()and the Serial Monitor, giving garbled text.
Key points
setup()runs once;loop()repeats for ever.pinMode(pin, OUTPUT)prepares a pin;digitalWrite(pin, HIGH or LOW)switches it.delay(ms)pauses everything for that many milliseconds.Serial.begin(9600)andSerial.println()send text to the Serial Monitor; match the baud rate.- Variables declared outside
loop()keep their values; your own functions with parameters avoid repeated code.
Exercise
Make a "heartbeat" pattern on the L LED: two quick flashes (100 ms on, 100 ms off each), then a pause of 700 ms, repeating for ever. Print beat 1, beat 2 and so on at the start of each heartbeat. Work out how long one heartbeat takes.
Show solution
unsigned long beats = 0;
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
while (!Serial && millis() < 3000) { }
}
void loop() {
beats++; // same as beats = beats + 1
Serial.print("beat ");
Serial.println(beats);
for (int i = 0; i < 2; i++) {
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
delay(100);
}
delay(700);
}beat 1 beat 2 beat 3
One heartbeat takes 2 × (100 + 100) + 700 = 1100 ms, about 55 beats per minute.
Quick Quiz
1. What does pinMode(LED_BUILTIN, OUTPUT) do?
pinMode prepares the pin. digitalWrite then switches it HIGH or LOW.
2. How long does delay(250) pause the program?
delay() takes milliseconds, so 250 means a quarter of a second.
3. Why is blinkCount declared outside loop()?
A variable declared inside loop() is created again on every pass, so it would always restart at 0.
4. The Serial Monitor shows random symbols. What is the most likely cause?
Both ends must use the same speed, for example 9600 baud.
Learn IoT & Arduino with a mentor
Free lessons get you started. Our IoT & Embedded Systems training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
