Electronics project notes/Arduino and AVR notes

From Helpful
Jump to: navigation, search
This is for beginners and very much by a beginner / hobbyist.

It's intended to get an intuitive overview for hobbyist needs. It may get you started, but to be able to do anything remotely clever, follow a proper course or read a good book.

Some basics and reference: Volts, amps, energy, power · Ground · batteries · resistors · changing voltage · transistors · fuses · diodes · varistors · capacitors · inductors · transformers · baluns · amplifier notes · frequency generation · skin effect

And some more applied stuff:

IO: Input and output pins · wired local IO · wired local-ish IO · ·  Various wireless · 802.11 (WiFi) · cell phone

Sensors: General sensor notes, voltage and current sensing · Knobs and dials · Pressure sensing · Temperature sensing · humidity sensing · Light sensing · Movement sensing · Capacitive sensing · Touch screen notes

Actuators: General actuator notes, circuit protection · Motors and servos · Solenoids

Some stuff I've messed with: Avrusb500v2 · GPS · Hilo GPRS · JY-MCU · DMX · Thermal printer ·

Noise stuff: Stray signals and noise · sound-related noise names · electronic non-coupled noise names · electronic coupled noise · ground loop · strategies to avoid coupled noise · Sampling, reproduction, and transmission distortions

Audio notes: See avnotes

Microcontroller and computer platforms · Arduino and AVR notes · ESP series notes · STM32 series notes · · · ·

Less sorted: Ground · device voltage and impedance, audio and otherwise · electricity and humans · power supply considerations · Common terms, useful basics, soldering · PLL · pulse modulation · signal reflection · resource metering · SDR · Project boxes · vacuum tubes · Unsorted stuff

See also Category:Electronics.

See also Electronics project notes/Microcontroller and computer platforms


Environment/compilation; differences between basic AVR and Arduino coding

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

