Electronics project notes/Arduino and AVR notes

From Helpful
Jump to: navigation, search
This is for beginners and very much by a beginner. It's meant to try to cover hobbyist needs, and as a starting point to find out which may be the relevant details for you, not for definitive information.

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: IO and wired communication · localish communication · wireless (ISM RF, GSM, RFID, more) · 802.11 (WiFi) · 802.15 (including zigbee)


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 · Bluetooth serial · JY-MCU · DMX · ESC/POS notes

Audio notes: basic audio hacks · microphones · amps and speakers · device voltage and impedance, audio and otherwise ·

Less sorted: Common terms, useful basics, soldering · Microcontroller and computer platforms · Arduino and AVR notes · ESP series notes · Electronics notes/Phase Locked Loop notes · mounts, chip carriers, packages, connectors · signal reflection · pulse modulation · electricity and humans · Unsorted stuff


See also Category:Electronics.

Contents

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.


On time

Time is a hardware thing. Some projects don't care about time, or only need 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).

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

http://www.bildr.org/forum/viewtopic.php?f=17&t=386




See also:



Arduino 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 is now probably the most common board. The (older) Diecimila and (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 an Arduino is an Atmel AVR-series microcontroller. That AVR does most of the work, and in many ways the Arduino board around the AVR represents mostly 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):

  • Arduino Duemilanove (lit. '2009', introduced in 2009)
USB socket handled by FTDI's FT232RL

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.

  • Arduino Uno (introduced late 2010) is basically a sightly updated duemilanove:
USB handled via a simple uC (Atmega8U2) instead (which can potentially do more than the FTDI it replaces)
http://arduino.cc/en/Main/ArduinoBoardUno
http://www.ladyada.net/library/arduino/unofaq.html
  • Leonardo
ATmega32U4 (which speaks USB directly)


"I need more pins" boards:

  • Arduino Mega
Uses ATmega1280 (128KB flash, 8KB SRAM, 4KB EEPROM)
http://arduino.cc/en/Main/ArduinoBoardMega
  • Arduino Mega 2560 (introduced late 2010)
Mostly like Mega, but with 256KB flash instead of 128KB
Like Uno, USB socket handled via an Atmega8U2
http://arduino.cc/en/Main/ArduinoBoardMega2560
  • and e.g. the Due (also faster, see below)


Some more-specific-function boards:

  • Arduino BT
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
http://arduino.cc/en/Main/ArduinoBoardBluetooth
  • Arduino Fio
Set up for XBee, and LiPo charging
http://arduino.cc/en/Main/ArduinoBoardFio
  • Lilypad Arduino
http://arduino.cc/en/Main/ArduinoBoardLilyPad



Smaller boards:

  • Arduino Mini
ATmega168
also a crammed board (smaller than the nano, heh)
omits some components omitted, where 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
http://arduino.cc/en/Main/ArduinoBoardMini
  • Pro Mini
physically like the Mini, in idea like the Pro
ATmega168
3.3V and 8MHz,   or 5V and 16 MHz
http://arduino.cc/en/Main/ArduinoBoardProMini
  • Arduino Pro
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)
http://arduino.cc/en/Main/ArduinoBoardPro
  • Arduino Nano
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
http://arduino.cc/en/Main/ArduinoBoardNano
  • Various Lilypads
  • Lilypad USB
ATmega32U4 (note other Lilypads are Atmeta328 or Atmeta168)
  • Micro
  • ATmega32U4 (which speaks USB directly)
  • Pro Micro
ATmega32U4 (which speaks USB directly)

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


Faster boards

  • Genuino Zero
ARM Cortex-M0+ at 48 MHz (ATSAMD21G18)
32KB SRAM
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
board form factor like earlier arduinos
  • MKR Zero
comparable to Genuino, smaller and aimed a little more at audio
  • MKR 1000 WiFi
mostly like zero, but with wifi


  • Arduino Due (note: nothing to do with duemilenove)
ARM Cortex-M3 at 84MHz (AT91SAM3X8E)
64+32KB SRAM
512 KB flash
CPU is 3.3V, and its GPIO isn't 5V tolerant.
12-bit ADC (12 wired on the board)
2-channel 12-bit DAC
board form factor like earlier mega
  • Note: You may also care about the teensy 3 series


