Programming the 328

Ok, after my very lengthy previous post, the problem was finally solved.

So now I come back with a new question :stuck_out_tongue: This one should be a really quick answer.

Following this http://www.arduino.cc/en/Hacking/PinMapping, I now have 20 I/O pins to use from the 328. However, I need 22... What are two more pins I can use (I'm pretty sure I can use pins 9 and 10...), and what do I write in the programming to tell them to be used?

I've already made a test board, to make sure that all the pins work as digital outputs (0-19 on arduino software, pins 2-6, 11-19, and 23-28 on the 328) (I need two more digital I/O pins)

"Ok, after my very lengthy previous post, the problem was finally solved." How so?

You can use PB6 & PB7, but you have to run from internal oscillator. I am not familiar with changing the fuses to do so.

Port B (PB7:0) XTAL1/XTAL2/TOSC1/TOSC2
Port B is an 8-bit bi-directional I/O port with internal pull-up resistors (selected for each bit). The
Port B output buffers have symmetrical drive characteristics with both high sink and source
capability. As inputs, Port B pins that are externally pulled low will source current if the pull-up
resistors are activated. The Port B pins are tri-stated when a reset condition becomes active,
even if the clock is not running.
Depending on the clock selection fuse settings, PB6 can be used as input to the inverting Oscillator
amplifier and input to the internal clock operating circuit.
Depending on the clock selection fuse settings, PB7 can be used as output from the inverting
Oscillator amplifier.
If the Internal Calibrated RC Oscillator is used as chip clock source, PB7...6 is used as
TOSC2...1 input for the Asynchronous Timer/Counter2 if the AS2 bit in ASSR is set.
The various special features of Port B are elaborated in ”Alternate Functions of Port B” on page
84 and ”System Clock and Clock Options” on page 27.

As Crossroads says, you need to set the fuse bits to use the internal oscillator (a virgin atmega328p is already set this way, however it is also set to prescale the 8MHz clock by 8, giving you a 1MHz clock). The pins are Port B bits 6 and 7 as shown on the pin mapping. To access them, see Arduino Reference - Arduino Reference.

Alternatively, use the 32-pin SMT version of the chip, which gives you 2 extra port C pins without sacrificing the clock pins.

There is a section on programming the fuse bytes in my blog at Prototyping small embedded projects with Arduino | David Crocker's Solutions blog.

"32-pin SMT version of the chip, which gives you 2 extra port C pins without sacrificing the clock pins"

Those are analog mux input pins only.

In either case, I believe you need to modify pins_arduino.h to add the pins to the list of mapped pins.

CrossRoads:
"32-pin SMT version of the chip, which gives you 2 extra port C pins without sacrificing the clock pins"

Those are analog mux input pins only.

Ah - I see from the data sheet you are right - I was assuming they could be reassigned as digital i/o pins like the other analog pins.

CrossRoads:
In either case, I believe you need to modify pins_arduino.h to add the pins to the list of mapped pins.

Only if you want to call pinMode, digitalWrite etc. - not if you access the port registers directly.

@ Crossroads: Check the last page here: http://arduino.cc/forum/index.php/topic,70199.90.html

