Sunday, 9 April 2017

AVR atmega328 PORTC not working AVCC

One of the things I've personally struggled with, switching between Arduino and PIC is the way the Arduino IDE/language deals with digital pins. I like to use terms like PORTB.5 (the sixth pin on portB) rather than the Arduino-specific "pin 13". Of course you can use direct port access with Arduino, but the convention is to address each individual pin using the crazy sequential numbering system.

I've been working with a couple of guys on a custom "Arduino" board - in actual fact, it's little more than an ATMega328P AVR chip on a custom PCB; necessary only because we wanted to use 8 inputs, 8 outputs, SPI and a single, reversible pin for serial communication. At first we wanted to use an Arduino Pro Mini but no matter which way we tried to route things, we always ended up with pins 10-17 (yep, digital 17) as inputs with pull-up resistors enabled.

As most Arduino users know, on most Arduino boards, pin 13 has an onboard LED. Which means we can't use it as an input (since the inline resistor on the LED is pulling the input pin low despite the internal pull-up).

We also wanted to use a full-bridge rectifier to protect our little delicate AVR chips (they really don't like being powered up in reverse and can easily let out the blue magic smoke if you get the power and ground pins the wrong way around!)

So we figured that the best idea would be a custom board with an AVR atmega328, with connectors for our inputs and outputs (routed to the nearest pins on the mcu, not necessarily in the digital pin number sequence) and multiple connectors for power and ground connected not to the AVR chip, but to pins 2 and 3 of the rectifier. The output of the rectifier is then connected to the AVR chip (pin1 to ground, pin 4 to power). This gives us power sockets which can be connected without worrying about the polarity of the power source.

So everything appeared to be working just fine - the chip booted up and sent data over serial, irrespective of the polarity of the power supply. We tested all the inputs and could see that they were all working. But we were surprised to see that some of our outputs simply didn't work; the serial debug log indicated that the inputs were being read correctly, but the outputs simply failed to go high.

We'd moved some pins around, putting our inputs onto the lower numbered pins with outputs on pins 10-17 (in case we ever wanted to return to the Arduino pre-made boards and needed to use the i/o pin with an LED connected to it). But it turned out that every one of our output pins numbered above 13 was not working. That's A0 (digital pin 14) A1 (pin 15) A2 (pin 16) and A3 (pin 17).

We've used pins numbered 14 - 19 as digital i/o in the past; pins 20-21 can be set to digital inputs but not outputs, but we've had no trouble in the past making A2 light up an LED, for example. But there was something not right with our isolated AVR chip on our custom board....

It took some desoldering and a while testing for continuity before we discovered a hairline fracture in the trace connecting Vcc to the AVcc pins. It turns out that you need power connected to the AVcc pin for any of PORTC to work as digital outputs.

And it also turns out that PORTC happen to include the Arduino digital pins 14 (C0) through to 19 (C5). So without power on our AVcc pin, pins 14-19 fail to work as outputs.

A quick bit of tack-soldering and short length of wire and everything worked perfectly! So there you have it - if your digital pins 14-19 fail to work as outputs, double-check your connection between Vcc and AVcc; it's not just some useless "alternative" connection, it does actually serve a purpose!