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 0 | PC0 * | 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 1 | PC1 * | |
Analog 2 | PC2 * | |
Analog 3 | PC3 * | |
Analog 4 | PC4 * | |
Analog 5 | PC5 * | |
Digital 0 | PD0 | These two are used by the RS232 circuit, see the [light grey] pads in JP2. |
Digital 1 | PD1 | |
Digital 2 | PD2 * | At the top-right of the processor IC (U1) [green]. |
Digital 3 | PD3 | Used 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 4 | PD4 * | These three are all above or left of the processor [green]. |
Digital 5 | PD5 * | |
Digital 6 | PD6 * | |
Digital 7 | PD7 | These two are used by the push buttons, see the [yellow] pads in Figure 1. |
Digital 8 | PB0 | |
Digital 9 | PB1 * | These two are to the right of the right-most pushbutton, S3 [green]. |
Digital 10 | PB2 * | |
Digital 11 | PB3 | Used 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 12 | PB4 | At the programming header connector, JP3 pin 1 [brown], the square pad. |
Digital 13 | PB5 | At the programming header connector, JP3 pin 3 [brown]. |
AREF | AREF | Not highlighted in Figure 1, however it is available on the board, just below the “U1” designator. |
GND | Gnd | Several 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. |
5V | Vcc | If 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. |
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). |
2 | Rx of the ext. port | Serial data OUT from board (PD1/TXD). |
3 | Tx of the ext. port | Serial data IN to board (PD0/RXD). |
4 | Vcc | Can 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. |
5 | Ground | |
6 | Ground |
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:
- 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.
- Halve all of the values of the sole argument to all delayMicroseconds calls.
- 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.