Since Arduino hardware design is open source, there are other manufacturers of Arduino boards, and a number of derivatives/variations of the official boards. 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), and some things that do little more than use the AVR, cheaper chinese-made variants, etc.

By now, there are many.


Many variants (and derivatives) use AVRs in their PDIP package, unless they're pressed for space.


Most AVRs seem to be rated to work fine up to 20MHz. Many still run at 16MHz, in part just to not break timing with older sketches that assume 16MHz clock. You can run them faster - or at a very specific rate, 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.

See also:



Notes that apply to various boards

FT232 and 8U2

Boards up to the Duemilenove used the FTDI FT232(RL) USB-to-serial chip.

Recent Arduino boards (Uno, Mega 2560) tend to use an Atmega8U2 to handle USB.


The 8U2 is programmable - by default it is just a USB-to-serial device, functionally almost identical to the FT232, but you can e.g. make it act like vaious other USB devices (mostly HID, like keyboard, mouse, joystick. Also some others, like MIDI, disk).

8U2-based boards also have a separate 3.3V regulator (150mA) (previously you got ~50mA from the FT232).


Coding

Intro

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

ADC

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 you can select a number of physical pins to sample from.

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 (or rather, 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 and accuracy

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

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 default)

The Arduino's defaults to the 125kHz/~9.6k setting. And is slightly slower than that (I've gotten ~8.9ksamples/sec) because of a little extra code around the actual sampling (some of which you can do a little faster with specific-case hardcoding).

The AVR specs mention that the ADC will only really give ~10 bit resolution under 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

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.


The implementation of analogRead() chooses a channel via ADMUX (and may wait a bit for a stable reading), so arguably the only reason to do that with 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;
}


Setting the rate is done via three bits in ADCSRA, see the relevant datasheet, or something like [4]


Setting the channel is done setting bits in ADMUX. (Note that ADMUX also controls the voltage reference, which you often don't want to change at the same time)

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


People suggest a delay beween ADMUX and starting the first sample. This seems to stem from two potential problems:

  • For high-impedance signals (datasheet mentions 10kOhm, but it may have to be higher to be noticeable) the sample-hold capacitor may not stabilize immediately after an ADMUX change
    • A small delay ought to be enough to work around that - 100us may be enough
  • When you use ADMUX, you may see the ADCH and ADCL from different channels/conversions . Ways to work around this:
    • Read ADCL before ADCH: reading ADCL locks both until ADCH is read and ensures both come from the same conversion.
    • delay 1ms (less is probably enough) to make sure the ADC has set both from the new conversion. Probably slower than...
    • poll for complete conversion (ADSC bit in ADCSR register; something like
      while ((ADCSRA & (1<<ADSC)) != 0) ;
      or
      while (bit_is_set(ADCSRA, ADSC)) ;
    • throw away the first read value (verify)


Readout in interrupt

In some cases where timing of your other code is very important, you figure it off, then get an ADC-specific interrupt handler to toggle a variable that you'll check for later.

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


Free-running mode

The ADC continuously does conversions, meant to be used with an interrupt handler called at the end of every conversion.

You would do this e.g. to get more conversion at a stricter interval.

http://yaab-arduino.blogspot.com/2015/02/fast-sampling-from-analog-input.html



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
    low=ADCL;
    high=ADCH;
    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

the range is ~138mV for a 130-degree-C range, which means it'll never really 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 AVG 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:

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 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

Serial-to-USB:

  • 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.:
               ('/dev/ttyUSB0','/dev/ttyUSB1',11,10,9,8,7,6,5,4,3,2,1,0)
            ...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 
 
    ret=None
    for try_port in try_ports:
        try:
            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
            pass 
    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

TWI (I2C)

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:


Libraries

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

Notes:

  • 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).

SPI

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

Interrupts

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)[5], which assigns a handler for an interrupt (...number).

where

  • 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[6].
  • interrupts are disabled while in an interrupt handler (by default)
