You could buy a new Arduino Uno for every project you do, but that would be rather expensive and not very efficient. An Uno has lots of hardware you might not need.
Instead, you could use your Uno only for prototyping, and build your own custom Arduino for the actual product.
To me, it was a lot easier than I imagined.

The hardware

I learned what parts I needed and how to connect them from this article.
The only things you actually need for a working Arduino Uno are an ATMega328P-PU microcontroller (same as the one found on an ‘real’ Uno), a 4.7 kΩ or 10 kΩ resistor for the RESET pin, a programmer and a power source.
If you’d only use these components, the ATMega would run using its inbuilt 8MHz crystal. We can double its speed by adding a 16MHz crystal.

The list of needed parts is: (I’ve included links to where I bought them)

  • 1x ATMega328P-PU * (link)
  • 1x 16MHz crystal (link)
  • 2x 22pF capacitors – to connect to the crystal (link)
  • 1x 4.7kΩ resistor – as pull-up resistor for the RESET pin(link)
  • 1x 0.1uF decoupling capacitor – for de-noising the power source (link)
  • 1x A power source of at least 3.78V and at most 5.5V ** (link)
  • 1x Programmer (see below)
  • Breadboard or pcb, and some wires (link and link)

* ATMega328’s can be bought with or without Arduino bootloader. If you are planning to programm the microcontroller over serial, and don’t have a programmer, you need to buy one with bootloader preloaded. If you have a programmer, you can flash the bootloader to the ATMega328 yourself. More information about bootloaders in the section ‘Bootloading the ATMega’.
** I’ll use three 1.5V AA batteries. But keep in mind that if you use a different MHz oscillator, the required minimum voltage might differ.

Optionally, you can also buy the following:

  • 1x 3mm or 5mm LED and a ±10kΩ resistor
  • 1x Push button (link)
  • 1x 28 pin IC socket (e.g. this one)
  • A voltage regulator (to be able to connect the Arduino to a power source of more than 5V! I don’t cover this in this tutorial, but here’s a how-to: link)
  • 1x USB to Serial converter (for example a FT232 with cable or FT232 without cable)

The ATMega328 doesn’t have the pin numbers written on it, but they are as follows:

If you wish to print it out, here is a PDF: Pinouts. This pdf also includes the pinouts of ISP programmers.

Connections

Make the following connections:

  • + to VCC on the ATMega
    • + to AVCC on the ATMega
    • Ground to GND on the ATMega
    • Ground to the other GND on the ATMega
  • A 4.7kΩ resistor between + and RESET on the ATMega
  • The 0.1uF capacitor between + and Ground on the breadboard
  • The legs of the 16MHz crystal to the two crystal pins (PB6 and PB7) on the ATMega
  • Two times a 2.2pF capacitor between a crystal leg and Ground

And optionally make the following connections:

  • A LED and a (±1kΩ) resistor in series between + and Ground
  • A push button between the RESET pin and Ground
  • VCC on the FT232 to + on the breadboard
  • Ground on the FT232 to Ground on the breadboard
  • RX on the FT232 to TX on the ATMega
  • TX on the FT232 to RX on the ATMega

The ATMega328 will reset if the input to the RESET pin is LOW, which is why we need to add an pull-up resistor between + and RESET. It’s also why the reset button needs to be connected to RESET and ground.
From this stackexchange answer:

The reset line has an internal pull-up resistor, but if the environment is noisy it can be insufficient and reset can therefore occur sporadically. Refer to datasheet for value of pull-up resistor on specific devices. Connecting the RESET so that it is possible to enter both high-voltage programming and ordinary low level reset can be achieved by applying a pull-up resistor to the RESET line. This pull-up resistor makes sure that reset does not go low unintended. The pull-up resistor can in theory be of any size, but if the Atmel AVR should be programmed from e.g. STK500/AVRISP the pull-up should not be so strong that the programmer cannot activate RESET by draw the RESET line low. The recommended pull-up resistor is 4.7kΩ or larger when using STK500 for programming. For debugWIRE to function properly, the pull-up must not be smaller than 10kΩ.

The programmer

For setting the fuses, bootloading (see the ‘USB to serial’ section below), and if you’re not using a USB to serial converter also for uploading sketches, you’ll need some way to program the ATMega. There are two options: use an Arduino board as an AVR ISP (In-System Programmer) or use a programmer (like the USBasp, which is the one I use).
Here is a tutorial on how to use an Arduino Uno as AVR ISP.

Connecting the USBasp

Your USBasp will either come with a 6-pin or a 10-pin connector. Both pinouts are included in the pdf mentioned earlier. If you hold the 6 or 10 pin connector in front of you with the plastic tap facing upwards, the VCC pin is the pin leftmost in the bottom row.
Connecting the USBasp is very straightforward: RESET on the USBasp to RESET on the ATMega, MISO to MISO, etc. The USBasp provides 5V, so make sure you have any other power source disconnected when you connect the USBasp.

