Program Structure and Digital I/O
Every sketch is built around setup() and loop(). Inside setup() you call pinMode(pin, mode) where mode is INPUT, OUTPUT, or INPUT_PULLUP. For digital lines, digitalWrite(pin, HIGH/LOW) drives an output and digitalRead(pin) returns HIGH or LOW. Serial.begin(baud) starts the serial link, and you print with Serial.print() and Serial.println(). Keep these five functions in muscle memory because they appear in nearly every sketch you write, from a first LED blink to a complex sensor node.
Cricket analogy: Memorizing these core calls is like a batter drilling the forward defensive and the cover drive until reflexive — pinMode and digitalWrite are the basic strokes you play in almost every innings without thinking.
// Quick-reference skeleton covering the most-used calls
void setup() {
pinMode(13, OUTPUT); // digital output
pinMode(2, INPUT_PULLUP); // button, idles HIGH
Serial.begin(9600); // start serial at 9600 baud
}
void loop() {
int btn = digitalRead(2); // read a digital pin
int light = analogRead(A0); // 0..1023 from ADC
analogWrite(9, 128); // ~50% PWM duty on pin 9
digitalWrite(13, btn == LOW ? HIGH : LOW);
long mapped = map(light, 0, 1023, 0, 255); // rescale a range
int clamped = constrain(mapped, 0, 200); // clamp to bounds
Serial.print(F("light="));
Serial.println(clamped);
delay(200); // pacing (prefer millis in real code)
}Analog, PWM, and Math Helpers
analogRead(pin) reads an analog input returning 0–1023 on the Uno's 10-bit ADC, while analogWrite(pin, 0–255) outputs PWM on the ~ marked pins. Two helpers appear constantly: map(value, fromLow, fromHigh, toLow, toHigh) linearly rescales a number between ranges, and constrain(value, min, max) clamps it within bounds. For timing use millis() and micros(), which return elapsed unsigned time since boot, and delay(ms) / delayMicroseconds(us) for blocking pauses. Note that map() uses integer math and truncates, so rescaling with it loses fractional precision — do floating-point scaling manually when precision matters.
Cricket analogy: map() rescaling a sensor range is like converting a strike rate onto a 0–100 impact scale — a linear transform, though its integer truncation is like rounding a partial run down and losing a fraction of the contribution.
Cheat sheet — data types on AVR: byte/uint8_t (0–255), int (16-bit, -32768..32767), unsigned int (0..65535), long (32-bit), unsigned long (0..4,294,967,295 — used by millis()), float (32-bit, ~6-7 significant digits), and bool. Note there is NO double precision on AVR: double is the same 32-bit float as float.
Communication Quick Calls
For serial, Serial.available() reports bytes waiting and Serial.read() consumes one. For I2C, include Wire.h and use Wire.begin(), Wire.beginTransmission(addr), Wire.write(), Wire.endTransmission(), and Wire.requestFrom(addr, n). For SPI, include SPI.h and use SPI.begin() plus SPI.transfer(data), managing each device's chip-select line manually. Servos use the Servo library with attach(pin) and write(angle) from 0 to 180. Keep the include and the three or four key calls per bus handy, because forgetting Wire.begin() or an endTransmission() is the most common reason an I2C device silently fails to respond.
Cricket analogy: The fixed call sequence for I2C is like a bowler's run-up, delivery, and follow-through — skip the follow-through (endTransmission) and the whole delivery is a no-ball that does not count.
On AVR boards, double is not higher precision than float — both are 32-bit. Do not expect scientific-grade accuracy from Arduino floating point. Also remember analogWrite() only works on PWM-capable pins (marked with ~ on the board); calling it on a non-PWM pin will not produce the expected fading behavior.
- Core structure: setup() once, loop() forever; pinMode/digitalWrite/digitalRead for digital I/O.
- analogRead() returns 0–1023 (10-bit ADC); analogWrite() outputs 0–255 PWM on ~ pins only.
- map() rescales ranges (integer, truncates) and constrain() clamps values within bounds.
- millis()/micros() give non-blocking elapsed time; delay()/delayMicroseconds() block.
- AVR data types: uint8_t, int (16-bit), unsigned long (millis), float — and double equals float.
- I2C uses Wire (begin/beginTransmission/write/endTransmission/requestFrom); SPI uses SPI.transfer.
- The Servo library uses attach(pin) and write(0–180) for angle control.
Practice what you learned
1. What does map(value, 0, 1023, 0, 255) do, and what is a caveat?
2. Which type does millis() return?
3. On an AVR Arduino, how does double compare to float?
4. What is a common reason an I2C device silently fails to respond?
5. Which function clamps a value between a minimum and maximum?
Was this page helpful?
You May Also Like
Arduino Best Practices
Practical conventions for writing reliable, readable, and memory-safe Arduino sketches, from non-blocking timing to power and wiring discipline.
Arduino Interview Questions
Common Arduino interview topics with correct, concise answers spanning core concepts, memory, timing, communication, and hardware fundamentals.
Building a Temperature Monitor Project
A complete walkthrough of building an Arduino temperature monitor: wiring a sensor, reading it in code, adding thresholds, and displaying or logging results.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics