In voorbereidingStarten met de ATtiny2313

Ledlamp in werking

Gerelateerde pagina's: AVR Butterfly demo board met de ATmega, vuurvliegjes als een toepassing van de ATtiny, en verder de ATtiny software en hardware pagina's.

Probleemp: een I²C-chip (PCA9634) die ik graag als RGB powerLED-controller wilde gebruiken (als uitbreiding voor mijn Rabbit, en om te spelen met I²C op mijn omgebouwde NSLU2) is als hobbyist haast niet betaalbaar verkrijgbaar, in ieder geval niet in een behuizing die soldeerbaar is; pootjes minder als 1 mm apart ga ik niet zelf zitten hobbyen... Wat te doen? Kan ik dit probleem op een andere manier oplossen?

Als ik nu eens een goedkope microcontroller neem, en zelf de functionaliteit daarin programmeer? Flexibel, ook voor andere zaken inzetbaar, en effectief nog goedkoper ook. Zo gezegd, zo gedaan? Wel, er komt natuurlijk wel een aantal extra stappen bij kijken:

  • De chip moet goed verkrijgbaar (en betaalbaar) en hanteerbaar zijn
  • De chip moet voldoende mogelijkheden hebben; hier I²C slave en PWM (Pulse Width Modulation) uitgangen
  • Je hebt een programmer nodig
  • Je hebt ontwikkeltools nodig, liefst C/C++

Lastige chips zijn wel te bestellen, maar wel met forse bestel- en verzendkosten (20..30€) etc. Een mogelijke leverancier voor wat ik zocht is DigiKey; die leveren ook aan particulieren. Alleen, de behuizing die ik zocht was er niet, en een TSSOP20-behuizing is mij te klein...

