Using the ChronulatorSMD as an Arduino

Tessellated Circuits: Home => Old Home => The Chronulator SMD => Arduino usage  

Introduction.

Starting with a ChronulatorSMD running Chronulator code, very little has to be done to run an Arduino program. This is because the original Chronulator was based on the Arduino software and processor. The SMD version of the Chronulator has had some additions so that all the I/O pins that are used by an Arduino are available.

Steps needed.

First, look at the pins that are needed for your Arduino application. There are 6 (of the Arduino's 14) digital I/O pins that are “free and clear” and all 6 analog pins are available with no modifications needed. Look at Table 1 and Figure 1 to locate the I/O pads. In Table 1 the 12 easiest to use are marked with an asterisk (*). Of these, the analog pins are nicely grouped however the digital ones are scattered about. 4 pins are used by the Chronulator circuitry, two to drive the current sources and two to sense the push buttons. If you can avoid using three of these (Digital 3 (PD3), Digital 7 (PD7) and Digital 8 (PB0)) then it is likely that no modifications need to be made to the board except soldering in either headers or wires to the needed I/O pads.

Note that this is not meant to imply that an Arduino shield can be used: to use a shield would require that a special PCB be designed to adapt the ChronulatorSMD to the particular header pin pattern of the Arduino.

Table 1.
Arduino pin
name.
ChronulatorSMD
& processor pin name.
ChronulatorSMD's location. Colours are referenced to Figure 1, below.
Analog 0PC0 *All 6 Analog inputs are part of the group of pads just below the right-most mounting hole. See the [purple] coloured pads in Figure 1.
Analog 1PC1 *
Analog 2PC2 *
Analog 3PC3 *
Analog 4PC4 *
Analog 5PC5 *

Digital 0PD0These two are used by the RS232 circuit, see the [light grey] pads in JP2.
Digital 1PD1
Digital 2PD2 *At the top-right of the processor IC (U1) [green].
Digital 3PD3Used as the PWMed hours output for the Chronulator software [blue, top of JP1]. SJ3 must be bridged to bring this out instead of the PWM current.
Digital 4PD4 *These three are all above or left of the processor [green].
Digital 5PD5 *
Digital 6PD6 *
Digital 7PD7These two are used by the push buttons, see the [yellow] pads in Figure 1.
Digital 8PB0
Digital 9PB1 *These two are to the right of the right-most pushbutton, S3 [green].
Digital 10PB2 *
Digital 11PB3Used as the minutes PWM output for the Chronulator software, available at JP1-4 [blue], and at the programming header pin4 [blue as well]. To access it at JP1, SJ4 has to be jumpered correctly, however to access it at the programming header this does not matter.
Digital 12PB4At the programming header connector, JP3 pin 1 [brown], the square pad.
Digital 13PB5At the programming header connector, JP3 pin 3 [brown].

AREFAREFNot highlighted in Figure 1, however it is available on the board, just below the “U1” designator.
GNDGndSeveral pads exist where the board's ground can be connected to.
RESET---No expilcit pad was added for the reset, however it can be picked up at the programming connector, pin 5 (lower right) or at the via which is just below the “PD2” label.
3V3---There is no on-board 5 V to 3.3 V regulator as there is on an Arduino. You could, however, power your Chronulator from a 3.3 V supply.
5VVccIf you are powering your Chronulator from 5 V then this is available at the power supply input
VIN---In an Arduino this is the same as the voltage at the power jack, less a diode drop. There is not a direct equivalent here.
Figure 1. I/O pad locations.

Second, the hook-up to your PC will be via a USB serial adaptor, just like is required for the Mini and Nano Arduino boards. Header JP2 is the connector for this. Table 2 shows the pin definitions for this header.

To use the Arduino software on your PC with the board you must select the correct board type under the Board option of the tools menu, see the third step, below.

Table 2.
JP2-Function.Direction
1 (the square pad)Reset (from DTR of ext. port) Input (to PC6/Reset via a series capacitor).
2Rx of the ext. portSerial data OUT from board (PD1/TXD).
3Tx of the ext. portSerial data IN to board (PD0/RXD).
4VccCan be used to provide 5 V power to the board from the USB to serial adapter. If the board is already powered then likely this should not be connected.
5Ground
6Ground

Third, ensure that the Arduino code knows about the slower clock used by the Chronulators. To do this, make a change to the boards.txt file which is found in the arduino<version>/hardware/arduino directory. See Listing 1, below for the changes. The first block of code that is shown below should match a block that is there already, one that defines a Lilypad with the same type of processor that the Chronulators use. The second block is my modification of the first: all changes are highlighted with red. The name you use in the first line is optional: it will appear under the Tools->Board menu item once the change has been saved and the Arduino code (re)started. (This is from version 1.0.1 of the Arduino code in case it matters.)

##############################################################

lilypad.name=LilyPad Arduino w/ ATmega168

lilypad.upload.protocol=arduino
lilypad.upload.maximum_size=14336
lilypad.upload.speed=19200

lilypad.bootloader.low_fuses=0xe2
lilypad.bootloader.high_fuses=0xdd
lilypad.bootloader.extended_fuses=0x00
lilypad.bootloader.path=lilypad
lilypad.bootloader.file=LilyPadBOOT_168.hex
lilypad.bootloader.unlock_bits=0x3F
lilypad.bootloader.lock_bits=0x0F

lilypad.build.mcu=atmega168
lilypad.build.f_cpu=8000000L
lilypad.build.core=arduino
lilypad.build.variant=standard

##############################################################

chronulator.name=ChronulatorSMD w/ ATmega168

chronulator.upload.protocol=arduino
chronulator.upload.maximum_size=14336
chronulator.upload.speed=19200

chronulator.bootloader.low_fuses=0xe2
chronulator.bootloader.high_fuses=0xdd
chronulator.bootloader.extended_fuses=0x00
chronulator.bootloader.path=lilypad
chronulator.bootloader.file=LilyPadBOOT_168.hex
chronulator.bootloader.unlock_bits=0x3F
chronulator.bootloader.lock_bits=0x0F

chronulator.build.mcu=atmega168
chronulator.build.f_cpu=4000000L
chronulator.build.core=arduino
chronulator.build.variant=standard

Listing 1. Changes to boards.txt.


Warning. There is a problem with changing to a 4 MHz clock since no standard Arduino boards use 4 MHz. Specifically, the delayMicroseconds function produces delays that are half of what they should be. This can be worked around or circumvented by doing one and only one of the following:

  1. Remove the 32 kHz crystal at X1 and substitute an 8 MHz crystal at X1A. If you do this however, you will also have to use a different bootloader and that will have to be programmed into the processor using a programmer.
  2. Halve all of the values of the sole argument to all delayMicroseconds calls.
  3. Improve the code in wiring.c to handle a 4 MHz clock. The following (listing 2) might do the trick (it has not been tested yet, so beware!): it is meant to replace all the code defining the delayMicroseconds routine in wiring.c (found at arduino<version>/hardware/ arduino/cores/arduino). Note that the software, which this is just a snippet from, is GNU licensed.
/* Delay for the given number of microseconds. Handles 20, 16, 8 or 4 MHz clock */
/* The 20 MHz change was in V1.0.1, the 4 MHz is my unofficial change.          */
void delayMicroseconds(unsigned int us)
{
	// calling avrlib's delay_us() function with low values (e.g. 1 or
	// 2 microseconds) gives delays longer than desired.
	//delay_us(us);
#if F_CPU >= 20000000L
	// for the 20 MHz clock on rare Arduino boards

	// for a one-microsecond delay, simply wait 2 cycle and return. The
	// overhead of the function call yields a delay of exactly 1 microsecond.
	__asm__ __volatile__ (
		"nop" "\n\t"
		"nop"); //just waiting 2 cycle
	if (--us == 0)
		return;

	// the following loop takes a 1/5 of a microsecond (4 cycles)
	// per iteration, so execute it five times for each microsecond of
	// delay requested.
	us = (us<<2) + us; // x5 us

	// account for the time taken in the preceeding commands.
	us -= 2;

#elif F_CPU >= 16000000L
	// for the 16 MHz clock on most Arduino boards

	// for a one-microsecond delay, simply return.  the overhead
	// of the function call yields a delay of approximately 1 1/8 us.
	if (--us == 0)
		return;

	// the following loop takes a quarter of a microsecond (4 cycles)
	// per iteration, so execute it four times for each microsecond of
	// delay requested.
	us <<= 2;

	// account for the time taken in the preceeding commands.
	us -= 2;
#elif F_CPU >= 8000000L
	// for the 8 MHz internal clock on the ATmega168

	// for a one- or two-microsecond delay, simply return.  the overhead of
	// the function calls takes more than two microseconds.  can't just
	// subtract two, since us is unsigned; we'd overflow.
	if (--us == 0)
		return;
	if (--us == 0)
		return;

	// the following _asm_ loop takes 4 cycles (half a microsecond at 8 MHz)
	// per iteration, so execute it twice for each microsecond of
	// delay requested.
	us <<= 1;

	// partially compensate for the time taken by the preceeding commands.
	// we can't subtract any more than this or we'd overflow w/ small delays.
	us--;
#else
	// For the 4 MHz case:  Do not change us.

	// for a 1 microsecond delay, simply return.  The overhead of
	// the function calls takes more than four microseconds.
	if (--us == 0)
		return;

	// the following _asm_ loop takes 4 cycles (one microsecond at 4MHz)
	// per iteration, so execute once for every microsecond of the argument.

#endif

	// busy wait
	__asm__ __volatile__ (
		"1: sbiw %0,1" "\n\t" // 2 cycles
		"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
	);
}

Listing 2. Suggested Arduino code change to fix delayMicroseconds() for 4 MHz clock.