Diy AT-Tiny Breakout Board/ Tutorial - DevBhoomi Robots

Home Top Ad

Responsive Ads Here

Post Top Ad

Your Ad Spot

Tuesday, September 18, 2018

Diy AT-Tiny Breakout Board/ Tutorial

One of the breakout boards was made breadboard friendly by attaching the 6 pin ICSP header and the I/O pin headers. In this configuration it fits neatly  over the central gap of most breadboards and makes it easier to experiment and prototype applications.
attiny_bo_built-upIn some upcoming projects I intend to embed some processing intelligence into small devices. The smaller Arduino boards are too big and expensive for these applications.
After some investigation, I settled on using the ATTiny series of 8 pin microcontrollers. These processors vary in capability (from a very low end) and all provide 6 I/O ports. Tools compatible with the Arduino ecosystem are also available.
As a first step, I designed a small breakout board for the SOP8 version of these MCUs.

My design goals were relatively simple:
  • Make the board as small as possible and still be practical to use.
  • Include sensibly sized solder pads for wires and/or other headers.
  • Include a programming interface on the board.
Minimizing size meant that the only component on the breakout board is the SOP8 package, so it was straightforward to create an Eagle schematic to fit requirements. As most, if not all, the 8 pin Atmel processors chips are pin compatible, this design also provides the flexibility to choose the MCU that suits the final application. The schematic and PCB files can be downloaded here.
attiny_bo_schematic
An important consideration with the SOP8 ICs was to have some way of programming the MCU. Unlike the DIP package, these cannot be mounted in a socket for removal and programming. At the cost of a making the PCB bigger, the board includes holes for a 6 pin ICSP header.
Finally, implementing the board in a system means that wires will need to be attached to it, so standard sized and spaced pads make this job easier.

The resulting PCB design was approximately the size of my thumb’s fingernail (dimensions on the left are in millimeters).
attiny_bo_pcb
As most PCB fabrication houses price to a minimum 5cm square size, I decided to panelize the board as 2×2. This was my first time panelizing so I Googled “how-to” and followed the instructions. The output yield improved from ten ‘boards’ to forty, which I expect will be lasting me a long time!

attiny_bo_panelized
attiny_bo_built-up


The PCBs were manufactured by DirtyPCBs. The panelized boards worked fine except for the silk screening – lesson learnt for next time I use this service.
The MCU ICs were soldered on before separating the individual boards, as the panelized board was easier to handle. The first batch of 4 boards are using ATTiny13A MCUs, as they are dirt cheap and provide enough capability for the simple applications I have planned.







The summarized results for code size (in bytes) are in the table on the left. As expected, the libraries do add some overhead. For this application this amounts to around 50 bytes of flash memory – not a huge amount in bytes but around 25% of the original code size and 5% of the available flash memory. I do expect, however, that the library overhead is a fixed amount and as a proportion of the total code it should reduce as the code size increases.
Once I had some hardware to test with, the next steps were to work out how to get a program onto the ATTiny and how to write efficient code. As 1kb of flash memory is not much to play with, space efficiency was a likely programming challenge!

The first step was to find a hardware core definition for the ATTiny13 that would work with the Arduino IDE. An internet search uncovered a few candidates, with the most recent evolutionary attempt (MicroCore) also looking like the most promising for my purposes as it supported the latest IDE versions. It was easy enough to load the board definition through the Arduino IDE by following the instructions at the release site.
attiny_benchmark
MicroCore also supports directly programming the ATTiny13 from the IDE through the programmer. In my case I was using the ArduinoAsISP setting and the shield I described in an earlier post.
Programming the ATTiny13 is a two step process. For a new device the fuses on the hardware need to be set, an easy process described in the MicroCore documentation and driven by a few choices in the IDE menu. The fuses are then written to the hardware as if it was loading a bootloader into the MCU.
To subsequently load compiled code, a simple ‘upload’ from the IDE does all the work. It could not be simpler and hats off to the MicroCore developers.

Benchmarking