Fuses

If you now go ahead and flash the ATMega with your sketch, you might notice that it runs at half speed! Why?
The ATMega is still configured to use its inbuilt 8MHz crystal, but your sketch has been compiled for 16MHz use. So we’ll have to reconfigure the fuses to use a 16MHz external crystal.
The fuses of an AVR microcontroller (like our ATMega328) are 3 bytes (therfore 24 bits) of memory that don’t loose their value when power is turned of. The setting of these bits determine for example the brown-out voltage, whether the reset pin is enabled, and whether an external crystal is used. Find more information about fuses here.

Setting the fuse bits

We’ll use AVRDUDE for setting the fuses. You can either do that using the command line, or you can use a GUI, which is easier and safer. There’s enough choice of AVRDUDE GUI’s. I’m a Mac user and I use AVRFuses, if you’re a Windows or Linux user you can use for example AVRDUDDESS. The way these GUI’s work is mostly the same:

– When you open AVRFuses for the first time, the preferences pane will open. Select the path to AVRDUDE. On Mac OSX and if you have installed AVRDUDE yourself, the path would be something like /usr/local/bin/avrdude.
If you can’t find AVRDUDE there, you can use the AVRDUDE included with the Arduino IDE. Then the path would become: /Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin/avrdude.

– Next, select the programmer (in my case USBasp – if you use an Arduino as AVR ISP, select AVR ISP) and the port (USB). Then click ‘Close’.

-Select the correct device (ATMega328P) and go to the ‘Fuses’ tab.

– Now we need to know what fuse settings we need to apply:
The default settings for an Arduino Uno are: Low: 0xFF High: 0xDE Extended: 0x05.). You should use these settings if you want to use your ATMega with the Arduino bootloader. If you don’t need a bootloader, you should use these settings: Low: 0xFF High: 0xDF Extended: 0x05. If you want to further customize you fuse bits, here is a fuse calculator. But be careful with fuses, improper configuration may result in an microcontroller that is no longer programmable.

– Connect the programmer to the ATMega328 and plug in the programmer to the computer. Now you can finally hit the ‘Program’ button!

Note: if you get the error part m328p not found please refer to another article of mine for the solution.

With or without bootloader?

In this article I’ve mentioned the Arduino bootloader a couple of times in this article, and you might be wondering what it is and whether you need one on your 328.
A bootloader is a piece of software in the flash memory that allows you to program the ATMega over serial (USB) without needing a programmer.
But because it is stored in the same flash memory as your sketch, the maximum size of your sketch is reduced by 2 kB, which is a drawback.
If you don’t need the added luxury of not having to grab that USBasp every time you want to update your code (though you will need a USB to serial converter), and also don’t need all the memory available, it doesn’t really matter whether you have a bootloader or not.
But if you do want to add or remove the Arduino bootloader, here’s how:

Bootloading your ATMega

‘Bootloading’ simply means uploading a bootloader to a microcontroller. It’s really easy using the Arduino IDE, but you’ll need an external programmer (if you don’t have one, you can always buy an ATMega with the Arduino bootloader preloaded on it).
Select in the Tools menu the correct board (Uno) and programmer (e.g. USBasp or AVR ISP). Now select the ‘Burn Bootloader’ option. Done!

Removing the bootloader

If you need the 2kB of extra space, you may as well remove the bootloader. To do that, open AVRFuses (or your equivalent) and press ‘Erease device’ to, well, erase the memory. This will of course erase your sketch, and probably also the EEPROM.
Next, set the fuses to disable a bootloader (by setting the BOOTRST aka Boot reset vector enabled bit to 0), and programming the fuses again. I’ve given the correct fuse settings for with or without bootloader in the Fuses section of this article.

Uploading your sketch

With a programmer

Now it’s time to upload your sketch to the ATMega328. Open your Sketch in the Arduino IDE. Select the programmer you use in the menu Tools -> Programmer, e.g. ‘USBasp’ or ‘AVR ISP’. Make sure you have ‘Uno’ selected as board in Tools -> Board.
Next, select Upload using programmer from the menu to upload your sketch.

With a USB to serial converter

If you’ve connected a USB to serial converter with a bootloaded ATMega328, just use the conventional way to upload sketches: select the board (Uno), select the serial port and hit the Upload button.

Done!

Actually, I’ve left out one way to program a bootloaded ATMega328P-PU. Because if you have an Uno board with one on it, you can remove the ATMega from the Uno and replace it with yours. Then connect the Uno to your computer and program it the conventional way. When done, switch the ATMega’s again.

That’s it for now. I hope this article has been helpfull to you.
If you have any questions or suggestions, please leave a comment!