Fix an Arduino sketch that waits for the serial monitor

8 min read · Published November 4, 2026

while(!Serial); in setup() stops the sketch until a serial monitor opens the USB connection, so a board on its own supply never leaves its default start screen. Delete the line for standalone running, or replace it with while(!Serial && millis() < 2000); so the sketch gives up waiting after 2 seconds and runs.

The board is not broken and the upload did not fail. setup() contains while(!Serial);, a debug line that stops the sketch until a serial monitor opens the USB connection. On bench power with no computer attached, the port never opens, the sketch never gets past that line, and the display holds its default start screen until someone plugs in USB. The fix is one line: delete it, or bound it with a timeout, while(!Serial && millis() < 2000);. This page shows which boards the wait actually blocks, why the board resets when the monitor opens, and how to verify the fix with a stopwatch and no USB cable.

Why does the board stay on its start screen until I open the serial monitor?

Your setup() contains while(!Serial);, a debug line that halts the sketch until a serial monitor opens the USB connection, so the board shows its default start screen at every power-up and runs only while a host holds the port open.

The line sits in setup(), usually right after Serial.begin(9600);. Serial is the board's USB serial connection. On a board whose main processor runs the USB port itself, that connection exists only while a program on the computer holds the port open. The while loop tests it over and over. Until you open a monitor, the test fails and nothing after the line runs: no display-module init, no radio begin, no first draw call, and no loop().

The default start screen is what the board or its display module shows before your sketch draws its first frame. The sketch is alive the whole time, spinning on a single test, waiting for a host that never comes.

What does each symptom point to?

Five symptoms tell this fault apart from the others, and each one names its cause: the pattern is a board that runs only while a host holds the port open and falls back to its start screen the moment it runs alone.

  • Start screen after every cold power-up, sketch output the moment a monitor opens: while(!Serial); in setup(). This is the fault this page fixes.
  • CPU reset, display-module reset and radio reset all change nothing: the wait lives in firmware, so any reset just reruns setup() and waits again.
  • The board ran all through development and shows the start screen the next morning: nothing regressed overnight. During development the monitor was open, so the wait always ended.
  • The sketch jumps back to its first line every time you open the monitor: the DTR auto-reset, covered below, and normal.
  • The wait passes instantly and the start screen stays: on that board the wait was never the blocker. Check that the upload reached the board and that the display module got its init command.

Does while(!Serial) block on every board?

It blocks only on boards whose USB port is the main processor's own USB hardware; on boards that use a separate USB-to-serial bridge chip, Serial reads ready as soon as power arrives, the wait passes immediately, and the start screen points somewhere else.

Two USB architectures behave differently here. On a native-USB board, the main processor speaks USB itself and Serial is that connection, false until a host opens it. On a bridge board, a second chip converts USB to UART, and from the sketch's side the UART is ready the moment power arrives, so while(!Serial); falls through at once.

The practical read: the runs-only-with-a-monitor pattern belongs to native-USB boards. If your board has a bridge chip and still parks on its start screen, go to the last bullet in the symptom list, because the cause sits elsewhere.

Why does the sketch restart each time I open the monitor?

Opening the port asserts the DTR handshake line, the board's auto-reset circuit reads that pulse as a reset, and setup() runs again from its first line; the restart on every open is built-in behavior, not a fault in your sketch.

The auto-reset exists so the IDE can restart the bootloader for a new upload without a finger on the reset button. The price is that every serial-terminal open restarts your sketch too.

It also explains why the board seems to come back to life when you connect. You open the monitor, DTR pulses, the board resets into setup(), and this time the port is already open, so the wait passes and your first frame draws. Two things happened at once; the sketch was never crashed.

For bench work: open the monitor before you need the data, expect a restart with every open, and finish your wiring before you start logging.

How do I make the sketch run from power-up?

Delete the wait for a board that must run on its own, or replace it with while(!Serial && millis() < 2000);, which waits up to 2000 ms for a monitor and then continues without one, so the worst-case boot delay is 2.0 s.

  1. Open the sketch in the IDE and go to setup().
  2. Find the hold: while(!Serial); or while (!Serial) { }.
  3. Board that must run alone: delete the line, or comment it out.
  4. Board you still debug over USB: replace it with while(!Serial && millis() < 2000);.
  5. Upload, unplug USB, and power the board from its own supply.
  6. Watch the display: the start screen must give way within 2.0 s.

One safety point if the sketch drives anything physical: after this change the board restarts on its own after every power cut with nobody attached, so confirm an unattended restart is safe for whatever it switches.

Why a 2000 ms timeout, and can I pick another number?

2000 ms is the value the common timeout pattern uses, long enough for the IDE to reopen the port right after an upload and short enough that nobody stares at a dead screen; anything from 1000 ms to 10000 ms is defensible once you know who opens the port.