Whilst MicroCore supports a useful subset of the Arduino libraries, I wanted to test the overhead imposed by using the libraries.
I decided to use a test project of 2 LEDs connected to 2 separate outputs and have the ATTiny flash them alternately on/off (ie, only one on at any time). To create a more ‘real world’ scenario for the types of applications I envisioned  for these MCUs, I added an optional switch to control the free running flash cycle.
This basic application was then coded using library functions (eg, digitalWrite()) in one version and direct port manipulation in another. For the latter case, one two variants were created – using loop() and using main(). All versions of this code can be found at the end of this article.
So what does this all mean? I probably can stick to the Arduino libraries and write portable code. If things get tight, however, I know I can gain at least 5% in program memory.

Code using libraries (Blink.ino)

/*
 Blink
 Alternately turns 2 LEDs on for one ON_TIME, then off for OFF_TIME.
 Uses Arduino library throughout.
*/

#define CONTROLLED 0

const uint8_t pinLED1 = 2;
const uint8_t pinLED2 = 1;
#if CONTROLLED
const uint8_t pinSw = 3;
#endif

const uint16_t ON_TIME = 500; // milliseconds
const uint16_t OFF_TIME = 500; // milliseconds

void setup() 
{
  // initialize digital pin as output
  pinMode(pinLED1, OUTPUT);
  pinMode(pinLED2, OUTPUT);

  // Set initial values for digital output (dfefault 0)
  digitalWrite(pinLED2, HIGH);
 
#if CONTROLLED
  // initialize switch input, pullup
  pinMode(pinSw, INPUT_PULLUP);
#endif
}

void loop() 
{
#if CONTROLLED
  if (digitalRead(pinSw) == LOW)
#endif
  {
    digitalWrite(pinLED1, HIGH);
    digitalWrite(pinLED2, LOW);
    delay(ON_TIME);
    digitalWrite(pinLED1, LOW);
    digitalWrite(pinLED2, HIGH);
    delay(OFF_TIME);
  }
}

Code using direct port writes (Blink_Direct.ino)

/*
 Blink_Direct
 Alternately turns 2 LEDs on for ON_TIME, then off for OFF_TIME.
 Uses direct port manipulation
*/

#define CONTROLLED 0

static const uint8_t pinLED1 = 2;
static const uint8_t pinLED2 = 1;
#if CONTROLLED
static const uint8_t pinSw = 3;
#endif

static const uint16_t ON_TIME = 500; // milliseconds
static const uint16_t OFF_TIME = 500; // milliseconds

void setup() 
{
  // initialize digital pin as output
  DDRB = _BV(pinLED1) | _BV(pinLED2);

  // Set initial values for digital output (dfefault 0)
  PORTB = _BV(pinLED2);

#if CONTROLLED
  // initialize switch input, pullup
  // input mode set by default
  PORTB |= _BV(pinSw);
#endif
}

void loop()
{
#if CONTROLLED
  if (!(PINB & _BV(pinSw)))
#endif
  {
    PINB = _BV(pinLED1) | _BV(pinLED2); // toggle the LEDs
    delay(ON_TIME); 
    PINB = _BV(pinLED1) | _BV(pinLED2); // toggle the LEDs
    delay(OFF_TIME);
  }
}

Code using direct port writes and main() (Blink_Direct_Main.ino)

/*
 Blink_Direct
 Alternately turns 2 LEDs on for ON_TIME, then off for OFF_TIME.
 Uses direct port manipulation and includes main()
*/

#define CONTROLLED 0

static const uint8_t pinLED1 = 2;
static const uint8_t pinLED2 = 1;
#if CONTROLLED
static const uint8_t pinSw = 3;
#endif

static const uint16_t ON_TIME = 500; // milliseconds
static const uint16_t OFF_TIME = 500; // milliseconds

void setup() 
{
  // initialize digital pin as output and initialise to zero
  DDRB = _BV(pinLED1) | _BV(pinLED2);
  PORTB = _BV(pinLED2);

#if CONTROLLED
  // initialize switch input, pullup
  // input mode set by default
  PORTB |= _BV(pinSw);
#endif
}

int main() 
{
 setup();

  while(1)
  {
#if CONTROLLED
    if (!(PINB & _BV(pinSw)))
#endif
    {
      PINB = _BV(pinLED1) | _BV(pinLED2); // toggle the LEDs
      delay(ON_TIME); // flash on time
      PINB = _BV(pinLED1) | _BV(pinLED2); // toggle the LEDs
      delay(OFF_TIME); // flash off time
    }
  }
}






Post Top Ad

Your Ad Spot