Level 3Reference

What changes this year

Last year your device sat on the desk in front of you. This year it does not.

You put it on a roof, in a corridor, in a store room. You walk away. You come back a week later and find out what it did while nobody was watching.

That one change — leaving the room — makes almost everything harder, and it is the whole point of Level 3. A device you are standing next to can be rescued. A device on a roof cannot. It has to survive a dropped WiFi connection, a power cut, a sensor that goes strange at 3am, and a week of nobody looking at it.

The three new skills

  • It reports. The number leaves the board and arrives on a screen somewhere else.
  • It survives. When something fails — and it will — it recovers by itself instead of sitting there dead.
  • It is honest over time. You can say what it did for seven days, not what it did in the ninety seconds you demonstrated it.
💡 Tip
Level 2 asked “is your measurement accurate?” Level 3 asks a harder question: was it still accurate on Thursday night?

The board changes too

You move from the Arduino Uno to the ESP32. It is faster, has far more memory, and — the reason we are using it — it has WiFi built into the chip. No extra module, no shield. It can join a network, and it can be a network.

Before anything else: the 3.3 volt rule

The Uno ran at 5 volts. The ESP32 runs at 3.3 volts, and it is not tolerant about it.

Putting 5 V onto an ESP32 input pin can destroy the pin, and sometimes the whole board. There is no fuse, no warning, no smell. It just stops working, usually a week later.

What you seeWhyWhat to do
A sensor marked 3.3VSafe. Wire it exactly as the diagram shows.Power from the 3V3 pin, not VIN.
A sensor marked 3–5VSafe. Most modern modules are.Still power it from 3V3 unless the book says otherwise.
A sensor marked 5V onlyIts output will be 5V. Not safe on an input pin.Ask your teacher. It needs a divider or a level shifter.
Motors, relays, pumpsNever from the board, at any voltage.Own supply, common ground. Same rule as Level 2.
⚠ Careful
The 5V pin on the ESP32 is an output for powering things, not an input level the pins can handle. Powering the board from USB and also from VIN at the same time is the other way people kill these.

The pins you will actually use

ESP32USB3V3power out for sensorsGNDgroundGPIO 36analogue IN onlyGPIO 39analogue IN onlyGPIO 34analogue IN onlyGPIO 35analogue IN onlyGPIO 15avoid at power-onGPIO 2onboard LEDGPIO 0avoid at power-on5Vpower OUT, not an input levelGNDgroundGPIO 23freeGPIO 22I2C clock (SCL)GPIO 21I2C data (SDA)GPIO 19freeGPIO 18freeGPIO 5freeGPIO 12avoid at power-onsafe to useI2Cread the noteavoidPin names vary slightly between boards. Check yours against the silkscreen.
Photograph this page. You will come back to it all year.
  • 3V3 and GND — power for sensors.
  • GPIO 21 (SDA) and GPIO 22 (SCL) — I2C, same job as A4/A5 on the Uno.
  • GPIO 2 — the onboard LED on most boards. Free test output.
  • GPIO 34, 35, 36, 39 — analogue in only. They cannot be outputs. Reading 0–4095, not 0–1023.
  • Avoid GPIO 0, 2, 12, 15 as inputs at power-on. The board reads them while booting and a wire there can stop it starting.

The rules of this room

  • 3.3 volts, not 5. Read page 4 before you connect anything to an ESP32 input. There is no fuse and no warning.
  • Nothing goes in the bin until it is checked against the card. You are sharing boards this year; a missing one stops two teams, not one.
  • Power off while you wire. Two people check before power on.
  • Anything that heats, moves or pumps gets its own supply and a driver. Never straight off a pin.
  • Write in your notebook every session, with the date — including what you asked an AI and what you did with the answer.
  • Ask before you deploy anywhere. A named adult says yes to the location before a device is left there. Every time.

How this book works

Same five parts as Level 2, plus one that only matters now that your device leaves the room.

  1. What we are making — the finished thing, and what it does.
  2. The idea — the new concept, explained before you build.
  3. Wire it up — the diagram. Copy it hole for hole.
  4. The code — a full C++ listing, explained line by line.
  5. Try it — what should happen.
  6. What breaks it — the failure this session is actually teaching you to survive.

A note on the two network modes

Your school's WiFi may or may not let a small device talk to the wider internet. That is a decision made by people who are not in this room, and it can change. So this book teaches both paths from Session 2 onward, and everything after that works either way.

Can your board reach the school network?Yes, it joins school WiFiMode B — station mode. Your laptop opens the board's address.No, or you are outdoorsMode A — the board makes its own WiFi. Your phone joins it.Yes, and it reaches the internetMode C — add a broker. Optional. Everything else still works without it.

You will test which of these you have in Session 2, in about ten minutes.

💡 Tip
Mode A is not the fallback. It is the mode most real deployed devices use for setup, and it is the one that works in a field with no infrastructure at all. Do not think of it as second best.
◆

Reference · keep this page

The staple, and the eight slots

One program, all year. Your teacher gives you the file. You do not retype it, and you do not change anything that is not inside a slot.

You have already written most of it

The WiFi lines are from session 2. Serving a page is session 3. An address that does something is session 4, and the style is session 5. Nothing on the next page is new to you — it is the five things you built separately, put in one file and given eight marked gaps.