Use 1000 ms when you only want the first prints after an upload, since the IDE opens the port for you. Use a longer value when you power the board first and open a monitor by hand. Past 10000 ms the dead screen at every power-up becomes part of what people see.

On the counter itself: millis() returns the milliseconds since reset as an unsigned 32-bit number, and it wraps to zero after 4,294,967,296 ms, about 50 days. The test millis() < 2000 runs only in the first two seconds after reset, so the wrap never touches it. For timers that run for weeks, write the subtraction form, millis() - start >= interval, which stays correct across the wrap.

Example: how does the timeout behave from a cold power-up?

With the timeout in place, a board powered at time zero holds its start screen for exactly 2000 ms and then runs; if you open a monitor partway through, it starts at that moment instead, so the wait is a ceiling on boot delay and never a floor.

Take a bench board that drives a two-line status display at 9600 baud and lives on a bench supply.

Old code, Monday: power on at 08:00, no USB cable. The start screen is still up at 09:15 when a technician plugs in and opens the monitor. The port opens, the wait ends, and the first frame draws. The display sat dead for 75 minutes over one missing line of code.

Fixed code, next cold start: power at t = 0, Serial.begin(9600); runs, and the wait tests its condition every pass. At t = 2000 ms the condition millis() < 2000 fails, setup() continues, and the first frame draws at 2.0 s. Open the monitor earlier, say at t = 1400 ms, and the wait ends at 1400 ms instead: 2000 - 1400 = 600 ms of boot delay recovered.

What that delay costs in content: at 9600 baud, with 10 bits per character (one start, eight data, one stop), the link moves 9600 / 10 = 960 characters per second. A 60-character status frame takes 60 / 960 = 62.5 ms, so a 2.0 s boot delay equals 2000 / 62.5 = 32 frames of status you did not send. If you push whole images over the wire, the same arithmetic sets your frame rate; see serial image refresh rate limits. Heavy content belongs on the card, with only commands on the wire: the pattern is in Arduino serial image commands for memory-card playback. The bytes a display expects between frames are covered under serial command byte encoding.

How do I check the fix on the bench?

Power the board from its own supply with the USB cable out and count to two: the start screen must give way by 2.0 s, and passing that one test with no monitor anywhere in the sequence shows the sketch now starts standalone.

  1. Cold start: external supply, USB cable removed. The start screen gives way by 2.0 s. Film 10 s at 30 fps and the transition lands near frame 60.
  2. Late attach: let the board run standalone for a minute, then open the monitor. It resets, as above, and runs immediately, because the port is open before the wait can block.
  3. Close the monitor while loop() runs: the content keeps updating. The wait executed once, in setup().
  4. Start screen still up past 2.0 s: the wait is gone, so look downstream. Re-check the upload target, the supply voltage under load, and the display module's init call.

Which form should ship in the final sketch?

Ship the deletion on any board that runs unattended behind a panel or on a bench supply. Keep the 2000 ms timeout form only while you still watch boot messages over USB; it covers both jobs and adds just 2.0 s of boot delay at power-up.

Recommendation: Delete while(!Serial); from any sketch that runs from a bench supply or an installed power feed, and use while(!Serial && millis() < 2000); only while you still open a monitor to watch boot messages; when the board goes into its enclosure, ship the plain deletion.

If the end job is a notice or status screen that plays finished content on its own, with no controller and no sketch, a shop-floor screen that plays from a memory card does that job directly.

Questions

How do I still see debug output after adding the timeout?

Test the port inside loop() with if (Serial). When a host holds the port open the test is true and your status line goes out once per pass; when nothing is attached the test is false and the sketch runs on without waiting. Debug output then appears any time you plug in, with no boot delay at all.

Can I use a longer timeout when I open the monitor by hand?

Yes. 2000 ms assumes the port opens for you right after an upload. If you power the board first and open a monitor by hand afterwards, use 5000 ms so you have time to bring up the IDE. Keep it under about 10000 ms, because past that the dead start screen at every power-up becomes visible to anyone watching the display.

Does closing the serial monitor stop a running sketch?

No. The wait executes once, in setup(). Once it has passed, loop() keeps running with the port open or closed, and closing the monitor never re-blocks it. Only the open matters, because opening the port asserts DTR and the auto-reset restarts the sketch from its first line.

What if the start screen stays even after the fix?

Work downstream of the wait. Confirm the upload finished to the board and not to another port, measure the supply voltage under load at the board's terminals, and check that the display module received its init command, since a display that never initializes holds its factory screen. On a bridge-chip board the wait never blocked at all, so these checks come first.

Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.

Keep reading

Build your signAsk for a quote