avr-libc is a stripped-down implementation of libc. Not everything you might expect is in avr-libc (or Arduino's code). For example, (s)printf won't handle %f.

Both avr-libc and Arduino's additions have a bunch of code that makes things work consistently on different AVRs.

Coding based on just avr-libc is often done in C, and compiled with avr-gcc.

Arduino's additions ((the stuff mentioned here)) are C++, and the Arduino IDE compiles with avr-g++/avr-c++.

Arduino uses C++ for things like inheriting code from Stream / Print. (I'm not sure why exactly they chose it. It can, under certain conditions, compile to more code than really necessary)

This means that you can't always easily copy Arduino code into your own C projects - it's not hard to use C code in C++ compilation, but you simply cannot use C++ code in C.

...but since the form of C++ you can use is limited, it tends to be nothing fancier than bookkeeping in objects, so often enough you can strip out the useful code and rewrite things as a bunch of C functions.

Another option is to switch your project to C++. There's a avr-c++/avr-g++ and no reason it couldn't work (see [1]. Arduino does it, and so have other people, though it may practice it may require a bunch of fiddling and web searching about lower level details before it works nicely.

Telling it about your hardware

Most hardware features are only available after you include avr/io.h, which will only work if you have defined a variable stating which specific AVR variant you are compiling for (e.g. __AVR_ATmega328P__).

Some things also require F_CPU to be set, to the clock rate you are running at in Hz.

In the IDE, this is effectively done via the "Tools/Board" menu, so this only really comes up during CLI compilation.

On time

Some projects don't care about time, or only need ("halt eveything for x" style) delays, so don't have code for timekeeping.

Timekeeping on AVR is usually based on using one of its hardware timers to generate interrupts, and having an interrupt handler that increments a variable (with knowledge of the CPU clock rate).

For example, millis() reports a counter that is updated from an interrupt hooked to Timer0(verify).

You can roll your own. You'll need to learn how to use the timers, or copy non-buggy code from somewhere.


See also:

Arduino hardware notes

Note: things related primarily to AVRs and barely to Arduinos should be moved to #AVR notes below.

Note that much of the below is biased to be about the Duemilanove as it was written when that the most common board. The older Diecimila is hard to find now. The newer Uno are similar in most ways.

Arduino IDE[2] (itself derived from Processing[3]) makes it easier to write and compile code, program the microcontroller (using avrdude), and monitor the serial port when you want to.

Intro - the more official Arduinos

Arduino refers both to the board designs and to the programming environment that is very commonly used to work with these boards.

The core of most Arduinos is an Atmel AVR-series microcontroller. That AVR does most of the work, and the board around it mostly represents convenience - easily pluggable pins, USB/serial interface (for programming as well as communication), regulated power, (automatic switching to) power plug, crystal clock (not strictly necessary; see notes below), and such.

Many of the common Arduino boards currently use the ATmega328 AVR, older boards used the ATmega168 (and even older ones the ATmega8). Boards like the Mega choose more complex variants like the 1280 and similar. The faster Due and Zero and use ARMs.

There are about a dozen distinct Arduino boards with names. These may have different amounts of flash and RAM, IO pins, and a number are specialized - for example stripped down and/or small, are geared to be LiPo-powered, to do Bluetooth, or such. See http://www.arduino.cc/en/Main/Hardware for a list and details of each. (There are also a few revisions of a number of these boards, occasionally just with slightly different component specs (sometimes a slightly newer AVR), and in one or two cases with mildly different pinouts. (see e.g. the difference between the Nano 2.x versus Nano 3.x))

The basic-size arduinos have actually seen a lot of revisions. Right now you'll probably mostly see (from latest to older):

  • There's also Arduino Diecimila (literally '10000', referring to the amount of arduinos shipped at the time of design), not seen anymore, and the Arduino NG (Nuova Generazione, 'New Generation'), not produced anymore. Since these are not made anymore, and they used earlier AVR chips, you can ignore these.
  • Duemilanove[4] (lit. '2009', introduced in 2009)
USB socket: handled by FTDI FT232RL
  • Uno[5] (introduced late 2010) is basically a sightly updated duemilanove:
USB socket handled Atmega8U2 (a simple USB-capable uC) instead
relevant revision differences:
R1 and R2 use Atmega8U2, R3 uses ATMEGA16U2
R2 and R3 add solder pads exposing the U2's PB4, PB5, PB6, PB7 (apparently to give you more communication options. These are also interrupt/timer pins, which is sometimes pretty useful)
R2 and R3 pull the U2's HWB line to ground, making its DFU mode simpler to use
R3 extended pin headers
The pin-8-to-13 header with SCL, SDA - which are the same as A4 and A5 on the other side (seems done to ease shield designs that also fit e.g. the Leonardo; its uC puts I2C on different physical pins)
The power header adds IOREF (5V or 3.3V depending on what you run the board at, and an unused pin
different reset circuit - seems to solve an issue in this and previous boards where the auto-reset pulse (from the USB-to-serial) occasionally had other side effects[6](verify)
slightly cheaper than Uno
Uses ATmega32U4 as the main uC (which speaks USB directly, and this board existed before the Uno so it was a selling point)
sometimes easier to deal with than doing USB on an Uno (verify)
otherwise most comparable with the Uno
differences with similar-sized boards:
more pins usable as analog in
one more PWM out
using I2C doesn't take away A4 and A5 (but D2 and D3 and their interrupt use instead)
two UARTs, Serial being the USB-serial link, Serial1 the exposed pins (verify)

More PWM pins More digital pins full stop A second hardware serial port

"I need more pins" boards:

  • Mega
Uses ATmega1280 (128KB flash, 8KB SRAM, 4KB EEPROM)
  • Mega 2560[8] (introduced late 2010)
Mostly like Mega, but with 256KB flash instead of 128KB
Like Uno, USB socket handled via an Atmega8U2
  • and e.g. the Due (also faster, see below)

Some more-specific-function boards:

Has a bluetooth module (and no USB, or physical serial port)
Otherwise much like the NG (/ Diecimila)
(Uses an ATmega168)
Can be programmed over bluetooth
Set up for XBee, and LiPo charging
  • Various Lilypad boards
often Atmega328 or Atmega168; ATmega32U4 for Lilypad USB

Smaller boards:

somewhat like a SMD variant of the Duemilenove-style board (seems to come with the 168 as well as 328, in 3.3V and 5V variants, at 8MHz and 16MHz)
flatter than, still mostly the same area as, a classical arduino

Nano 2.x uses ATmega168, Nano3.x uses ATmega328
basically a Duemilanove crammed onto a smaller size with the same components (non-replacable SMD AVR, mini-B USB connector, no DC socket (but still has the regulator, so this is just a wiring thing))
pin headers on the bottom, easily plugged into a solderless breadboard.
Not easy to use with shields designed for the Duemilinove/Mega
ATmega168 / ATmega328
also a crammed board - smaller than the nano because it omits some components you can handle them yourself when you know what you're doing - no power regulator, no FTDI (so no USB, and no 3.3V), and apparently no ICSP.
Doesn't have board pins for all analog channels. You can solder the rest, but it makes it harder to stick the mini onto a breadboard
Not easy to use with shields designed for the Duemilinove/Mega
There is an official USB adapter board for the Mini
ATmega168 / ATmega328P
physically like the Mini (e.g. no usb)
can also be run at 3.3V (at 8MHz max), needs to be 5V at 16 MHz (verify)

  • Micro / Pro Micro[15]
ATmega32U4 (which speaks USB directly)
5V run at 16kHz, 3.3V version run at 8kHz

Side note: In terms of small form factor, you may also care about the teensy 2 series

Faster boards

ARM Cortex-M0+ at 48 MHz (ATSAMD21G18)
256KB flash
CPU is 3.3V, and its GPIO isn't 5V tolerant(verify)
ADC is 12-bit (earlier were 10-bit)
1-channel 10-bit DAC
faster PWM (verify)
board form factor like earlier arduinos
  • Due[17] (note: nothing to do with duemilenove)
ARM Cortex-M3 at 84MHz (AT91SAM3X8E)
64+32KB SRAM
512 KB flash
CPU is 3.3V, GPIO isn't 5V tolerant.
12-bit ADC (12 wired on the board)
2-channel 12-bit DAC
faster PWM, and on more pins
board form factor like earlier mega
  • Note: You may also care about the teensy 3 series
  • MKR
itself refers to a form factor (size/shape), with a few distinct boards
all with the ARM M0+ (so 3.3V, and not 5V tolerant)
each with a specialisation, e.g. MKR WiFi, MKR Zero aimed somewhat at audio, MKR WAN that speaks LoRa, MKR Vidor does video processing
and a bunch of existing shields (communication, sensors, etc)

Since Arduino hardware design is open source, there are other manufacturers of Arduino boards, and a number of derivatives/variations of the official boards. By now, there are many. See for example freeduino, roboduino, DFRduino, iDuino, sanguino, Seeeduino, Really Bare Bones Board (RBBB), Imaguino, some single-sided versions (so you can etch your own), cheaper chinese-made variants, etc.


Notes that apply to various boards

Clock speed

Most AVRs seem to be rated to work fine up to 20MHz.

Most arduinos run at 16MHz, in part just to not break timing with older sketches that assume 16MHz clock.

You can run them faster or slower, which some people do when that makes their timing simpler (e.g. for TV signal generation), you just have to pay attention to a few extra details, e.g. library assumptions.



On libraries and separating into files

You usually want to use the IDE - it hides a bunch of hidden compilation trickery. (people interested in doing it themselves are often the ones with the background to manage anyway)

See http://www.arduino.cc/en/Hacking/BuildProcess

Power (classic boards)

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

When you want to fiddle with the way you supply power, keep in mind that most basic boards do something like:

Powerjack -- polarity protection -- Vin -- 5V regulator -+- AVR
                   diode                                 |
                                                         +- 5V pin 

(See also duemilanove board schematic - and check when you use a less usual Arduino)

Power-related pins:

  • Gnd (in various places, for convenience)
  • RESET: Functionally equivalent to the reset button. Occasionally used to expose this on shields
  • 5V: post-regulator power from jack/Vin, or taken from USB (which is already regulated)
  • Vin: in the path metioned below, before the regulator (called RAW on some(verify)).
E.g. a battery or adapter without the power-jack plug could be put here. You can also effectively leech from a power-jack-plugged adapter here.
  • 3V3: 3.3V
    • on pre-Uno USB boards this comes from the FTDI chip which can supply at most 50mA. It seems that boards with the FTDI always power that FTDI so 3.3V is present whenever there's power on Jack/Vin-powered, not only when USB-powered(verify) (For the Nano, the hardware description mentions the FTDI is only on when USB-powered)
    • on boards with the 8U2 (Uno and later), 3.3V comes from a regulator, which is specced for 150mA

The Duemilenove and newer boards can automatically choose between the jack and USB power (preferring the jack/Vin). Older versions had a jumper to select one of the two.

On external power, and drawing current from it

  • The Arduino's regulator is a simple linear regulator (may be one of various, it's not strictly specced - I've seen people mention 400mA and 800mA, so don't count on more than 400mA).
    • it prefers 7V to perhaps 12V
    • it will work with as little as 6V but may then output less than 5V, which can mean not all components are stable enough
    • it can deal with up to perhaps 20V, but will likely heat up and die faster from the heat (regulator's heat genration being proportional to current times voltage drop. It'll already get warm dropping from 12V when drawing ~100mA, so if you want adde components to draw that or more, try to get a better-matched voltage, like 7.5V -- or make the draw path external to that regulator via a transistor or relay or such)
  • The polarity protection diode seems specced at 1A
  • You should probably assume the traces cannot take more than 1A anyway.
  • There is a polyfuse limiting power from USB to ~500mA.

Powering the board can be done e.g. with:

  • USB power
    • hardware (e.g. a non-powered hub) may give no more than 100mA
    • 100mA is by USB specs, more is possible but has to be negotiated -- in theory. You can often draw up to the USB maximum (500mA, or 900mA for USB3) without it actively complaining or cutting you off.
    • Protected on the Arduino side with a 500mA polyfuse (Computer USB ports should have polyfuses too; by-specs USB can deal with short circuits because of them)
  • A DC adapter on the power jack (through the regulator, as does the polarity protection diode)
    • Wallwarts supplying something between 7.5 and 9V are probably handiest (if you may draw more than a little current, then preferably a regulated one so you know voltage won't drop too much); see also notes below
    • 12V is doable, but the regulator starts heating up at a lower current (over ~200mA already means it's pretty hot)
    • You can steal power via Vin - you bypass and don't tax the regulator, but it's still after the polarity protection diode so keep it below 1A
  • Well-regulated 5V can be plugged into 5V (bypassing both diode and regulator).
    • Perhaps only useful if you have a more efficient regulator; if you do this from a DC adapter, all you save is a few dozen milli-amps, which in most situations is peanuts.
    • ...and it's easier to fry stuff if you make the mistake of flipping the polarity
    • Batteries on the 5V line are a bad idea, mainly because it's hard to get the voltage right. voltage. Four 1.2V AA rechargables is okay, four 1.5V AA alkalines is too much. One Lithium cell not enough, two too much.
    • different story when you configure the AVR for 3.3V operation(verify)
  • A battery plugged onto Vin (board regulator applies), but needs to be >6V.
A 9V battery is easiest to deal with (easier than five penlites)

Other current limits:

  • ~40mA from any one IO pin (if you want more, you want a transistor, darlington/fetlington, or such, and collect power from 5V (few hundred mA max), Vin (~1A max), or something external).
  • the 5V pin is limited by coming from the regulator - so can source a few hundred mA in practice, less if it has to drop a bunch of voltage.
  • the 3V3 pin can supply 50mA if it comes from the FTDI, 150mA from the Uno's regulator. Pretty little.

Expectable current drawn in practice

The AVR and Arduino board around it seems to draw a little under 30mA when not driving anything (and clocked at the usual 16MHz). Running it slower than that will make it draw a little less (~20mA?(verify)).

This may come for a decent part from the regulator - unless specifically low-loss, it may have ~10mA quiescent current (low-loss variants may be <1mA).

Some shields are power hogs in comparison, easily drawing 100-200mA.

Arduino - IO, communication, chip programming

Other special, pin-tied functionality

The regular Arduino boards have

  • 20 GPIO pins
  • 6 are selectable by the ADC (single muxer; see notes below) - referred to as A0..A5
  • the others are referred to as D0..D13
  • PWM on some of them (clock-based, 8-bit). (three or six. Some other boards have more)
  • Supports I2C / TWI on pins A4 and A5
  • Supports SPI on pins D10..D13 (note: overlap with ICSP pins)
  • hardware interrupts can be tied to pins D2 and D3; see AttachInterrupt
  • Pins D0 and D1 go to the USB-to-serial chip, and to the AVR's UART. This is RS232-style serial, but at 5V.
    • (The non-soldered four-pin header labeled X3 are the FTDI's CTS, DSR, DCD, and RI)
  • Pin D13 has a resistor+led on board. Can be useful to signal roughly what your code is up to.
  • supports ICSP (on the 3x2 header)

The larger boards can have more interrupts, more UARTs, more PWM, more analog pins, and such. There are a whole bunch of specialized boards, particularly if you count all the arduino derivatives.

See also:

Bootloader and serial

The ATmega comes preloaded with a bootloader (uses a small portion of Flash space, e.g. 2KB of 32KB), which means it speaks Atmel's STK500 protocol (on TX, RX), which is why and how you can reprogram the rest of Flash memory without having to use a programmer.

Most boards not additionally use the (usb-to-serial's) DTR line, tied to the AVR's reset line, so that on most boards you don't have to press reset at the right time.

You could also use this to reset the AVR remotely via serial.

This DTR line seems to also be the reason that in some cases, the AVR reset when you connect USB.

If you really want to use the Flash that the bootloader uses, you'll need a programmer - they're relatively cheap/simple to buy/build. There are more compact bootloaders, and you could go completely without a bootloader (but you'd need the programmer each time)

See e.g.

IO: All digital, some analog

Board labeling split pins into analog and digital pins, but actually all of them are GPIO (general-purpose IO) pins.

For example, on the smallish boards with 6 analog pins and 14 digital pins, this can be better described as 20 GPIO pins with 6 routable to the ADC, and

  • A0 is also D14
  • A1 is also D15
  • A2 is also D16
  • A3 is also D17
  • A4 is also D18
  • A5 is also D19



This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

See also 'AVR120: Characterization and Calibration of the ADC on an AVR'

Many AVRs have one ADC, which in most cases has a multiplexer in front of it so it can easily switch between sampling from a number of its physical pins.

In most variants the ADC has up to 10-bit resolution, and is usually run in single-ended conversion mode, in which it returns values in the 0..1023 range for 0V to Vref (truncated, so 0 means ≤0V, 1023 means ≥Vref).

(Some AVRs in some packages can also be run in differential mode, but don't count on this)(verify)

Vref can be one of three references:

  • analogReference(DEFAULT) - 5V (probably Vcc?(verify))
  • analogReference(INTERNAL) - an internal reference (1.1V on ATmega168, 328 and many others; 2.56V on ATmega8)
  • analogReference(EXTERNAL) - The voltage on the Aref pin (possibly a minimum voltage of about 1V?(verify))

On speed

The ADC takes 13 of its own clocks for conversion, and is run at a division of the input clock. This makes the maximum sample rate (avr_clock/(adc_divisor*13)), which is (16MHz/(adc_divisor*13)) on most arduinos.

The speed is set by tweaking three bits in ADCSRA. When dividing a 16MHz clock, speeds are:

                    Resulting  clocked   samples    theoretical max
ADPS2 ADPS1 ADPS0    Divisor        at   per sec    accuracy note
  0     0     0       2           8MHz     ~615k      (inaccurate)
  0     0     1       2           8MHz     ~615k      (inaccurate)
  0     1     0       4           4MHz     ~307k      (not so accurate)
  0     1     1       8           2MHz     ~153k      (not so accurate)
  1     0     0       16          1MHz      ~76k      (lessened accuracy becomes noticable)
  1     0     1       32        500kHz      ~38k          
  1     1     0       64        250kHz      ~19k          
  1     1     1       128       125kHz     ~9.6k      (the most accurate, the arduino default)

Arduino boards defaults to the 125kHz/~9.6k setting. And is slightly slower than that in use because of a little extra code around the actual sampling, some of which you can do a little faster with specific-case hardcoding rather than analogRead calls. I've gotten ~8.9ksamples/sec out of this, so good enough.

The AVR specs mention that the ADC will only really give ~10 bit resolution when run slower than 200kHz, but also that resolution is still acceptable up to 1MHz, so it seems feasible enough to use 16MHz divided by 64, 32, or 16.

You may also find use for /8 for 2Mhz, /4 for 4Mhz or even /2 for 8MHz, though aside from the lower accuracy, you may also have trouble using the data (or moving it off) fast enough. It could still make sense for some fast triggering logic.

If you want more channels or more accuracy, look at external ADCs, e.g. http://www.arduino.cc/playground/Main/InterfacingWithHardware#adcdac

On accuracy

There are a few different influences on overall accuracy

  • the sampling speed (see above)
  • output impedance of what you're sampling
if it's on the order of 10kOhm or higher, the ADC's sample and hold capacitor is basically a part of things
resulting in crossbleed to the next conversion - which is an issue when that's on another pin
in code, you could wait. In electronics, you could insert a buffer.
this effect will be larger at higher sample speeds (verify)
  • the rest of the input block, e.g. whether the digital input on the same pin is still connected
because you rarely need to use the same pins as digital in as well,
and if that digital in part of the port is floating, that will be some extra switching noise
and present some capacitance, which can be some issue sensing high-impedance things
Look in the datasheet, around DIDR0
  • switching noise of the processor itself
which is why there's a "sample while sleeping" mode
Manual ADC stuff
This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

If you decide to do the ADC stuff at lower level, there are a few useful snippets of code, and a few details you may want to know about.

Details vary slightly between boards, so if you're stripping code, steal it from the Arduino library.

Not muxing between reads

The implementation of analogRead() chooses to always set channel via ADMUX, so one reason to use more manual code is if you want repeated reads from one channel to be a little faster.

A variant without that ADMUX set would be something like:

inline int read_adc() {
  // Does an ADC sample with the current ADMUX settings
  byte low,high;
  ADCSRA |= _BV(ADSC); // start the conversion. Also seen as  sbi(ADCSRA, ADSC);
  while (bit_is_set(ADCSRA, ADSC))
    ; // ADSC is cleared when the conversion finishes   
  low=ADCL;  // reading ADCL locks both of these
  high=ADCH; // until reading ADCH; seems to ensure the value comes from the same conversion.
  return (high<<8) | low;

Older code had delay(1) between ADMUX change and the conversion.

This seems motivated by two potential problems:

  • For high-impedance reason (see above)
order of 100us to 1ms is usually enough, depending on the impedance
  • When you use ADMUX, you may see the ADCH and ADCL from different channels/conversions. Ways to work around this:
    • throw away the first value you read out, use the next (verify)
    • delay 1ms (less is probably enough) to make sure the ADC has set both from the new conversion. Probably slower than...
    • Read ADCL before ADCH: reading ADCL locks both until ADCH is read and ensures(verify) both come from the same conversion.
    • poll for complete conversion (ADSC bit in ADCSR register; something like
      while ((ADCSRA & (1<<ADSC)) != 0) ;
      while (bit_is_set(ADCSRA, ADSC)) ;

Note that in certain conditions, the delay is not necessary at all.

Faster-returning versions; interrupt stuff

In some cases where spending the most time on your other code is very important, you can fire off the conversion, e.g. get an interrupt handler to read it out and toggle that there's something new to read.

There is e.g. an example here: https://www.gammon.com.au/adc

The Mozzi project does something similar. Its mozziAnalogRead()

returns the most recently read value from the channel
places a request for the pin to be read (will be picked up in the background via interrupt handler)
since it doesn't do a conversion itself (~100us), it is a few multiples faster (~16us)
...assuming you're calling it slower than the conversion speed
...and at the cost of one conversion worth of latency - which in most applications doesn't matter

Also, Free-running mode means the ADC continuously does conversions.

This is meant to be used with an interrupt handler called at the end of every conversion, as the main reason to do this is conversion at a very regular interval.

It also works out as a faster readout, though now there's more focus on you using the values soon enough.


Sampling while the AVR sleeps

There's an AVR sleep mode that allows ADC sampling during it, which makes the sampling slightly less noisy, because it avoids some switching noise next to it.

It's probably only interesting when you want to squeeze out a little more accuracy (at the cost of some AVR time/speed, and don't mind that this interferes with varied timing-sensitive things.

Code I've seen for this tends to resemble: (verify)

inline int read_adc_lownoise() {
    ADCSRA |= _BV( ADIE );          // tell ADC to interrupt when finished
    set_sleep_mode(SLEEP_MODE_ADC); // tell AVR the sleep mode to use
    sleep_enable();                 // allow sleep (doesn't trigger it yet)
    do { // for robustness, loop until finished  (because _any_ interrupt might wake the CPU, not just ADC completed)
        sei();        // make sure interrupts are on. Are enabled to start with, but will be disabled two lines below
        sleep_cpu();  // sleep the AVR (also triggers the ADC(?))
        cli();        // avoids race condition in 'conversion finished' check (apparently; not sure what that note meant)
    } while( ( (ADCSRA & (1<<ADSC)) != 0 ) ); // keep looping until the ADC tells us it is finished.
    //done, so return to normal operation
    sleep_disable(); // disallow sleep
    sei();           // make sure interrupts are on
    ADCSRA &= ~_BV( ADIE ); //turn the ADC interrupt off again - some code might not expect this interrupt
    return (high<<8) | low;
Internal temperature
This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

You can roughly measure the temperature of the AVR chip, for ...P variants of the AVR, such as the 328P (and quite possibly others(verify)), in that you can switch their ADC muxer to an internal temperature reference (against the internal 1.1V voltage reference).

This is fairly low resolution

it varies ~138mV in a 130-degree-C range, which means it'll never be better than ~1°C, and that much only with some added cleverness
and it's worse (easily a few degrees) unless you do:
good calibration (preferably two-point) as the relation to real-world temperature varies per chip
supersampling to remove jitter
AVR temperature is a poor measure of the air around it - particularly since the AVR itself produces heat
you're measuring a diode, which is pretty linear (yay)

See also:


This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

On most AVRs except the Mega there is one serial port, on the Mega series there are four. The first of them (pin 0+1) is typically wired to the board's serial connector or USB via serial-to-USB.

Technical details


  • Before the Uno this was an FTDI chip, typically the FT232R or the FT232RL (the SSOP variant).
  • Since the Uno this is an Atmel chip, the Atmel 8U2. By default this fills much the same purpose as the FTDI (needs its own driver), but can be reprogrammed to do more than that.

You may be interested in datasheets:

AVR and usb-to-serial chips seem do only 0..5V-level serial (and seem to work with 3.3V), so don't connect them to a classic -15..+15V serial port directly.

People seem to commonly use the AVR at 9600 baud (the FTDI auto-bauds to what the AVR uses, so you don't have to worry about it).

Some computer-side programs may only understand one of the more basic baud rates, one of 300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, or 115200.

The AVR (and FTDI) can be run at arbitrary baud rates - useful e.g. for MIDI (at 31250Hz), and at up to two megabaud, but timing can be finicky, and it's not easy to usefully use that speed (when actually doing something useful on the AVR as well). There are Arduino oscilloscope projects that use the faster speeds (along with fast ADC sampling), to move off something like 360000 values per second.

Notes on the PC side

In linux the FTDI is most likely to go on /dev/ttyUSB0. If you use more than one, or plug out and in very fast, you might also want to try /dev/ttyUSB1 (and probably higher).

On windows, the FTDI driver seems to start putting ports at COM5 and higher, so the highest-numbered port is often the one you want.

If you have multiple Arduinos hooked up, you may want them to identify themselves (probably with some hardcoded identifier) if you want a program to use them consistenty.

If you want your code to take a best guess at returning the port that's probably the arduino, you might want something like the following (here for example for python and pyserial)

There is no cleverness to this, other than assuming that (linux) they're on /dev/ttyUSB*, and (windows) they're on the highest-numbered available port.

import serial
def best_guess_arduino_port( port_speed=9600, try_ports=None , **kwargs):
    """ Returns a pyserial object for the first port that seemed usable,
                or None if there are no ports that can be used (within the specified set).
        try_ports - a sequence, of port paths and numbers.
            Use of None (the default) means it defaults to looking relatively exhaustively. 
            In most cases you can safely give your smaller ranges, e.g.:
            ...meaning COM12..COM1 under windows, /dev/ttyS11../dev/ttyS0 under linux)
        The idea behind the descending order is that a plug-in device tends to be assigned 
        a port above physical serial ports, so you usually want the highest-numbered port.
        Any other (keyword) arguments are passed through to the Serial constructor.
    if try_ports==None:
      try_ports = ['/dev/ttyUSB0','/dev/ttyUSB1']
      try_ports.extend( range(31,-1,-1) # 31..0 
    for try_port in try_ports:
            ret = serial.Serial(try_port, port_speed, timeout=0.15, **kwargs)
            break # if the above succeeds, we're done
        except serial.serialutil.SerialException: # probably the complaint that it doesn't exist
    return ret
Notes on the arduino serial code

With one-serial-port boards you have a predefined object called Serial. With mega variants, the second, third and fourth ports are Serial1, Serial2, and Serial3.

Hardware serial implementation comes from HardwareSerial.h/HardwareSerial.cpp, which uses Print.h/print.cpp and its behaviour (as do SoftwareSerial and some other things).

Writing through Serial.write() seems to be a single-byte write, in that there is no transmit buffer (probably a design decision to keep things simple, as you would have to serve that transmit buffer through interrupts, and in most situations it would not help enough to be worth it)(verify). Serial.print and Serial.println will mostly just Serial.write the the given data per character (and use the Print class to avoid duplicate code).

The Serial code stores received data into a 128-byte circular buffer in RAM. Serial.available() reports whether there is data in that buffer, Serial.read() returns data from that buffer.

This buffer also means you don't need flow control for incoming data if you can guarantee that buffer never fills up. Which depends both on data size and speed of polling, but can often be done.

If the AVR has to receive more than 128 bytes in the interval between you checking and emptying that buffer (available(), read()), you may wish to plan for loss, or to use flow control (when you can).

You can change the size of this buffer if you need to (in HardwareSerial.cpp), but realize that if you set it higher, you're trimming your already scarce SRAM. (Note: If you set it to ≥256 you may need to look for (u)int8-based things that now need to be uint16-based, which as of this writing means changing the declaration of available()).

When reading large chunks of data, you probably don't want to rely purely on available() - you want to know how much data you're waiting for, or have some delimiter in the data (e.g. a newline).

(People have reported that available() can report 0 immediately after reading data, even when you know there is data (for example when you read only part of the data reported to be available()). I don't immediately see a cause for this in the current code, so this may have been fixed, I don't know. If true, it means that code that does something like while (Serial.available() > 0) will be flaky too.)

See also (serial)


This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

On basic Arduino boards: Analog 4 (SDA) and analog 5 (SCL).

On Mega boards, this is pin 20 and 21.

The AVR seems to be capable of speeds up to 400kHz. The Wire library uses 100kHz by default

If you run the AVR slower, the max speed lowers, e.g. 100kHz is probably sustainable on an AVR clocked at 2MHz, 400kHz down to perhaps 8MHz.

See also:


The Arduino IDE provides the Wire library (referring to TWI).


  • Wire has a 32-byte buffer it uses for queueing bytes to be sent, and for received data
  • Wire.begin() enables the internal pullups on SDA and SCL.
    • They are higher-resistance than you might wish for (AVR's datasheet mentions as 20..50kOhm, which is pretty high). This may work, but you may wish to disable them after adding your own pullups on the bus.
  • Sending (in master mode): beginTransmission/endTransmission is for sending data. The former mostly sets some library stuff, the latter actually starts communication (sends the contents of the buffer that you fill through calling Wire.send())
  • Wire's communiations does blocking reads/writes, which may potentially hang your programming (given specific wiring trouble)
  • requestFrom() does a blocking read (available() and read() just report on the already-filled buffer)

See also:

Other libraries

E.g. the one here, which adds timeout. Master-only (right now).


If you want to talk to SPI devices, you can choose to use the AVR's ability to speak SPI, making it handle the actual on-the-wire communication, or you can choose to bit-bang it, which isn't as fast but can be done on any pins.

The AVR's hardware SPI is wired to:

  • arduino pin 11 for MOSI
  • arduino pin 12 for MISO
  • arduino pin 13 for SCLK

Pin 10 is only special when using the AVR as an SPI slave. When the Arduino is a master you can use any pin(s) to select slave(s).

Note that MOSI+MISO+SCLK are also exposed in the 2x3 ICSP header (the other three there being Vcc, reset, and ground). Some shields use SPI via those pins, particularly when they want to be compatible with the Mega boards as well(verify).

It is not very hard to access the SPI hardware directly yourself (select, write byte to AVR register, wait for transfer to complete, read from AVR register and unselect), but there is now an SPI library (since arduino 0019) that makes your life a little simpler.

Speed can matter, as some devices do not do high-speed communication (and some are faster than the AVR). The speed division (and remember that SPI2X does not apply in all AVRs):

SPI2X SPR1 SPR0   Divisor   Speed on 16MHz arduinos
  0    0    0     4           4MHz
  0    0    1     16          1MHz
  0    1    0     64        250kHz
  0    1    1     128       125kHz
  1    0    0     2           8MHz
  1    0    1     8           2MHz
  1    1    0     32        500kHz
  1    1    1     64        250kHz

See also:

Some usage examples:

Direct port access (digital pins)

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

The GPIO pins on a ATmega328 and similar are on ports B, C, and D.

digitalRead and digitalWrite access these ports, but also do a bunch of work around it:

  • figures out hardware port register for the pin
  • figures out bit in that for the pin
  • disables PWM timer if it was on
  • for read: reads port, masks the bit corresponding to the pin, returns HIGH/LOW accordingly
  • for write: reads port, changes the corresponding bit in the pin values, writes the result to the port

Direct port access refers to reading and writing out the registers directly. This is faster than digitalRead/digitalWrite if you don't care about all of the extra work it does, and certainly when you want to change multiple than one pin at once.

You do have to assume PWM is off, and you are hardcoding for a specific AVR/board.

For each port there is

  • a direction register (usually altered by pinMode())
  • a register that corresponds to the value to write for each pin when it's in output mode
  • a register that corresponds to the value read for each the pin

For a regular-sized board (Duemilinove and such):

Port D is digital pins 0 to 7

Port B is digital pins 8 through 13 (The highest two bits in the are not usable; connected to the crystal)

Port C are the pins mentioned as analog input pins 0 to 5 (6 and 7 only accessible on the Arduino Mini). These are general-purpose IO pins like the digital pins (hence they have the same-style access ports), meaning they can be used as digital pins whenever they're not used by the ADC:

  • DDRC - The Port C Data Direction Register - read/write
  • Write to PORTC (read-write), read from PINC (read only)

These pins can additionally be used by the 6-channel ADC (...In the PDIP package mostly seen in arduinos, there are variations), which can sample one pin at a time; the implementation of analogRead() is roughly:

  • sets that channel, and the analog reference
  • starts the conversion
  • waits on the ADC status for that conversion to finish
  • Reads ADCL, ADCH, and returns (high<<8)|low


AVRs have a bunch of inteerrupts, most of them internal (timer, wdt, spi, i2c, usart, adc), and a few external.

External interrupts, i.e. trigger based on change on GPIO pins, is registered like:

  • interrupt number
    • ATmega8, 168, 328 family has two:
      • interrupt 0 means arduino digital pin 2
      • interrupt 1 means arduino digital pin 3
      • inerrupt 4, 5, and 6 are "something happened on this port"
    • Atmega1280 and friends have:
      • interrupt 0 means arduino digital pin 21
      • interrupt 1 means arduino digital pin 20
      • interrupt 2 means arduino digital pin 19
      • interrupt 3 means arduino digital pin 18
      • interrupt 4 means arduino digital pin 2
      • interrupt 5 means arduino digital pin 3
      • TODO: complete this list

You can configure this with attachInterrupt(interrupt, function, mode)[18], which assigns a handler for an interrupt (...number).


  • interrupt - the number above
  • function - what to call call
  • mode:
    • RISING: low-to-high edge
    • FALLING: high-to-low edge
    • CHANGE: any edge
    • LOW: trigger whenever low (continuously?(verify))

It seems you can actually use any GPIO pin for on-change (-only) interrupts. While there is an interrupt vector for every pin, all pins on a port share the same interrupt, you'll need some code checking which pin generated each interrupt.(verify)

Notes and caveats:

  • You want to avoid noise triggering interrupts.
particularly from floating; a pull-up or pull-down is typically enough here.
  • Any globals you alter from an interrupt function and also access from your regular code should be declared volatile[19].
  • interrupts are disabled while in an interrupt handler (by default)
This means everything that relies on interrupts:
PWM pauses
serial receiving will be postponed - and may lose bytes if you postpone too long
any other communication will probably make a timing mistakes
so keep your interrupt handler as fast as possible. Consider any work that isn't time-critical to your main loop
you can enable interrupts while in an interrupt handler , but this allows nested interrupts, which should be used with care
  • delayMicroseconds() turns off interrupts while it's running
  • an interrupt takes at least 3 clock cycles (verify) to get started, plus the time it takes to save and restore registers.
  • If you want to be sure some code is not interrupted (may be necessary when you're thinking about signal generation with microsecond-scale accuracy), you can temporarily disable interrupts
Note this means you cannot rely on timekeeping anymore, and while you can often fix that for your code, this may make timing/interrupt behaviour worse for something else - including anything served via interrupts.

Toggling interrupts:

  • disable globally with
  • re-enable globally with

You can also more selectively mask out interrupts, but this tends to mean lower-level register tweaking. If you're comfortable with that you probably already read up and know what you're doing anyway.

See also:


The AVR used in the basic arduinos have three timers/counters (and a watchdog timer).

The Arduino code uses one of these for its timing and delay functions (interrupt handler does simple counting), and all three for PWM. All three can be used more flexibly - but you'll want to know how that affects timekeeping and PWM.

ATmega8, 168 and 328:


  • 8-Bit
  • Can do PWM (Phase Correct, and a simpler variant)
  • Can trigger interrupts
  • can be prescaled (divided) by 1, 8, 64, 256, or 1024
  • Arduino uses it for PWM (pins 5 and 6), millis(), micros(), delay()


  • 16 bit
  • Can do PWM (Phase Correct, and a simpler variant)
  • Can trigger interrupts
  • can be prescaled (divided) by 1, 8, 64, 256, or 1024
  • Arduino uses it for PWM (pins 9,10)


  • 8-Bit
  • Can trigger interrupts
  • can be prescaled (divided) by 1, 8, 64, 256, or 1024
  • Arduino uses it for PWM (pins 3 and 11)

ATmega32u4 has much the same features in a timer0, timer1, (no timer 2), timer3, and adds a timer4

ATmega1280 and friends:

See also:


This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

ATmega8, 168 and 328 have two 8-bit and one 16-bit timers (by default used as 8-bit), making for six PWM-capable pins

ATmega1280 and friends have a bunch more timers (6?(verify)) and PWM pins (15?(verify))

ATmega32U4 has one 8-bit, two 16-bit, and one more specialized high speed 10-bit (up to 7 PWM pins combined(verify))

This refers to hardware PWM based on internal timers/counters, comparators, and the interrupts they can trigger. (Note that, as on any uC, you can also bit-bang PWM on all GPIO pins using most CPU power, or use timer interrupts to do slower but simpler PWM on more pins, though at lower speeds than hardware PWM can)

AVR PWM is typically actually a little more capable than arduino exposes, but for uniform behaviour across most boards (and because in some cases you also alter timekeeping and thereby various communication) Arduino libraries default to 8-bit PWM, a higher prescaler (so slower speed), and phase-correct on most pins, making for max ~490Hz for many boards (~980 Hz on fast-mode pins, and some boards deviate[20]).

You can get up to a few kHz 8-bit PWM on many, and get 16-bit on some, but you have to configure it knowing the AVR and the side effects. (analogWriteResolution() just for Due, Zero, MKR, i.e. the ARM-based boards), on most other boards you have to do it more directly.

See also:

More and other IO

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

If you want to control more separate outputs, options include:

  • IO expander ICs
    • often something like 4, 8, 16, 24 digital ports
    • connected via something like I2C, SPI or such
    • can sometimes be used for well-timed IO independent of the uC
    • can sometimes also be a handy way to connect different voltage levels
  • Another AVR (there are simpler/cheaper variants, such as the ATtiny series)
    • useful if you want to PWM or do something else complex, otherwise can be a little overkill (then again, it's not horribly expensive)
    • ...although the most stripped-down AVR+oscillator setup should cost you no more than some other solutions

More inputs:

  • IO expanders
  • ADCs

Other IO:

  • MIDI is a serial protocol at 31250 bits per second. You can make the hardware serial do that, so you mostly just need the right DIN socket/plug. [21]
  • obdev's v-usb-stack is a code-only implementation of a (low-speed) USB device. (see e.g. [22] for some projects that use it)

Bit-banging serial

You can get serial on any GPIO pins.

It's less efficient than hardware serial, and easier to have specific issues with. For example, even the libraries that can receive on multiple pins can only do so on one at a time.

Can still be very useful for informed use, for example send-only, or question-response so that you know when you have to receive, and can ignore the pin most of the time)

Or temporary use (e.g. spitting out debug during development whenever you need the hardware serial for the real design).

Keep in mind that at lower baud rates you'll probably need to use, things take more than a few milliseconds to send out or receive.

Useful e.g. when you need the hardware serial for the real device - but e.g. still want to debug.

The upside is that you can add can be used on any pair of pins, and you can usually print/println as with Serial.

Arduino's own
This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)


Can't go faster than 9600.

Baud rates of 1200 and lower noticeably affect millis() timing. People seem to report that 2400 is a reliable choice.

The main loop has to pay attention to incoming data, meaning data sent to use while there is no read() listening is lost, there is no receive buffer (there's little point), available() doesn't work, and read() blocks until data arrives(verify).

Also, it may itself disturb (other) time-critical code you may have, because it uses delayMicroseconds() for timing, which implies that it disables interrupts frequently (which also affects millis()), even though it's for short amounts of time.

AFSoftSerial and NewSoftSerial
This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

(AFSoftSerial.h, NewSoftSerial.h)

AFSoftSerial was a solid improvement over older SoftwareSerial, which was then further adapted into NewSoftSerial.

Since Arduino 1.0 (~2012), NewSoftSerial was adopted as the implementation of SoftwareSerial, so you should no longer have to care about this.

Uses pin-change interrupts to receive data, and a (64-byte) receive buffer.

Spends more time in its interrupts, meaning less time for your program but also that it it's harder to mess up.

Supports more baud rates than SoftwareSerial.h code does - mostly higher ones.


If you get garbage characters
  • Both sides should share ground. If not, you may see slight to total mangling of your data.
  • Overly high (or low) baud rates may be more susceptible to certain types of trouble (may also depend on the rest of your code). Check documentation for support, and forums for reports about what works better than others.
  • Anything that uses interrupts may interrupt in the middle of reads and writes.

If the interrupt fires rarely, you'll probably see mostly good transmission and occasional garbage. If you have a common and unavoidable interrupt (e.g. external interrupt), this can make software serial effectively useless.

Add-on shields

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

Power draw:

  • Ethernet module shield ~150mA
  • a GPRS module probably takes ~200mA average, and ~2A in short (sub-millisecond) transmission spikes?

Ethernet shield

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

There is more than one Ethernet shield out there (and more designs than shields - see e.g. [23]).

The more official and common shield, and the standard Ethernet library, are based on the Wiznet W5100. The W5100 speaks SPI and the shield use pin 10, 11, 12, and 13 (the AVR's hardware SPI), and passes all of the pins through (including the SPI ones - but note the bus bug in the older variant).

Most network-related processing is done on the shield, but talking to the shield (via SPI) may still take at least a few milliseconds - which can matter.

There was an older design of that more official board:

  • has a non-functional SD slot (at least, not officially supported - some people have reported getting it to work.)
  • seems to have a bug where it doesn't release the bus (MISO?), meaning you can't use other SPI devices.
  • Not wired to work with the Mega variants out of the box, but can be made to without too much trouble.(verify)

The newer one (now the one listed at [24])

  • is marked "ETHShield SD" and "mega compatible" (the latter because it uses SPI over the ICSP header)
  • Has a MAC address on a sticker on the back
  • has a functional microSD slot (its slave select is on digital pin 4(verify)[25]. )
  • seems to not have the bus bug the earlier one has (...since the microSD card also uses the SPI bus)

Both will work with the basic library - and various others will too.

On libraries

That basic library requires you to configure:

  • a MAC address (manually; a random number should work - but you may want to pay attention to the two special bits)
  • an IP address (manually)
  • optionally a gateway and subnet (...if you actually want to use the internet)

After that is configured, the shield can be used as a server or client. The basic library only supports TCP and up to four socket connections (in+out total) at a time.

More on the basic ethernet library:

  • Incoming connections on the Server are returned as Client instantiations.
  • It seems that according to server.available(), a client is not considered a client when it connects but only once it has something to say. Even if only want your arduino to write out some reading, the client will still have to send data before available() will return it as a Client you can write to (one byte of dummy data is enough).(verify)

There are also other libraries than the standard one, that offer more features for this and/or other boards (such as DHCP, DNS, UDP, OSC, Bonjour). (see e.g. [26], [27], [28])

(particularly DHCP and DNS are handy as it means you need no hardcoding beyond a unique MAC)

On power

Datasheet mentions it typically dissipates approx ~140mA (183mA max) - at 3.3V. Can't be powered off.(verify)

See also:

Other libraries:

Similar devices:

GPRS shields

There are a few, including:

WiFi shields

XBee shield

GPS shields

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

The sparkfun GPS shield mostly a GPS module, plus a fairly simple PCB. Summary:

  • a GPS module you can plug in
    • socket for the given receiver (plus three different, unpopulated spots)
  • stackable headers to make it an actual shield
  • reset button - connected to the Arduino reset pin
  • power LED {{comment|(seems wired to the Arduino's 3.3V, so is just as semi-informative as the Arduino's "board is powered" LED
  • takes power from 3.3V or 5V lines (depending on the GPS module used)
  • a switch that controls power to the GPS module (separately switches both 3.3V and 5V lines)
  • a switch that connects the GPS serial lines to either
    • pins 0 and 1 - the Arduino UART. (Don't use this setting when you want to upload code to the Arduino)
    • pins 2 and 3 (by default; could be changed with a little soldering work)
  • spots for headers to get at GPS lines beyond its RX and TX -- but note this doesn't apply to the EM406 or EM408 (those mostly just give VCC, Gnd, RX and TX). The extra lines are mostly interesting when using the EB-85A or SUP500(verify)

By default, the GPS module outputs NMEA sentences at 4800bps (and doesn't need any configuration).

The simplest way to get all features is a library that parses them, such as TinyGPS (~2500 bytes of program). For simpler uses you can write code that reads just the few messages you're interested in.

When you use bit-banging serial, you probably want NewSoftSerial and not Arduino's own SoftSerial

Semi-sorted notes

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

ATmega8U2 / ATmega16U2 / ATmega32U2 notes

Boards up to the Duemilenove used the FTDI FT232(RL) USB-to-serial chip. (or CH340 on cheaper chinese copies)

Recent Arduino boards like the Uno and Mega 2560 tend to instead use separate Atmega8U2 or Atmega16U2, and the Leonardo and Micro are an ATmega32U4.

These U2s are programmable AVR themselves. Default firmware used on arduino makes it a USB-to-serial device, but you can make it act like vaious other USB devices (like MIDI; HID like keyboard, mouse, joystick, MIDI; disk). (These 8U2 and 16U2 have most pins unconnected, at least on Arduino boards)

Note that in the case of the Leonardo, the microcrontroller is a single ATmega32U4 (note: U4), having both roles. In Arduino naming, its Serial is the usb-serial interface, Serial1 the board-exposed hardware serial pins)

On U2 programming

DFU (Device Firmware Update) refers to the protocol used to update USB device firmware - a wider USB standard, used on a whole bunch of devices.

In our case it would update the ATmega8U2 / ATmega16U2 / ATmega32U2's flash, i.e. firmware. It's useful to us because it's a separate protocol over the same wire, making it easy for us to distinguish between updating the U2, and the main AVR over serial.

(some different details on a Leonardo, given what it is)

There are different solutions to programming both the U2 and the central uC (e.g. ISP for both, as the ICSP headers for both are exposed) - pick the one that makes the most sense to you.

Note that once you reprogram the U2 to be/default to something other than USB-serial device, the one-click IDE upload no longer works. So you may wish to see if your chosen firmware will go to usb-serial based on a jumper, because that's pretty convenient.




On U2 firmware

Most people seem to use firmware based on LUFA (apparently arduino itself uses its usb-serial(verify)).





  • Moco[30] is the idea that you can have the uC speak regular serial-MIDI (which you can also put on a plug) and have the U2 translate that to usb-midi.
which technically imposes a 31kbaud bandwidth limit where you can avoid it, but unless you're doing things like MPE you're probably fine



Data types

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)
  • char: 8-bit, signed
  • byte: 8-bit, unsigned
  • int: 16-bit (signed or unsigned)
  • word: same as (unsigned) int
  • long: 32-bit (signed or unsigned)
  • float: 32-bit, apparently standard IEEE754
  • double: the same as float (at least currently)

You can define (only 8-bit) literals in a bit-wise way, like B10011001


The Print class (from Print.h/Print.cpp) is also the base of hardware Serial, SoftwareSerial, and some libraries (e.g. some LCD libraries), so you can often print/println to them, and it'll handle all the built-in types.

You can also use sprintf(), but note that it doesn't handle floats.

Printing integer data:

By default, integer types will print as decimal-base ASCII (human-readable numbers). Using print/println's second argument makes sense primarily for integers; the value is implicitly passed in as a long (32-bit integer), and...

  • DEC, HEX, OCT, and BIN ask to print text assuming those respective bases (seems to cast the value via a long)
  • BYTE casts to a char and prints out the value as a byte. Meant to write bytes out as their binary selves and not represented as text.

Printing floats:

print()/println() for floats calls printFloat(n, 2) to ask for two digits. Do not try to ask for amount of digits on the print/println call - that leads to the overloaded choice of printing it as if it were a (long) int, which makes no sense.

The underlying printFloat function (and printNumber, used internally for printing integers) are private members of the Print clas (probably just because they shouldn't be part of the external interface), so if you want to control the amount of digits when printing floats/doubles:

  • the quick hack is to change Print.h/Print.cpp to make printFloat public - it's not portable, but not nasty either. (you could also add your function to Print.h/print.cpp, but the most obvious case where you define a print(double,int) would create an overload ambiguity.
  • a more portable way would be to copy out Print's printFloat code into your sketch - but you should then only ever use that copy (unless you don't mind wasting memory having almost identical code in your AVR twice). You could adapt this function to act like sprintf/strcat (and that does make it more convenient that having to write to a temporary string to be strcatted later)

More string testing/manipulation/formatting

  • You could do some manual string manipulation, since this is basic null-terminated C-string stuff[31], but that can get tiresome for some of the more complex things.
  • sprintf is flexible, but pulls in about 2k of code. If you are pressed for space you may wish to look for alternatives
  • If your target is serial-port writing, see if you can get away with the type-dependent formatting you get from handing single variables to Serial.print/Serial.println calls, which is actually the Print class (see note below)
  • PString lets you do Print/Println to to memory, and adds a little string safety. Apparently adds 100 to 600 bytes of code.
  • String (formerly TextString), e.g.
converting from other types (e.g. String(13, HEX);)
convenience functions for comparisons, and a few alterations (...useful for basic protocol stuff)
  • Streaming is mostly syntax convenience around using Print(-derived) objects such as Serial. Doesn't print to memory by itself (you'ld probably combine it with PString or such). Apparently takes zero extra memory in itself.

Bootloader stuff

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

The bootloader is convenient, but not required.

Without the bootloader, you get to use the flash space it would use, and save a little time at bootup that they wait for new uploads.

With a bootloader, you can use the plain serial port (rather than ISP or JTAG, which is more wires) to upload new sketches.

The bootloader describes the first 512 bytes to 2KByte of code in an Arduino's AVR's flash.

The bootloader runs when the Arduino is powered up, or is reset. It does a few basic bits of setup most wouldn't care about, but more importantly:

It listening on the serial port for a second for something that sounds like Atmel's STK500 protocol. If valid, this is an upload of code that needs to go to the rest of flash.

If not runs the last-stored program.

What the (USB) Arduino boards added to this is tying the FTDI chip's DTR line to the AVR's reset, so that the serial port can do a timed reset yourself as you did on older boards.

There are also some variations on the bootloader, and modifications you can do. For example,

  • the no-wait bootloader only looks for programing after reset, not at powerup (makes sense on USB arduinos)
  • optiboot is mostly smaller (512 bytes), and can be made faster (the basic bootloader runs at speeds like 19200)

Programming the AVR without a bootloader is also not very complex.

The cheapest, if you have another arduino, is to program it as an ISP programmer, see [32].

Or even using ParallelProgrammer via a standard parallel port -- except having those on PCs (and particularly laptops, has gone out of style so you'ld probably need a USB-parallel adapter, so it's not the handiest.

If you do this a lot, then you may like something dedicated (and probably with a plug that fits on the ICSP header, it's easier). There's a bunch of options, including

  • AVRISP mkII: USD ~35.00
  • USBtinyISP: USD ~25.00
  • an STK500 board

See also:

Timing and timekeeping

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)


  • milliseconds since program start
  • returns an unsigned long (not an int)
  • overflows every 49 days (232 milliseconds)


  • milliseconds since program start
  • returns an unsigned long (not an int)
  • overflows every 71 minutes (232 microseconds)
  • resolution of four microseconds (increments with that much)

More on millis

Interrupt handlers generally pause timekeeping, which makes the time counters run slower

When doing intervals, it's generally best to use subtraction, like:

if ((millis() - last_trigger_time) >= duration ) {

This will work around integer overflow, roughly because subtraction overflows in the same way. (This assumes the wraparound is the integer overflowing, and not coded to wrap earlier, as it was in Arduino 0011 and earlier. It also assumes duration is shorter than 2**32 milliseconds, i.e. 49.71 days).

There are slightly more explicit ways of dealing with wrapover issues. TODO: work out in more detail


  • the code above will have an interval slower than duration, because the code takes nonzero time
To avoid that, you can do last_trigger_time+=duration and/or set last_trigger_time before that code
  • ...in either those cases, consider what happens when your code takes significant time - and what you want to happen.
(e.g, most often, it'll trigger continuously)

Keep in mind that millis() returns an unsigned long (uint32_t), and storing that in a signed long (or in an int) will lead to weirdness.

When you want to do things at regular intervals, you could write code like:

wait_until=now + interval; 
while (millis() < wait_until) {
  // wait

however, this will glitch around wrapover time (it triggers early(verify), TODO: explain why).

more on micros
More on timekeeping

The timing for millis() and micros() is not accurate enough for long-term timekeeping.

This isn't specific to the functions, or to arduinos, but to oscillators in general.

Don't count on any basic oscillator doing much better than on the order of 50 ppm or so {{{1}}}, which means it'll be off by up to ~4 seconds per day. Some are better (and pricier), some is constant and can be calibrated away once you measure it, some of it depends on measurable things like temperature, some of it just is variable.

Getting accurate times

This tends to mostly be a ~EUR10 antenna, you still have to do a bunch of receiving.
that said, this is arguably the easiest way to not drift over the long term
  • if you have something that has a GPS receiver, use that - GPS is one of the best time sources available in general
however, while the module itself has very accurate time, not all make it easy to get it out - read up on 1PPS outputs
also, GPS is a relatively expensive component to get just for this
  • if you have Ethernet/Wifi access anyway, you can interface with NTP servers
if not, it's a complex and pricy way to go

If instead of regular corrections you want to set time once, then keep it accurate on its own for a long time, there are (tiny-battery-backed) clock modules, e.g. TWI / I2C ones. You'll still have to set them,

they may still be no better than 10ppm (approx a second per day)
some of them perhaps 2ppm (1 second per ~5 days, approx. 1 minute per year)

A few modules you interface with have built-in clocks for some reason, and you may be able to use that

Arduino Time library is a convenience library that lets you set a time (from an external source) and the continues counting using the AVR timers. If using GPS or radio time, and syncing regularly, this tends to be more than enough.

There is some code to interface it with an RTC module, with NTP (using ethernet shield), and from GPS.

Power saving

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

See also: http://www.arduino.cc/playground/Learning/ArduinoSleepCode

Arduino itself can power-save by sleeping. A sleeping AVR can only be woken up by interrupts (or a reset).

If you do this to save power, note that some of the basic power draw comes from the regulator (say, a 78xx series always uses ≥ ~10mA)(verify), so the AVR isn't the only thing you should be looking at.

The arduino has five sleep modes:

    • stops main CPU, IO still on (least savings)
    • useful when you want to do work only in reaction to incoming IO (...interrupts)
  • SLEEP_MODE_ADC - 'ADC Noise Reduction Mode'
    • stops CPU and IO
    • ...to minimize switching noise during ADC sampling
    • AVR wakes up again when the ADC interrupts to signal 'conversion complete'
  • SLEEP_MODE_PWR_SAVE (verify)
    • everything disabled except internal oscillator (when you use it in the first place)
    • useful when you want faster startup than regular (verify)
  • SLEEP_MODE_PWR_DOWN (lowest-power mode)
    • saves registers, freezes internal(?) oscillator (verify)

See also

Relatively board-specific notes


Seeeduino mega

ATmega 1280-based board.

Basically a cheaper and smaller variant of the the Arduino Mega.

Seeeduino stalker v1

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

Released Dec 2009, replaced by the v2 a year later and the v1 is no longer in production.

While some summaries mention the v1 uses the 168 and not the 328, both variants have been available.

Differences with arduino:

  • The 5-pin serial interface under the XBee socket is connected to (from top to bottom):
    • DTR - you'll want this when programming the AVR (it does automatic reset), though with some timely pressing of the reset button you can do without it
    • Gnd
    • Bee socket's pin 3 (RX) and arduino pin 1 (UART's TX)
    • Bee socket's pin 2 (TX) and arduino pin 0 (UART's RX)
    • 5V (post protection)
  • LEDs (top to bottom):
    • D5: 'user define' - like the basic arduino pin 13 LED
    • D3: XBee pin 15 (association / IO 5)
    • D1 (green) & D2 (red): Power, reset
  • Jumper near the center: Wire the Bee socket's pin 15 (XBee: association/IO 5) to arduino digital pin 2 (to let you attach an interrupt handler)
  • 4x2 block, top right: I2C connectors, 3.3V and 5V
  • The CR2032 battery holder is to keep the RTC holding onto the time while the board is not powered
  • SD socket is I2C, selector is on pin 10

I'm not sure what the default AVR code does, but I needed to program Blink to clear the serial line and talk to an XBee in the socket.

Seeeduino stalker v2

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

Released Dec 2010.


Arduino IDE and environment notes


In general, the C rand() call uses the libc random() function(verify), which can be one of a few PRNGs [33].

There are others you could use, which can be useful e.g. if you want one of a known faster speed[http://engineeringnotes.blogspot.com/2015/07/a-fast-random-function-for-arduinoc.html ].

You should assume that that always generates the same sequence.

When getting a sequence that looks arbitrary enough, changing moderately quickly, that doesn't necessarily matter even if it is always the same.

Getting something random enough to probably be different each time is enough, is a little harder, but doable.

One way is to sample floating pins (ADC if you have it), checking that it's not always the same, and then using some average.

Getting something that will be different each time, and hard to influence externally, which you may need for secure solutions, is harder.

The ADC solution may be somewhat predictable (it may e.g. be you're using one of a few thousand seeds), and it may be influencable (with an electric field, or just grounding), so this is not ideal solution to e.g. generate tokens that should be entirely random, certificates, etc.

You now run into the question of good entropy sources, testing them, and the fact that that is slow. If you need this, read up.


If you don't like the editor much, take a look at PlatformIO, an extension to VSCode

Compilation environment

Different tabs

data types

AVR notes

Anything above that has no Arduino-specific detailsmay be moved here

Some AVRs

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

To get an indication when it's useful to get specific variants: (Note that there are many AVR variants, and a single digit or letter difference can matter. The below is mostly a list of things you're relatively likely to see)

Some of the common AVRs, memorywise:

  • ATmega328 (common on Arduino Duemilanove boards and comparable)
    • has 32 KB Flash memory (2KB(verify) used by bootloader), stores your program
    • has 2KB (S)RAM, stores variables
    • has a 1KB EEPROM
    • 6 ADC pins in DIP (8 in others(verify))
    • 6 PWM pins
  • ATmega168 (but now you'll usually see a 328 instead)
    • has 16 KB Flash memory (2KB(verify) used by bootloader)
    • has 1KB (S)RAM, stores variables
    • has a 512B EEPROM
    • 6 ADC pins in DIP (8 in others(verify))
    • 6 PWM pins (verify)
  • ATmega8 (not seen much anymore)
    • has 8 KB Flash memory
    • has 1KB (S)RAM, stores variables
    • has a 512B EEPROM
    • 6 ADC pins in DIP (8 in others(verify))
    • 3 PWM pins (verify)
  • ATmega1280 (used on Arduino Mega (before late 2010, when Mega2560 and Uno were released))
    • has 128KB Flash (8 KB used by bootloader)
    • has 8KB (S)RAM
    • Has 4KB EEPROM
    • 4 USARTs intead of 1
    • 16 ADC pins
    • 14 PWM pins (verify) (six timers)
    • 86 IO pins (though Arduino boards don't expose them all)
  • ATmega2560 (used on Arduino Mega2560)
    • has 256KB Flash (8 KB used by bootloader)
    • has 8KB (S)RAM
    • Has 4KB EEPROM
    • 4 USARTs intead of 1
    • 16 ADC pins
    • 14 PWM pins (verify) (six timers)
    • 86 IO pins (though Arduino boards don't expose them all)

If you're going for small and/or single-purpose, you can look at the ATTiny series. There are a lot of variations, a sliding scale of price versus features. Some of the ones I've looked at at:

  • ATTiny84
    • 8KB Flash
    • 512B RAM
    • 512B EEPROM
    • DIP version is 14-pin
  • ATTiny85
    • 8KB Flash
    • 512B RAM
    • 512B EEPROM
    • DIP version is 8-pin
  • ATTiny45
    • 4KB Flash
    • 256B RAM
    • 256B EEPROM
    • DIP version is 8-pin
  • ATTiny2313
    • 2KB Flash
    • 128B RAM
    • 128B EEPROM
    • DIP version is 20-pin
  • ATTiny13
    • 1Kb Flash
    • 64B SRAM
    • 64B EEPROM
    • has only one timer
    • DIP version is 8-pin

Keep in mind

  • you'll probably want to program these via ISP (rather than the one click serial STK bootloader way), so you'll probably want to use one one Arduino as an AVR ISP (or buy/build your own ISP).
  • the 8-pin versions can be very cramped. Even if the feature's there, it may be on the same pin as another you want.

Programming the hardware

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

All(verify) the real-world options build on one of the two basic ways to program an AVR:

  • via a previously burned bootloader set up to program the rest of flash
  • via ISP

Both are built on hardware-level AVR features.

Programming via bootloader

The bootloader is an optional step in the AVR boot process. When used, it means a small portion of flash is run first, and allowed to write to the rest of flash.

The AVRs on arduinos have a bootloader that, after reset and before starting the program, talks stk500 (An Atmel protocol) via the serial port. This is how arduinos are updateable with a single mouse click (give or take - recent arduinos use the usb-serial to trigger a reset. Older arduinos required well-timed manual resetting).

Since the bootloader cannot overwrite itself, or set the AVR configuration (the fuses), this also means it's hard to get the AVR into an unresponsive state than with ISP.

The cost for this convenience is (usually) 1KB or 2KB of flash space.

In-system programming

The lower-level way is to use in-system programming (ISP), which lets write write flash, change/add/remove the bootloader, and set the fuses (Atmel's name for AVR low-level configuration bits, see below).

The pins used for this are in the 3x2 ICSP header (alongside power, and ground, and reset). (These pins are shared with the SPI lines, which sounds similar but has little relation)

See AVR910 on more details on how AVRs do ISP.

Because ISP is simple, and its timing fairly strict, you need something more or less dedicated to programming, so your setup will often look something like:

PC <----- serial -----> ISP programmer hardware <----- SPI lines------> Target AVR
                                                     (talking ISP)

These programmers tend to speak AVRISP protocol (see AVR069) and stk500 as part of that (verify).

The simplest way to get an ISP programmer is probably to use an extra Arduino with a sketch that makes it an ISP programmer.

You can get dedicated ISP programmer hardware for a little less than what an Arduino costs.

It is possible to bit-bang ISP, for example via a PC parallel or serial port (or e.g. an Arduino board you have lying around). This lets you program AVRs with little more than a plug and some resistors - but it's very very slow, and sometimes fragile, but can be handy if you need to do just once or twice. (For example, the avrusb500‎ ISP programmer is designed to be bit-banged via its own FT232 - which means you don't need a programmer to program this programmer, you don't need a bootloader to be present - any old AVR chip will do)

In terms of hardware options and cost: (the cheaper of prices I've found for each, no shipping included, etc.)

  • Bit banging
    • Slow
    • sometimes fragile
    • you can buy a serial or parallel bit banger, often for less than EUR15. You can build your own for less
    • bit-banging an arduino's AVR via the Arduino's FT232 can be done for almost free. You mostly need to wire some FT232 lines to SPI lines. Slow.
    • It can be hard hard to find (friendly) software that does the actual bit-banging. In particular USB-to-serial-FT232 is hard to find. Doing so on a generic serial port is a little easier to find.

  • ISP programmers:
    • Arduino board, with an ISP-programming sketch[[34]]. If you have one around anyway, this is basically free. Arguably the easiest way to get a programmer, and to reprogram another Arduino.
    • Sparkfun's Pocket AVR Programmer (~EUR10) - seems targeted primarily at 168 and 328, may not work for all others(verify)
    • AVRISP mkII and clones (~EUR25) - sort of the classic
    • USBtinyISP (~EUR15)
    • avrusb500‎ (~EUR20)
    • STK500 development board (~EUR60?) - makes it easy enough to program all of the AVR series (DIP variants) without having to think about it. But relatively pricy.
    • AVR dragon development board (~EUR40?) - can be used as an ISP programmer, and as an AVR debugger itself

See also:

  • Technical reference:
    • AVR061 - stk500 protocol
    • AVR068 - stk500 protocol, v2
    • AVR069 - AVRISP mkII Communication Protocol
    • AVR910 - In-System Programming


AVRs have some low-level configuration bits, which Atmel calls 'fuses'. (No idea why the name, they have nothing to do with fuses as the protective circuit element)

They can't be set via code, only by an ISP programmer.

There are two or three bytes worth of them. Meaning of their bits varies slightly between AVR series (but is usually constant within a series)(verify).

You'll probably want to use a fuse calculator to be sure you're using the right values for your AVR.

The sort of things you can set:

  • Select the clock source - external, or internal (and its speed),
  • Whether to use boot code, and how large it is (and implicitly what the boot vector is)
  • Brown-out detection - basically the choice to stop working when the voltage dips, to avoid potentially working unpredictably. Can usually be set to 4.0 (for 5.0V operation), 2.7V (for 3.3V operation), and in some cases 1.8V.
  • allow use of watchdog timer?
  • Control whether the reset pin is treated as that, or as an I/O pin.
  • Whether to keep or erase EEPROM memory when the flash is erased
  • Enable serial programming / data downloading? (basically a read-only toggle that you'ld need to change before doing the actual programming)

Minimal AVR hardware

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

You can strip down the AVR to minimal requirements, for example for price in larger projects, or to use simple slave AVRs dedicated to specific time-critical tasks (consider e.g. that an Atmega8 costs ~EUR2).

You can use an AVR with little more than a power line (strictly not even an external clock source) and communication with your main AVR.

If you want to build an AVR setup from scratch (which you can't really call Arduino - Arduino refers mostly to the whole boards around the AVR uC) you'll want to know a few things, like:

For power: If you have a regulated 5V adapter, you can hook it up directly. However, if you want to be robust to unregulated or higher-voltage adapters, add a 5V regulator such as a 7805 - and know that their minimum input is a little higher.

If you want to be robust to plug where you can make polarity mistakes (e.g. DC barrel plugs), add a polarity protection diode.

For the clock source:

  • the no-component solution is to use the AVR's internal oscillator, which can be configured at a few different frequencies.
    • However, even at its fastest this is significantly slower than the AVR's capability, and also somewhat more jittery than a crystal (to the point where it can affect certain types and speeds of communication)
    • you'll need an ISP programmer to tell the AVR to use that oscillator (you may need one anyway, since AVRs generally don't come with Arduino-like bootloaders).
  • A crystal plus two load capacitors
    • Can be bought for at most EUR 3 (combined)
    • Useful when you want higher speed than the internal oscillator, want a specific speed (e.g. for dedicated video signal generation), or need lower jitter than the internal oscillator or a resonator gives you
  • A resonator
    • Should cost around EUR 1
    • more jittery than a crystal, so comparable to the internal oscillator, but if you want it faster than the internal one and don't need time-critical stuff, it's cheaper than a crystal.

See also:

See also:

(If you're doing this for price, note you can get some cheaper versions of an arduino, e.g. boarduino))


Dealextreme sells a 10-EUR AVR board, with little more than an AVR, a crystal, a 3.3V regulator, and pin headers - and adds a few buttons and LEDs. The USB port is just for power.

Watchdog timer (and software reset)

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

A watchdog is typically a "if I don't check in every X often, do Y" thing.

The watchdog timer consists of

  • its own clock source (~128kHz)
  • a resettable counter
Checking in consists of clearing this (with a dedicated opcode)
  • ...and which, when at a configurable threshold...
  • does one of (configurable)
AVR reset
interrupt, or
nothing (verify)

Using it for reset is often a "my code can sometimes get stuck, and I want it to restart completely rather than be hung forever"

For this, configure it for reset, and have the main loop (and everything that takes some time) check in.

It also allows code to trigger an intentional reset from code: (probably first change to the shortest timeout (~15ms), then) enable and configure for reset, then just don't check in (if you think your sketch might have watchdog checkins anywhere, the easiest way to ensure it doesn't is to then do an infinite loop).

Configuring for interrupt is often used either

in combination with sleep (e.g. letting you wake the AVR every few seconds, to save power).
for the interrupt handler you then also define (but note the general timers are often more flexible for this)

The watchdog can be used/enabled

  • via registers (see wdt_enable, or look for WDTCR)
  • via fuses (can't be disabled with code)

Arduino's wdt.h is targeted only at reset(verify). It defines:

  • wdt_enable(timeout)
which you also handle one of WDTO_15MS, WDTO_30MS, WDTO_60MS, WDTO_120MS, WDTO_250MS, WDTO_500MS, WDTO_1S, WDTO_2S, defined in the same file
Some devices also have a WDTO_4S and WDTO_8S
  • wdt_disable()
  • wdt_reset()
    (which is actually a single inlined assembly instruction)


  • the times seem to be slower at 3V.
Don't count on watchdog times being precise anyway.
  • on many devices, the watchdog stays enabled after reset; you may want to disable it early during setup, or a long setup might make for an eternally resetting AVR
  • Code varies a little for some AVRs.
The Due has entirely different watchdog functionality (verify)

Consider that timeouts in your setup would lead to perpetual resets. In some cases you want it to fail early and fail hard, but often enough you want to enable the watchdog after all your init code.

On memory

See #Some AVRs for the memory various AVRs have.

Note there is no protection between the uses of RAM - the stack will happily dip into the heap and overwrite heap data, .bss, and .data (see also the next section).

You probably want to make sure that the worst-case stack size will not clobber any of your data. So avoid (variable/unknown depths) recursion, and other things that could use a lot of stack.

Probably also avoid any (unbounded/unpredictable-sized) dynamic allocation, where you can.

Libraries will often pull in variables and take a few bytes of SRAM or more.

Serial is one of the largest examples, with its 128-byte ringbuffer.

Note that literal strings will sit in RAM, so are often large users of RAM too. If you use a lot of strings, one at a time, look to #On storing data in Flash to alleviate that.

When you use Serial, then easily ~220 bytes will be used before you start doing much. It's easy to have that be at ~400 bytes once you have a bunch of code.

You could argue that whatever you can do in static, pre-allocated variables (in .bss/.data) is less of an unknown than when you do it with malloc/free (on the heap), and that dynamic memory allocation on an uC is rarely necessary anyway.

Free memory
This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

Basically, see http://www.arduino.cc/playground/Code/AvailableMemory

It lists the two basic common types of implementations:

"figure out the difference between the bottom of the stack and the top of the heap"

Fast, because it's trivial math on some existing global variables.

It works because the default memory layout is:

.data variables
.bss variables
the heap (growing up)
the stack (growing down from the end of memory) 

That layout means there is a single chunk of memory that can be used by the stack and heap, and it makes sense to report that as free memory.

There are minor variations of the implementation. They look something like:

inline int available_memory() {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 

or (arduino-specific?)

inline int available_memory() {
   if((int)__brkval == 0)
      return ((int)&free_memory) - ((int)&__bss_end);
      return ((int)&free_memory) - ((int)__brkval);


  • assumes that memory layout. (Still, you'ld probably know about it if you use a different one)
  • implementations are specific to compilation environments
  • since memory will fragment if you malloc/free in a mixed way, this code will underestimate (but arguably less than the try-to-allocate method)

See also http://www.nongnu.org/avr-libc/user-manual/malloc.html

"try to allocate the largest block you can (and free it immediately)"
int available_memory(int size=2048) { // start size
  byte *buf;
  while ((buf = (byte *)malloc(--size)) == NULL) ;
  return size;

Setting the start size no larger than possibly for a given AVR makes the function finish faster. For ATmega328, 2K is a reasonable default. On some 1K is enough, on some you'll need 4K or 8K. (in practice, you could start 100-200 bytes lower, because the variables, stack, library use tend to sum to at least that much. But this will vary with your exact code, so the above is a decent default)

Intuitively this implementation feels iffy, particularly to programmers used to garbage collectors or relying on fancy low-fragmenting malloc implementations. Yet the malloc implementation here is a simple linked list thing(verify) and you immediately free after the first successful allocation, it just leaves things as they were before the call.

(some people report crashes?)


  • it finds the largest contiguous free block, not the total; if you have previously mixed malloc/free sizes, it will underestimate (though perfectly estimate the largest single allocation you can do)
  • It's slow, because it tries every size. You could make it a little coarser and faster by doing size-=2 or so.

External storage
This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)


For "keep things around" needs, note you can often get I2C EEPROMs for a few bucks per MBit (for example, the 24LC256 (32KByte) for under $2).


For more scratch-space needs, you can get SPI (/QPI) PSRAM for rather less than that.

See for example what the Teensy 4.1 does [35]

Flash, probably SD cards

When you want more than a few kilobytes, SD cards tend to be a price-efficient option. SD by specs must speak SPI so are easy enough to communiate with.

That's not their fastest interface, the library may not be optimizing for speed, and the nature of flash means that flushing small chunks is inefficient.

Even for good cases, don't count on more than 1..2mbit/s. Though you probably don't need more.

While you can use it as arbitrary blocks of storage, the arduino SD library speaks FAT16 and FAT32, and this lets you plug it into a PC and copy data off as files.

You can buy SD card sockets, or just solder the SD card to some wires (finicky for microSD).

SD card shields exist, for example this SD data logger shield, microSD shield (USD/EUR ~15).

You'll also find SD sockets on some shields with some other primary purpose (data transfer for the audio shield, a seemingly non-functional SD slot on the older wiznet ethernet shield, and apparently a functional microSD slot on the new ethernet shield)

And some smaller boards, sometimes just breakouts, sometimes with level shifters and regulators so that it's usable from 3-5V.

See also:

On storing data in Flash (PROGMEM)

Variables will by default go to RAM.

When you have data you consider to be read-only, you can tell the compiler to place them in flash, to be fetched (fairly explicitly) only when you need them.

Useful when

  • you want data that's larger than RAM, that you can use small parts at a time
e.g. a wavetable
  • you can move things you use rarely and don't need quickly, freeing up RAM for regular use
e.g. error messages.
Note however that that having RAM you don't use is pointless, so this largely applies when you need this trick to squeeze all your static use in (and helps when you have dynamic uses of RAM)

It's relevant for many microcontrolleres, as RAM is a scarer resource than flash space. e.g. the ATmega328 has 2KB SRAM and ~32KB flash (sketch+data).


  • it has to be fetched to RAM to be used, making it slower
  • only really helps when you never need much of that data at once.
e.g. true for arrays (e.g. wavetables), sets of strings (e.g. error messages), and some structs.
  • everything that uses is must be aware of progmem
(you could fetch data and hand it to something progmem-unaware, but see previous point)

There are helper functions that specifically deal with PROGMEM strings. This makes it easy to have RAM-cheap debug output, and also for things like logic for a string-based protocol (static stuff), sometimes lookup tables (but because of the speed hit only when it's complex to calculate), and such.


  • Read-only, so only for truly static data
  • Using this data means some special consideration/treatment, mostly because the actual data is not in the usual address space.
  • Fetching data to RAM is slower than things always in RAM
  • It only really save space when you store strings, arrays, or nontrivial structures, because you still need a pointer to know what to look up, which for primitives often saves nothing.
  • When you use only a few PROGMEM structures, the extra code (from *_P functions, or your own added code) may mean you see a larger increase in Flash use than a decrease in RAM. Which can still be worth it, but it's something to keep in mind.

Under the covers, it works by using storing pointers that just happen to be offsets within Flash, nor RAM. You can't dereference these as pointers yourself, because that would resolve them in RAM. You'll need to use the provided functions to actually get the implied data.

This means that regular functions that take pointers will happily accept PROGMEM pointers and do the wrong thing with them. For example, Serial.println( PSTR("Hello World One!\n") ); will compile and run, but will certainly not do what you intend.

You can use pointer arithmetic and such if you wish, though.

There are a few different use cases / ways you can choose to use this, including:

  • picking elements out of PROGMEM arrays (or characters our of strings) one at a time. (Sort of the general case, because it's the easiest way to avoid still needing the original amount of RAM)
    • usually means pgm_read_byte(addr), pgm_read_word(addr), pgm_read_dword(addr), or pgm_read_float(addr) (which don't map directly to the Arduino types, but close enough. You could write some helper functions.)
    • handy when you would use arrays/strings one at a time anyway, e.g. in serial communication
  • using the data while still in Flash (which is much like the element-at-a-time case, but slightly more abstracted using progmem-aware functions)(verify)
    • there are a bunch of analogues to the standard memory and string functions (...where they make sense)
      • these functions include memchr_P, memcmp_P, memcpy_P, memmem_P, memrchr_P, strcat_P, strchr_P, strchrnul_P, strcmp_P, strcpy_P, strcasecmp_P, strcasestr_P, strcspn_P, strlcat_P, strlcpy_P, strlen_P, strnlen_P, strncmp_P, strncasecmp_P, strncat_P, strncpy_P, strpbrk_P, strrchr_P, strsep_P, strspn_P, strstr_P
      • There are apparently also a few _PF (far-pointer) equivalents; see notes on the 64KB border
  • copying out part of the data into RAM ((look to memcpy_P() and such)
    • You could e.g. write code that uses many strings only has one of them stored in RAM at a time (which may save enough RAM, and means you can use this data as regular strings)
    • When you know at any one time you'll only ever need a small part of all the progmem data
    • When you want an alterable copy in RAM but want to initialize it from data stored in Flash
  • one-off strings - the macro PSTR returns a progmem-style pointer to the literal string that it forces into program space. Can be useful yo save some typing when you use the string exactly once (e.g. hardcoded output, debug writes) but note that that only really makes sense when you hand it to a function that knows how to deal with progmem strings (...you could assign the pointer to a variable, but in that case there's little difference between that and char name[] PROGMEM = "literalinit")

Other notes:

  • PROGMEM is an AVR-gcc thing. Other compilers may do it differently

See also:

Some example code

When you want to use PROGMEM strings for serial output (e.g. debug strings), a helper function like serial_write_P() below may be useful.

Some code experimenting:

#include <avr\pgmspace.h>
byte flash_list[16] PROGMEM = { 0x03,0x04,0x05,0x06,0xa0,0xa1,0xa2,0xa3,0xa4,0xff,0xfe,0xfe,0x80,0x06,0x06,0x01 };
const char flash_string[] PROGMEM = "This will be stored in flash\n";
const char *HW; //pointer set later (as you can't use PSTR() globablly)
int available_memory(int size=2048) { 
  // assuming ATmega328 as a default, so don't start checking for more than 2KB
  byte *buf;
  while ((buf = (byte *)malloc(--size)) == NULL) ;
  return size;
void serial_write_P(const char *data) {
  // Takes a program-space string, writes it out over Serial byte by byte
  byte t=pgm_read_byte(data);
  while(t != 0x00) {
      t = pgm_read_byte(++data);
void setup() {
  HW = PSTR("Hello World\n"); //you could use PSTR like this, 
                              //  though there's little point over a global PROGMEM string
void loop() {
  Serial.print("\n\nRAM: "); 
  // Use function that know how to use progmem-style pointers. 
  // Example for three styles of using such strings:
  serial_write_P( HW );            //assigned from PSTR
  serial_write_P( flash_string );  //progmem-style declaration
  serial_write_P( PSTR("And inline\n") );
  // Or copy to RAM before using it normally (here mallocced, but you may have your own ideas)
  char *tempmem = (char *)malloc( strlen_P(HW)+1 );
  // pick bytes out of that array
  for (int i=0;i<16;i++) {
    Serial.print( (byte)pgm_read_byte( &flash_list[i] ),  HEX );
    Serial.print( " " );

In this case, commenting almost all of the program out only has a few bytes of effect on RAM use (probably just the global pointers), but increase Flash use by more than 1KB because of the data and code you add (and is pulled in).

64K border

If you have more than 64KB of flash and the (bootloader plus) pgm data is larger than 64KB, things will break unless you know how to work with it.

Security on embedded platforms