Why it works this way

  • Fifty lines typed by hand is fifty chances to make a typing mistake, and none of them teach you anything.
  • Everything you add fits on one card. You can see your whole contribution at once.
  • A session becomes three or four lines, not a page. That leaves time to get it working.
  • When something breaks, it is in your slots. That is four lines to look at, not fifty.

The eight slots

SlotWhat goes in it Looks like
1A library your part needs#include <DHT.h>
2Your parts, your chosen numbers, and any function of your ownDHT sensor(4, DHT11);
3Read a sensor. Return text.return String(t) + " C";
4What the page says"<h1>" + reading() + "</h1>"
5Start a part, once, at switch-onsensor.begin();
6Another address the page can link toserver.on("/open", handleOpen);
7An extra line in the page's headauto-refresh, in session 17
8The page's background colourred when something is wrong
💡 Tip
Two slots do nearly all the work. Slot 3 reads something; slot 4 says what the page shows. Most sessions are those two and one line in slot 2. If you understand those three, you understand this whole year.

The rule about AI

You may use a chatbot to help write what goes in a slot. There are two conditions and they are not negotiable.

  1. It drafts, you verify. Anything it gives you gets compiled and run before you believe it. It will invent functions that do not exist; this is normal and not a reason to stop using it.
  2. You must be able to explain any line you keep. Line by line, out loud, to your teacher. A line you cannot explain comes out, even if it works.
⚠ Careful
The second rule is the one that matters at the exhibition. A visitor will point at your screen and ask what a line does. ‘The AI wrote that bit’ is a true answer and a bad one. Twenty minutes spent understanding four lines is worth more than an hour spent generating forty.
station.ino — the staple. You are given this file.
1// ====================================================================
2// station.ino -- THE STAPLE
3// Your teacher gives you this file. You never retype it, and you never
4// change anything that is not inside a SLOT.
5// ====================================================================
6#include <WiFi.h>
7#include <WebServer.h>
8// >>> SLOT 1 -- libraries for your parts
9 
10const char* ssid = "YOUR_NETWORK";
11const char* password = "YOUR_PASSWORD";
12const char* teamName = "Team 1";
13 
14WebServer server(80);
15 
16// >>> SLOT 2 -- your parts, your numbers, and your own functions
17 
18// ----------------------------------------------- the staple's own helpers
19String background() {
20 // >>> SLOT 8 -- change the page colour when something is wrong
21 return "#16293D";
22}
23 
24String pageHead() {
25 String h = "<html><head>";
26 h += "<meta name='viewport' content='width=device-width, initial-scale=1'>";
27 // >>> SLOT 7 -- extra lines in the page's head
28 h += "<style>body{font-family:sans-serif;text-align:center;";
29 h += "background:" + background() + ";color:white;}";
30 h += "h1{font-size:90px;margin:40px 0 0 0;}";
31 h += "p{font-size:22px;color:#9FB3C8;}";
32 h += "a{display:inline-block;padding:18px 40px;margin:10px;font-size:24px;";
33 h += "background:#1F7A6F;color:white;text-decoration:none;border-radius:10px;}";
34 h += "</style></head><body>";
35 return h;
36}
37 
38String pageFoot() {
39 return "<p>" + String(teamName) + "</p></body></html>";
40}
41 
42void connectWiFi() {
43 WiFi.begin(ssid, password);
44 while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
45 Serial.println();
46 Serial.println(WiFi.localIP()); // type this into your browser
47}
48 
49// ----------------------------------------------- the two you fill in
50String reading() {
51 // >>> SLOT 3 -- read your sensor and return it as text
52 return "nothing yet";
53}
54 
55String body() {
56 // >>> SLOT 4 -- what your page says
57 return "<h1>" + reading() + "</h1>";
58}
59 
60void handleRoot() {
61 server.send(200, "text/html", pageHead() + body() + pageFoot());
62}
63 
64void setup() {
65 Serial.begin(115200);
66 // >>> SLOT 5 -- start your parts
67 connectWiFi();
68 server.on("/", handleRoot);
69 // >>> SLOT 6 -- extra addresses, if your device has buttons
70 server.begin();
71}
72 
73void loop() {
74 server.handleClient();
75}

How to fill a slot

Find the comment line. Type underneath it. Leave the comment where it is, so you and your teacher can both still find the slot next week.

A filled slot looks like this — 1 slot
SLOT 3
read the temperature and return it as text
float t = sensor.readTemperature();
return String(t, 1) + " C";
New words
SlotA marked place in the staple where your lines go.
StapleThe program itself. Given to you, not typed by you.
reading()The function that fetches a number. Slot 3 lives in it.
body()The function that decides what the page says. Slot 4 lives in it.
CompileChecking the program is valid C++ before it goes to the board.

The three rules of working this way

  1. One slot at a time. Fill it, upload, look at the page. Then the next one.
  2. Never delete a slot comment. It is how you find your way back.
  3. If it stops working, look at the last slot you touched. It is almost always that one, because nothing else changed.
What you seeWhyWhat to do
It will not compile and points at a librarySlot 1 is empty, or the library is not installed.Add the #include, then Tools → Manage Libraries.
'sensor' was not declaredSlot 2 is empty.The part has to be declared in slot 2 before slot 3 can use it.
The page says nothing yetSlot 3 still has the staple's own line in it.Your return has to replace that one, not sit under it.
It compiled yesterday and not todayA brace was deleted with a slot comment.Compare against a fresh copy of the staple. Keep one unopened.
A chatbot's line will not compileIt invented a function.Expected. Check the function exists in the library's own documentation, then fix or drop the line.