Al met al is de keuze gevallen op de Atmel ATtiny2313. Een goed verkrijgbare microcontroller met FLASH geheugen, in een eenvoudig verwerkbare 20-pins DIL behuizing. Online gekocht, bij Conrad €2.14 (#154166-89); voor iets meer geld heb je bijvoorbeeld de ATmega ATMEG8535-16PU met 8-kanaals A/D etc (#154257-89, maar was voor mij niet nodig; ooit in een ander project?). Veel informatie op internet. Past zo op de standaard gaatjesprint die ik gebruik voor prototypen.

Een AVR-programmer voor de seriële poort is zo gemaakt, en de tiny2313 is 'in-circuit'-programmeerbaar, dus je hoeft de chip niet eens uit je schakeling te halen om de functionaliteit te veranderen.

De Atmel ATtiny2313

ATtiny2313 pinoutDe ATtiny2313 is (als opvolger/vervanger van de AT90S2313) een prima AVR microcontroller voor beginners. Een overzichtje van de eigenschappen en functies van de ATtiny2313; zie ook de uitgebreide documentatie in de datasheet (PDF 2MB):

  • 8-bit AVR architectuur (1..2 cycles/instruction; Harvard memory arch)
  • 2kB flash programma geheugen, 10.000x schrijfbaar
  • 128 bytes ram geheugen
  • 128 bytes eeprom geheugen, 100.000x schrijfbaar
  • Seriële poorten, timers, counters, etc
  • 4 PWM kanalen (Puls Breedte Modultatie)
  • I²C (TWI) slave en master mogelijkheid
  • 20 pins, waarvan 18 als I/O te gebruiken
  • maximaal 20 miljoen instructies per seconde bij een 20MHz klok
  • interne oscillator, geen extern kristal noodzakelijk (maar kan wel)
  • Voeding 2.7 (1.8 voor V versie) tot 5.5V, dus werkt ook op twee batterijen

De programmer

De programmer-componenten

1x Sub-D connector, 9-polig
3x weerstand 4K7
1x weerstand 10K
1x weerstand 33K
1x transistor BC549C
1x diode 1N4148
2x zener 5V1
1x 20-polig IC voetje
1x condensator 0.1 uF
1x condensator 33 uF/16V
1x 3-polige header
1x 2x5-polige header
gaatjesprint met eilandjes

Ik heb gekozen voor een low-cost programmer voor gebruik met een seriële poort. Erg low-cost (denk minder dan € 10, en geen IC's nodig); volgens het web veiliger voor de computer dan de parallelle poort uitvoering, en zo in elkaar te zetten met standaard verkrijgbare onderdelen; in een uurtje had ik mijn programmer compleet.

Mijn versie is gebaseerd op het schema van de seriële programmer AVR programmer Olimex AVR-PG1, en de vergelijkbare AVR programmer van electronics-diy. Paar kleine modificaties, met name haal ik de 5 Volt uit de USB-poort van mijn laptop, dus een USB-kabeltje gehalveerd en hiervan de ground en +5V aangesloten op de 3-polige header, zodat de tiny2313 voeding heeft en ook zonder seriële kabel programma'tjes kan uitvoeren. En ik heb naast de 2x5-pins ISP (In-System Programming) header een 20-polig IC-voetje geplaatst (Vcc op pin 20, GND op pin 10, reset pin 1, etc), kan dus zowel losse 2313's als bordjes met ISP (in-system programming) programmeren. Zie de foto hieronder, met al een ATtiny in het 20-pins voetje (opmerking: enkele SMD-weerstanden zitten aan de onderkant).

Seriële programmer

Deze programmer is zowel compatible met de avrdude software als met de PonyProg software (zie bij 'De Tools'). De programmer is ook gelijk een mini-applicatiebordje, in de zin dat programma's er ook gelijk kunnen draaien; zie bijvoorbeeld 'Het eerste programma'tje' verderop.

De Tools

AVR met Linux: aanpassen

Om GCC en avrdude onder Linux werkend te maken was even tricky. avrdude in combinatie met een trage (128 kHz low power) clock van de ATtiny  draaide voor mij te snel onder Linux (windows was OK), en ik moest de -i 40 parameter toevoegen. O ja, en -P /dev/ttyS0 ipv -P com1

Ook de Code::Blocks configuratie was niet optimaal voor avrdude, voeg -R .fuse -R .lock -R .signature toe in de build options: pre/post build steps, eerste avr-objcopy commando.

Verder heb ik standaard de volgende compiler-opties toegevoegd: -gdwarf-2 -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums

Wil je een .lss file, voeg dan aan de pre/post build steps toe: avr-objdump -h -S $(TARGET_OUTPUT_FILE) > $(TARGET_OUTPUT_FILE).lss

Ik wil de tools kunnen draaien op een laptop met Windows XP, of Ubuntu Linux. Daar ik liever niet in assembler programmeer (weer een andere assembly-taal) ga ik voor C: de GCC compiler suite is ook verkrijgbaar voor de 2313. Minimaal is nodig de WinAVR GCC omgeving, dit is de Windows GCC C/C++ compiler voor de AVR processoren, met alle bijhorende tools (Linux/Ubuntu: AVR-GCC .deb packages). Een belangrijk onderdeel hiervan is de runtime library AVR-libc, met uitgebreide AVR-libc documentatie en voorbeelden (ook over bijvoorbeeld interrupts, mixen met assembler code, etc).

De hele AVR GCC suite is command-line gebaseerd (dus zo'n ouderwets DOS boxje), gebruik je liever een complete grafische IDE, kijk dan naar de Atmel AVR Studio 4 (Windows). Dit programma is gratis te downloaden (eerst het programma, en dan de twee service packs, en in de goede volgorde installeren: programma, dan SP1, dan pas SP2). Werkt samen met de GCC compiler, maar je kan ook in assembler werken. Als alternatief, en óók onder Linux, kan je de Code::Blocks IDE gebruiken, heeft standaard ook de AVR configuratie in zijn templates (al linkt'ie iets anders, waardoor de binary niet exact hetzelfde is als bij AVR Studio).

Als je een programma gecompileerd hebt, moet je het ook in de 2313 zien te krijgen, oftewel je hebt een tool nodig om met de programmer te kunnen praten. Het eenvoudigst qua omgeving is om hiervoor avrdude te gebruiken; meegeleverd in WinAVR. Wil je echter dit niet vanaf de command line hoeven te doen, dan kan je ook PonyProg gebruiken, deze heeft een vriendelijker grafische gebruikersomgeving. Ik heb het zelf overigens niet gebruikt, gebruik alleen avrdude.

Meer info over de C compiler: zie de software tips pagina.

Het eerste programma'tje

De 'hello world' voor embedded systems is het laten knipperen van een LEDje... Ik ben hiervoor uitgegaan van de Nederlandstalige intro 'Knipperende LED', waar op de site behoorlijk wat over de tiny2313 wordt uitgelegd. Zeker lezen! Op de programmer twee extra onderdelen geplaatst: weerstand 470 Ohm plus een rode LED, en in serie aangesloten tussen Vcc en pin PD2 (pin 6 op het voetje): dus anders dan in de tutorial! Dit omdat ik ook een extern kristal wil kunnen gebruiken: deze wordt op pin 4 en 5 aangesloten, waar in de tutorial de LED zit. Ook de source (bij mij knipper.c) dus even hierop aanpassen...

Ik gebruik AVR Studio om te compileren; met 'F7' vertaal je de hele boel. In de directory 'default' vind je de gegenereerde files; de .hex file bevat de binary om in de chip te branden. de .lss file bevat een uitgebreide listing, inclusief startup code. AVR Studio doet een aantal stappen; de meest belangrijke is het aanroepen van de compiler; hieronder (verkort) weergegeven om te laten zien met welke opties vertaald wordt:

avr-gcc -mmcu=attiny2313 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums knipper.c

De -Os optimaliseerd voor grootte. Let op: na dit commando volgt er nog een aantal commando's om de uiteindelijke hex file te maken; hier niet weergegeven (doet AVR Studio voor je, maar wel van belang als je zelf een .bat of een makefile wilt maken). Downloaden naar de chip gaat met avrdude en de zojuist gemaakte seriële programmer:

avrdude -p t2313 -c siprog -P com1 -U flash:w:knipper.hex

En ja, het LEDje gaat na het downloaden vanzelf knipperen. Het hele programma is 116 bytes (de grootte van de te downloaden binary, dus inclusief libraries en opstartcode), niet slecht voor een heel C programma!

Losgekoppeld van de computer, en op een regelbare voeding aangesloten. Eens kijken hoe ver ik de voeding kan laten dalen... Zelfs bij 1.33 Volt (de laagste stand die ik haal) blijft de uitgang keurig op en neer gaan, al is door de te lage spanning de LED al niet meer zichtbaar. Netjes, formeel is'ie maar vanaf 2.7 Volt gegarandeerd (en de V-versie vanaf 1.8V). Houdt in dat'ie ook op twee oplaadbare batterijen werkt, handig voor een volgens project dat ik in gedachten heb (soort vuurvliegjes gebaseerd op de zonnecel van zo'n oude LED-tuinlamp).

Fuse programming met AVRDUDE

Dit stukje is verhuisd naar de software tips pagina...

Interrupts

Altijd handig om een gevoel van tijd te hebben, dus een interrupt-routine om ticks te tellen is plezierig. De timers lopen toch al (vanwege de PWM), dus ik gebruik timer 0 overflow om elke periode een interrupt te genereren. Met een 4 MHz kristal; prescaler op 8, en 256 ticks voor een PWM-ronde kom ik zo op een PWM- en interrupt-frequentie van haast 2 kHz (4MHz / 8 / 256). In de interrupt-routine gebruik ik dit (om te testen) om een LEDje te laten knipperen; ziet er op de scope goed uit. Timer 0 instellen als pwm en in TIMSK timer overflow interrupt aanzetten, en de globale enable flag aanzetten met de sei() functie:

#include <avr/interrupt.h>
volatile int pwm_counter;

ISR(TIMER0_OVF_vect)    // T0 interrupt service routine
{
  PORTD ^= (1 << PD2);  // toggle LED output at 1 kHz
}
...
// in main: timer0 as fast PWM, clear pwm output on match
TCCR0A = (1 << COM0A1) | (1 << WGM01) | (1 << WGM00);
TCCR0B = (1 << CS01);   // timer0 prescale by factor 8
TIMSK |= (1 << TOIE0);  // enable timer0 overflow interrupt
sei();                  // global enable interrupts
...

De timer interrupt wordt uiteindelijk gebruikt voor onder andere het  geleidelijk aan- en uit-zetten van de leds, en het bijhouden van de real-time klok.

De I²C (of TWI)

Atmel noemt I²C "TWI", Two-Wire Interface, om trade-mark issues te voorkomen. Ik had gehoopt code van het Arduino project te kunnen gebruiken, maar helaas: hardware is anders. De ATtiny2313 heeft een USI poort (Universal Serial Interface), die meerdere standaarden — waaronder I²C — aankan. Toch was er ook voor de tiny op internet wel wat te vinden; twee projecten vond ik met name van belang (de Atmel eigen code uit de app-notes werkt volgens fora niet altijd betrouwbaar, deze links hebben bijgewerkte versies):

  • Deze I²C dimmer applicatie, waar een circulaire buffer voor communicatie gebruikt wordt: handig als je een message-based protocol wilt. Overigens is deze app ook een slimme manier om een 8-kanaals PWM te implementeren op de ATtiny.
  • Deze I²C eeprom simulatie, die zich gedraagt als een seriële eeprom, dus meer een memory-mapped manier van communicatie

Ben met de eprom-simulatie aan de slag gegaan; was het eenvoudigst hier een register-gebaseerde interface á la PCA9634 mee op te bouwen. De code deed niet helemaal wat er gezegd werd, heb wat kleine wijzigingen doorgevoerd, zoals de merge van de send- en receive-buffer in een geheugenbuffer. De hele code is minder dan 500 bytes, dus ik heb nog meer dan 3/4 over voor de eigenlijke applicatie. Alle i2c-communicatie wordt in de interrupt afgehandeld; het main program is een lege eindeloze loop.

Ook gezorgd dat de LED en een switch (met een weerstand van 1K, van PD3/pin 7 naar aarde) ergens in het "eprom"-geheugengebied zijn gemapped door in de eindeloze loop van het 'main'-programma deze waarden heen en weer te kopiëren van de I/O naar de geheugenbuffer waar de eeprom gesimuleerd wordt. Ja, ik kan nu (vanuit de NSLU2) de LED aan en uitzetten, en de schakelaar uitlezen (via de i2cset en i2cget commando's)! I²C werkt. Ongeveer een week nadat ik de onderdelen van de programmer binnenkreeg, toch netjes.

Ik ga overigens niet een 8-kanaals PCA9634 exact nabouwen (waarvoor de dimmer-app een goed startpunt zou zijn); maar de extra intelligentie van de tiny gebruiken voor een besturing op hoger niveau (commando's als ga in zoveel seconden naar die helderheid); misschien dat dan een message-based protocol als in de dimmer dan toch meer toepasselijk is. Bovendien (in verband met de gevoeligheid van het menselijk oog) wil ik meer een logarithmische curve, en daarvoor heb ik meer dan 8 (lineaire) bits nodig, zit aan 12 te denken... Maar, dat wordt misschien nog wel eens een andere pagina.

HEXFET power LED driverEen krachtiger LED

Bij Conrad enkele power LEDs besteld, rood/groen/blauw, per kleur ongeveer 1 Watt. Deze LEDs (181159-89; €14,14) mogen per stuk 350 mA hebben (mits goed gekoeld, 188052-89), en dat is wat veel voor de ATtiny. Met enkele low-cost HEXFETs IRL510 (162789-89; € 0,60) is het echter wel goed te doen.

RGB power LED lampEen simpel schema'tje geeft ook een stroom­begrenzing, zodat ongeacht de voedings­spanning de stroom binnen de veilige grenzen blijft: als de spanning over R2 te hoog gaat, gaat T1 geleiden, en knijpt T2 dicht --> stroom wordt minder en de spanning over R2 daalt, evenwicht bij ongeveer 0.63V. Let op, als de FET in stroombegrenzingsmode werkt, valt er wel spanning over (gaat als weerstand werken), en dissipeert hij dus ook vermogen: bescheiden koelplaatje is nodig! Bij de gegeven waardes, en de blauwe LED (3.5V spanning, x2) op 350 mA staat er 2.9V over R3, en dus 1.45V over de FET --> 0.5W (en 1W over R3), bij de rode LED (2.5V, x2) meer: 3.45V resp. 1.2W over de FET.

De ingang is compatible met de ATtiny op 5 Volt, en aangesloten op de PWM-uitgangen op pin 14..16 (3 FETs in totaal, dus). Dit geeft een lamp met behoorlijke lichtopbrengst, en instelbare kleur en helderheid.

Ledlamp in werkingEen eerste testprogramma'tje is gebaseerd op een RGB-LED tutorial, hierin wordt gedemonstreerd hoe je de pulsbreedte modulatie (PWM) gebruikt. Er zijn voor mij enkele kleine aanpassingen nodig: de driver-trap zoals geschreven gedraagt zich als een inverter, dus uit → aan, en omgedraaid. De 2313 heeft in zijn configuratie­registers bits om de uitgang om te draaien (zie b.v. COM0A1), daarmee gedraagt het programma zich zoals gewenst.

En verder...

Ben nog met wat extra zaken bezig, zoals een low-cost AD conversie op de ATtiny; zie meer op mijn ATtiny Hardware Tips pagina... En tips over de software/debug kant op de software tips pagina.

Plus: Een ongesorteerde dump van mijn bookmarks over de AVR:

Algemeen:

Programmers:

Onderdelen nodig?

Top of page Opmerkingen, commentaar, feedback: mail naar .
Nuttige site? Antwoorden gevonden? Zet dan een link naar mijn site op je eigen site, hebben anderen er misschien ook wat aan!