This means everything that relies on interrupts:
PWM pauses
millis()
delay()
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
    cli()
    or
    noInterrupts()
    (difference?(verify)
  • re-enable globally with
    sei()
    or
    interrupts()
    (difference?(verify)

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:

Timers

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:

Timer0

  • 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()

Timer1

  • 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)

Timer2

  • 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 have a fourth timer (aimed at faster PWM, PLL (verify))


ATmega1280 and friends: also have a Timer3, Timer4, and Timer5

See also:

PWM

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 more capable, but for uniform behaviour across most boards (and because in some cases you also alter timekeeping and thereby various communication) Arduino libraries defaults to 8-bit PWM, a higher prescaler, and phase-correct on most pins making for max ~490Hz for many boards (~980 Hz on fast-mode pins, and some boards deviate[7]).

While various timers on various boards can go faster (even on Atmega328) and/or more precise, you have to configure this specifically. You can sometimes do this via Arduino libraries (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. [8]
  • obdev's v-usb-stack is a code-only implementation of a (low-speed) USB device. (see e.g. [9] 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)

(SoftwareSerial.h)

Can't go faster than 9600.

Baud rates of 1200 and lower noticeably disturb 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 SoftwareSerial, which was then further adapted into NewSoftSerial, so you probably want the latter)


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.

http://arduiniana.org/libraries/NewSoftSerial/


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.

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.

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


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 (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);
   else
      return ((int)&free_memory) - ((int)__brkval);
}


Downsides:

  • 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) ;
  free(buf);
  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?)

Downsides:

  • 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)

You can often get I2C EEPROMs for a few bucks per MBit (for example, the 24LC256 (32KByte) for under $2).


When you want more than a few kilobytes, SD cards tend to be a price-efficient option. SD by specs must speak SPI (some have mentioned that's optional in microSD, but specs don't seem to say that), so are easy enough to communiate with.

If you want to plug it into a PC and copy data off as files, then you want a FAT library. If you just want permanent memory on your AVR it's often easier to use the card as one big array of bytes.

You can buy SD slots, which aren't expensive, 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). SD slots are also seen 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)


See also:

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. [10]).

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).

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


There are currently two major designs variations of that more official board:

  • The older one
    • 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 [11])
    • 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)[12]. )
    • 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. [13], [14], [15])

(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 use that is a library that parses them, such as TinyGPS (~2500 bytes of program).

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)


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

Printing

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[17], 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) - 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 describes 1KB or 2KB of code in an Arduino's AVR's Flash space.

That flash region is locked after a bootloader is written, to avoid programs from accidentally overwriting it.

The bootloader runs when the Arduino is powered up, or is reset. It

  • sets up a few basic things (internal/external oscillator, )
  • pulses pin 13
  • waits a little, listening on the serial port for new programming - via Atmel's STK500 protocol
  • runs the last-stored program (or, if none has been sent, the bootloader)


Note that an USB arduino can be reset using the FTDI chip using the DTR line, which is why you don't have to do the quick press-reset-press-upload trick on them anymore (and why such an Arduino may reset when you connect the USB cable).

Since the reset-and-upload sequence is signaled from the computer, newer bootloaders also don't have to wait as long for upload, so will start running your program more immediately.


If your sketch looks for data at startup (e.g. config), you may want the PC side to wait a few seconds before starting to send, so that you are certain the sketch has started up.


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 (and can also be used to upload sketches faster)


You can program the AVR without a bootloader if you really need the last bit of Flash that the bootloader takes (note that writing optimized and lower-level code is often quite effective too).


AVR Programmers include (often connected via the ICSP header):

  • AVRISP mkII: USD ~35.00
  • USBtinyISP: USD ~25.00
  • Some very simple programmers, such as the ParallelProgrammer (though these days you'll need a USB-parallel adapter to have a parallel port. The cheapest come at around EUR10)
  • 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)

millis():

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

micros():

  • 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)




When you want to do things at regular intervals, the simplest code is probably something like:

unsigned long last_triggered=0; // or perhaps =millis() in setup. Makes the first trigger predictable
unsigned long now;
 
