Saturday, October 06, 2012
Upgrading a Nanode to a ATmega1284 microcontroller
One of the problems encountered with Nanode, or Arduino is that sooner or later you come up against the physical limitations of the ATmega328.
With 32K of flash and 2K of RAM, the '328 is great for small projects - but when you start to do anything that uses a lot of RAM - such as lots of string handling, the 2K limit is quickly exhausted - and strange things start to happen in your code.
So this week, my challenge was to familiarise myself with the ATmega1284, and assess whether it might be a suitable upgrade for some of my projects.
Earlier in the week, I looked at using the real time clock and SD card on the Nanode RF to make a 4 channel real time datalogger, and it was whilst developing this code, that the RAM limitations of the '328 really started to cause problems.
Fortunately, there is a fairly simple upgrade to the '328, and this is the ATmega1284P. In a 40 pin DIP package it makes prototyping on breadboard easy, and with 16K of RAM, and 128K of flash it gives plenty of space for developing larger applications.
In addition to the extra RAM and Flash, it also has two more analogue input lines, a second UART, an extra INT pin, an option for a 32KHz crystal and 8 more I/O lines.
The I/O ports are arranged almost symmetrically around the 40 pin DIP, making the circuit layout very straightforward. For reference, the ATmega1284P summary datasheet is here.
An ATmega1284 on a breadboard
The first thing to do was to build a minimum system on a breadboard consisting of the microcontroller, the 16MHz crystal, the reset circuit and a FTDI programming connector.
Above is the simple breadboard layout, with the crystal, 22pF capacitors and reset circuit at the bottom centre of the picture and the FTDI compatible programming connector at the top right of the breadboard. This is the simplest possible circuit configuration (using 16MHz external crystal and remote RESET), and it leaves all the other remaining pins as I/O.
To begin to use this microcontroller, it first has to be bootloaded with an Arduino IDE compatible bootloader, and the files which describe it's registers and physical pinout have to be incorporated into the Arduino IDE. To do this, I followed Maniacbug's excellent tutorial, and it wasn't long before I was up and running simply Blinky code on the ATmega1284.
The almost symmetrical layout of the I/O ports makes of a logical arrangement of functions. There are four 8-bit ports Port A, Port B, Port C, and Port D. Unlike the ATmega328, there is no need to devote port pins to the 16MHz crystal or reset pin - so all 32 lines are available - compared to just 20 on the '328. Additionally, there are 8 analogue input pins on Port A, and these do not share the I2C functions - as on the '328, so if you need more analogue inputs and I2C, the '1284 offers an extra bonus.
To make the '1284 compatible with the Arduino IDE, it needs to have it's physical port pins mapped to the Arduino pin numbering system. There are many unique ways in which this could be done, but I personally would prefer to have a pin-mapping that is similar to the Arduino '328 - so the likes of RX, TX, INT0, INT1 are given their familiar Dig 0, Dig 1, Dig 2 Dig 3 numbering, and the SPI bus appears on the familiar Dig 10 - Dig 13 pins. This way you can remember what is where - without having to tie your mind in mental knots trying to port sketches and libraries from the '328 to the '1284.
Port A is the analogue input port. It appears on pins 40 down to 33 on the IC, with the related (and useful) AREF, GND and AVCC on the adjacent pins 32,31 and 30. It makes sense to bring all of these analogue pins out to a common connector. The order of A0 - A7 may appear in reverse to the Arduino user. This is not a problem as the pin mapping file can be used to reverse the order in which these pins are named. Unline the 10-bit ADC in the '328 - this ADC has an input stage with selectable gain of x1, x10 and x200, and can be used both single- ended or differentially. The high gain stage makes direct reading of thermocouples a possibility.
Pins 1 to 8 of the package are home to Port B, the upper half B4 - B7 has the hardware SPI lines present. As Nanode uses three SPI connected devices on board, it would be neat to cluster the chip select lines for these devices on the same port - so provisionally allocating Port B0 - Port B5 as CS lines seems sensible.
Port D is located on pins 14 to 21 of the package. It has our familiar pin functions like RX, TX INT0 and INT1, as well as four consecutive PWM pins on Port D4 - Port D7. If six pwm lines are required - for example driving 3 phase bridge circuits, there are a further pair of pwm channels on Port B3 and B4. There is a second UART available on Port D2 and Port D3 - if the INT0 and INT1 functions are not needed.
Port C runs along pins 22 to 29. First are the I2C pins SCL and SDA on package pins 22 and 23. These are useful for reading devices such as the real time clock on the Nanode. The ATmega1284P is also provided with a JTAG port on pins 24 to 27. If JTAG programming/debug is not needed, then these form a useful additional 4 general purpose I/O lines - but if you need JTAG, be careful what hardware you connect to them, which may interfere with the JTAG operation. You may have to disable the JTAG function in the fuse settings if you want these lines for general use.
The ATmega1284P has a second on chip oscillator - designed to work with a 32768Hz watch crystal - or other 32KHz input. These crystal pins are on pins 28 and 29. If you use a watch crystal to implement an RTC - it is possible to wake the microcontroller from sleep at regular intervals, whilst otherwise keeping it in low power mode.
In addition to the rich peripheral set accessed by the ports, the ATmega1284P also has an additional 16 bit timer, and 4K of E2 non-volatile memory.
Connecting it up to a Nanode.
Having made up the simple breadboard, it was time to connect it up to a Nanode.
Most of the Nanode ICs are connected to the microcontroller using the SPI bus, and so the MOSI, MISO, SCK and any chip select lines would be needed. The RTC clock/calendar IC on the Nanode uses the I2C bus, so SCL and SDA would be needed too. Finally the Nanode board would need to be powered, and provide a reset so +5V, 0V and RESET were wired back to the breadboard.
During tests it was found that the ATmega1284 would run at 3V3, but not program successfully at 3V3. It was therefore decided to run the '1284 at 5V, and use potential divider resistors on all the output lines between the '1284 and the Nanode RF board where almost all of the hardware runs on a 3V3 supply i.e. the ENC28J60, the RFM12 and the SDcard.
Dividers were thus needed on MOSI, SCK, and the three chip selects ENC28J60_CS, RFM12_CS and SDcard_CS. The RTC connected to the I2C bus is 5V tolerant and so no divider was needed.
In the top photograph, the lower breadboard made from clear plastic has these potential divider resistors - and some diagnostic LEDs. The Nanode Rf with the '328 microcontroller removed is on the right.
The next blog post in this series will have links to code developed to run the Nanode RF using the ATmega1284.