Essentially, all the chips that I was trying were screwed up in some way. The first one I probably buggered myself, the second as well, the third one I tried just didnt work (it was brand new, and I only tested it once using the command window, and it gave the same errors as the first two, and the fourth one just worked. Haven't tried a fifth one yet, I just need one for now to move on to the next stage of testing.

I'll test out the suggestions, and then edit this post with results.

I personally added 4 pins to the X3 connecter next to the FTDI chip, jumper 4 wires over to the ICSP header (so the FTDI controls MISO, MOSI, SCK , Reset), and program blank parts installed in onboard socket using the "Burnnig bootloader without AVR" method. Worked great, no jumpering over to a breadboard needed.
I can post the link for that when I get home.
I would recommend that seeing as you have a Duemilanove.
Just follow the software setup steps carefully.
Or spend $13 and get an AVR ISP programmer, will make your life a lot easier. I use one from mdfly.com.

Link for modified Duemillanove as bootloader

http://www.geocities.jp/arduino_diecimila/bootloader/index_en.html

Thank you for that link, but it looks fantastically confusing. I just spent the past month (ish) trying to get the arduino to work as a bootloader, and I (with the gracious help of this forum (coding badly and DC, I'm looking at you) finally got it working. I'm not going to learn another way of doing it :stuck_out_tongue: Not yet at least.

It was a lot of little steps. I just followed along, step by step, worked great when all done.

Looking through the Arduino Port manipulation page, I came across this: "PORTB maps to Arduino digital pins 8 to 13 The two high bits (6 & 7) map to the crystal pins and are not usable" Does that mean I can't use the crystal pins?

Also, the clock is prescaled to 1Mhz, can I leave it at that? From my understanding, you just need a higher Mhz if you want more precise timing sequences, but I don't need it that precise, so can I leave it at 1Mhz?

It was said that I need to define the pins in pins_arduino.h, do I just edit it as a text file then resave it? Or should I make a new library and include it in the sketch.

You can use the crystal pins, you have to use the internal oscillator, and add some lines to pins_arduino.h.
May need to download via ICSP also at that point, not sure if bootloader will support correct baud rates for serial download.

I posted recently about where I thought pins_arduino.h needed update to use the extra analog mux inputs, would need similar changes for using the xtal pins as I/O. Let me see if I can find that thread ...

Here we go

Do similar, but instead of adding the A6/A7 pins, add the crystal pins.

Awesome, Thank you very much. I'm off to work now, but I'll be sure to check it out when I get home.

Ok, so I've been looking through this and have a few questions.

  • Do I modify pins_arduino.h or .c?

  • The other person was working on modifying pins A6 and A7, which you said can only be used as analogue inputs. From what you've said earlier, I understand that they can be used as an input, or an output, depending on the fuse settings. Correct? Or can they just be used as whatever I tell them to in changing the file

A6 & A7 are analog inputs Only. They feed into the analog multiplexer:

"ADC7:6 (TQFP and QFN/MLF Package Only)
In the TQFP and QFN/MLF package, ADC7:6 serve as analog inputs to the A/D converter.
These pins are powered from the analog supply and serve as 10-bit ADC channels."

Modify pins_arduino.c. I may typed ...h by mistake.

Ok so I modified the file following what you said, (added the PC's, added the NOT_A_TIMER's, and added the BV()'s) but I just did it following the steps, so if I wanted to use A6 and A7. I was looking through the file, and found these instances that are refering to PB6 and PB7, so I'm assuming that they are telling me what to change... But I have no idea what to do.

const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
// PIN IN PORT
...
_BV( 6 ) , // PB 6 ** 12 ** PWM12
_BV( 7 ) , // PB 7 ** 13 ** PWM13

And

const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
// TIMERS
...
TIMER1B , // PB 6 ** 12 ** PWM12
TIMER0A , // PB 7 ** 13 ** PWM13

The ... meaning that there is a bunch of stuff inbetween the header and the reference to PB 6 or 7

I think those references are for the 1280/2560 section, going by the PWM comments.
You want to add the port stuff in the 168 area farther down, where there are just the 20 I/O pins listed.

Here is the information about the 168 (that I could find). Its all at the bottom:

const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
NOT_ON_TIMER, /* 0 - port D /
NOT_ON_TIMER,
NOT_ON_TIMER,
// on the ATmega168, digital pin 3 has hardware pwm
#if defined(AVR_ATmega8)
NOT_ON_TIMER,
#else
TIMER2B,
#endif
NOT_ON_TIMER,
// on the ATmega168, digital pins 5 and 6 have hardware pwm
#if defined(AVR_ATmega8)
NOT_ON_TIMER,
NOT_ON_TIMER,
#else
TIMER0B,
TIMER0A,
#endif
NOT_ON_TIMER,
NOT_ON_TIMER, /
8 - port B /
TIMER1A,
TIMER1B,
#if defined(AVR_ATmega8)
TIMER2,
#else
TIMER2A,
#endif
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER, /
14 - port C */
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
};
#endif

So do I add the PC's, not_a_timer's, and the BV's? Or do I change something different....

Sorry if I'm missing something important, this is all new to me.

You need to go farther up in the file, where I added some notes:
<<<< add after here
I've only done this once also, was not easy to figure out, and no guarantee that this correct either.

#else
// these arrays map port names (e.g. port B) to the
// appropriate addresses for various functions (e.g. reading
// and writing)
const uint16_t PROGMEM port_to_mode_PGM[] = {
	NOT_A_PORT,
	NOT_A_PORT,
	&DDRB,
	&DDRC,
	&DDRD,
};

const uint16_t PROGMEM port_to_output_PGM[] = {
	NOT_A_PORT,
	NOT_A_PORT,
	&PORTB,
	&PORTC,
	&PORTD,
};

const uint16_t PROGMEM port_to_input_PGM[] = {
	NOT_A_PORT,
	NOT_A_PORT,
	&PINB,
	&PINC,
	&PIND,
};

const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
	PD, /* 0 */
	PD,
	PD,
	PD,
	PD,
	PD,
	PD,
	PD,
	PB, /* 8 */
	PB,
	PB,
	PB,
	PB,
	PB,
	PC, /* 14 */
	PC,
	PC,
	PC,
	PC,
	PC, <<<< add after here
};

const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
	_BV(0), /* 0, port D */
	_BV(1),
	_BV(2),
	_BV(3),
	_BV(4),
	_BV(5),
	_BV(6),
	_BV(7),
	_BV(0), /* 8, port B */
	_BV(1),
	_BV(2),
	_BV(3),
	_BV(4),
	_BV(5),
	_BV(0), /* 14, port C */
	_BV(1),
	_BV(2),
	_BV(3),
	_BV(4),
	_BV(5),   <<<< add them after here also, address as D20/21?
};

const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
	NOT_ON_TIMER, /* 0 - port D */
	NOT_ON_TIMER,
	NOT_ON_TIMER,
	// on the ATmega168, digital pin 3 has hardware pwm
#if defined(__AVR_ATmega8__)
	NOT_ON_TIMER,
#else
	TIMER2B,
#endif
	NOT_ON_TIMER,
	// on the ATmega168, digital pins 5 and 6 have hardware pwm
#if defined(__AVR_ATmega8__)
	NOT_ON_TIMER,
	NOT_ON_TIMER,
#else
	TIMER0B,
	TIMER0A,
#endif
	NOT_ON_TIMER,
	NOT_ON_TIMER, /* 8 - port B */
	TIMER1A,
	TIMER1B,
#if defined(__AVR_ATmega8__)
	TIMER2,
#else
	TIMER2A,
#endif
	NOT_ON_TIMER,
	NOT_ON_TIMER,
	NOT_ON_TIMER,
	NOT_ON_TIMER, /* 14 - port C */
	NOT_ON_TIMER,
	NOT_ON_TIMER,
	NOT_ON_TIMER,
	NOT_ON_TIMER,   <<<< need to add more of these as well
};
#endif