What makes Arduino the go-to rapid-prototyping platform?
Arduino pairs open-source hardware (AVR/ARM micro-controllers) with a beginner-friendly IDE, libraries, and an active community—lowering the barrier for physical-computing projects.
.ino
sketch in IDE.avr-gcc
, flashes over bootloader).The high-pin-count workhorse for data-heavy projects
MCU | ATmega2560 @ 16 MHz |
---|---|
Flash | 256 KB (8 KB bootloader) |
SRAM | 8 KB |
EEPROM | 4 KB |
GPIO | 54 digital / 15 PWM |
Analog In | 16 × 10-bit ADC (0–5 V) |
Serial | 4 UARTs + USB CDC |
Timers | 6 (3 × 8-bit, 3 × 16-bit) |
Peripherals | I²C, SPI, CAN (via transceiver), external interrupts |
IDE, CLI, and debugging options
$ brew install arduino-cli
$ arduino-cli core install arduino:avr
$ arduino-cli upload -b arduino:avr:mega -p /dev/ttyUSB0
#define DEBUG_LEVEL 2
& wrap prints in if(DEBUG_LEVEL)
.Driving pins, reading sensors, and generating waveforms
// LED Blink (pin 13)
void setup() {
pinMode(13, OUTPUT);
}
void loop() {
digitalWrite(13, HIGH); delay(500);
digitalWrite(13, LOW); delay(500);
}
const uint8_t ECG_IN = A0;
void setup() { Serial.begin(115200); }
void loop() {
int sample = analogRead(ECG_IN); // 0‒1023 → 0‒5 V
Serial.println(sample);
}
Creating stable sample clocks with hardware timers
volatile uint16_t sample;
ISR(TIMER5_COMPA_vect){ // fires every 1 ms
sample = analogRead(A0);
}
void setup() {
noInterrupts();
TCCR5A = 0; // CTC mode
TCCR5B = (1<loop() {
uint16_t s = sample;
Serial.println(s);
}
Busy-loop delays (delay()
) jitter sampling; ISR-driven acquisition keeps timing deterministic for DSP & biomedical analysis.
Streaming data and talking to peripherals
Serial
USB CDC → PC loggingSerial1
→ HC-05 BluetoothSerial2
→ ESP-01 Wi-Fi (AT commands)Serial3
→ GPS, GSM, etc.
#include <SPI.h>
#define CS 10
void setup() {
SPI.begin(); pinMode(CS, OUTPUT);
}
void writeDAC(uint16_t v){
digitalWrite(CS, LOW);
SPI.transfer(0x30 | (v>>8)); // MCP4921
SPI.transfer(v & 0xFF);
digitalWrite(CS, HIGH);
}
From microphone to filtered digital waveform
const int16_t fir[5] = {2, 8, 12, 8, 2}; // simple 31 Hz LP @1 kHz
volatile uint16_t buf[5];
ISR(TIMER5_COMPA_vect){
memmove(buf+1, buf, 4*sizeof(uint16_t));
buf[0] = analogRead(A0);
uint32_t acc=0;
for(uint8_t i=0;i<5;i++) acc += buf[i]*fir[i];
uint16_t y = acc>>8; // scaled result
Serial.write(highByte(y));
Serial.write(lowByte(y));
}
ECG, EMG, EEG on a shoestring (but safe!)
Always power the patient side from battery only. Use optocouplers or ADuM digital isolators before USB connection.
#include <TimerOne.h>
void sendSample(){ Serial.println(analogRead(A0)); }
void setup() {
Serial.begin(115200);
Timer1.initialize(1000); // 1 kHz
Timer1.attachInterrupt(sendSample);
}
void loop(){} // empty loop
Save hours of debugging with these habits
Use static
ring-buffers to avoid fragmentation; keep heap usage < 1 KB.
Where to dive deeper