Sunday, 24 March 2013

Adventures with an ATTiny85

As a little diversion on the bumpy road to the 8bit world of the 6809, I've been playing about with some AVR ATTiny's, specifically the ATTiny85. Mostly to see what they can do and to see if they could be used for interfacing peripherals to an 8bit MPU.

These are amazing little beauties; 8Kbyte flash, a tiny amount of RAM, some EEPROM, 5 I/O pins, 4 ADCs, timers, a watchdog - all in a 8 pin package! Programmable with an ISP programmer, just like an ATMega. The biggest difference to its bigger brother is perhaps the lack of a UART.

As a test and learning exercise I've made an attempt at replicating the LED strobe effect on an Apple Mac; an LED that appears to slowly dim and brighten when the machine is in standby. This works by turning the LED on and off rapidly with differing amounts of on and off time to effect an apparent level of brightness. To make things more fun the speed with which the LED ramps between dim and bright is to be controlled by the analog to digital converter, which has a pot attached giving a full Vcc to 0V swing.

For completeness, the circuit below includes the ISP programmer header and MCU reset button. Even then it is still trivial. It seems to be harmless having an LED attached to the ISP lines; you do get to see pulses as the AVR is programmed though. I put the pot on the last ADC port, just because it requires abit more code to do so.


And here is a picture of the circuit on breadboard. I finally got fedup with my solution to the 10 pin IDC ISP header problem and soldered up a small piece of stripboard with an IDC pin header on one side and 10 PCB pins on the other. Much nicer then stuffing wires in the plug!


The software is simple enough. I had to play with the microsecond sleep values to get the right effect and it will be different for different LEDs. I'm fairly happy with the results, though a diffuser would mean the LED could go dimmer.  A more elegant solution would involve reading the ADC on an interrupt and using PWM mode outputs to strobe the LED. Perhaps if I get time I will.

#include <avr/io.h>
#include <util/delay.h>

void strobeled(int brightness);

int main(void)
{
    int b = 0; int up = 1;
   
    DDRB = 0x01;           /* make the LED pin an output */

    ADMUX = 0;
    ADMUX |= (1 << MUX0) | (1 << MUX1);    /* Use ADC3. */
    ADMUX |= (1 << ADLAR);    /* Left align. */
   
    ADCSRA |= (1 << ADATE);    /* Free running. */
    ADCSRA |= (1 << ADEN);  /* Enable DC. */
    ADCSRA |= (1 << ADSC);  /* Start converting. */

    while (1)
    {
        int step = (ADCH / 4) + 2;
       
        if (up)
        {
            b += step;
            if (b > 255)
            {
                b = 255; up = 0;
            }
        }
        else
        {
            b -= step;
            if (b < 0)
            {
                b = 0; up = 1;
            }
        }
        strobeled(b);
    }
    return 0;               /* never reached */
}

/* brighness is from 0 to 255. */
void strobeled(int brightness)
{
    PORTB = 1;
    _delay_us(brightness);
    PORTB = 0;
    _delay_us((255 - brightness) * 75);
}
 

Sadly I managed to lock myself out of two of my ATTiny85s by flashing in the wrong fuses values. I won't bin them though as its possible I could rescue them at a later date.

Refs:
In other news, I was annoyed with myself today to find a small mistake in the EEPROM programmer circuit. The low byte 74HC590 should have its pin 12 tied low. This is the carry-in pin. While it still works when I tested it without the tie on breadboard, its not ideal. Hopefully the circuit is not yet being manufsctured.... If it is then it might need a jump wire fix, or some other bodge.

No comments:

Post a Comment