void loop() {
   now=millis();
   if ((now-last_triggered)>2000) { //2000 being the interval, in milliseconds
       last_triggered=now;
       //do stuff
   }
}

Notes:

  • This should work predictably enough around wraparound (while wait_until=millis()+interval; while (millis()<wait_until)-style code will glitch) - because when stored in the same-sized integer (a long), subtraction will overflow in the same way the timer does, and subtracted intervals should work fine (assuming the wraparound is purely the integer overflowing, and not coded to wrap earlier, as it apparently was in Arduino 0011 and earlier).
  • the above will shift over time. (More so if you do things that affect timing, such as using interrupts). If you want to avoid that shift and be as true to the internal timing as possible, last_triggered+=interval probably makes the most sense.
  • consider, in general, what happens if your 'do stuff' code takes long, particularly if longer than the interval. In the case of the above code (and in particular in the shiftless tweak), it would trigger continuously.
  • If you want a 'since we last completed', set last_triggered=millis() at the end of the 'do stuff' code, but this can be less regular.
  • this is only as accurate as millis() is - and you can disturb that by disturbing the timer it's based on, using interrupt handlers, and such.



The timing for millis() and micros() is not enough for long-term timekeeping. Don't count on an external oscillator doing much better than ~50 ppm(verify), which means it can be off by ~4 seconds per day. Some of that is constant and can be calibrated away once you measure it, but some of it is variable. Also, if something uses the Arduino's interrupts then the timers may get paused and the error will likely be larger.

Also, the internal oscillator is probably rather worse[18].


If you want more accurate timekeeping and/or a source for real time:

  • there are (tiny-battery-backed) clock modules, e.g. TWI / I2C ones. You'll still have to set them, and they may still be 10ppm (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. Note that GPS is one of the best time sources available in general (though using it to within less than a second takes a little more work and requires it to have 1PPS output).
  • You could buy a receiver for radio frequency time. This tends to mostly be a ~EUR10 antenna, you still have to do a bunch of receiving.




Arduino Time library is a convenience library that lets you set a time (from an external source) and counts on using the AVR timers.

This can help if you don't want to add real time hardware, but synchronizing it occasionally is easy enough (e.g. when you have a serial cable attached).

It also lets you get (and set) days, minutes, years, and such, which can be useful for some uses.

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:

  • SLEEP_MODE_IDLE
    • 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)
  • SLEEP_MODE_STANDBY
    • 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

Seeduino

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.

http://garden.seeedstudio.com/index.php?title=Seeeduino_Stalker_v2.0

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[[19]]. 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


Fuses

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 a little 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))


JY-MCU

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)


The point of reset is often a quick-and-dirty fix for code you think could ever get stuck, to not have it be stuck forever until a manual reset. 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 (The easiest way to ensure that is to intentionally do an infinite loop).


Configuring for interrupt is often used either

in combination with sleep sleep (e.g. letting you wake the AVR every few seconds, to save power).
for the interrupt handler you then also define (but note you may prefer the general timers 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)


Notes:

  • 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

On storing data in Flash (PROGMEM)

You can tell the compiler to compile read-only data to go only to Flash, instead of always being in RAM.

It's useful since RAM is typically a scarcer resource than flash space. Because it has to be fetched to RAM, it is both slower and doesn't help for entirely-monolithic data.

As such, PROGMEM data is primarily useful when you have a lot of data that you can use a piece at a time, i.e. that doesn't all have to be in RAM at the same time. This can be true for arrays, sets of strings, and some structs.


In ideal cases, you can do this one byte at a time, and save almost all of the space that would have been in RAM. In worse cases, you may need to fetch big chunks of data to hand to PROGMEM-unaware functions.


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.


Caveats:

  • 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) ;
  free(buf);
  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) {
      Serial.write(t);
      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
  Serial.begin(115200);
}
 
void loop() {
  Serial.print("\n\nRAM: "); 
  Serial.println(available_memory());
 
  // 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 );
  strcpy_P(tempmem,HW);
  Serial.write(tempmem);
  free(tempmem);
 
  // 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( " " );
  }
 
  delay(500);
}

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.

See also

See also: